summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2018-04-20 13:56:48 +0200
committerGitHub <noreply@github.com>2018-04-20 13:56:48 +0200
commit5e572e886afa4ffd899fc8165f708d76541c5b86 (patch)
tree83c216448b2d93d84ddff562ae915a981bb5b72b /zebra
parentMerge pull request #2051 from donaldsharp/PBRD_EXTRA (diff)
parentzebra: Cleanup lines over 80 columns (diff)
downloadfrr-5e572e886afa4ffd899fc8165f708d76541c5b86.tar.xz
frr-5e572e886afa4ffd899fc8165f708d76541c5b86.zip
Merge pull request #2057 from donaldsharp/fix_1916
Fix 1916
Diffstat (limited to 'zebra')
-rw-r--r--zebra/rt_netlink.c8
-rw-r--r--zebra/zebra_vxlan.c318
-rw-r--r--zebra/zebra_vxlan.h4
3 files changed, 203 insertions, 127 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index df53a06bc..9fd8ecb27 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -2220,11 +2220,11 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
* in re-adding the neighbor if it is a valid "remote" neighbor.
*/
if (ndm->ndm_state & NUD_VALID)
- return zebra_vxlan_local_neigh_add_update(
+ return zebra_vxlan_handle_kernel_neigh_update(
ifp, link_if, &ip, &mac, ndm->ndm_state,
ext_learned);
- return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
+ return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -2237,7 +2237,7 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
/* Process the delete - it may result in re-adding the neighbor if it is
* a valid "remote" neighbor.
*/
- return zebra_vxlan_local_neigh_del(ifp, link_if, &ip);
+ return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip);
}
static int netlink_neigh_table(struct sockaddr_nl *snl, struct nlmsghdr *h,
@@ -2412,7 +2412,7 @@ int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac)
{
- return netlink_neigh_update2(ifp, ip, mac, NUD_REACHABLE, RTM_NEWNEIGH);
+ return netlink_neigh_update2(ifp, ip, mac, NUD_NOARP, RTM_NEWNEIGH);
}
int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip)
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index fa8f83740..6e901a045 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -1930,6 +1930,183 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
return;
}
+static int zvni_local_neigh_update(zebra_vni_t *zvni,
+ struct interface *ifp,
+ struct ipaddr *ip,
+ struct ethaddr *macaddr)
+{
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ zebra_neigh_t *n = NULL;
+ zebra_mac_t *zmac = NULL, *old_zmac = NULL;
+
+ /* create a dummy MAC if the MAC is not already present */
+ zmac = zvni_mac_lookup(zvni, macaddr);
+ if (!zmac) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "AUTO MAC %s created for neigh %s on VNI %u",
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
+
+ zmac = zvni_mac_add(zvni, macaddr);
+ if (!zmac) {
+ zlog_warn("Failed to add MAC %s VNI %u",
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
+ return -1;
+ }
+
+ memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
+ memset(&zmac->flags, 0, sizeof(uint32_t));
+ SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
+ }
+
+ /* If same entry already exists, it might be a change or it might be a
+ * move from remote to local.
+ */
+ n = zvni_neigh_lookup(zvni, ip);
+ if (n) {
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+ if (memcmp(n->emac.octet, macaddr->octet,
+ ETH_ALEN) == 0) {
+ /* Update any params and return - client doesn't
+ * care about a purely local change.
+ */
+ n->ifindex = ifp->ifindex;
+ return 0;
+ }
+
+ /* If the MAC has changed,
+ * need to issue a delete first
+ * as this means a different MACIP route.
+ * Also, need to do some unlinking/relinking.
+ */
+ zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
+ &n->emac, 0);
+ old_zmac = zvni_mac_lookup(zvni, &n->emac);
+ if (old_zmac) {
+ listnode_delete(old_zmac->neigh_list, n);
+ zvni_deref_ip2mac(zvni, old_zmac, 0);
+ }
+
+ /* Update the forwarding info. */
+ n->ifindex = ifp->ifindex;
+ memcpy(&n->emac, macaddr, ETH_ALEN);
+
+ /* Link to new MAC */
+ listnode_add_sort(zmac->neigh_list, n);
+
+ } else
+ /* Neighbor has moved from remote to local. */
+ {
+ /* If MAC has changed, do the unlink/link */
+ if (memcmp(n->emac.octet, macaddr->octet,
+ ETH_ALEN) != 0) {
+ old_zmac = zvni_mac_lookup(zvni, &n->emac);
+ if (old_zmac) {
+ listnode_delete(old_zmac->neigh_list,
+ n);
+ zvni_deref_ip2mac(zvni, old_zmac, 0);
+ }
+
+ /* Link to new MAC */
+ memcpy(&n->emac, macaddr, ETH_ALEN);
+ listnode_add_sort(zmac->neigh_list, n);
+ }
+
+ /* Mark appropriately */
+ UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
+ n->r_vtep_ip.s_addr = 0;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ n->ifindex = ifp->ifindex;
+ }
+ } else {
+ /* New neighbor - create */
+ n = zvni_neigh_add(zvni, ip, macaddr);
+ if (!n) {
+ zlog_err(
+ "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
+ ipaddr2str(ip, buf2, sizeof(buf2)),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ ifp->name, ifp->ifindex, zvni->vni);
+ return -1;
+ }
+ /* Set "local" forwarding info. */
+ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ n->ifindex = ifp->ifindex;
+ }
+
+ /* Before we program this in BGP, we need to check if MAC is locally
+ * learnt as well
+ */
+ if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
+ ipaddr2str(ip, buf2, sizeof(buf2)),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
+
+ return 0;
+ }
+
+ /* Inform BGP. */
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
+ ipaddr2str(ip, buf2, sizeof(buf2)),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
+ ZEBRA_NEIGH_SET_ACTIVE(n);
+
+ return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, 0);
+}
+
+static int zvni_remote_neigh_update(zebra_vni_t *zvni,
+ struct interface *ifp,
+ struct ipaddr *ip,
+ struct ethaddr *macaddr,
+ uint16_t state)
+{
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+ zebra_neigh_t *n = NULL;
+ zebra_mac_t *zmac = NULL;
+
+ /* If the neighbor is unknown, there is no further action. */
+ n = zvni_neigh_lookup(zvni, ip);
+ if (!n)
+ return 0;
+
+ /* If a remote entry, see if it needs to be refreshed */
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
+#ifdef GNU_LINUX
+ if (state & NUD_STALE)
+ zvni_neigh_install(zvni, n);
+#endif
+ } else {
+ /* We got a "remote" neighbor notification for an entry
+ * we think is local. This can happen in a multihoming
+ * scenario - but only if the MAC is already "remote".
+ * Just mark our entry as "remote".
+ */
+ zmac = zvni_mac_lookup(zvni, macaddr);
+ if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
+ zlog_err("Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
+ ipaddr2str(&n->ip, buf2, sizeof(buf2)),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
+ return -1;
+ }
+
+ UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
+ n->r_vtep_ip = zmac->fwd_info.r_vtep_ip;
+ }
+
+ return 0;
+}
+
/*
* Make hash key for MAC.
*/
@@ -4626,13 +4803,14 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,
}
/*
- * Handle neighbor delete (on a VLAN device / L3 interface) from the
- * kernel. This may result in either the neighbor getting deleted from
- * our database or being re-added to the kernel (if it is a valid
+ * Handle neighbor delete notification from the kernel (on a VLAN device
+ * / L3 interface). This may result in either the neighbor getting deleted
+ * from our database or being re-added to the kernel (if it is a valid
* remote neighbor).
*/
-int zebra_vxlan_local_neigh_del(struct interface *ifp,
- struct interface *link_if, struct ipaddr *ip)
+int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
+ struct interface *link_if,
+ struct ipaddr *ip)
{
char buf[INET6_ADDRSTRLEN];
char buf2[ETHER_ADDR_STRLEN];
@@ -4708,20 +4886,21 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
}
/*
- * Handle neighbor add or update (on a VLAN device / L3 interface)
- * from the kernel.
+ * Handle neighbor add or update notification from the kernel (on a VLAN
+ * device / L3 interface). This is typically for a local neighbor but can
+ * also be for a remote neighbor (e.g., ageout notification). It could
+ * also be a "move" scenario.
*/
-int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
- struct interface *link_if,
- struct ipaddr *ip,
- struct ethaddr *macaddr, uint16_t state,
- uint8_t ext_learned)
+int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
+ struct interface *link_if,
+ struct ipaddr *ip,
+ struct ethaddr *macaddr,
+ uint16_t state,
+ uint8_t ext_learned)
{
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
zebra_vni_t *zvni = NULL;
- zebra_neigh_t *n = NULL;
- zebra_mac_t *zmac = NULL, *old_zmac = NULL;
zebra_l3vni_t *zl3vni = NULL;
/* check if this is a remote neigh entry corresponding to remote
@@ -4746,114 +4925,11 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
ifp->ifindex, state, ext_learned ? "ext-learned " : "",
zvni->vni);
- /* create a dummy MAC if the MAC is not already present */
- zmac = zvni_mac_lookup(zvni, macaddr);
- if (!zmac) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("AUTO MAC %s created for neigh %s on VNI %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)),
- zvni->vni);
-
- zmac = zvni_mac_add(zvni, macaddr);
- if (!zmac) {
- zlog_warn("Failed to add MAC %s VNI %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- zvni->vni);
- return -1;
- }
-
- memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
- memset(&zmac->flags, 0, sizeof(uint32_t));
- SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
- }
-
- /* If same entry already exists, it might be a change or it might be a
- * move from remote to local.
- */
- n = zvni_neigh_lookup(zvni, ip);
- if (n) {
- if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
- if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN)
- == 0) {
- /* Update any params and return - client doesn't
- * care about a purely local change.
- */
- n->ifindex = ifp->ifindex;
- return 0;
- }
-
- /* If the MAC has changed,
- * need to issue a delete first
- * as this means a different MACIP route.
- * Also, need to do some unlinking/relinking.
- */
- zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
- old_zmac = zvni_mac_lookup(zvni, &n->emac);
- if (old_zmac) {
- listnode_delete(old_zmac->neigh_list, n);
- zvni_deref_ip2mac(zvni, old_zmac, 0);
- }
-
- /* Set "local" forwarding info. */
- SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
- n->ifindex = ifp->ifindex;
- memcpy(&n->emac, macaddr, ETH_ALEN);
-
- /* Link to new MAC */
- listnode_add_sort(zmac->neigh_list, n);
- } else if (ext_learned)
- /* The neighbor is remote and that is the notification we got.
- */
- {
- /* TODO: Evaluate if we need to do anything here. */
- return 0;
- } else
- /* Neighbor has moved from remote to local. */
- {
- UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
- n->r_vtep_ip.s_addr = 0;
- SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
- n->ifindex = ifp->ifindex;
- }
- } else {
- n = zvni_neigh_add(zvni, ip, macaddr);
- if (!n) {
- zlog_err(
- "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
- ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, zvni->vni);
- return -1;
- }
- /* Set "local" forwarding info. */
- SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
- n->ifindex = ifp->ifindex;
- }
-
- /* Before we program this in BGP, we need to check if MAC is locally
- * learnt as well */
- if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Skipping neigh %s add to client as MAC %s is not local on VNI %u",
- ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- zvni->vni);
-
- return 0;
- }
-
- /* Inform BGP. */
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("neigh %s (MAC %s) is now ACTIVE on L2-VNI %u",
- ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- zvni->vni);
- ZEBRA_NEIGH_SET_ACTIVE(n);
+ /* Is this about a local neighbor or a remote one? */
+ if (!ext_learned)
+ return zvni_local_neigh_update(zvni, ifp, ip, macaddr);
- return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
+ return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
}
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index 16b01e6ac..6153c7d7e 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -122,10 +122,10 @@ extern int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
extern int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if);
extern int zebra_vxlan_svi_down(struct interface *ifp,
struct interface *link_if);
-extern int zebra_vxlan_local_neigh_add_update(
+extern int zebra_vxlan_handle_kernel_neigh_update(
struct interface *ifp, struct interface *link_if, struct ipaddr *ip,
struct ethaddr *macaddr, uint16_t state, uint8_t ext_learned);
-extern int zebra_vxlan_local_neigh_del(struct interface *ifp,
+extern int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
struct interface *link_if,
struct ipaddr *ip);
extern int zebra_vxlan_local_mac_add_update(struct interface *ifp,