Skip to content

Commit

Permalink
bgpd: route-map to filter received EVPN routes based on VNI does not …
Browse files Browse the repository at this point in the history
…work

Issue1: When "neighbor X.X.X.X route-map RM-VNI-FILTER in" is configured under evpn address-family,
all the received routes are dropped regardless of whether the route has a matching vni or not.

Issue2: Routes with 2 labels are not filtered correctly

Issue3: Interpreting the label based on tunnel type, vxlan was not done correctly.
Vxlan label has 24 bits, whereas, MPLS label is 20 bits long

Fix1: The handler bgp_update() that services the received route ignored the route's label while deciding whether to filter it or not. As part of the fix, the handler now uses the label info to make the decision about whether to filter the route or not.

Fix2: route_match_vni() now tries to match both the labels within the route, not just the one.

Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
  • Loading branch information
lkrishnamoor committed May 11, 2019
1 parent 764252d commit 351d8d3
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 11 deletions.
17 changes: 12 additions & 5 deletions bgpd/bgp_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -1192,10 +1192,12 @@ static int bgp_cluster_filter(struct peer *peer, struct attr *attr)

static int bgp_input_modifier(struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
const char *rmap_name)
const char *rmap_name, mpls_label_t *label,
uint32_t num_labels)
{
struct bgp_filter *filter;
struct bgp_path_info rmap_path;
struct bgp_path_info rmap_path = { 0 };
struct bgp_path_info_extra extra = { 0 };
route_map_result_t ret;
struct route_map *rmap = NULL;

Expand Down Expand Up @@ -1225,6 +1227,11 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p,
/* Duplicate current value to new strucutre for modification. */
rmap_path.peer = peer;
rmap_path.attr = attr;
rmap_path.extra = &extra;
extra.num_labels = num_labels;
if (label && num_labels && num_labels <= BGP_MAX_LABELS)
memcpy(extra.label, label,
num_labels * sizeof(mpls_label_t));

SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);

Expand Down Expand Up @@ -3063,8 +3070,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
* commands, so we need bgp_attr_flush in the error paths, until we
* intern
* the attr (which takes over the memory references) */
if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL)
== RMAP_DENY) {
if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL,
label, num_labels) == RMAP_DENY) {
reason = "route-map;";
bgp_attr_flush(&new_attr);
goto filtered;
Expand Down Expand Up @@ -10925,7 +10932,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,

/* Filter prefix using route-map */
ret = bgp_input_modifier(peer, &rn->p, &attr,
afi, safi, rmap_name);
afi, safi, rmap_name, NULL, 0);

if (type == bgp_show_adj_route_filtered &&
!route_filtered && ret != RMAP_DENY) {
Expand Down
36 changes: 30 additions & 6 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,26 +802,50 @@ struct route_map_rule_cmd route_match_mac_address_cmd = {
"mac address", route_match_mac_address, route_match_mac_address_compile,
route_match_mac_address_free};

/* `match vni' */

/* Match function should return 1 if match is success else return
zero. */
/*
* Match function returns:
* ...RMAP_MATCH if match is found.
* ...RMAP_NOMATCH if match is not found.
* ...RMAP_OKAY to bypass this check..
*/
static route_map_result_t route_match_vni(void *rule,
const struct prefix *prefix,
route_map_object_t type, void *object)
{
vni_t vni = 0;
unsigned int label_cnt = 0;
struct bgp_path_info *path = NULL;
struct prefix_evpn *evp = (struct prefix_evpn *) prefix;

if (type == RMAP_BGP) {
vni = *((vni_t *)rule);
path = (struct bgp_path_info *)object;

/*
* This rmap filter is valid for vxlan tunnel type only.
* For any other tunnel type, return RMAP_OKAY, so, we don't
* RMAP_DENY this, which can happen by returning
* RMAP_MATCH or RMAP_NOMATCH.
*/
if (path->attr && path->attr->encap_tunneltype !=
BGP_ENCAP_TYPE_VXLAN)
return RMAP_OKAY;

/*
* We do not want to filter type 3 routes because
* they do not have vni associated with them.
*/
if (evp && evp->prefix.route_type == BGP_EVPN_IMET_ROUTE)
return RMAP_OKAY;

if (path->extra == NULL)
return RMAP_NOMATCH;

if (vni == label2vni(&path->extra->label[0]))
return RMAP_MATCH;
for ( ; label_cnt < BGP_MAX_LABELS &&
label_cnt < path->extra->num_labels; label_cnt++) {
if (vni == label2vni(&path->extra->label[label_cnt]))
return RMAP_MATCH;
}
}

return RMAP_NOMATCH;
Expand Down

0 comments on commit 351d8d3

Please sign in to comment.