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; }