Skip to content

Commit

Permalink
zebra: fix speed set to UINT32_MAX
Browse files Browse the repository at this point in the history
get_iflink_speed() returns UINT32_MAX when the speeds is unknown.
Routing daemons (at least ospfd) interprets it as the high value.

Return errors in get_iflink_speed() to avoid the confusion.

Signed-off-by: Philippe Guibert <[email protected]>
Signed-off-by: Louis Scalbert <[email protected]>
  • Loading branch information
pguibert6WIND committed Jan 25, 2024
1 parent 9b9abe1 commit 1d3e071
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 6 deletions.
13 changes: 10 additions & 3 deletions zebra/if_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
int sd;
int rc;
const char *ifname = interface->name;
uint32_t ret;

if (error)
*error = 0;
Expand All @@ -285,7 +286,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
ifname, errno, safe_strerror(errno));
/* no vrf socket creation may probably mean vrf issue */
if (error)
*error = -1;
*error = INTERFACE_SPEED_ERROR_READ;
return 0;
}
/* Get the current link state for the interface */
Expand All @@ -299,14 +300,20 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
ifname, errno, safe_strerror(errno));
/* no device means interface unreachable */
if (errno == ENODEV && error)
*error = -1;
*error = INTERFACE_SPEED_ERROR_READ;
ecmd.speed_hi = 0;
ecmd.speed = 0;
}

close(sd);

return ((uint32_t)ecmd.speed_hi << 16) | ecmd.speed;
ret = ((uint32_t)ecmd.speed_hi << 16) | ecmd.speed;
if (ret == UINT32_MAX) {
if (error)
*error = INTERFACE_SPEED_ERROR_UNKNOWN;
ret = 0;
}
return ret;
}

uint32_t kernel_get_speed(struct interface *ifp, int *error)
Expand Down
6 changes: 3 additions & 3 deletions zebra/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static void if_zebra_speed_update(struct event *thread)
* interfaces not available.
* note that loopback & virtual interfaces can return 0 as speed
*/
if (error < 0)
if (error == INTERFACE_SPEED_ERROR_READ)
return;

if (new_speed != ifp->speed) {
Expand All @@ -76,7 +76,7 @@ static void if_zebra_speed_update(struct event *thread)
changed = true;
}

if (changed || new_speed == UINT32_MAX) {
if (changed || error == INTERFACE_SPEED_ERROR_UNKNOWN) {
#define SPEED_UPDATE_SLEEP_TIME 5
#define SPEED_UPDATE_COUNT_MAX (4 * 60 / SPEED_UPDATE_SLEEP_TIME)
/*
Expand All @@ -91,7 +91,7 @@ static void if_zebra_speed_update(struct event *thread)
* to not update the system to keep track of that. This
* is far simpler to just stop trying after 4 minutes
*/
if (new_speed == UINT32_MAX &&
if (error == INTERFACE_SPEED_ERROR_UNKNOWN &&
zif->speed_update_count == SPEED_UPDATE_COUNT_MAX)
return;

Expand Down
3 changes: 3 additions & 0 deletions zebra/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ struct zebra_if {
ifindex_t link_ifindex;
struct interface *link;

#define INTERFACE_SPEED_ERROR_READ -1
#define INTERFACE_SPEED_ERROR_UNKNOWN -2

uint8_t speed_update_count;
struct event *speed_update;

Expand Down

0 comments on commit 1d3e071

Please sign in to comment.