Testing the effect of interface manipulation on the values of IFF_UP and IFF_RUNNING.
Links:
Issues:
IFF_LOWER_UP
significant?IFF_DEBUG
?
From include/uapi/linux/if.h
:
/** * enum net_device_flags - &struct net_device flags * * These are the &struct net_device flags, they can be set by drivers, the * kernel and some can be triggered by userspace. Userspace can query and * set these flags using userspace utilities but there is also a sysfs * entry available for all dev flags which can be queried and set. These flags * are shared for all types of net_devices. The sysfs entries are available * via /sys/class/net/<dev>/flags. Flags which can be toggled through sysfs * are annotated below, note that only a few flags can be toggled and some * other flags are always preserved from the original net_device flags * even if you try to set them via sysfs. Flags which are always preserved * are kept under the flag grouping @IFF_VOLATILE. Flags which are volatile * are annotated below as such. * * You should have a pretty good reason to be extending these flags. * * @IFF_UP: interface is up. Can be toggled through sysfs. * @IFF_BROADCAST: broadcast address valid. Volatile. * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs. * @IFF_LOOPBACK: is a loopback net. Volatile. * @IFF_POINTOPOINT: interface is has p-p link. Volatile. * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs. * Volatile. * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile. * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile. * @IFF_PROMISC: receive all packets. Can be toggled through sysfs. * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through * sysfs. * @IFF_MASTER: master of a load balancer. Volatile. * @IFF_SLAVE: slave of a load balancer. Volatile. * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs. * @IFF_PORTSEL: can set media type. Can be toggled through sysfs. * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs. * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled * through sysfs. * @IFF_LOWER_UP: driver signals L1 up. Volatile. * @IFF_DORMANT: driver signals dormant. Volatile. * @IFF_ECHO: echo sent packets. Volatile. */ enum net_device_flags { /* for compatibility with glibc net/if.h */ #if __UAPI_DEF_IF_NET_DEVICE_FLAGS IFF_UP = 1<<0, /* sysfs */ IFF_BROADCAST = 1<<1, /* volatile */ IFF_DEBUG = 1<<2, /* sysfs */ IFF_LOOPBACK = 1<<3, /* volatile */ IFF_POINTOPOINT = 1<<4, /* volatile */ IFF_NOTRAILERS = 1<<5, /* sysfs */ IFF_RUNNING = 1<<6, /* volatile */ IFF_NOARP = 1<<7, /* sysfs */ IFF_PROMISC = 1<<8, /* sysfs */ IFF_ALLMULTI = 1<<9, /* sysfs */ IFF_MASTER = 1<<10, /* volatile */ IFF_SLAVE = 1<<11, /* volatile */ IFF_MULTICAST = 1<<12, /* sysfs */ IFF_PORTSEL = 1<<13, /* sysfs */ IFF_AUTOMEDIA = 1<<14, /* sysfs */ IFF_DYNAMIC = 1<<15, /* sysfs */ #endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */ #if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO IFF_LOWER_UP = 1<<16, /* volatile */ IFF_DORMANT = 1<<17, /* volatile */ IFF_ECHO = 1<<18, /* volatile */ #endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */ };
Administrative versus operational state:
Linux distinguishes between administrative and operational state of an interface. Administrative state is the result of "ip link set dev <dev> up or down" and reflects whether the administrator wants to use the device for traffic. However, an interface is not usable just because the admin enabled it - ethernet requires to be plugged into the switch and, depending on a site's networking policy and configuration, an 802.1X authentication to be performed before user data can be transferred. Operational state shows the ability of an interface to transmit this user data. Thanks to 802.1X, userspace must be granted the possibility to influence operational state. To accommodate this, operational state is split into two parts: Two flags that can be set by the driver only, and a RFC2863 compatible state that is derived from these flags, a policy, and changeable from userspace under certain rules.
ifconfig
is getting hex value from SIOCGIFFLAGS
which does dev_get_flags(dev)
.
4163:
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.0.15 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fd00:f81d:f81:4062:2e56:dcff:fe25:ad47 prefixlen 64 scopeid 0x0<global> inet6 fe80::2e56:dcff:fe25:ad47 prefixlen 64 scopeid 0x20<link> ether 2c:56:dc:25:ad:47 txqueuelen 1000 (Ethernet) RX packets 81232 bytes 92092778 (87.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 36768 bytes 9024553 (8.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
4098:
enp3s0: flags=4098<BROADCAST,MULTICAST> mtu 1500 inet 192.168.0.15 netmask 255.255.255.0 broadcast 192.168.0.255 ether 2c:56:dc:25:ad:47 txqueuelen 1000 (Ethernet) RX packets 81290 bytes 92110209 (87.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 36836 bytes 9042100 (8.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
UP, shortly followed by RUNNING:
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.0.15 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fd00:f81d:f81:4062:2e56:dcff:fe25:ad47 prefixlen 64 scopeid 0x0<global> inet6 fe80::2e56:dcff:fe25:ad47 prefixlen 64 scopeid 0x20<link> ether 2c:56:dc:25:ad:47 txqueuelen 1000 (Ethernet) RX packets 1268514 bytes 1611028865 (1.5 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 396222 bytes 65965632 (62.9 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
4099:
enp3s0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.0.15 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fd00:f81d:f81:4062:2e56:dcff:fe25:ad47 prefixlen 64 scopeid 0x0<global> inet6 fe80::2e56:dcff:fe25:ad47 prefixlen 64 scopeid 0x20<link> ether 2c:56:dc:25:ad:47 txqueuelen 1000 (Ethernet) RX packets 81318 bytes 92115343 (87.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 36917 bytes 9052750 (8.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
This is how ifconfig
gets its info – via dev_get_flags()
and ioctl command SIOCGIFFLAGS
:
/* * Perform the SIOCxIFxxx calls, inside rcu_read_lock() */ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd) { int err; struct net_device *dev = dev_get_by_name_rcu(net, ifr->ifr_name); if (!dev) return -ENODEV; switch (cmd) { case SIOCGIFFLAGS: /* Get interface flags */ ifr->ifr_flags = (short) dev_get_flags(dev); return 0;
Volatile flags are supported via RFC2863 operstates.
/** * dev_get_flags - get flags reported to userspace * @dev: device * * Get the combination of flag bits exported through APIs to userspace. */ unsigned int dev_get_flags(const struct net_device *dev) { unsigned int flags; flags = (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI | IFF_RUNNING | IFF_LOWER_UP | IFF_DORMANT)) | (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); if (netif_running(dev)) { if (netif_oper_up(dev)) flags |= IFF_RUNNING; if (netif_carrier_ok(dev)) flags |= IFF_LOWER_UP; if (netif_dormant(dev)) flags |= IFF_DORMANT; } return flags; } EXPORT_SYMBOL(dev_get_flags);