mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 07:23:41 +00:00
Merge pull request #4979 from ton31337/feature/route-map_aggregate_command_7.2
bgpd: [7.2] Apply route-map for aggregate-address
This commit is contained in:
commit
19804885a1
@ -724,10 +724,13 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
|
|||||||
struct community *community,
|
struct community *community,
|
||||||
struct ecommunity *ecommunity,
|
struct ecommunity *ecommunity,
|
||||||
struct lcommunity *lcommunity,
|
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 attr;
|
||||||
struct attr *new;
|
struct attr *new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
memset(&attr, 0, sizeof(struct attr));
|
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.label = MPLS_INVALID_LABEL;
|
||||||
attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
|
attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
|
||||||
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
|
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_ATOMIC_AGGREGATE);
|
||||||
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
|
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
|
||||||
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
|
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_index = BGP_INVALID_LABEL_INDEX;
|
||||||
attr.label = MPLS_INVALID_LABEL;
|
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);
|
aspath_unintern(&new->aspath);
|
||||||
return new;
|
return new;
|
||||||
|
@ -272,8 +272,9 @@ extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin,
|
|||||||
struct community *community,
|
struct community *community,
|
||||||
struct ecommunity *ecommunity,
|
struct ecommunity *ecommunity,
|
||||||
struct lcommunity *lcommunity,
|
struct lcommunity *lcommunity,
|
||||||
int as_set,
|
struct bgp_aggregate *aggregate,
|
||||||
uint8_t atomic_aggregate);
|
uint8_t atomic_aggregate,
|
||||||
|
struct prefix *p);
|
||||||
extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
|
extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *,
|
||||||
struct stream *, struct attr *,
|
struct stream *, struct attr *,
|
||||||
struct bpacket_attr_vec_arr *vecarr,
|
struct bpacket_attr_vec_arr *vecarr,
|
||||||
|
@ -5704,6 +5704,8 @@ static struct bgp_aggregate *bgp_aggregate_new(void)
|
|||||||
|
|
||||||
static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
|
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);
|
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_node *rn;
|
||||||
struct bgp_table *table;
|
struct bgp_table *table;
|
||||||
struct bgp_path_info *pi, *orig, *new;
|
struct bgp_path_info *pi, *orig, *new;
|
||||||
|
struct attr *attr;
|
||||||
|
|
||||||
table = bgp->rib[afi][safi];
|
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)
|
if (pi)
|
||||||
bgp_path_info_delete(rn, 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,
|
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
|
||||||
bgp->peer_self,
|
bgp->peer_self, attr, rn);
|
||||||
bgp_attr_aggregate_intern(bgp, origin, aspath,
|
|
||||||
community, ecommunity,
|
|
||||||
lcommunity,
|
|
||||||
aggregate->as_set,
|
|
||||||
atomic_aggregate),
|
|
||||||
rn);
|
|
||||||
SET_FLAG(new->flags, BGP_PATH_VALID);
|
SET_FLAG(new->flags, BGP_PATH_VALID);
|
||||||
|
|
||||||
bgp_path_info_add(rn, new);
|
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 */
|
/* 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,
|
afi_t afi, safi_t safi,
|
||||||
struct bgp_aggregate *aggregate)
|
struct bgp_aggregate *aggregate)
|
||||||
{
|
{
|
||||||
@ -5982,7 +5989,7 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
|
|||||||
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)
|
safi_t safi, struct bgp_aggregate *aggregate)
|
||||||
{
|
{
|
||||||
struct bgp_table *table;
|
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,
|
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);
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
int ret;
|
int ret;
|
||||||
@ -6451,8 +6459,9 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
|
|||||||
|
|
||||||
/* Old configuration check. */
|
/* Old configuration check. */
|
||||||
rn = bgp_node_get(bgp->aggregate[afi][safi], &p);
|
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");
|
vty_out(vty, "There is already same aggregate network.\n");
|
||||||
/* try to remove the old entry */
|
/* try to remove the old entry */
|
||||||
ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
|
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->summary_only = summary_only;
|
||||||
aggregate->as_set = as_set;
|
aggregate->as_set = as_set;
|
||||||
aggregate->safi = safi;
|
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);
|
bgp_node_set_bgp_aggregate_info(rn, aggregate);
|
||||||
|
|
||||||
/* Aggregate address insert into BGP routing table. */
|
/* 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,
|
DEFUN (aggregate_address,
|
||||||
aggregate_address_cmd,
|
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"
|
"Configure BGP aggregate entries\n"
|
||||||
"Aggregate prefix\n"
|
"Aggregate prefix\n"
|
||||||
"Generate AS set path information\n"
|
"Generate AS set path information\n"
|
||||||
"Filter more specific routes from updates\n"
|
"Filter more specific routes from updates\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;
|
int idx = 0;
|
||||||
argv_find(argv, argc, "A.B.C.D/M", &idx);
|
argv_find(argv, argc, "A.B.C.D/M", &idx);
|
||||||
char *prefix = argv[idx]->arg;
|
char *prefix = argv[idx]->arg;
|
||||||
|
char *rmap = NULL;
|
||||||
int as_set =
|
int as_set =
|
||||||
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
|
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
|
||||||
idx = 0;
|
idx = 0;
|
||||||
@ -6496,25 +6517,33 @@ DEFUN (aggregate_address,
|
|||||||
? AGGREGATE_SUMMARY_ONLY
|
? AGGREGATE_SUMMARY_ONLY
|
||||||
: 0;
|
: 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),
|
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,
|
DEFUN (aggregate_address_mask,
|
||||||
aggregate_address_mask_cmd,
|
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"
|
"Configure BGP aggregate entries\n"
|
||||||
"Aggregate address\n"
|
"Aggregate address\n"
|
||||||
"Aggregate mask\n"
|
"Aggregate mask\n"
|
||||||
"Generate AS set path information\n"
|
"Generate AS set path information\n"
|
||||||
"Filter more specific routes from updates\n"
|
"Filter more specific routes from updates\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;
|
int idx = 0;
|
||||||
argv_find(argv, argc, "A.B.C.D", &idx);
|
argv_find(argv, argc, "A.B.C.D", &idx);
|
||||||
char *prefix = argv[idx]->arg;
|
char *prefix = argv[idx]->arg;
|
||||||
char *mask = argv[idx + 1]->arg;
|
char *mask = argv[idx + 1]->arg;
|
||||||
|
char *rmap = NULL;
|
||||||
int as_set =
|
int as_set =
|
||||||
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
|
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
|
||||||
idx = 0;
|
idx = 0;
|
||||||
@ -6522,6 +6551,10 @@ DEFUN (aggregate_address_mask,
|
|||||||
? AGGREGATE_SUMMARY_ONLY
|
? AGGREGATE_SUMMARY_ONLY
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
argv_find(argv, argc, "WORD", &idx);
|
||||||
|
if (idx)
|
||||||
|
rmap = argv[idx]->arg;
|
||||||
|
|
||||||
char prefix_str[BUFSIZ];
|
char prefix_str[BUFSIZ];
|
||||||
int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
|
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),
|
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 (no_aggregate_address,
|
||||||
@ -6581,17 +6614,20 @@ DEFUN (no_aggregate_address_mask,
|
|||||||
|
|
||||||
DEFUN (ipv6_aggregate_address,
|
DEFUN (ipv6_aggregate_address,
|
||||||
ipv6_aggregate_address_cmd,
|
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"
|
"Configure BGP aggregate entries\n"
|
||||||
"Aggregate prefix\n"
|
"Aggregate prefix\n"
|
||||||
"Generate AS set path information\n"
|
"Generate AS set path information\n"
|
||||||
"Filter more specific routes from updates\n"
|
"Filter more specific routes from updates\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;
|
int idx = 0;
|
||||||
argv_find(argv, argc, "X:X::X:X/M", &idx);
|
argv_find(argv, argc, "X:X::X:X/M", &idx);
|
||||||
char *prefix = argv[idx]->arg;
|
char *prefix = argv[idx]->arg;
|
||||||
|
char *rmap = NULL;
|
||||||
int as_set =
|
int as_set =
|
||||||
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
|
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)
|
int sum_only = argv_find(argv, argc, "summary-only", &idx)
|
||||||
? AGGREGATE_SUMMARY_ONLY
|
? AGGREGATE_SUMMARY_ONLY
|
||||||
: 0;
|
: 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,
|
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)
|
if (bgp_aggregate->summary_only)
|
||||||
vty_out(vty, " 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");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,10 @@ struct bgp_aggregate {
|
|||||||
uint8_t as_set;
|
uint8_t as_set;
|
||||||
|
|
||||||
/* Route-map for aggregated route. */
|
/* Route-map for aggregated route. */
|
||||||
struct route_map *map;
|
struct {
|
||||||
|
char *name;
|
||||||
|
struct route_map *map;
|
||||||
|
} rmap;
|
||||||
|
|
||||||
/* Suppress-count. */
|
/* Suppress-count. */
|
||||||
unsigned long 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,
|
extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t,
|
||||||
safi_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,
|
extern void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
|
||||||
struct bgp_path_info *path, afi_t afi,
|
struct bgp_path_info *path, afi_t afi,
|
||||||
safi_t safi);
|
safi_t safi);
|
||||||
|
@ -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
|
/* If su='0.0.0.0' (command 'match peer local'), and it's a
|
||||||
NETWORK,
|
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)) {
|
if (sockunion_same(su, &su_def)) {
|
||||||
int ret;
|
int ret;
|
||||||
if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
|
if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
|
||||||
|| CHECK_FLAG(peer->rmap_type,
|
|| CHECK_FLAG(peer->rmap_type,
|
||||||
PEER_RMAP_TYPE_REDISTRIBUTE)
|
PEER_RMAP_TYPE_REDISTRIBUTE)
|
||||||
|
|| CHECK_FLAG(peer->rmap_type,
|
||||||
|
PEER_RMAP_TYPE_AGGREGATE)
|
||||||
|| CHECK_FLAG(peer->rmap_type,
|
|| CHECK_FLAG(peer->rmap_type,
|
||||||
PEER_RMAP_TYPE_DEFAULT))
|
PEER_RMAP_TYPE_DEFAULT))
|
||||||
ret = RMAP_MATCH;
|
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 peer *peer;
|
||||||
struct bgp_node *bn;
|
struct bgp_node *bn;
|
||||||
struct bgp_static *bgp_static;
|
struct bgp_static *bgp_static;
|
||||||
|
struct bgp_aggregate *aggregate;
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
struct route_map *map;
|
struct route_map *map;
|
||||||
char buf[INET6_ADDRSTRLEN];
|
char buf[INET6_ADDRSTRLEN];
|
||||||
@ -3331,6 +3335,35 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
|
|||||||
safi);
|
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. */
|
/* For redistribute route-map updates. */
|
||||||
|
@ -1211,6 +1211,7 @@ struct peer {
|
|||||||
#define PEER_RMAP_TYPE_NOSET (1 << 5) /* not allow to set commands */
|
#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_IMPORT (1 << 6) /* neighbor route-map import */
|
||||||
#define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */
|
#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 */
|
/* peer specific BFD information */
|
||||||
struct bfd_info *bfd_info;
|
struct bfd_info *bfd_info;
|
||||||
|
@ -685,6 +685,11 @@ Route Aggregation-IPv4 Address Family
|
|||||||
|
|
||||||
This command specifies an aggregate address.
|
This command specifies an aggregate address.
|
||||||
|
|
||||||
|
.. index:: aggregate-address A.B.C.D/M route-map NAME
|
||||||
|
.. clicmd:: aggregate-address A.B.C.D/M route-map NAME
|
||||||
|
|
||||||
|
Apply a route-map for an aggregated prefix.
|
||||||
|
|
||||||
.. index:: aggregate-address A.B.C.D/M as-set
|
.. index:: aggregate-address A.B.C.D/M as-set
|
||||||
.. clicmd:: aggregate-address A.B.C.D/M as-set
|
.. clicmd:: aggregate-address A.B.C.D/M as-set
|
||||||
|
|
||||||
@ -699,11 +704,11 @@ Route Aggregation-IPv4 Address Family
|
|||||||
|
|
||||||
.. index:: no aggregate-address A.B.C.D/M
|
.. index:: no aggregate-address A.B.C.D/M
|
||||||
.. clicmd:: no aggregate-address A.B.C.D/M
|
.. clicmd:: no aggregate-address A.B.C.D/M
|
||||||
|
|
||||||
This command removes an aggregate address.
|
This command removes an aggregate address.
|
||||||
|
|
||||||
|
|
||||||
This configuration example setup the aggregate-address under
|
This configuration example setup the aggregate-address under
|
||||||
ipv4 address-family.
|
ipv4 address-family.
|
||||||
|
|
||||||
.. code-block:: frr
|
.. code-block:: frr
|
||||||
@ -713,6 +718,7 @@ Route Aggregation-IPv4 Address Family
|
|||||||
aggregate-address 10.0.0.0/8
|
aggregate-address 10.0.0.0/8
|
||||||
aggregate-address 20.0.0.0/8 as-set
|
aggregate-address 20.0.0.0/8 as-set
|
||||||
aggregate-address 40.0.0.0/8 summary-only
|
aggregate-address 40.0.0.0/8 summary-only
|
||||||
|
aggregate-address 50.0.0.0/8 route-map aggr-rmap
|
||||||
exit-address-family
|
exit-address-family
|
||||||
|
|
||||||
|
|
||||||
@ -726,6 +732,11 @@ Route Aggregation-IPv6 Address Family
|
|||||||
|
|
||||||
This command specifies an aggregate address.
|
This command specifies an aggregate address.
|
||||||
|
|
||||||
|
.. index:: aggregate-address X:X::X:X/M route-map NAME
|
||||||
|
.. clicmd:: aggregate-address X:X::X:X/M route-map NAME
|
||||||
|
|
||||||
|
Apply a route-map for an aggregated prefix.
|
||||||
|
|
||||||
.. index:: aggregate-address X:X::X:X/M as-set
|
.. index:: aggregate-address X:X::X:X/M as-set
|
||||||
.. clicmd:: aggregate-address X:X::X:X/M as-set
|
.. clicmd:: aggregate-address X:X::X:X/M as-set
|
||||||
|
|
||||||
@ -744,16 +755,17 @@ Route Aggregation-IPv6 Address Family
|
|||||||
This command removes an aggregate address.
|
This command removes an aggregate address.
|
||||||
|
|
||||||
|
|
||||||
This configuration example setup the aggregate-address under
|
This configuration example setup the aggregate-address under
|
||||||
ipv4 address-family.
|
ipv6 address-family.
|
||||||
|
|
||||||
.. code-block:: frr
|
.. code-block:: frr
|
||||||
|
|
||||||
router bgp 1
|
router bgp 1
|
||||||
address-family ipv6 unicast
|
address-family ipv6 unicast
|
||||||
aggregate-address 10::0/64
|
aggregate-address 10::0/64
|
||||||
aggregate-address 20::0/64 as-set
|
aggregate-address 20::0/64 as-set
|
||||||
aggregate-address 40::0/64 summary-only
|
aggregate-address 40::0/64 summary-only
|
||||||
|
aggregate-address 50::0/64 route-map aggr-rmap
|
||||||
exit-address-family
|
exit-address-family
|
||||||
|
|
||||||
.. _bgp-redistribute-to-bgp:
|
.. _bgp-redistribute-to-bgp:
|
||||||
@ -2321,7 +2333,7 @@ attribute.
|
|||||||
Displaying Routes by Large Community Attribute
|
Displaying Routes by Large Community Attribute
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
The following commands allow displaying routes based on their
|
The following commands allow displaying routes based on their
|
||||||
large community attribute.
|
large community attribute.
|
||||||
|
|
||||||
.. index:: show [ip] bgp <ipv4|ipv6> large-community
|
.. index:: show [ip] bgp <ipv4|ipv6> large-community
|
||||||
@ -2338,8 +2350,8 @@ large community attribute.
|
|||||||
|
|
||||||
These commands display BGP routes which have the large community attribute.
|
These commands display BGP routes which have the large community attribute.
|
||||||
attribute. When ``LARGE-COMMUNITY`` is specified, BGP routes that match that
|
attribute. When ``LARGE-COMMUNITY`` is specified, BGP routes that match that
|
||||||
large community are displayed. When `exact-match` is specified, it display
|
large community are displayed. When `exact-match` is specified, it display
|
||||||
only routes that have an exact match. When `json` is specified, it display
|
only routes that have an exact match. When `json` is specified, it display
|
||||||
routes in json format.
|
routes in json format.
|
||||||
|
|
||||||
.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD
|
.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD
|
||||||
@ -2352,8 +2364,8 @@ large community attribute.
|
|||||||
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD json
|
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD json
|
||||||
|
|
||||||
These commands display BGP routes for the address family specified that
|
These commands display BGP routes for the address family specified that
|
||||||
match the specified large community list. When `exact-match` is specified,
|
match the specified large community list. When `exact-match` is specified,
|
||||||
it displays only routes that have an exact match. When `json` is specified,
|
it displays only routes that have an exact match. When `json` is specified,
|
||||||
it display routes in json format.
|
it display routes in json format.
|
||||||
|
|
||||||
.. _bgp-display-routes-by-as-path:
|
.. _bgp-display-routes-by-as-path:
|
||||||
|
10
tests/topotests/bgp_aggregate-address_route-map/r1/bgpd.conf
Normal file
10
tests/topotests/bgp_aggregate-address_route-map/r1/bgpd.conf
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
router bgp 65000
|
||||||
|
neighbor 192.168.255.2 remote-as 65001
|
||||||
|
address-family ipv4 unicast
|
||||||
|
redistribute connected
|
||||||
|
aggregate-address 172.16.255.0/24 route-map aggr-rmap
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
route-map aggr-rmap permit 10
|
||||||
|
set metric 123
|
||||||
|
!
|
@ -0,0 +1,9 @@
|
|||||||
|
!
|
||||||
|
interface lo
|
||||||
|
ip address 172.16.255.254/32
|
||||||
|
!
|
||||||
|
interface r1-eth0
|
||||||
|
ip address 192.168.255.1/24
|
||||||
|
!
|
||||||
|
ip forwarding
|
||||||
|
!
|
@ -0,0 +1,4 @@
|
|||||||
|
router bgp 65001
|
||||||
|
neighbor 192.168.255.1 remote-as 65000
|
||||||
|
exit-address-family
|
||||||
|
!
|
@ -0,0 +1,6 @@
|
|||||||
|
!
|
||||||
|
interface r2-eth0
|
||||||
|
ip address 192.168.255.2/24
|
||||||
|
!
|
||||||
|
ip forwarding
|
||||||
|
!
|
@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# bgp_aggregate-address_route-map.py
|
||||||
|
# Part of NetDEF Topology Tests
|
||||||
|
#
|
||||||
|
# Copyright (c) 2019 by
|
||||||
|
# Network Device Education Foundation, Inc. ("NetDEF")
|
||||||
|
#
|
||||||
|
# Permission to use, copy, modify, and/or distribute this software
|
||||||
|
# for any purpose with or without fee is hereby granted, provided
|
||||||
|
# that the above copyright notice and this permission notice appear
|
||||||
|
# in all copies.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||||
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||||
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||||
|
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
# OF THIS SOFTWARE.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
bgp_aggregate-address_route-map.py:
|
||||||
|
|
||||||
|
Test if works the following commands:
|
||||||
|
router bgp 65031
|
||||||
|
address-family ipv4 unicast
|
||||||
|
aggregate-address 192.168.255.0/24 route-map aggr-rmap
|
||||||
|
|
||||||
|
route-map aggr-rmap permit 10
|
||||||
|
set metric 123
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
import pytest
|
||||||
|
import functools
|
||||||
|
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
sys.path.append(os.path.join(CWD, '../'))
|
||||||
|
|
||||||
|
# pylint: disable=C0413
|
||||||
|
from lib import topotest
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
|
from lib.topolog import logger
|
||||||
|
from mininet.topo import Topo
|
||||||
|
|
||||||
|
class TemplateTopo(Topo):
|
||||||
|
def build(self, *_args, **_opts):
|
||||||
|
tgen = get_topogen(self)
|
||||||
|
|
||||||
|
for routern in range(1, 3):
|
||||||
|
tgen.add_router('r{}'.format(routern))
|
||||||
|
|
||||||
|
switch = tgen.add_switch('s1')
|
||||||
|
switch.add_link(tgen.gears['r1'])
|
||||||
|
switch.add_link(tgen.gears['r2'])
|
||||||
|
|
||||||
|
def setup_module(mod):
|
||||||
|
tgen = Topogen(TemplateTopo, mod.__name__)
|
||||||
|
tgen.start_topology()
|
||||||
|
|
||||||
|
router_list = tgen.routers()
|
||||||
|
|
||||||
|
for i, (rname, router) in enumerate(router_list.iteritems(), 1):
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_ZEBRA,
|
||||||
|
os.path.join(CWD, '{}/zebra.conf'.format(rname))
|
||||||
|
)
|
||||||
|
router.load_config(
|
||||||
|
TopoRouter.RD_BGP,
|
||||||
|
os.path.join(CWD, '{}/bgpd.conf'.format(rname))
|
||||||
|
)
|
||||||
|
|
||||||
|
tgen.start_router()
|
||||||
|
|
||||||
|
def teardown_module(mod):
|
||||||
|
tgen = get_topogen()
|
||||||
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
def test_bgp_maximum_prefix_invalid():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
router = tgen.gears['r2']
|
||||||
|
|
||||||
|
def _bgp_converge(router):
|
||||||
|
output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
|
||||||
|
expected = {
|
||||||
|
'192.168.255.1': {
|
||||||
|
'bgpState': 'Established',
|
||||||
|
'addressFamilyInfo': {
|
||||||
|
'ipv4Unicast': {
|
||||||
|
'acceptedPrefixCounter': 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
def _bgp_aggregate_address_has_metric(router):
|
||||||
|
output = json.loads(router.vtysh_cmd("show ip bgp 172.16.255.0/24 json"))
|
||||||
|
expected = {
|
||||||
|
'paths': [
|
||||||
|
{
|
||||||
|
'med': 123
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_converge, router)
|
||||||
|
success, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
|
||||||
|
|
||||||
|
assert result is None, 'Failed to see bgp convergence in "{}"'.format(router)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_aggregate_address_has_metric, router)
|
||||||
|
success, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
|
||||||
|
|
||||||
|
assert result is None, 'Failed to see applied metric for aggregated prefix in "{}"'.format(router)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
sys.exit(pytest.main(args))
|
Loading…
Reference in New Issue
Block a user