diff options
Diffstat (limited to 'zebra/if_netlink.c')
| -rw-r--r-- | zebra/if_netlink.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 4e49c1fc58..3583d63d31 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -68,6 +68,7 @@ #include "zebra/kernel_netlink.h" #include "zebra/if_netlink.h" #include "zebra/zebra_errors.h" +#include "zebra/zebra_vxlan.h" extern struct zebra_privs_t zserv_privs; @@ -731,6 +732,7 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family, /* Form the request, specifying filter (rtattr) if needed. */ memset(&req, 0, sizeof(req)); req.n.nlmsg_type = type; + req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.ifm.ifi_family = family; @@ -923,6 +925,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) uint8_t flags = 0; char *label = NULL; struct zebra_ns *zns; + uint32_t metric = METRIC_MAX; + uint32_t kernel_flags = 0; zns = zebra_ns_lookup(ns_id); ifa = NLMSG_DATA(h); @@ -959,12 +963,18 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) return -1; } + /* Flags passed through */ + if (tb[IFA_FLAGS]) + kernel_flags = *(int *)RTA_DATA(tb[IFA_FLAGS]); + else + kernel_flags = ifa->ifa_flags; + if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */ { char buf[BUFSIZ]; zlog_debug("netlink_interface_addr %s %s flags 0x%x:", nl_msg_type_to_str(h->nlmsg_type), ifp->name, - ifa->ifa_flags); + kernel_flags); if (tb[IFA_LOCAL]) zlog_debug(" IFA_LOCAL %s/%d", inet_ntop(ifa->ifa_family, @@ -1021,7 +1031,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) } /* Flags. */ - if (ifa->ifa_flags & IFA_F_SECONDARY) + if (kernel_flags & IFA_F_SECONDARY) SET_FLAG(flags, ZEBRA_IFA_SECONDARY); /* Label */ @@ -1031,6 +1041,9 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (label && strcmp(ifp->name, label) == 0) label = NULL; + if (tb[IFA_RT_PRIORITY]) + metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]); + /* Register interface address to the interface. */ if (ifa->ifa_family == AF_INET) { if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) { @@ -1043,7 +1056,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (h->nlmsg_type == RTM_NEWADDR) connected_add_ipv4(ifp, flags, (struct in_addr *)addr, ifa->ifa_prefixlen, - (struct in_addr *)broad, label); + (struct in_addr *)broad, label, + metric); else connected_delete_ipv4( ifp, flags, (struct in_addr *)addr, @@ -1064,12 +1078,13 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) * time, Quagga * does query for and will receive all addresses. */ - if (!(ifa->ifa_flags + if (!(kernel_flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))) connected_add_ipv6(ifp, flags, (struct in6_addr *)addr, (struct in6_addr *)broad, - ifa->ifa_prefixlen, label); + ifa->ifa_prefixlen, label, + metric); } else connected_delete_ipv6(ifp, (struct in6_addr *)addr, (struct in6_addr *)broad, @@ -1097,6 +1112,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifindex_t bridge_ifindex = IFINDEX_INTERNAL; ifindex_t bond_ifindex = IFINDEX_INTERNAL; ifindex_t link_ifindex = IFINDEX_INTERNAL; + uint8_t old_hw_addr[INTERFACE_HWADDR_MAX]; zns = zebra_ns_lookup(ns_id); @@ -1298,6 +1314,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp); zebra_if_set_ziftype(ifp, zif_type, zif_slave_type); + memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX); + netlink_interface_update_hw_addr(tb, ifp); if (if_is_no_ptm_operative(ifp)) { @@ -1316,6 +1334,22 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) "Intf %s(%u) PTM up, notifying clients", name, ifp->ifindex); zebra_interface_up_update(ifp); + + /* Update EVPN VNI when SVI MAC change + */ + if (IS_ZEBRA_IF_VLAN(ifp) && + memcmp(old_hw_addr, ifp->hw_addr, + INTERFACE_HWADDR_MAX)) { + struct interface *link_if; + + link_if = + if_lookup_by_index_per_ns( + zebra_ns_lookup(NS_DEFAULT), + link_ifindex); + if (link_if) + zebra_vxlan_svi_up(ifp, + link_if); + } } } else { ifp->flags = ifi->ifi_flags & 0x0000fffff; |
