summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-03-30 21:51:29 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-04-03 20:49:35 +0200
commit535fe877a9b70084db581e4897452fb4a8dd4e85 (patch)
tree5e438c831e8b6762d111506d3ac112bbb2bb771b /zebra
parentlib, zebra: Add ability to pass interface speed up from zebra (diff)
downloadfrr-535fe877a9b70084db581e4897452fb4a8dd4e85.tar.xz
frr-535fe877a9b70084db581e4897452fb4a8dd4e85.zip
zebra: Retrieve interface speed when creating interface
When we get notification from the kernel about the creation of a new interface, retrieve the speed of it from the kernel Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'zebra')
-rw-r--r--zebra/if_netlink.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 0a1cafd87..b1d4dd81d 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,45 @@ 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));
+ }
+
+ 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 +423,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. */