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 <julien.floret@6wind.com>
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Julien Floret 2019-08-06 11:15:05 +02:00 committed by Philippe Guibert
parent 215e03fe53
commit 594c287816
4 changed files with 24 additions and 7 deletions

View File

@ -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 */

View File

@ -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,

View File

@ -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);
/*

View File

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