bgpd: Parse EVPN RT-5 NLRI and store gateway IP for EVPN route

While installing this route in the EVPN table, make sure all the conditions
mentioned in the draft
https://tools.ietf.org/html/draft-ietf-bess-evpn-prefix-advertisement-11 are
met.
Draft mentions following conditions:
  - ESI and gateway IP cannot be both nonzero at the same time.
  - ESI, gateway IP, RMAC and VNI label all cannot be 0 at the same time.

If the received EVPN RT-5 route does not meet these conditions, the route is
treated as withdraw.

Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
This commit is contained in:
Ameya Dharkar 2021-01-10 21:40:42 -08:00
parent 8304dabfab
commit 66ff60895a
3 changed files with 49 additions and 46 deletions

View File

@ -315,3 +315,4 @@ extern bool is_zero_gw_ip(const union gw_addr *gw_ip, const afi_t afi)
return false;
}

View File

@ -3972,7 +3972,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
mpls_label_t label; /* holds the VNI as in the packet */
int ret;
afi_t gw_afi;
bool is_valid_update = false;
bool is_valid_update = true;
/* Type-5 route should be 34 or 58 bytes:
* RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
@ -4001,9 +4001,9 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
/* Additional information outside of prefix - ESI and GW IP */
memset(&evpn, 0, sizeof(evpn));
/* Fetch ESI */
/* Fetch ESI overlay index */
if (attr)
memcpy(&attr->esi, pfx, sizeof(esi_t));
memcpy(&evpn.eth_s_id, pfx, sizeof(esi_t));
pfx += ESI_BYTES;
/* Fetch Ethernet Tag. */
@ -4052,25 +4052,53 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
* field
*/
/*
* An update containing a non-zero gateway IP and a non-zero ESI
* at the same time is should be treated as withdraw
*/
if (bgp_evpn_is_esi_valid(&evpn.eth_s_id)
&& !is_zero_gw_ip(&evpn.gw_ip, gw_afi)) {
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.",
peer->host);
is_valid_update = false;
} else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id))
evpn.type = OVERLAY_INDEX_ESI;
else if (!is_zero_gw_ip(&evpn.gw_ip, gw_afi))
evpn.type = OVERLAY_INDEX_GATEWAY_IP;
if (attr) {
is_valid_update = true;
if (is_zero_mac(&attr->rmac) &&
is_zero_gw_ip(&evpn.gw_ip, gw_afi))
if (is_zero_mac(&attr->rmac)
&& !bgp_evpn_is_esi_valid(&evpn.eth_s_id)
&& is_zero_gw_ip(&evpn.gw_ip, gw_afi) && label == 0) {
flog_err(EC_BGP_EVPN_ROUTE_INVALID,
"%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero",
peer->host);
is_valid_update = false;
}
if (is_mcast_mac(&attr->rmac) || is_bcast_mac(&attr->rmac))
is_valid_update = false;
}
/* Process the route. */
if (is_valid_update)
if (attr && is_valid_update)
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
&prd, &label, 1, 0, &evpn);
else
else {
if (!is_valid_update) {
char attr_str[BUFSIZ] = {0};
bgp_dump_attr(attr, attr_str, BUFSIZ);
zlog_warn(
"Invalid update from peer %s vrf %u prefix %pFX attr %s - treat as withdraw",
peer->hostname, peer->bgp->vrf_id, &p,
attr_str);
}
ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
&prd, &label, 1, &evpn);
}
return ret;
}

View File

@ -3442,23 +3442,6 @@ struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
return new;
}
static void overlay_index_update(struct attr *attr,
union gw_addr *gw_ip)
{
if (!attr)
return;
if (gw_ip == NULL) {
struct bgp_route_evpn eo;
memset(&eo, 0, sizeof(eo));
bgp_attr_set_evpn_overlay(attr, &eo);
} else {
struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
bgp_attr_set_evpn_overlay(attr, &eo);
}
}
static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
union gw_addr *gw_ip)
{
@ -3641,6 +3624,11 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (has_valid_label)
assert(label != NULL);
/* Update overlay index of the attribute */
if (afi == AFI_L2VPN && evpn)
memcpy(&attr->evpn_overlay, evpn,
sizeof(struct bgp_route_evpn));
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
if (!soft_reconfig
@ -3816,12 +3804,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
goto filtered;
}
/* Update Overlay Index */
if (afi == AFI_L2VPN) {
overlay_index_update(&new_attr,
evpn == NULL ? NULL : &evpn->gw_ip);
}
/* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
* condition :
* Suppress fib is enabled
@ -3856,10 +3838,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
&& (!has_valid_label
|| memcmp(&(bgp_path_info_extra_get(pi))->label, label,
num_labels * sizeof(mpls_label_t))
== 0)
&& (overlay_index_equal(
afi, pi,
evpn == NULL ? NULL : &evpn->gw_ip))) {
== 0)) {
if (get_active_bdc_from_pi(pi, afi, safi)
&& peer->sort == BGP_PEER_EBGP
&& CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
@ -3867,7 +3846,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_debug_rdpfxpath2str(
afi, safi, prd, p, label,
num_labels, addpath_id ? 1 : 0,
addpath_id, NULL, pfx_buf,
addpath_id, evpn, pfx_buf,
sizeof(pfx_buf));
zlog_debug("%s rcvd %s", peer->host,
pfx_buf);
@ -3893,7 +3872,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_debug_rdpfxpath2str(
afi, safi, prd, p, label,
num_labels, addpath_id ? 1 : 0,
addpath_id, NULL, pfx_buf,
addpath_id, evpn, pfx_buf,
sizeof(pfx_buf));
zlog_debug(
"%s rcvd %s...duplicate ignored",
@ -3920,7 +3899,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (bgp_debug_update(peer, p, NULL, 1)) {
bgp_debug_rdpfxpath2str(
afi, safi, prd, p, label, num_labels,
addpath_id ? 1 : 0, addpath_id, NULL,
addpath_id ? 1 : 0, addpath_id, evpn,
pfx_buf, sizeof(pfx_buf));
zlog_debug(
"%s rcvd %s, flapped quicker than processing",
@ -3934,7 +3913,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (bgp_debug_update(peer, p, NULL, 1)) {
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
num_labels, addpath_id ? 1 : 0,
addpath_id, NULL, pfx_buf,
addpath_id, evpn, pfx_buf,
sizeof(pfx_buf));
zlog_debug("%s rcvd %s", peer->host, pfx_buf);
}
@ -4207,7 +4186,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
addpath_id ? 1 : 0, addpath_id, NULL,
addpath_id ? 1 : 0, addpath_id, evpn,
pfx_buf, sizeof(pfx_buf));
zlog_debug("%s rcvd %s", peer->host, pfx_buf);
}
@ -4239,11 +4218,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
}
/* Update Overlay Index */
if (afi == AFI_L2VPN) {
overlay_index_update(new->attr,
evpn == NULL ? NULL : &evpn->gw_ip);
}
/* Nexthop reachability check. */
if (((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
@ -4353,7 +4327,7 @@ filtered:
}
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
addpath_id ? 1 : 0, addpath_id, NULL,
addpath_id ? 1 : 0, addpath_id, evpn,
pfx_buf, sizeof(pfx_buf));
zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
peer->host, pfx_buf, reason);