diff --git a/lib/if.h b/lib/if.h index 49f2a52478..e8e84ffc88 100644 --- a/lib/if.h +++ b/lib/if.h @@ -229,6 +229,9 @@ struct interface /* Interface metric */ uint32_t metric; + /* Interface Speed in Mb/s */ + uint32_t speed; + /* Interface MTU. */ unsigned int mtu; /* IPv4 MTU */ unsigned int mtu6; /* IPv6 MTU - probably, but not neccessarily same as mtu */ diff --git a/lib/zclient.c b/lib/zclient.c index 4455644345..71b95ae7db 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1003,6 +1003,8 @@ zebra_router_id_update_read (struct stream *s, struct prefix *rid) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | metric | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | speed | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifmtu | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ifmtu6 | @@ -1185,6 +1187,7 @@ zebra_interface_if_set_value (struct stream *s, struct interface *ifp) ifp->ptm_enable = stream_getc (s); ifp->ptm_status = stream_getc (s); ifp->metric = stream_getl (s); + ifp->speed = stream_getl (s); ifp->mtu = stream_getl (s); ifp->mtu6 = stream_getl (s); ifp->bandwidth = stream_getl (s); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 0a1cafd87e..28538fabdf 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include "linklist.h" #include "if.h" @@ -298,6 +300,47 @@ netlink_vrf_change (struct nlmsghdr *h, struct rtattr *tb, const char *name) } } +static int +get_iflink_speed (const char *ifname) +{ + struct ifreq ifdata; + struct ethtool_cmd ecmd; + int sd; + int rc; + + /* initialize struct */ + memset(&ifdata, 0, sizeof(ifdata)); + + /* set interface name */ + strcpy(ifdata.ifr_name, ifname); + + /* initialize ethtool interface */ + memset(&ecmd, 0, sizeof(ecmd)); + ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ + ifdata.ifr_data = (__caddr_t) &ecmd; + + /* use ioctl to get IP address of an interface */ + sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); + if(sd < 0) { + zlog_debug ("Failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + return 0; + } + + /* Get the current link state for the interface */ + rc = ioctl(sd, SIOCETHTOOL, (char *)&ifdata); + if(rc < 0) { + zlog_debug("IOCTL failure to read interface %s speed: %d %s", + ifname, errno, safe_strerror(errno)); + ecmd.speed_hi = 0; + ecmd.speed = 0; + } + + close(sd); + + return (ecmd.speed_hi << 16 ) | ecmd.speed; +} + /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ static int @@ -382,6 +425,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 0; + ifp->speed = get_iflink_speed (name); ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Hardware type and address. */ diff --git a/zebra/interface.c b/zebra/interface.c index e9c54a629b..1d015e8588 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1056,8 +1056,8 @@ if_dump_vty (struct vty *vty, struct interface *ifp) return; } - vty_out (vty, " index %d metric %d mtu %d ", - ifp->ifindex, ifp->metric, ifp->mtu); + vty_out (vty, " index %d metric %d mtu %d speed %u ", + ifp->ifindex, ifp->metric, ifp->mtu, ifp->speed); if (ifp->mtu6 != ifp->mtu) vty_out (vty, "mtu6 %d ", ifp->mtu6); vty_out (vty, "%s flags: %s%s", VTY_NEWLINE, diff --git a/zebra/zserv.c b/zebra/zserv.c index f9205a12c8..85fdd53122 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -167,6 +167,7 @@ zserv_encode_interface (struct stream *s, struct interface *ifp) stream_putc (s, ifp->ptm_enable); stream_putc (s, ifp->ptm_status); stream_putl (s, ifp->metric); + stream_putl (s, ifp->speed); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth);