]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Apply route-map for aggregate-address command
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Wed, 21 Aug 2019 15:16:05 +0000 (18:16 +0300)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Fri, 13 Sep 2019 11:52:34 +0000 (14:52 +0300)
Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap.c
bgpd/bgpd.h

index e21c84355e22cd34f9d41a5dadb16652b3f6f479..ab9dc3092aea6ac38ce964c6320627f1b20b4333 100644 (file)
@@ -724,10 +724,13 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
                                       struct community *community,
                                       struct ecommunity *ecommunity,
                                       struct lcommunity *lcommunity,
-                                      int as_set, uint8_t atomic_aggregate)
+                                      struct bgp_aggregate *aggregate,
+                                      uint8_t atomic_aggregate,
+                                      struct prefix *p)
 {
        struct attr attr;
        struct attr *new;
+       int ret;
 
        memset(&attr, 0, sizeof(struct attr));
 
@@ -778,7 +781,7 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
        attr.label = MPLS_INVALID_LABEL;
        attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
        attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
-       if (!as_set || atomic_aggregate)
+       if (!aggregate->as_set || atomic_aggregate)
                attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
        attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
        if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
@@ -789,7 +792,42 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
        attr.label_index = BGP_INVALID_LABEL_INDEX;
        attr.label = MPLS_INVALID_LABEL;
 
-       new = bgp_attr_intern(&attr);
+       /* Apply route-map */
+       if (aggregate->rmap.name) {
+               struct attr attr_tmp = attr;
+               struct bgp_path_info rmap_path;
+
+               memset(&rmap_path, 0, sizeof(struct bgp_path_info));
+               rmap_path.peer = bgp->peer_self;
+               rmap_path.attr = &attr_tmp;
+
+               SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
+
+               ret = route_map_apply(aggregate->rmap.map, p, RMAP_BGP,
+                                     &rmap_path);
+
+               bgp->peer_self->rmap_type = 0;
+
+               if (ret == RMAP_DENYMATCH) {
+                       /* Free uninterned attribute. */
+                       bgp_attr_flush(&attr_tmp);
+
+                       /* Unintern original. */
+                       aspath_unintern(&attr.aspath);
+                       return NULL;
+               }
+
+               if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+                       bgp_attr_add_gshut_community(&attr_tmp);
+
+               new = bgp_attr_intern(&attr_tmp);
+       } else {
+
+               if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+                       bgp_attr_add_gshut_community(&attr);
+
+               new = bgp_attr_intern(&attr);
+       }
 
        aspath_unintern(&new->aspath);
        return new;
index 1592a8df4edae90fe0d627dc39c13c95a8bf2082..f1a871fe430cdd23d5dfc3f0bd08e423e6c97416 100644 (file)
@@ -272,8 +272,9 @@ extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
                                              struct community *community,
                                              struct ecommunity *ecommunity,
                                              struct lcommunity *lcommunity,
-                                             int as_set,
-                                             uint8_t atomic_aggregate);
+                                             struct bgp_aggregate *aggregate,
+                                             uint8_t atomic_aggregate,
+                                             struct prefix *p);
 extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
                                       struct stream *, struct attr *,
                                       struct bpacket_attr_vec_arr *vecarr,
index 32c9fb16f3b35572e1debd9ed0f88837f63e73ff..5eeab3674218290afc81cd3d87c3d2b3b05357f5 100644 (file)
@@ -5704,6 +5704,8 @@ static struct bgp_aggregate *bgp_aggregate_new(void)
 
 static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
 {
+       XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
+       route_map_counter_decrement(aggregate->rmap.map);
        XFREE(MTYPE_BGP_AGGREGATE, aggregate);
 }
 
@@ -5754,6 +5756,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
        struct bgp_node *rn;
        struct bgp_table *table;
        struct bgp_path_info *pi, *orig, *new;
+       struct attr *attr;
 
        table = bgp->rib[afi][safi];
 
@@ -5791,14 +5794,18 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
                if (pi)
                        bgp_path_info_delete(rn, pi);
 
+               attr = bgp_attr_aggregate_intern(
+                       bgp, origin, aspath, community, ecommunity, lcommunity,
+                       aggregate, atomic_aggregate, p);
+
+               if (!attr) {
+                       bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
+                       return;
+               }
+
                new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
-                               bgp->peer_self,
-                               bgp_attr_aggregate_intern(bgp, origin, aspath,
-                                                         community, ecommunity,
-                                                         lcommunity,
-                                                         aggregate->as_set,
-                                                         atomic_aggregate),
-                               rn);
+                               bgp->peer_self, attr, rn);
+
                SET_FLAG(new->flags, BGP_PATH_VALID);
 
                bgp_path_info_add(rn, new);
@@ -5821,7 +5828,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
 }
 
 /* Update an aggregate as routes are added/removed from the BGP table */
-static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
+void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
                                afi_t afi, safi_t safi,
                                struct bgp_aggregate *aggregate)
 {
@@ -5982,7 +5989,7 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
                              aggregate);
 }
 
-static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
+void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
                                 safi_t safi, struct bgp_aggregate *aggregate)
 {
        struct bgp_table *table;
@@ -6426,7 +6433,8 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
 }
 
 static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
-                            safi_t safi, uint8_t summary_only, uint8_t as_set)
+                            safi_t safi, const char *rmap, uint8_t summary_only,
+                            uint8_t as_set)
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
        int ret;
@@ -6451,8 +6459,9 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
 
        /* Old configuration check. */
        rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
+       aggregate = bgp_node_get_bgp_aggregate_info(rn);
 
-       if (bgp_node_has_bgp_path_info_data(rn)) {
+       if (aggregate) {
                vty_out(vty, "There is already same aggregate network.\n");
                /* try to remove the old entry */
                ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
@@ -6468,6 +6477,15 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
        aggregate->summary_only = summary_only;
        aggregate->as_set = as_set;
        aggregate->safi = safi;
+
+       if (rmap) {
+               XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
+               route_map_counter_decrement(aggregate->rmap.map);
+               aggregate->rmap.name =
+                       XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
+               aggregate->rmap.map = route_map_lookup_by_name(rmap);
+               route_map_counter_increment(aggregate->rmap.map);
+       }
        bgp_node_set_bgp_aggregate_info(rn, aggregate);
 
        /* Aggregate address insert into BGP routing table. */
@@ -6478,17 +6496,20 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
 
 DEFUN (aggregate_address,
        aggregate_address_cmd,
-       "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
+       "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
        "Generate AS set path information\n"
        "Filter more specific routes from updates\n"
        "Filter more specific routes from updates\n"
-       "Generate AS set path information\n")
+       "Generate AS set path information\n"
+       "Apply route map to aggregate network\n"
+       "Name of route map\n")
 {
        int idx = 0;
        argv_find(argv, argc, "A.B.C.D/M", &idx);
        char *prefix = argv[idx]->arg;
+       char *rmap = NULL;
        int as_set =
                argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
        idx = 0;
@@ -6496,25 +6517,33 @@ DEFUN (aggregate_address,
                                   ? AGGREGATE_SUMMARY_ONLY
                                   : 0;
 
+       idx = 0;
+       argv_find(argv, argc, "WORD", &idx);
+       if (idx)
+               rmap = argv[idx]->arg;
+
        return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
-                                summary_only, as_set);
+                                rmap, summary_only, as_set);
 }
 
 DEFUN (aggregate_address_mask,
        aggregate_address_mask_cmd,
-       "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>]",
+       "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
        "Configure BGP aggregate entries\n"
        "Aggregate address\n"
        "Aggregate mask\n"
        "Generate AS set path information\n"
        "Filter more specific routes from updates\n"
        "Filter more specific routes from updates\n"
-       "Generate AS set path information\n")
+       "Generate AS set path information\n"
+       "Apply route map to aggregate network\n"
+       "Name of route map\n")
 {
        int idx = 0;
        argv_find(argv, argc, "A.B.C.D", &idx);
        char *prefix = argv[idx]->arg;
        char *mask = argv[idx + 1]->arg;
+       char *rmap = NULL;
        int as_set =
                argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
        idx = 0;
@@ -6522,6 +6551,10 @@ DEFUN (aggregate_address_mask,
                                   ? AGGREGATE_SUMMARY_ONLY
                                   : 0;
 
+       argv_find(argv, argc, "WORD", &idx);
+       if (idx)
+               rmap = argv[idx]->arg;
+
        char prefix_str[BUFSIZ];
        int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
 
@@ -6531,7 +6564,7 @@ DEFUN (aggregate_address_mask,
        }
 
        return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
-                                summary_only, as_set);
+                                rmap, summary_only, as_set);
 }
 
 DEFUN (no_aggregate_address,
@@ -6581,17 +6614,20 @@ DEFUN (no_aggregate_address_mask,
 
 DEFUN (ipv6_aggregate_address,
        ipv6_aggregate_address_cmd,
-       "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>]",
+       "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
        "Generate AS set path information\n"
        "Filter more specific routes from updates\n"
        "Filter more specific routes from updates\n"
-       "Generate AS set path information\n")
+       "Generate AS set path information\n"
+       "Apply route map to aggregate network\n"
+       "Name of route map\n")
 {
        int idx = 0;
        argv_find(argv, argc, "X:X::X:X/M", &idx);
        char *prefix = argv[idx]->arg;
+       char *rmap = NULL;
        int as_set =
                argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
 
@@ -6599,8 +6635,13 @@ DEFUN (ipv6_aggregate_address,
        int sum_only = argv_find(argv, argc, "summary-only", &idx)
                               ? AGGREGATE_SUMMARY_ONLY
                               : 0;
-       return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, sum_only,
-                                as_set);
+
+       argv_find(argv, argc, "WORD", &idx);
+       if (idx)
+               rmap = argv[idx]->arg;
+
+       return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
+                                sum_only, as_set);
 }
 
 DEFUN (no_ipv6_aggregate_address,
@@ -12467,6 +12508,9 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
                if (bgp_aggregate->summary_only)
                        vty_out(vty, " summary-only");
 
+               if (bgp_aggregate->rmap.name)
+                       vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
+
                vty_out(vty, "\n");
        }
 }
index 704cd39710d8069909a2de8a673e357f3234972c..ba4e32c23d0cd866ac5ec054a1e825db14dd579a 100644 (file)
@@ -313,7 +313,10 @@ struct bgp_aggregate {
        uint8_t as_set;
 
        /* Route-map for aggregated route. */
-       struct route_map *map;
+       struct {
+               char *name;
+               struct route_map *map;
+       } rmap;
 
        /* Suppress-count. */
        unsigned long count;
@@ -545,6 +548,10 @@ extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t);
 extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t,
                                      safi_t);
 
+extern void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
+                                safi_t safi, struct bgp_aggregate *aggregate);
+extern void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, afi_t afi,
+                               safi_t safi, struct bgp_aggregate *aggregate);
 extern void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
                                    struct bgp_path_info *path, afi_t afi,
                                    safi_t safi);
index 545ca19762997fd1d2e1db2b507090a7f9eee891..b1f1819b6baac61d4230dced6e137f13e1625181 100644 (file)
@@ -269,13 +269,16 @@ route_match_peer(void *rule, const struct prefix *prefix,
 
                /* If su='0.0.0.0' (command 'match peer local'), and it's a
                   NETWORK,
-                   REDISTRIBUTE or DEFAULT_GENERATED route => return RMAP_MATCH
+                   REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
+                  => return RMAP_MATCH
                   */
                if (sockunion_same(su, &su_def)) {
                        int ret;
                        if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
                            || CHECK_FLAG(peer->rmap_type,
                                          PEER_RMAP_TYPE_REDISTRIBUTE)
+                           || CHECK_FLAG(peer->rmap_type,
+                                         PEER_RMAP_TYPE_AGGREGATE)
                            || CHECK_FLAG(peer->rmap_type,
                                          PEER_RMAP_TYPE_DEFAULT))
                                ret = RMAP_MATCH;
@@ -3248,6 +3251,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
        struct peer *peer;
        struct bgp_node *bn;
        struct bgp_static *bgp_static;
+       struct bgp_aggregate *aggregate;
        struct listnode *node, *nnode;
        struct route_map *map;
        char buf[INET6_ADDRSTRLEN];
@@ -3331,6 +3335,35 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
                                                  safi);
                        }
                }
+
+               /* For aggregate-address route-map updates. */
+               for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
+                    bn = bgp_route_next(bn)) {
+                       aggregate = bgp_node_get_bgp_aggregate_info(bn);
+                       if (!aggregate)
+                               continue;
+
+                       if (!aggregate->rmap.name
+                           || (strcmp(rmap_name, aggregate->rmap.name) != 0))
+                               continue;
+
+                       if (!aggregate->rmap.map)
+                               route_map_counter_increment(map);
+
+                       aggregate->rmap.map = map;
+
+                       if (route_update) {
+                               if (bgp_debug_zebra(&bn->p))
+                                       zlog_debug(
+                                               "Processing route_map %s update on aggregate-address route %s",
+                                               rmap_name,
+                                               inet_ntop(bn->p.family,
+                                                         &bn->p.u.prefix, buf,
+                                                         INET6_ADDRSTRLEN));
+                               bgp_aggregate_route(bgp, &bn->p, afi, safi,
+                                                   aggregate);
+                       }
+               }
        }
 
        /* For redistribute route-map updates. */
index 477c0360095767d670286d56aece45ca6d70c887..4bbb256de7abb85dd1c7bfd0aad352fca0087a6e 100644 (file)
@@ -1211,6 +1211,7 @@ struct peer {
 #define PEER_RMAP_TYPE_NOSET          (1 << 5) /* not allow to set commands */
 #define PEER_RMAP_TYPE_IMPORT         (1 << 6) /* neighbor route-map import */
 #define PEER_RMAP_TYPE_EXPORT         (1 << 7) /* neighbor route-map export */
+#define PEER_RMAP_TYPE_AGGREGATE      (1 << 8) /* aggregate-address route-map */
 
        /* peer specific BFD information */
        struct bfd_info *bfd_info;