mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 05:58:17 +00:00
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:
parent
8304dabfab
commit
66ff60895a
@ -315,3 +315,4 @@ extern bool is_zero_gw_ip(const union gw_addr *gw_ip, const afi_t afi)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
mpls_label_t label; /* holds the VNI as in the packet */
|
||||||
int ret;
|
int ret;
|
||||||
afi_t gw_afi;
|
afi_t gw_afi;
|
||||||
bool is_valid_update = false;
|
bool is_valid_update = true;
|
||||||
|
|
||||||
/* Type-5 route should be 34 or 58 bytes:
|
/* Type-5 route should be 34 or 58 bytes:
|
||||||
* RD (8), ESI (10), Eth Tag (4), IP len (1), IP (4 or 16),
|
* 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 */
|
/* Additional information outside of prefix - ESI and GW IP */
|
||||||
memset(&evpn, 0, sizeof(evpn));
|
memset(&evpn, 0, sizeof(evpn));
|
||||||
|
|
||||||
/* Fetch ESI */
|
/* Fetch ESI overlay index */
|
||||||
if (attr)
|
if (attr)
|
||||||
memcpy(&attr->esi, pfx, sizeof(esi_t));
|
memcpy(&evpn.eth_s_id, pfx, sizeof(esi_t));
|
||||||
pfx += ESI_BYTES;
|
pfx += ESI_BYTES;
|
||||||
|
|
||||||
/* Fetch Ethernet Tag. */
|
/* Fetch Ethernet Tag. */
|
||||||
@ -4052,25 +4052,53 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
* field
|
* 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) {
|
if (attr) {
|
||||||
is_valid_update = true;
|
if (is_zero_mac(&attr->rmac)
|
||||||
if (is_zero_mac(&attr->rmac) &&
|
&& !bgp_evpn_is_esi_valid(&evpn.eth_s_id)
|
||||||
is_zero_gw_ip(&evpn.gw_ip, gw_afi))
|
&& 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;
|
is_valid_update = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_mcast_mac(&attr->rmac) || is_bcast_mac(&attr->rmac))
|
if (is_mcast_mac(&attr->rmac) || is_bcast_mac(&attr->rmac))
|
||||||
is_valid_update = false;
|
is_valid_update = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process the route. */
|
/* Process the route. */
|
||||||
if (is_valid_update)
|
if (attr && is_valid_update)
|
||||||
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
|
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
|
||||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||||
&prd, &label, 1, 0, &evpn);
|
&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,
|
ret = bgp_withdraw(peer, (struct prefix *)&p, addpath_id, attr,
|
||||||
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||||
&prd, &label, 1, &evpn);
|
&prd, &label, 1, &evpn);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3442,23 +3442,6 @@ struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
|
|||||||
return new;
|
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,
|
static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
|
||||||
union gw_addr *gw_ip)
|
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)
|
if (has_valid_label)
|
||||||
assert(label != NULL);
|
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
|
/* When peer's soft reconfiguration enabled. Record input packet in
|
||||||
Adj-RIBs-In. */
|
Adj-RIBs-In. */
|
||||||
if (!soft_reconfig
|
if (!soft_reconfig
|
||||||
@ -3816,12 +3804,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||||||
goto filtered;
|
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
|
/* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
|
||||||
* condition :
|
* condition :
|
||||||
* Suppress fib is enabled
|
* 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
|
&& (!has_valid_label
|
||||||
|| memcmp(&(bgp_path_info_extra_get(pi))->label, label,
|
|| memcmp(&(bgp_path_info_extra_get(pi))->label, label,
|
||||||
num_labels * sizeof(mpls_label_t))
|
num_labels * sizeof(mpls_label_t))
|
||||||
== 0)
|
== 0)) {
|
||||||
&& (overlay_index_equal(
|
|
||||||
afi, pi,
|
|
||||||
evpn == NULL ? NULL : &evpn->gw_ip))) {
|
|
||||||
if (get_active_bdc_from_pi(pi, afi, safi)
|
if (get_active_bdc_from_pi(pi, afi, safi)
|
||||||
&& peer->sort == BGP_PEER_EBGP
|
&& peer->sort == BGP_PEER_EBGP
|
||||||
&& CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
|
&& 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(
|
bgp_debug_rdpfxpath2str(
|
||||||
afi, safi, prd, p, label,
|
afi, safi, prd, p, label,
|
||||||
num_labels, addpath_id ? 1 : 0,
|
num_labels, addpath_id ? 1 : 0,
|
||||||
addpath_id, NULL, pfx_buf,
|
addpath_id, evpn, pfx_buf,
|
||||||
sizeof(pfx_buf));
|
sizeof(pfx_buf));
|
||||||
zlog_debug("%s rcvd %s", peer->host,
|
zlog_debug("%s rcvd %s", peer->host,
|
||||||
pfx_buf);
|
pfx_buf);
|
||||||
@ -3893,7 +3872,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
|
|||||||
bgp_debug_rdpfxpath2str(
|
bgp_debug_rdpfxpath2str(
|
||||||
afi, safi, prd, p, label,
|
afi, safi, prd, p, label,
|
||||||
num_labels, addpath_id ? 1 : 0,
|
num_labels, addpath_id ? 1 : 0,
|
||||||
addpath_id, NULL, pfx_buf,
|
addpath_id, evpn, pfx_buf,
|
||||||
sizeof(pfx_buf));
|
sizeof(pfx_buf));
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s rcvd %s...duplicate ignored",
|
"%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)) {
|
if (bgp_debug_update(peer, p, NULL, 1)) {
|
||||||
bgp_debug_rdpfxpath2str(
|
bgp_debug_rdpfxpath2str(
|
||||||
afi, safi, prd, p, label, num_labels,
|
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));
|
pfx_buf, sizeof(pfx_buf));
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"%s rcvd %s, flapped quicker than processing",
|
"%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)) {
|
if (bgp_debug_update(peer, p, NULL, 1)) {
|
||||||
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
|
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
|
||||||
num_labels, addpath_id ? 1 : 0,
|
num_labels, addpath_id ? 1 : 0,
|
||||||
addpath_id, NULL, pfx_buf,
|
addpath_id, evpn, pfx_buf,
|
||||||
sizeof(pfx_buf));
|
sizeof(pfx_buf));
|
||||||
zlog_debug("%s rcvd %s", peer->host, 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,
|
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));
|
pfx_buf, sizeof(pfx_buf));
|
||||||
zlog_debug("%s rcvd %s", peer->host, 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. */
|
/* Nexthop reachability check. */
|
||||||
if (((afi == AFI_IP || afi == AFI_IP6)
|
if (((afi == AFI_IP || afi == AFI_IP6)
|
||||||
&& (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
|
&& (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
|
||||||
@ -4353,7 +4327,7 @@ filtered:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
|
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));
|
pfx_buf, sizeof(pfx_buf));
|
||||||
zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
|
zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
|
||||||
peer->host, pfx_buf, reason);
|
peer->host, pfx_buf, reason);
|
||||||
|
Loading…
Reference in New Issue
Block a user