diff options
Diffstat (limited to 'zebra/if_netlink.c')
| -rw-r--r-- | zebra/if_netlink.c | 44 |
1 files changed, 44 insertions, 0 deletions
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 <zebra.h> #include <net/if_arp.h> +#include <linux/sockios.h> +#include <linux/ethtool.h> #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. */ |
