mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 21:10:28 +00:00
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:
parent
97722e560e
commit
a317a9b9a4
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user