162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci================== 462306a36Sopenharmony_ciOperational States 562306a36Sopenharmony_ci================== 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci1. Introduction 962306a36Sopenharmony_ci=============== 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ciLinux distinguishes between administrative and operational state of an 1262306a36Sopenharmony_ciinterface. Administrative state is the result of "ip link set dev 1362306a36Sopenharmony_ci<dev> up or down" and reflects whether the administrator wants to use 1462306a36Sopenharmony_cithe device for traffic. 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciHowever, an interface is not usable just because the admin enabled it 1762306a36Sopenharmony_ci- ethernet requires to be plugged into the switch and, depending on 1862306a36Sopenharmony_cia site's networking policy and configuration, an 802.1X authentication 1962306a36Sopenharmony_cito be performed before user data can be transferred. Operational state 2062306a36Sopenharmony_cishows the ability of an interface to transmit this user data. 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciThanks to 802.1X, userspace must be granted the possibility to 2362306a36Sopenharmony_ciinfluence operational state. To accommodate this, operational state is 2462306a36Sopenharmony_cisplit into two parts: Two flags that can be set by the driver only, and 2562306a36Sopenharmony_cia RFC2863 compatible state that is derived from these flags, a policy, 2662306a36Sopenharmony_ciand changeable from userspace under certain rules. 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci2. Querying from userspace 3062306a36Sopenharmony_ci========================== 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ciBoth admin and operational state can be queried via the netlink 3362306a36Sopenharmony_cioperation RTM_GETLINK. It is also possible to subscribe to RTNLGRP_LINK 3462306a36Sopenharmony_cito be notified of updates while the interface is admin up. This is 3562306a36Sopenharmony_ciimportant for setting from userspace. 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciThese values contain interface state: 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciifinfomsg::if_flags & IFF_UP: 4062306a36Sopenharmony_ci Interface is admin up 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciifinfomsg::if_flags & IFF_RUNNING: 4362306a36Sopenharmony_ci Interface is in RFC2863 operational state UP or UNKNOWN. This is for 4462306a36Sopenharmony_ci backward compatibility, routing daemons, dhcp clients can use this 4562306a36Sopenharmony_ci flag to determine whether they should use the interface. 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ciifinfomsg::if_flags & IFF_LOWER_UP: 4862306a36Sopenharmony_ci Driver has signaled netif_carrier_on() 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciifinfomsg::if_flags & IFF_DORMANT: 5162306a36Sopenharmony_ci Driver has signaled netif_dormant_on() 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciTLV IFLA_OPERSTATE 5462306a36Sopenharmony_ci------------------ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cicontains RFC2863 state of the interface in numeric representation: 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciIF_OPER_UNKNOWN (0): 5962306a36Sopenharmony_ci Interface is in unknown state, neither driver nor userspace has set 6062306a36Sopenharmony_ci operational state. Interface must be considered for user data as 6162306a36Sopenharmony_ci setting operational state has not been implemented in every driver. 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ciIF_OPER_NOTPRESENT (1): 6462306a36Sopenharmony_ci Unused in current kernel (notpresent interfaces normally disappear), 6562306a36Sopenharmony_ci just a numerical placeholder. 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciIF_OPER_DOWN (2): 6862306a36Sopenharmony_ci Interface is unable to transfer data on L1, f.e. ethernet is not 6962306a36Sopenharmony_ci plugged or interface is ADMIN down. 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciIF_OPER_LOWERLAYERDOWN (3): 7262306a36Sopenharmony_ci Interfaces stacked on an interface that is IF_OPER_DOWN show this 7362306a36Sopenharmony_ci state (f.e. VLAN). 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciIF_OPER_TESTING (4): 7662306a36Sopenharmony_ci Interface is in testing mode, for example executing driver self-tests 7762306a36Sopenharmony_ci or media (cable) test. It can't be used for normal traffic until tests 7862306a36Sopenharmony_ci complete. 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciIF_OPER_DORMANT (5): 8162306a36Sopenharmony_ci Interface is L1 up, but waiting for an external event, f.e. for a 8262306a36Sopenharmony_ci protocol to establish. (802.1X) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ciIF_OPER_UP (6): 8562306a36Sopenharmony_ci Interface is operational up and can be used. 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ciThis TLV can also be queried via sysfs. 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ciTLV IFLA_LINKMODE 9062306a36Sopenharmony_ci----------------- 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cicontains link policy. This is needed for userspace interaction 9362306a36Sopenharmony_cidescribed below. 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciThis TLV can also be queried via sysfs. 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci3. Kernel driver API 9962306a36Sopenharmony_ci==================== 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciKernel drivers have access to two flags that map to IFF_LOWER_UP and 10262306a36Sopenharmony_ciIFF_DORMANT. These flags can be set from everywhere, even from 10362306a36Sopenharmony_ciinterrupts. It is guaranteed that only the driver has write access, 10462306a36Sopenharmony_cihowever, if different layers of the driver manipulate the same flag, 10562306a36Sopenharmony_cithe driver has to provide the synchronisation needed. 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci__LINK_STATE_NOCARRIER, maps to !IFF_LOWER_UP: 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciThe driver uses netif_carrier_on() to clear and netif_carrier_off() to 11062306a36Sopenharmony_ciset this flag. On netif_carrier_off(), the scheduler stops sending 11162306a36Sopenharmony_cipackets. The name 'carrier' and the inversion are historical, think of 11262306a36Sopenharmony_ciit as lower layer. 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ciNote that for certain kind of soft-devices, which are not managing any 11562306a36Sopenharmony_cireal hardware, it is possible to set this bit from userspace. One 11662306a36Sopenharmony_cishould use TLV IFLA_CARRIER to do so. 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cinetif_carrier_ok() can be used to query that bit. 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci__LINK_STATE_DORMANT, maps to IFF_DORMANT: 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ciSet by the driver to express that the device cannot yet be used 12362306a36Sopenharmony_cibecause some driver controlled protocol establishment has to 12462306a36Sopenharmony_cicomplete. Corresponding functions are netif_dormant_on() to set the 12562306a36Sopenharmony_ciflag, netif_dormant_off() to clear it and netif_dormant() to query. 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ciOn device allocation, both flags __LINK_STATE_NOCARRIER and 12862306a36Sopenharmony_ci__LINK_STATE_DORMANT are cleared, so the effective state is equivalent 12962306a36Sopenharmony_cito netif_carrier_ok() and !netif_dormant(). 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ciWhenever the driver CHANGES one of these flags, a workqueue event is 13362306a36Sopenharmony_cischeduled to translate the flag combination to IFLA_OPERSTATE as 13462306a36Sopenharmony_cifollows: 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci!netif_carrier_ok(): 13762306a36Sopenharmony_ci IF_OPER_LOWERLAYERDOWN if the interface is stacked, IF_OPER_DOWN 13862306a36Sopenharmony_ci otherwise. Kernel can recognise stacked interfaces because their 13962306a36Sopenharmony_ci ifindex != iflink. 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cinetif_carrier_ok() && netif_dormant(): 14262306a36Sopenharmony_ci IF_OPER_DORMANT 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cinetif_carrier_ok() && !netif_dormant(): 14562306a36Sopenharmony_ci IF_OPER_UP if userspace interaction is disabled. Otherwise 14662306a36Sopenharmony_ci IF_OPER_DORMANT with the possibility for userspace to initiate the 14762306a36Sopenharmony_ci IF_OPER_UP transition afterwards. 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci4. Setting from userspace 15162306a36Sopenharmony_ci========================= 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ciApplications have to use the netlink interface to influence the 15462306a36Sopenharmony_ciRFC2863 operational state of an interface. Setting IFLA_LINKMODE to 1 15562306a36Sopenharmony_civia RTM_SETLINK instructs the kernel that an interface should go to 15662306a36Sopenharmony_ciIF_OPER_DORMANT instead of IF_OPER_UP when the combination 15762306a36Sopenharmony_cinetif_carrier_ok() && !netif_dormant() is set by the 15862306a36Sopenharmony_cidriver. Afterwards, the userspace application can set IFLA_OPERSTATE 15962306a36Sopenharmony_cito IF_OPER_DORMANT or IF_OPER_UP as long as the driver does not set 16062306a36Sopenharmony_cinetif_carrier_off() or netif_dormant_on(). Changes made by userspace 16162306a36Sopenharmony_ciare multicasted on the netlink group RTNLGRP_LINK. 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ciSo basically a 802.1X supplicant interacts with the kernel like this: 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci- subscribe to RTNLGRP_LINK 16662306a36Sopenharmony_ci- set IFLA_LINKMODE to 1 via RTM_SETLINK 16762306a36Sopenharmony_ci- query RTM_GETLINK once to get initial state 16862306a36Sopenharmony_ci- if initial flags are not (IFF_LOWER_UP && !IFF_DORMANT), wait until 16962306a36Sopenharmony_ci netlink multicast signals this state 17062306a36Sopenharmony_ci- do 802.1X, eventually abort if flags go down again 17162306a36Sopenharmony_ci- send RTM_SETLINK to set operstate to IF_OPER_UP if authentication 17262306a36Sopenharmony_ci succeeds, IF_OPER_DORMANT otherwise 17362306a36Sopenharmony_ci- see how operstate and IFF_RUNNING is echoed via netlink multicast 17462306a36Sopenharmony_ci- set interface back to IF_OPER_DORMANT if 802.1X reauthentication 17562306a36Sopenharmony_ci fails 17662306a36Sopenharmony_ci- restart if kernel changes IFF_LOWER_UP or IFF_DORMANT flag 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ciif supplicant goes down, bring back IFLA_LINKMODE to 0 and 17962306a36Sopenharmony_ciIFLA_OPERSTATE to a sane value. 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ciA routing daemon or dhcp client just needs to care for IFF_RUNNING or 18262306a36Sopenharmony_ciwaiting for operstate to go IF_OPER_UP/IF_OPER_UNKNOWN before 18362306a36Sopenharmony_ciconsidering the interface / querying a DHCP address. 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ciFor technical questions and/or comments please e-mail to Stefan Rompf 18762306a36Sopenharmony_ci(stefan at loplof.de). 188