diff options
Diffstat (limited to '')
-rw-r--r-- | bgpd/bgp_evpn.c | 110 | ||||
-rw-r--r-- | bgpd/bgp_evpn.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 10 | ||||
-rw-r--r-- | include/linux/if_addr.h | 69 | ||||
-rw-r--r-- | include/subdir.am | 1 | ||||
-rw-r--r-- | lib/if.h | 9 | ||||
-rw-r--r-- | lib/zclient.h | 2 | ||||
-rw-r--r-- | zebra/connected.c | 13 | ||||
-rw-r--r-- | zebra/connected.h | 6 | ||||
-rw-r--r-- | zebra/if_ioctl.c | 5 | ||||
-rw-r--r-- | zebra/if_ioctl_solaris.c | 5 | ||||
-rw-r--r-- | zebra/if_netlink.c | 10 | ||||
-rw-r--r-- | zebra/kernel_socket.c | 6 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 12 | ||||
-rw-r--r-- | zebra/zebra_vxlan.c | 35 | ||||
-rw-r--r-- | zebra/zebra_vxlan_private.h | 6 |
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 \ @@ -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 |