summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zebra/if_netlink.c5
-rw-r--r--zebra/interface.c33
-rw-r--r--zebra/interface.h2
-rw-r--r--zebra/rt.h1
-rw-r--r--zebra/rt_socket.c5
5 files changed, 46 insertions, 0 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index f73506bf91..14905b738b 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -387,6 +387,11 @@ static int get_iflink_speed(const char *ifname)
return (ecmd.speed_hi << 16) | ecmd.speed;
}
+uint32_t kernel_get_speed(struct interface *ifp)
+{
+ return get_iflink_speed(ifp->name);
+}
+
static int netlink_extract_bridge_info(struct rtattr *link_data,
struct zebra_l2info_bridge *bridge_info)
{
diff --git a/zebra/interface.c b/zebra/interface.c
index 18588ee52c..906f796136 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -57,8 +57,29 @@ DEFINE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp),
DEFINE_HOOK(zebra_if_config_wr, (struct vty *vty, struct interface *ifp),
(vty, ifp))
+
static void if_down_del_nbr_connected(struct interface *ifp);
+static int if_zebra_speed_update(struct thread *thread)
+{
+ struct interface *ifp = THREAD_ARG(thread);
+ struct zebra_if *zif = ifp->info;
+ uint32_t new_speed;
+
+ zif->speed_update = NULL;
+
+ new_speed = kernel_get_speed(ifp);
+ if (new_speed != ifp->speed) {
+ zlog_info("%s: %s old speed: %u new speed: %u",
+ __PRETTY_FUNCTION__, ifp->name,
+ ifp->speed, new_speed);
+ ifp->speed = new_speed;
+ if_add_update(ifp);
+ }
+
+ return 1;
+}
+
static void zebra_if_node_destroy(route_table_delegate_t *delegate,
struct route_table *table,
struct route_node *node)
@@ -119,6 +140,16 @@ static int if_zebra_new_hook(struct interface *ifp)
route_table_init_with_delegate(&zebra_if_table_delegate);
ifp->info = zebra_if;
+
+ /*
+ * Some platforms are telling us that the interface is
+ * up and ready to go. When we check the speed we
+ * sometimes get the wrong value. Wait a couple
+ * of seconds and ask again. Hopefully it's all settled
+ * down upon startup.
+ */
+ thread_add_timer(zebrad.master, if_zebra_speed_update,
+ ifp, 15, &zebra_if->speed_update);
return 0;
}
@@ -141,6 +172,8 @@ static int if_zebra_delete_hook(struct interface *ifp)
list_delete_and_null(&rtadv->AdvPrefixList);
#endif /* HAVE_RTADV */
+ THREAD_OFF(zebra_if->speed_update);
+
XFREE(MTYPE_TMP, zebra_if);
}
diff --git a/zebra/interface.h b/zebra/interface.h
index 61c3359f3b..e13721448c 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -273,6 +273,8 @@ struct zebra_if {
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
+
+ struct thread *speed_update;
};
DECLARE_HOOK(zebra_if_extra_info, (struct vty *vty, struct interface *ifp),
diff --git a/zebra/rt.h b/zebra/rt.h
index 7f5bb4dd34..bb4ff5bee8 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -98,6 +98,7 @@ extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp,
extern int mpls_kernel_init(void);
+extern uint32_t kernel_get_speed(struct interface *ifp);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 0d1a80e737..0c29f0650c 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -473,4 +473,9 @@ extern int kernel_interface_set_master(struct interface *master,
return 0;
}
+uint32_t kernel_get_speed(struct interface *ifp)
+{
+ return ifp->speed;
+}
+
#endif /* !HAVE_NETLINK */