diff options
author | Russ White <russ@riw.us> | 2018-04-20 13:56:48 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-20 13:56:48 +0200 |
commit | 5e572e886afa4ffd899fc8165f708d76541c5b86 (patch) | |
tree | 83c216448b2d93d84ddff562ae915a981bb5b72b /zebra | |
parent | Merge pull request #2051 from donaldsharp/PBRD_EXTRA (diff) | |
parent | zebra: Cleanup lines over 80 columns (diff) | |
download | frr-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.c | 8 | ||||
-rw-r--r-- | zebra/zebra_vxlan.c | 318 | ||||
-rw-r--r-- | zebra/zebra_vxlan.h | 4 |
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, |