diff options
| author | Louis Scalbert <louis.scalbert@6wind.com> | 2024-01-10 16:47:03 +0100 | 
|---|---|---|
| committer | Louis Scalbert <louis.scalbert@6wind.com> | 2024-04-26 17:11:53 +0200 | 
| commit | c85ce39fe039b9f46c1b0304cf1b1c7e1d077084 (patch) | |
| tree | 96484de853962cae5fb51e2a0eb01df5d8dbdc8b | |
| parent | 57b9ecf3f96c0e87f3f759c067601731dcfaf5b8 (diff) | |
lib: take into account the iff_lower_up flag
In Linux, a network driver can set the interface flags IFF_UP and
IFF_RUNNING although the IFF_LOWER_UP flag is down, which means the
interface is ready but the carrier is down:
> These values contain interface state:
>
> ifinfomsg::if_flags & IFF_UP:
>  Interface is admin up
> ifinfomsg::if_flags & IFF_RUNNING:
>  Interface is in RFC2863 operational state UP or UNKNOWN. This is for
>  backward compatibility, routing daemons, dhcp clients can use this
>  flag to determine whether they should use the interface.
> ifinfomsg::if_flags & IFF_LOWER_UP:
>  Driver has signaled netif_carrier_on()
However, FRR considers an interface is operational as soon it is up
(IFF_UP) and running (IFF_RUNNING), disregarding the IFF_LOWER_UP flag.
This can lead to a scenario where FRR starts adding routes through an
interface that is technically down at the carrier level, resulting in
kernel errors.
> Jan 02 18:07:18 dut-vm zebra[283731]: [WVJCK-PPMGD][EC 4043309093] netlink-dp (NS 0) error: Network is down, type=RTM_NEWNEXTHOP(104), seq=243, pid=3112881162
> Jan 02 18:07:18 dut-vm zebra[283731]: [X5XE1-RS0SW][EC 4043309074] Failed to install Nexthop (318[if 164]) into the kernel
> Jan 02 18:07:18 dut-vm zebra[283731]: [HSYZM-HV7HF] Extended Error: Carrier for nexthop device is down
> Jan 02 18:07:18 dut-vm zebra[283731]: [WVJCK-PPMGD][EC 4043309093] netlink-dp (NS 0) error: Network is down, type=RTM_NEWNEXTHOP(104), seq=245, pid=3112881162
> Jan 02 18:07:18 dut-vm zebra[283731]: [HSYZM-HV7HF] Extended Error: Nexthop id does not exist
> Jan 02 18:07:18 dut-vm zebra[283731]: [WVJCK-PPMGD][EC 4043309093] netlink-dp (NS 0) error: Invalid argument, type=RTM_NEWROUTE(24), seq=246, pid=3112881162
> Jan 02 18:07:18 dut-vm zebra[283731]: [X5XE1-RS0SW][EC 4043309074] Failed to install Nexthop (320[10.125.0.2 if 164]) into the kernel
> Jan 02 18:07:18 dut-vm zebra[283731]: [VYKYC-709DP] default(0:254):0.0.0.0/0: Route install failed
Consider an interface is operational when it has the IFF_UP, IFF_RUNNING
and IFF_LOWER_UP flags.
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/operstates.rst?h=v6.7-rc8#n29
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/nexthop.c?h=v6.7-rc8#n2886
Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/netdevice.h?h=v6.7-rc8#n4198
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
| -rw-r--r-- | lib/if.c | 26 | 
1 files changed, 17 insertions, 9 deletions
@@ -674,21 +674,26 @@ int if_is_running(const struct interface *ifp)     if ptm checking is enabled, then ptm check has passed */  int if_is_operative(const struct interface *ifp)  { -	return ((ifp->flags & IFF_UP) -		&& (((ifp->flags & IFF_RUNNING) -		     && (ifp->ptm_status || !ifp->ptm_enable)) -		    || !CHECK_FLAG(ifp->status, -				   ZEBRA_INTERFACE_LINKDETECTION))); +	return ((ifp->flags & IFF_UP) && +		(((ifp->flags & IFF_RUNNING) +#ifdef IFF_LOWER_UP +		  && (ifp->flags & IFF_LOWER_UP) +#endif /* IFF_LOWER_UP */ +		  && (ifp->ptm_status || !ifp->ptm_enable)) || +		 !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));  }  /* Is the interface operative, eg. either UP & RUNNING     or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */  int if_is_no_ptm_operative(const struct interface *ifp)  { -	return ((ifp->flags & IFF_UP) -		&& ((ifp->flags & IFF_RUNNING) -		    || !CHECK_FLAG(ifp->status, -				   ZEBRA_INTERFACE_LINKDETECTION))); +	return ((ifp->flags & IFF_UP) && +		(((ifp->flags & IFF_RUNNING) +#ifdef IFF_LOWER_UP +		  && (ifp->flags & IFF_LOWER_UP) +#endif /* IFF_LOWER_UP */ +			  ) || +		 !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));  }  /* Is this loopback interface ? */ @@ -750,6 +755,9 @@ const char *if_flag_dump(unsigned long flag)  	strlcpy(logbuf, "<", BUFSIZ);  	IFF_OUT_LOG(IFF_UP, "UP"); +#ifdef IFF_LOWER_UP +	IFF_OUT_LOG(IFF_LOWER_UP, "LOWER_UP"); +#endif /* IFF_LOWER_UP */  	IFF_OUT_LOG(IFF_BROADCAST, "BROADCAST");  	IFF_OUT_LOG(IFF_DEBUG, "DEBUG");  	IFF_OUT_LOG(IFF_LOOPBACK, "LOOPBACK");  | 
