summaryrefslogtreecommitdiff
path: root/zebra/if_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/if_netlink.c')
-rw-r--r--zebra/if_netlink.c44
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;