bgpd, zebra: Handle EVPN router MAC per next hop

Ensure that when EVPN routes are installed into zebra, the router MAC
is passed per next hop and appropriately handled. This is required for
proper multipath operation.

Ticket: CM-18999
Reviewed By:
Testing Done: Verified failed scenario, other manual tests
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
This commit is contained in:
vivek 2017-11-28 23:40:30 -08:00 committed by Donald Sharp
parent 97722e560e
commit a317a9b9a4
12 changed files with 47 additions and 50 deletions

View File

@ -1070,7 +1070,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
/* Make Zebra API structure. */
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;
@ -1276,6 +1275,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
api_nh->label_num = 1;
api_nh->labels[0] = label;
}
memcpy(&api_nh->rmac, &(mpinfo->attr->rmac),
sizeof(struct ethaddr));
valid_nh_count++;
}
@ -1387,7 +1388,6 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info,
return;
memset(&api, 0, sizeof(api));
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
api.safi = safi;

View File

@ -975,8 +975,6 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
stream_putl(s, api->flags);
stream_putc(s, api->message);
stream_putc(s, api->safi);
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
stream_put(s, &(api->rmac), sizeof(struct ethaddr));
/* Put prefix information. */
stream_putc(s, api->prefix.family);
@ -1061,6 +1059,11 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
api_nh->label_num
* sizeof(mpls_label_t));
}
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
stream_put(s, &(api_nh->rmac),
sizeof(struct ethaddr));
}
}
@ -1101,8 +1104,6 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETL(s, api->flags);
STREAM_GETC(s, api->message);
STREAM_GETC(s, api->safi);
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
STREAM_GET(&(api->rmac), s, sizeof(struct ethaddr));
/* Prefix. */
STREAM_GETC(s, api->prefix.family);
@ -1212,6 +1213,11 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
api_nh->label_num
* sizeof(mpls_label_t));
}
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(api->flags, ZEBRA_FLAG_EVPN_ROUTE))
stream_get(&(api_nh->rmac), s,
sizeof(struct ethaddr));
}
}

View File

@ -298,6 +298,8 @@ struct zapi_nexthop {
/* MPLS labels for BGP-LU or Segment Routing */
uint8_t label_num;
mpls_label_t labels[MPLS_MAX_LABELS];
struct ethaddr rmac;
};
/*
@ -338,8 +340,6 @@ struct zapi_route {
vrf_id_t vrf_id;
uint32_t tableid;
struct ethaddr rmac;
};
/* Zebra IPv4 route message API. */

View File

@ -403,10 +403,10 @@ void connected_down(struct interface *ifp, struct connected *ifc)
* head.
*/
rib_delete(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, 0, 0, false, NULL);
&p, NULL, &nh, 0, 0, false);
rib_delete(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
&p, NULL, &nh, 0, 0, false, NULL);
&p, NULL, &nh, 0, 0, false);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
char buf[PREFIX_STRLEN];

View File

@ -1043,7 +1043,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_CHANGE)
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
NULL, 0, 0, true, NULL);
NULL, 0, 0, true);
if (!nh.type) {
nh.type = NEXTHOP_TYPE_IPV4;
@ -1058,7 +1058,7 @@ void rtm_read(struct rt_msghdr *rtm)
else
rib_delete(AFI_IP, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, true, NULL);
&nh, 0, 0, true);
}
if (dest.sa.sa_family == AF_INET6) {
/* One day we might have a debug section here like one in the
@ -1089,7 +1089,7 @@ void rtm_read(struct rt_msghdr *rtm)
if (rtm->rtm_type == RTM_CHANGE)
rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
NULL, 0, 0, true, NULL);
NULL, 0, 0, true);
if (!nh.type) {
nh.type = ifindex ? NEXTHOP_TYPE_IPV6_IFINDEX
@ -1106,7 +1106,7 @@ void rtm_read(struct rt_msghdr *rtm)
else
rib_delete(AFI_IP6, SAFI_UNICAST, VRF_DEFAULT,
ZEBRA_ROUTE_KERNEL, 0, zebra_flags, &p, NULL,
&nh, 0, 0, true, NULL);
&nh, 0, 0, true);
}
}

View File

@ -592,7 +592,7 @@ int zebra_del_import_table_entry(struct route_node *rn, struct route_entry *re)
rib_delete(afi, SAFI_UNICAST, re->vrf_id, ZEBRA_ROUTE_TABLE, re->table,
re->flags, &p, NULL, re->ng.nexthop,
zebrad.rtm_table_default, re->metric, false, NULL);
zebrad.rtm_table_default, re->metric, false);
return 0;
}

View File

@ -313,8 +313,7 @@ extern int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
extern void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
unsigned short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
uint32_t table_id, uint32_t metric, bool fromkernel,
struct ethaddr *rmac);
uint32_t table_id, uint32_t metric, bool fromkernel);
extern struct route_entry *rib_match(afi_t afi, safi_t safi, vrf_id_t vrf_id,
union g_addr *addr,

View File

@ -586,12 +586,12 @@ static int netlink_route_change_read_unicast(struct sockaddr_nl *snl,
if (gate)
memcpy(&nh.gate, gate, sz);
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
&p, NULL, &nh, table, metric, true, NULL);
&p, NULL, &nh, table, metric, true);
} else {
/* XXX: need to compare the entire list of nexthops
* here for NLM_F_APPEND stupidity */
rib_delete(afi, SAFI_UNICAST, vrf_id, proto, 0, flags,
&p, NULL, NULL, table, metric, true, NULL);
&p, NULL, NULL, table, metric, true);
}
}

View File

@ -1382,7 +1382,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
&(api_nh->gate.ipv4),
sizeof(struct in_addr));
zebra_vxlan_evpn_vrf_route_add(
vrf_id, &api.rmac, &vtep_ip,
vrf_id, &api_nh->rmac, &vtep_ip,
&api.prefix);
}
break;
@ -1415,7 +1415,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
&(api_nh->gate.ipv6),
sizeof(struct in6_addr));
zebra_vxlan_evpn_vrf_route_add(
vrf_id, &api.rmac, &vtep_ip,
vrf_id, &api_nh->rmac, &vtep_ip,
&api.prefix);
}
break;
@ -1522,7 +1522,7 @@ static void zread_route_del(ZAPI_HANDLER_ARGS)
rib_delete(afi, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &api.prefix, src_p, NULL, table_id, api.metric,
false, &api.rmac);
false);
/* Stats */
switch (api.prefix.family) {
@ -1724,7 +1724,7 @@ static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
table_id = zvrf->table_id;
rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &p, NULL, NULL, table_id, 0, false, NULL);
api.flags, &p, NULL, NULL, table_id, 0, false);
client->v4_route_del_cnt++;
stream_failure:
@ -2148,8 +2148,7 @@ static void zread_ipv6_delete(ZAPI_HANDLER_ARGS)
src_pp = NULL;
rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance,
api.flags, &p, src_pp, NULL, client->rtm_table, 0, false,
NULL);
api.flags, &p, src_pp, NULL, client->rtm_table, 0, false);
client->v6_route_del_cnt++;

View File

@ -2394,8 +2394,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
unsigned short instance, int flags, struct prefix *p,
struct prefix_ipv6 *src_p, const struct nexthop *nh,
uint32_t table_id, uint32_t metric, bool fromkernel,
struct ethaddr *rmac)
uint32_t table_id, uint32_t metric, bool fromkernel)
{
struct route_table *table;
struct route_node *rn;
@ -2569,7 +2568,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
&(tmp_nh->gate.ipv6),
sizeof(struct in6_addr));
}
zebra_vxlan_evpn_vrf_route_del(re->vrf_id, rmac,
zebra_vxlan_evpn_vrf_route_del(re->vrf_id,
&vtep_ip, p);
}
}

View File

@ -3238,15 +3238,9 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
/* handle rmac delete */
static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
static void zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac,
struct prefix *host_prefix)
{
zebra_mac_t *zrmac = NULL;
zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
if (!zrmac)
return -1;
host_list_delete_host(zrmac->host_list, host_prefix);
if (list_isempty(zrmac->host_list)) {
@ -3256,7 +3250,6 @@ static int zl3vni_remote_rmac_del(zebra_l3vni_t *zl3vni, struct ethaddr *rmac,
/* del the rmac entry */
zl3vni_rmac_del(zl3vni, zrmac);
}
return 0;
}
/*
@ -3394,15 +3387,9 @@ static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
}
/* handle nh neigh delete */
static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
struct prefix *host_prefix)
static void zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *nh,
struct prefix *host_prefix)
{
zebra_neigh_t *nh = NULL;
nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
if (!nh)
return -1;
host_list_delete_host(nh->host_list, host_prefix);
if (list_isempty(nh->host_list)) {
@ -3412,8 +3399,6 @@ static int zl3vni_remote_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip,
/* delete the nh entry */
zl3vni_nh_del(zl3vni, nh);
}
return 0;
}
/* handle neigh update from kernel - the only thing of interest is to
@ -3971,21 +3956,31 @@ void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id, struct ethaddr *rmac,
}
/* handle evpn vrf route delete */
void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id, struct ethaddr *rmac,
void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
struct ipaddr *vtep_ip,
struct prefix *host_prefix)
{
zebra_l3vni_t *zl3vni = NULL;
zebra_neigh_t *nh = NULL;
zebra_mac_t *zrmac = NULL;
zl3vni = zl3vni_from_vrf(vrf_id);
if (!zl3vni)
return;
/* find the next hop entry and rmac entry */
nh = zl3vni_nh_lookup(zl3vni, vtep_ip);
if (!nh)
return;
zrmac = zl3vni_rmac_lookup(zl3vni, &nh->emac);
/* delete the next hop entry */
zl3vni_remote_nh_del(zl3vni, vtep_ip, host_prefix);
zl3vni_remote_nh_del(zl3vni, nh, host_prefix);
/* delete the rmac entry */
zl3vni_remote_rmac_del(zl3vni, rmac, host_prefix);
if (zrmac)
zl3vni_remote_rmac_del(zl3vni, zrmac, host_prefix);
}
void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni,

View File

@ -160,7 +160,6 @@ extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
struct ipaddr *ip,
struct prefix *host_prefix);
extern void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
struct ethaddr *rmac,
struct ipaddr *vtep_ip,
struct prefix *host_prefix);