bgpd: Apply route-map for aggregate-address command

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
Donatas Abraitis 2019-08-21 18:16:05 +03:00
parent 4afb9e38ad
commit cde3c2b2ea
6 changed files with 152 additions and 28 deletions

View 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;

View 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,

View 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");
}
}

View 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);

View 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. */

View 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;