summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bgpd/bgp_evpn.c110
-rw-r--r--bgpd/bgp_evpn.h3
-rw-r--r--bgpd/bgp_vty.c3
-rw-r--r--bgpd/bgp_zebra.c10
-rw-r--r--include/linux/if_addr.h69
-rw-r--r--include/subdir.am1
-rw-r--r--lib/if.h9
-rw-r--r--lib/zclient.h2
-rw-r--r--zebra/connected.c13
-rw-r--r--zebra/connected.h6
-rw-r--r--zebra/if_ioctl.c5
-rw-r--r--zebra/if_ioctl_solaris.c5
-rw-r--r--zebra/if_netlink.c10
-rw-r--r--zebra/kernel_socket.c6
-rw-r--r--zebra/zebra_vty.c12
-rw-r--r--zebra/zebra_vxlan.c35
-rw-r--r--zebra/zebra_vxlan_private.h6
17 files changed, 203 insertions, 102 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 7f6d34808..c74d7829b 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -887,17 +887,26 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
/* Install EVPN route into zebra. */
static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
- struct in_addr remote_vtep_ip, uint8_t flags,
- uint32_t seq)
+ struct prefix_evpn *p, struct bgp_path_info *pi)
{
int ret;
+ uint8_t flags;
- if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
- ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
- 1, flags, seq);
- else
+ if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+ flags = 0;
+ if (pi->attr->sticky)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
+ if (pi->attr->default_gw)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+ if (is_evpn_prefix_ipaddr_v6(p) &&
+ pi->attr->router_flag)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
+ ret = bgp_zebra_send_remote_macip(
+ bgp, vpn, p, pi->attr->nexthop, 1, flags,
+ mac_mobility_seqnum(pi->attr));
+ } else {
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1);
+ }
return ret;
}
@@ -1121,11 +1130,9 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
{
struct bgp_path_info *old_select, *new_select;
struct bgp_path_info_pair old_and_new;
- struct prefix_evpn *evp;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
int ret = 0;
- uint8_t flags = 0;
/* Compute the best path. */
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
@@ -1133,7 +1140,6 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
old_select = old_and_new.old;
new_select = old_and_new.new;
- evp = (struct prefix_evpn *)&rn->p;
/* If the best path hasn't changed - see if there is still something to
* update
* to zebra RIB.
@@ -1144,20 +1150,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
&& !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
- if (bgp_zebra_has_route_changed(rn, old_select)) {
- if (old_select->attr->sticky)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (old_select->attr->default_gw)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
- if (is_evpn_prefix_ipaddr_v6(evp) &&
- old_select->attr->router_flag)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
-
+ if (bgp_zebra_has_route_changed(rn, old_select))
ret = evpn_zebra_install(
bgp, vpn, (struct prefix_evpn *)&rn->p,
- old_select->attr->nexthop, flags,
- mac_mobility_seqnum(old_select->attr));
- }
+ old_select);
UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
bgp_zebra_clear_route_change_flags(rn);
return ret;
@@ -1182,18 +1178,9 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_IMPORTED) {
- flags = 0;
- if (new_select->attr->sticky)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (new_select->attr->default_gw)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
- if (is_evpn_prefix_ipaddr_v6(evp) &&
- new_select->attr->router_flag)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
-
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
- new_select->attr->nexthop, flags,
- mac_mobility_seqnum(new_select->attr));
+ new_select);
+
/* If an old best existed and it was a "local" route, the only
* reason
* it would be supplanted is due to MAC mobility procedures. So,
@@ -1698,6 +1685,27 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
return route_change;
}
+static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
+ struct bgpevpn *vpn, struct bgp_node *rn)
+{
+ struct bgp_path_info *tmp_ri;
+ struct bgp_path_info *curr_select = NULL;
+
+ for (tmp_ri = bgp_node_get_bgp_path_info(rn);
+ tmp_ri; tmp_ri = tmp_ri->next) {
+ if (CHECK_FLAG(tmp_ri->flags, BGP_PATH_SELECTED)) {
+ curr_select = tmp_ri;
+ break;
+ }
+ }
+
+ if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
+ && curr_select->sub_type == BGP_ROUTE_IMPORTED)
+ evpn_zebra_install(bgp, vpn,
+ (struct prefix_evpn *)&rn->p,
+ curr_select);
+}
+
/*
* If the local route was not selected evict it and tell zebra to re-add
* the best remote dest.
@@ -1717,9 +1725,6 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp,
struct bgp_node *rn,
struct bgp_path_info *local_pi)
{
- struct bgp_path_info *tmp_pi;
- struct bgp_path_info *curr_select = NULL;
- uint8_t flags = 0;
char buf[PREFIX_STRLEN];
/* local path was not picked as the winner; kick it out */
@@ -1731,24 +1736,7 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp,
bgp_path_info_reap(rn, local_pi);
/* tell zebra to re-add the best remote path */
- for (tmp_pi = bgp_node_get_bgp_path_info(rn);
- tmp_pi; tmp_pi = tmp_pi->next) {
- if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) {
- curr_select = tmp_pi;
- break;
- }
- }
- if (curr_select &&
- curr_select->type == ZEBRA_ROUTE_BGP
- && curr_select->sub_type == BGP_ROUTE_IMPORTED) {
- if (curr_select->attr->sticky)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (curr_select->attr->default_gw)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
- evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
- curr_select->attr->nexthop, flags,
- mac_mobility_seqnum(curr_select->attr));
- }
+ evpn_zebra_reinstall_best_route(bgp, vpn, rn);
}
/*
@@ -5324,10 +5312,11 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp)
* Handle del of a local MACIP.
*/
int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
- struct ipaddr *ip)
+ struct ipaddr *ip, int state)
{
struct bgpevpn *vpn;
struct prefix_evpn p;
+ struct bgp_node *rn;
/* Lookup VNI hash - should exist. */
vpn = bgp_evpn_lookup_vni(bgp, vni);
@@ -5338,9 +5327,16 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
return -1;
}
- /* Remove EVPN type-2 route and schedule for processing. */
build_evpn_type2_prefix(&p, mac, ip);
- delete_evpn_route(bgp, vpn, &p);
+ if (state == ZEBRA_NEIGH_ACTIVE) {
+ /* Remove EVPN type-2 route and schedule for processing. */
+ delete_evpn_route(bgp, vpn, &p);
+ } else {
+ /* Re-instate the current remote best path if any */
+ rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+ if (rn)
+ evpn_zebra_reinstall_best_route(bgp, vpn, rn);
+ }
return 0;
}
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 8728fdcab..5c3d4ce3a 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -129,7 +129,8 @@ extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct prefix *p, struct bgp_path_info *ri);
extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp);
extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
- struct ethaddr *mac, struct ipaddr *ip);
+ struct ethaddr *mac, struct ipaddr *ip,
+ int state);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip,
uint8_t flags, uint32_t seq);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index c6e48cc16..2da19b28d 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -22,6 +22,7 @@
#include "command.h"
#include "lib/json.h"
+#include "lib/zclient.h"
#include "prefix.h"
#include "plist.h"
#include "buffer.h"
@@ -897,7 +898,7 @@ DEFUN_HIDDEN (no_bgp_local_mac,
return CMD_WARNING;
}
- rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
+ rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, ZEBRA_NEIGH_ACTIVE);
if (rv < 0) {
vty_out(vty, "Internal error\n");
return CMD_WARNING;
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 3c4b21946..17de94338 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -2480,6 +2480,7 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
char buf1[INET6_ADDRSTRLEN];
uint8_t flags = 0;
uint32_t seqnum = 0;
+ int state = 0;
memset(&ip, 0, sizeof(ip));
s = zclient->ibuf;
@@ -2503,6 +2504,8 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
if (command == ZEBRA_MACIP_ADD) {
flags = stream_getc(s);
seqnum = stream_getl(s);
+ } else {
+ state = stream_getl(s);
}
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -2510,16 +2513,17 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
return 0;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u",
+ zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u state %d",
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
flags, prefix_mac2str(&mac, buf, sizeof(buf)),
- ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum);
+ ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum,
+ state);
if (command == ZEBRA_MACIP_ADD)
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip,
flags, seqnum);
else
- return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
+ return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state);
}
static void bgp_zebra_process_local_ip_prefix(int cmd, struct zclient *zclient,
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
new file mode 100644
index 000000000..a924606f3
--- /dev/null
+++ b/include/linux/if_addr.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_IF_ADDR_H
+#define __LINUX_IF_ADDR_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct ifaddrmsg {
+ __u8 ifa_family;
+ __u8 ifa_prefixlen; /* The prefix length */
+ __u8 ifa_flags; /* Flags */
+ __u8 ifa_scope; /* Address scope */
+ __u32 ifa_index; /* Link index */
+};
+
+/*
+ * Important comment:
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ *
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
+ */
+enum {
+ IFA_UNSPEC,
+ IFA_ADDRESS,
+ IFA_LOCAL,
+ IFA_LABEL,
+ IFA_BROADCAST,
+ IFA_ANYCAST,
+ IFA_CACHEINFO,
+ IFA_MULTICAST,
+ IFA_FLAGS,
+ IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */
+ __IFA_MAX,
+};
+
+#define IFA_MAX (__IFA_MAX - 1)
+
+/* ifa_flags */
+#define IFA_F_SECONDARY 0x01
+#define IFA_F_TEMPORARY IFA_F_SECONDARY
+
+#define IFA_F_NODAD 0x02
+#define IFA_F_OPTIMISTIC 0x04
+#define IFA_F_DADFAILED 0x08
+#define IFA_F_HOMEADDRESS 0x10
+#define IFA_F_DEPRECATED 0x20
+#define IFA_F_TENTATIVE 0x40
+#define IFA_F_PERMANENT 0x80
+#define IFA_F_MANAGETEMPADDR 0x100
+#define IFA_F_NOPREFIXROUTE 0x200
+#define IFA_F_MCAUTOJOIN 0x400
+#define IFA_F_STABLE_PRIVACY 0x800
+
+struct ifa_cacheinfo {
+ __u32 ifa_prefered;
+ __u32 ifa_valid;
+ __u32 cstamp; /* created timestamp, hundredths of seconds */
+ __u32 tstamp; /* updated timestamp, hundredths of seconds */
+};
+
+/* backwards compatibility for userspace */
+#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+
+#endif
diff --git a/include/subdir.am b/include/subdir.am
index 731785d4b..0d7fed285 100644
--- a/include/subdir.am
+++ b/include/subdir.am
@@ -1,4 +1,5 @@
noinst_HEADERS += \
+ include/linux/if_addr.h \
include/linux/if_bridge.h \
include/linux/if_link.h \
include/linux/lwtunnel.h \
diff --git a/lib/if.h b/lib/if.h
index 166bfa92b..5b46ed820 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -341,6 +341,8 @@ DECLARE_QOBJ_TYPE(interface)
DECLARE_HOOK(if_add, (struct interface * ifp), (ifp))
DECLARE_KOOH(if_del, (struct interface * ifp), (ifp))
+#define METRIC_MAX (~0)
+
/* Connected address structure. */
struct connected {
/* Attached interface. */
@@ -388,6 +390,13 @@ struct connected {
/* Label for Linux 2.2.X and upper. */
char *label;
+
+ /*
+ * Used for setting the connected route's cost. If the metric
+ * here is set to METRIC_MAX the connected route falls back to
+ * "struct interface"
+ */
+ uint32_t metric;
};
/* Nbr Connected address structure. */
diff --git a/lib/zclient.h b/lib/zclient.h
index 95f0a990b..8a3423cdd 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -426,6 +426,8 @@ enum zapi_iptable_notify_owner {
#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */
#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */
+enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
+
struct zclient_options {
bool receive_notify;
};
diff --git a/zebra/connected.c b/zebra/connected.c
index ab66eb332..c449855f6 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -209,6 +209,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
.ifindex = ifp->ifindex,
.vrf_id = ifp->vrf_id,
};
+ uint32_t metric;
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
@@ -243,11 +244,13 @@ void connected_up(struct interface *ifp, struct connected *ifc)
break;
}
+ metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
+ ifc->metric : ifp->metric;
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
- NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+ NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
- NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+ NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
char buf[PREFIX_STRLEN];
@@ -276,7 +279,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
/* Add connected IPv4 route to the interface. */
void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
uint16_t prefixlen, struct in_addr *broad,
- const char *label)
+ const char *label, uint32_t metric)
{
struct prefix_ipv4 *p;
struct connected *ifc;
@@ -288,6 +291,7 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
ifc = connected_new();
ifc->ifp = ifp;
ifc->flags = flags;
+ ifc->metric = metric;
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
@@ -500,7 +504,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
struct in6_addr *broad, uint16_t prefixlen,
- const char *label)
+ const char *label, uint32_t metric)
{
struct prefix_ipv6 *p;
struct connected *ifc;
@@ -512,6 +516,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
ifc = connected_new();
ifc->ifp = ifp;
ifc->flags = flags;
+ ifc->metric = metric;
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
diff --git a/zebra/connected.h b/zebra/connected.h
index 415ecfd96..faba30b0d 100644
--- a/zebra/connected.h
+++ b/zebra/connected.h
@@ -36,7 +36,8 @@ extern struct connected *connected_check_ptp(struct interface *ifp,
extern void connected_add_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
- struct in_addr *broad, const char *label);
+ struct in_addr *broad, const char *label,
+ uint32_t metric);
extern void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
@@ -49,7 +50,8 @@ extern void connected_down(struct interface *ifp, struct connected *ifc);
extern void connected_add_ipv6(struct interface *ifp, int flags,
struct in6_addr *address, struct in6_addr *broad,
- uint16_t prefixlen, const char *label);
+ uint16_t prefixlen, const char *label,
+ uint32_t metric);
extern void connected_delete_ipv6(struct interface *ifp,
struct in6_addr *address,
struct in6_addr *broad, uint16_t prefixlen);
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index df79d285a..debc151d7 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -236,7 +236,8 @@ static int if_getaddrs(void)
}
connected_add_ipv4(ifp, flags, &addr->sin_addr,
- prefixlen, dest_pnt, NULL);
+ prefixlen, dest_pnt, NULL,
+ METRIC_MAX);
}
if (ifap->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *addr;
@@ -258,7 +259,7 @@ static int if_getaddrs(void)
#endif
connected_add_ipv6(ifp, flags, &addr->sin6_addr, NULL,
- prefixlen, NULL);
+ prefixlen, NULL, METRIC_MAX);
}
}
diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c
index 0206d4938..2c29930c3 100644
--- a/zebra/if_ioctl_solaris.c
+++ b/zebra/if_ioctl_solaris.c
@@ -302,10 +302,11 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr,
/* Set address to the interface. */
if (af == AF_INET)
connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen,
- (struct in_addr *)dest_pnt, label);
+ (struct in_addr *)dest_pnt, label,
+ METRIC_MAX);
else if (af == AF_INET6)
connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL,
- prefixlen, label);
+ prefixlen, label, METRIC_MAX);
return 0;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 0cecce5e7..47087d4ce 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -924,6 +924,7 @@ 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;
zns = zebra_ns_lookup(ns_id);
ifa = NLMSG_DATA(h);
@@ -1032,6 +1033,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) {
@@ -1044,7 +1048,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,
@@ -1070,7 +1075,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
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,
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index f3561cc19..acd7f911d 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -906,7 +906,8 @@ int ifam_read(struct ifa_msghdr *ifam)
connected_add_ipv4(ifp, flags, &addr.sin.sin_addr,
ip_masklen(mask.sin.sin_addr),
&brd.sin.sin_addr,
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL),
+ METRIC_MAX);
else
connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr,
ip_masklen(mask.sin.sin_addr),
@@ -923,7 +924,8 @@ int ifam_read(struct ifa_msghdr *ifam)
connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
NULL,
ip6_masklen(mask.sin6.sin6_addr),
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL),
+ METRIC_MAX);
else
connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL,
ip6_masklen(mask.sin6.sin6_addr));
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 87b279b1e..902c72651 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -389,11 +389,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
- if (re->type != ZEBRA_ROUTE_CONNECT) {
- json_object_int_add(json_route, "distance",
- re->distance);
- json_object_int_add(json_route, "metric", re->metric);
- }
+ json_object_int_add(json_route, "distance",
+ re->distance);
+ json_object_int_add(json_route, "metric", re->metric);
if (re->tag)
json_object_int_add(json_route, "tag", re->tag);
@@ -602,7 +600,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
srcdest_rnode2str(rn, buf, sizeof buf));
/* Distance and metric display. */
- if (re->type != ZEBRA_ROUTE_CONNECT)
+ if (((re->type == ZEBRA_ROUTE_CONNECT) &&
+ (re->distance || re->metric)) ||
+ (re->type != ZEBRA_ROUTE_CONNECT))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
} else {
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 280361df6..45e6caebb 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -81,7 +81,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]);
static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
struct ipaddr *ip, uint8_t flags,
- uint32_t seq, uint16_t cmd);
+ uint32_t seq, int state, uint16_t cmd);
static unsigned int neigh_hash_keymake(void *p);
static void *zvni_neigh_alloc(void *p);
static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
@@ -97,7 +97,7 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
uint8_t flags, uint32_t seq);
static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
struct ethaddr *macaddr,
- uint8_t flags);
+ uint8_t flags, int state);
static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
static zebra_vni_t *zvni_from_svi(struct interface *ifp,
@@ -2046,7 +2046,7 @@ static void zvni_print_hash_detail(struct hash_backet *backet, void *data)
*/
static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
struct ipaddr *ip, uint8_t flags,
- uint32_t seq, uint16_t cmd)
+ uint32_t seq, int state, uint16_t cmd)
{
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
@@ -2080,6 +2080,8 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
if (cmd == ZEBRA_MACIP_ADD) {
stream_putc(s, flags); /* sticky mac/gateway mac */
stream_putl(s, seq); /* sequence number */
+ } else {
+ stream_putl(s, state); /* state - active/inactive */
}
@@ -2218,7 +2220,7 @@ static void zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg)
&& IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
if (wctx->uninstall)
zvni_neigh_uninstall(wctx->zvni, n);
@@ -2354,7 +2356,7 @@ static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni,
ZEBRA_NEIGH_SET_INACTIVE(n);
n->loc_seq = 0;
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
}
}
}
@@ -2385,7 +2387,7 @@ static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni,
ZEBRA_NEIGH_SET_INACTIVE(n);
n->loc_seq = 0;
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
}
}
}
@@ -2418,17 +2420,18 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
- seq, ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
}
/*
* Inform BGP about local neighbor deletion.
*/
static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
- struct ethaddr *macaddr, uint8_t flags)
+ struct ethaddr *macaddr, uint8_t flags,
+ int state)
{
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
- 0, ZEBRA_MACIP_DEL);
+ 0, state, ZEBRA_MACIP_DEL);
}
/*
@@ -2749,7 +2752,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
/* Remove neighbor from BGP. */
zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
- ZEBRA_MACIP_TYPE_GW);
+ ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
@@ -2963,7 +2966,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
*/
if (IS_ZEBRA_NEIGH_ACTIVE(n))
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
old_zmac = zvni_mac_lookup(zvni, &n->emac);
if (old_zmac) {
old_mac_seq = CHECK_FLAG(old_zmac->flags,
@@ -3319,7 +3322,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
- seq, ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
}
/*
@@ -3328,7 +3331,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
{
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
- 0 /* seq */, ZEBRA_MACIP_DEL);
+ 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
}
/*
@@ -5255,7 +5258,7 @@ static void process_remote_macip_add(vni_t vni,
IS_ZEBRA_NEIGH_ACTIVE(n))
zvni_neigh_send_del_to_client(
zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
/* update neigh list for macs */
old_mac = zvni_mac_lookup(zvni, &n->emac);
@@ -7074,8 +7077,8 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
}
/* Remove neighbor from BGP. */
- if (IS_ZEBRA_NEIGH_ACTIVE(n))
- zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0);
+ zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
+ 0, n->state);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h
index 3be7dc012..cae0d62bb 100644
--- a/zebra/zebra_vxlan_private.h
+++ b/zebra/zebra_vxlan_private.h
@@ -313,11 +313,9 @@ struct rmac_walk_ctx {
struct json_object *json;
};
-enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
+#define IS_ZEBRA_NEIGH_ACTIVE(n) (n->state == ZEBRA_NEIGH_ACTIVE)
-#define IS_ZEBRA_NEIGH_ACTIVE(n) n->state == ZEBRA_NEIGH_ACTIVE
-
-#define IS_ZEBRA_NEIGH_INACTIVE(n) n->state == ZEBRA_NEIGH_INACTIVE
+#define IS_ZEBRA_NEIGH_INACTIVE(n) (n->state == ZEBRA_NEIGH_INACTIVE)
#define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE