diff options
Diffstat (limited to 'zebra/if_netlink.c')
| -rw-r--r-- | zebra/if_netlink.c | 127 |
1 files changed, 103 insertions, 24 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index be7a5ac78d..edfb564a6c 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -14,14 +14,15 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <zebra.h> #include <net/if_arp.h> +#include <linux/sockios.h> +#include <linux/ethtool.h> #include "linklist.h" #include "if.h" @@ -36,8 +37,10 @@ #include "privs.h" #include "nexthop.h" #include "vrf.h" +#include "vrf_int.h" #include "mpls.h" +#include "vty.h" #include "zebra/zserv.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" @@ -172,6 +175,48 @@ netlink_to_zebra_link_type (unsigned int hwt) } } + +//Temporary Assignments to compile on older platforms. +#ifndef IFLA_BR_MAX +#define IFLA_BR_MAX 39 +#endif + +#ifndef IFLA_VXLAN_ID +#define IFLA_VXLAN_ID 1 +#endif + +#ifndef IFLA_VXLAN_LOCAL +#define IFLA_VXLAN_LOCAL 4 +#endif + +#ifndef IFLA_VXLAN_MAX +#define IFLA_VXLAN_MAX 26 +#endif + +#ifndef IFLA_BRIDGE_MAX +#define IFLA_BRIDGE_MAX 2 +#endif + +#ifndef IFLA_BRIDGE_VLAN_INFO +#define IFLA_BRIDGE_VLAN_INFO 2 +#endif + +#ifndef BRIDGE_VLAN_INFO_PVID +#define BRIDGE_VLAN_INFO_PVID (1<<1) +#endif + +#ifndef RTEXT_FILTER_BRVLAN +#define RTEXT_FILTER_BRVLAN (1<<1) +#endif + +#ifndef NTF_SELF +#define NTF_SELF 0x02 +#endif + +#ifndef IFLA_BR_VLAN_FILTERING +#define IFLA_BR_VLAN_FILTERING 7 +#endif + #define parse_rtattr_nested(tb, max, rta) \ netlink_parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)) @@ -255,11 +300,52 @@ 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 netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct ifinfomsg *ifi; @@ -332,13 +418,14 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, } /* Add interface. */ - ifp = if_get_by_name_vrf (name, vrf_id); + ifp = if_get_by_name (name, vrf_id); set_ifindex(ifp, ifi->ifi_index, zns); ifp->flags = ifi->ifi_flags & 0x0000fffff; if (vrf_device) 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. */ @@ -360,7 +447,7 @@ interface_lookup_netlink (struct zebra_ns *zns) ret = netlink_request (AF_PACKET, RTM_GETLINK, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_interface, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; @@ -368,19 +455,17 @@ interface_lookup_netlink (struct zebra_ns *zns) ret = netlink_request (AF_INET, RTM_GETADDR, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; -#ifdef HAVE_IPV6 /* Get IPv6 address of the interfaces. */ ret = netlink_request (AF_INET6, RTM_GETADDR, &zns->netlink_cmd); if (ret < 0) return ret; - ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0); + ret = netlink_parse_info (netlink_interface_addr, &zns->netlink_cmd, zns, 0, 1); if (ret < 0) return ret; -#endif /* HAVE_IPV6 */ return 0; } @@ -434,7 +519,7 @@ netlink_address (int cmd, int family, struct interface *ifp, addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label, strlen (ifc->label) + 1); - return netlink_talk (&req.n, &zns->netlink_cmd, zns); + return netlink_talk (netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, 0); } int @@ -451,7 +536,7 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) int netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct ifaddrmsg *ifa; @@ -466,11 +551,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, zns = zebra_ns_lookup (ns_id); ifa = NLMSG_DATA (h); - if (ifa->ifa_family != AF_INET -#ifdef HAVE_IPV6 - && ifa->ifa_family != AF_INET6 -#endif /* HAVE_IPV6 */ - ) + if (ifa->ifa_family != AF_INET && ifa->ifa_family != AF_INET6) return 0; if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) @@ -570,7 +651,6 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, (struct in_addr *) addr, ifa->ifa_prefixlen, (struct in_addr *) broad); } -#ifdef HAVE_IPV6 if (ifa->ifa_family == AF_INET6) { if (h->nlmsg_type == RTM_NEWADDR) @@ -588,14 +668,13 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h, (struct in6_addr *) addr, ifa->ifa_prefixlen, (struct in6_addr *) broad); } -#endif /* HAVE_IPV6 */ return 0; } int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, - ns_id_t ns_id) + ns_id_t ns_id, int startup) { int len; struct ifinfomsg *ifi; @@ -667,7 +746,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, } /* See if interface is present. */ - ifp = if_lookup_by_index_per_ns (zns, ifi->ifi_index); + ifp = if_lookup_by_name_per_ns (zns, name); if (h->nlmsg_type == RTM_NEWLINK) { @@ -687,13 +766,13 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (ifp == NULL) { /* unknown interface */ - ifp = if_get_by_name_vrf (name, vrf_id); + ifp = if_get_by_name (name, vrf_id); } else { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) - if_update_vrf (ifp, name, strlen(name), vrf_id); + if_update (ifp, name, strlen(name), vrf_id); } /* Update interface information. */ |
