From: Julien Floret Date: Tue, 6 Aug 2019 09:15:05 +0000 (+0200) Subject: zebra: inform upper layer error when reading correct speed interface X-Git-Tag: base_7.3~314^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=594c28781672aeb80b62a6fc6f876db2d0f865e1;p=matthieu%2Ffrr.git zebra: inform upper layer error when reading correct speed interface speed interface is done 15 seconds after interface creation. during that time, the vrf or the interface may have disappeared. to protect this, return an error in case it is not possible to create a vrf socket or it is not possible to get speed of an interface because of a missing device. Signed-off-by: Julien Floret Signed-off-by: Philippe Guibert --- diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c71b95f753..6aea7e0702 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -365,7 +365,7 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, } } -static int get_iflink_speed(struct interface *interface) +static int get_iflink_speed(struct interface *interface, int *error) { struct ifreq ifdata; struct ethtool_cmd ecmd; @@ -373,6 +373,8 @@ static int get_iflink_speed(struct interface *interface) int rc; const char *ifname = interface->name; + if (error) + *error = 0; /* initialize struct */ memset(&ifdata, 0, sizeof(ifdata)); @@ -393,6 +395,9 @@ static int get_iflink_speed(struct interface *interface) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("Failure to read interface %s speed: %d %s", ifname, errno, safe_strerror(errno)); + /* no vrf socket creation may probably mean vrf issue */ + if (error) + *error = -1; return 0; } /* Get the current link state for the interface */ @@ -404,6 +409,9 @@ static int get_iflink_speed(struct interface *interface) zlog_debug( "IOCTL failure to read interface %s speed: %d %s", ifname, errno, safe_strerror(errno)); + /* no device means interface unreachable */ + if (errno == ENODEV && error) + *error = -1; ecmd.speed_hi = 0; ecmd.speed = 0; } @@ -413,9 +421,9 @@ static int get_iflink_speed(struct interface *interface) return (ecmd.speed_hi << 16) | ecmd.speed; } -uint32_t kernel_get_speed(struct interface *ifp) +uint32_t kernel_get_speed(struct interface *ifp, int *error) { - return get_iflink_speed(ifp); + return get_iflink_speed(ifp, error); } static int netlink_extract_bridge_info(struct rtattr *link_data, @@ -696,7 +704,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; - ifp->speed = get_iflink_speed(ifp); + ifp->speed = get_iflink_speed(ifp, NULL); ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Set zebra interface type */ diff --git a/zebra/interface.c b/zebra/interface.c index 6486c01430..771f05857b 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -70,10 +70,19 @@ static int if_zebra_speed_update(struct thread *thread) struct zebra_if *zif = ifp->info; uint32_t new_speed; bool changed = false; + int error = 0; zif->speed_update = NULL; - new_speed = kernel_get_speed(ifp); + new_speed = kernel_get_speed(ifp, &error); + + /* error may indicate vrf not available or + * interfaces not available. + * note that loopback & virtual interfaces can return 0 as speed + */ + if (error < 0) + return 1; + if (new_speed != ifp->speed) { zlog_info("%s: %s old speed: %u new speed: %u", __PRETTY_FUNCTION__, ifp->name, ifp->speed, diff --git a/zebra/rt.h b/zebra/rt.h index 59b42fed18..f311a6b9d3 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -66,7 +66,7 @@ extern int kernel_interface_set_master(struct interface *master, extern int mpls_kernel_init(void); -extern uint32_t kernel_get_speed(struct interface *ifp); +extern uint32_t kernel_get_speed(struct interface *ifp, int *error); extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); /* diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index dc0f29bdbc..981ef7a889 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -396,7 +396,7 @@ extern int kernel_interface_set_master(struct interface *master, return 0; } -uint32_t kernel_get_speed(struct interface *ifp) +uint32_t kernel_get_speed(struct interface *ifp, int *error) { return ifp->speed; }