]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Route-map VNI in-filter filters out all the routes for EVPN
authorLakshman Krishnamoorthy <lkrishnamoor@vmware.com>
Wed, 19 Jun 2019 21:29:34 +0000 (14:29 -0700)
committerLakshman Krishnamoorthy <lkrishnamoor@vmware.com>
Mon, 22 Jul 2019 15:08:25 +0000 (08:08 -0700)
Issue1: When a vni in-filter eg:"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.
(Where RM-VNI-FILTER contains "match evpn vni 100")

Issue2: Routes with 2 labels are not filtered correctly

Issue3: This filter should not get applied for MPLS routes. For MPLS routes,
we need route-map to handle a 3rd state besides match/nomatch called: noop.

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

Fix3: route_match_vni() should return noop when it encounters an mpls based
route. For this, route_map library should handle this 3rd state: RMAP_NOOP.

Related fix : Extract tunnel type
This fix relies on PR 4314 #4314 to extract the tunnel type from bgp extended
communities. The information about the route's tunnel type (vxlan or mpls)
is needed to apply "match evpn vni xx" rule.  This rule is applicable to
vxlan routes, and should exit safely for mpls based evpn routes.

Signed-off-by: Lakshman Krishnamoorthy lkrishnamoor@vmware.com
bgpd/bgp_route.c
bgpd/bgp_routemap.c

index 59372f693b1cb491e7fe51c1c5539c695f2404f1..bc49f7eb067dcfa789f9c91d888f0856fb6a1f70 100644 (file)
@@ -1243,10 +1243,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;
 
@@ -1276,6 +1278,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);
 
@@ -3149,8 +3156,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) {
                peer->stat_pfx_filter++;
                reason = "route-map;";
                bgp_attr_flush(&new_attr);
@@ -11284,7 +11291,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) {
index 72b32b31870535ee65c4decc91ba503325a3bb69..dd3382a1e7d0ffa3f2f3963c40645ebbd6dbedd2 100644 (file)
@@ -62,6 +62,7 @@
 #include "bgpd/bgp_mplsvpn.h"
 #include "bgpd/bgp_pbr.h"
 #include "bgpd/bgp_flowspec_util.h"
+#include "bgpd/bgp_encap_types.h"
 
 #if ENABLE_BGP_VNC
 #include "bgpd/rfapi/bgp_rfapi_cfg.h"
@@ -839,26 +840,51 @@ 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_cmd_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;
+
+               /*
+                * Apply filter to type 1, 2, 5 routes only.
+                * Other route types do not have vni label.
+                */
+               if (evp && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
+                       evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE &&
+                       evp->prefix.route_type != BGP_EVPN_IP_PREFIX_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;