Merge pull request #2057 from donaldsharp/fix_1916

Fix 1916
This commit is contained in:
Russ White 2018-04-20 07:56:48 -04:00 committed by GitHub
commit 5e572e886a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 212 additions and 136 deletions

View File

@ -2692,10 +2692,10 @@ DEFUN (no_bgp_evpn_default_originate,
return CMD_SUCCESS;
}
DEFUN (bgp_evpn_advertise_vni_subnet,
bgp_evpn_advertise_vni_subnet_cmd,
"advertise-subnet",
"Advertise the subnet corresponding to VNI\n")
DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
bgp_evpn_advertise_vni_subnet_cmd,
"advertise-subnet",
"Advertise the subnet corresponding to VNI\n")
{
struct bgp *bgp_vrf = NULL;
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
@ -2715,11 +2715,11 @@ DEFUN (bgp_evpn_advertise_vni_subnet,
return CMD_SUCCESS;
}
DEFUN (no_bgp_evpn_advertise_vni_subnet,
no_bgp_evpn_advertise_vni_subnet_cmd,
"no advertise-subnet",
NO_STR
"Advertise All local VNIs\n")
DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
no_bgp_evpn_advertise_vni_subnet_cmd,
"no advertise-subnet",
NO_STR
"Advertise All local VNIs\n")
{
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);

View File

@ -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)

View File

@ -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);
/* Is this about a local neighbor or a remote one? */
if (!ext_learned)
return zvni_local_neigh_update(zvni, ifp, ip, macaddr);
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);
return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr, n->flags);
return zvni_remote_neigh_update(zvni, ifp, ip, macaddr, state);
}

View File

@ -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,