diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index edaab88286..543df2b048 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1236,10 +1236,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; @@ -1269,6 +1271,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); @@ -3124,8 +3131,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; @@ -11191,7 +11198,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) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 85cab0d59f..790b2f7995 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -60,6 +60,7 @@ #include "bgpd/bgp_evpn_private.h" #include "bgpd/bgp_evpn_vty.h" #include "bgpd/bgp_mplsvpn.h" +#include "bgpd/bgp_encap_types.h" #if ENABLE_BGP_VNC #include "bgpd/rfapi/bgp_rfapi_cfg.h" @@ -795,26 +796,49 @@ 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_NOOP to ignore this match check. + */ static enum route_map_match_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 noop to ignore + * this check. + */ + if (path->attr && path->attr->encap_tunneltype != + BGP_ENCAP_TYPE_VXLAN) + return RMAP_NOOP; + + /* + * 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_NOOP; + 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;