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));
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))
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;
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);
}
struct bgp_node *rn;
struct bgp_table *table;
struct bgp_path_info *pi, *orig, *new;
+ struct attr *attr;
table = bgp->rib[afi][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);
}
/* 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)
{
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;
}
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;
/* 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);
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. */
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;
? 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;
? 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);
}
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,
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;
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,
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");
}
}
/* 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;
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];
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. */