diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 04f9be8ade..f63879159d 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1961,6 +1961,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, char buf2[INET6_ADDRSTRLEN]; zebra_neigh_t *n = NULL; zebra_mac_t *zmac = NULL, *old_zmac = NULL; + bool check_rbit = false; /* create a dummy MAC if the MAC is not already present */ zmac = zvni_mac_lookup(zvni, macaddr); @@ -1990,35 +1991,41 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n = zvni_neigh_lookup(zvni, ip); if (n) { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + + if (router_flag != + (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) + ? 1 : 0)) + check_rbit = true; + 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; - } + } else { - /* 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, + /* 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); + 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); } - /* 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. */ { @@ -2042,6 +2049,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->r_vtep_ip.s_addr = 0; SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); n->ifindex = ifp->ifindex; + check_rbit = true; } } else { /* New neighbor - create */ @@ -2058,25 +2066,38 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); n->ifindex = ifp->ifindex; + check_rbit = true; } + /*Mark Router flag (R-bit) */ + if (router_flag) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* 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", + "Skipping neigh %s add to client as MAC %s is not local on VNI %u with flags 0x%x", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), - zvni->vni); + zvni->vni, n->flags); return 0; } - /*Set router flag (R-bit) */ - if (router_flag) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + if (!check_rbit) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Skipping neigh %s with MAC %s on VNI %u add to client as router flag is not set.", + ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni); + return 0; + } /* Inform BGP. */ if (IS_ZEBRA_DEBUG_VXLAN) @@ -4965,10 +4986,11 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u", + "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, state, ext_learned ? "ext-learned " : "", + router_flag ? "router " : "", zvni->vni); /* Is this about a local neighbor or a remote one? */ @@ -5151,7 +5173,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; uint8_t sticky = 0; - u_char remote_gw = 0; + uint8_t remote_gw = 0; + uint8_t router_flag = 0; uint8_t flags = 0; struct interface *ifp = NULL; struct zebra_if *zif = NULL; @@ -5194,6 +5217,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) STREAM_GETC(s, flags); sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); l++; if (IS_ZEBRA_DEBUG_VXLAN) @@ -5325,6 +5349,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) */ n = zvni_neigh_lookup(zvni, &ip); if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0) + != router_flag) || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0) || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) update_neigh = 1; @@ -5365,6 +5391,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Set router flag (R-bit) to this Neighbor entry */ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); /* Install the entry. */ zvni_neigh_install(zvni, n);