X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;ds=sidebyside;f=bgpd%2Fbgp_route.c;h=eca632dd448cf1601fb46375646f9682b686326b;hb=d074383c621d904847d6c1cdf1e4d8825caf14ba;hp=99dc9d81249cab749d136a476cfd6cdcc7d66771;hpb=084854735228bfbdf26d5fbf1b5a0fda32d7e13d;p=mirror_frr.git diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 99dc9d812..eca632dd4 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -254,8 +254,9 @@ static void bgp_path_info_free(struct bgp_path_info *path) bgp_unlink_nexthop(path); bgp_path_info_extra_free(&path->extra); bgp_path_info_mpath_free(&path->mpath); - bgp_addpath_free_info_data(&path->tx_addpath, - path->net ? &path->net->tx_addpath : NULL); + if (path->net) + bgp_addpath_free_info_data(&path->tx_addpath, + &path->net->tx_addpath); peer_unlock(path->peer); /* bgp_path_info peer reference */ @@ -1224,6 +1225,20 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p, } } + /* RFC 8212 to prevent route leaks. + * This specification intends to improve this situation by requiring the + * explicit configuration of both BGP Import and Export Policies for any + * External BGP (EBGP) session such as customers, peers, or + * confederation boundaries for all enabled address families. Through + * codification of the aforementioned requirement, operators will + * benefit from consistent behavior across different BGP + * implementations. + */ + if (peer->bgp->ebgp_requires_policy + == DEFAULT_EBGP_POLICY_ENABLED) + if (!bgp_inbound_policy_exists(peer, filter)) + return RMAP_DENY; + /* Route map apply. */ if (rmap) { memset(&rmap_path, 0, sizeof(struct bgp_path_info)); @@ -1777,6 +1792,20 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, } } + /* RFC 8212 to prevent route leaks. + * This specification intends to improve this situation by requiring the + * explicit configuration of both BGP Import and Export Policies for any + * External BGP (EBGP) session such as customers, peers, or + * confederation boundaries for all enabled address families. Through + * codification of the aforementioned requirement, operators will + * benefit from consistent behavior across different BGP + * implementations. + */ + if (peer->bgp->ebgp_requires_policy + == DEFAULT_EBGP_POLICY_ENABLED) + if (!bgp_outbound_policy_exists(peer, filter)) + return 0; + if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) { @@ -2447,8 +2476,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* advertise/withdraw type-5 routes */ if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (advertise_type5_routes(bgp, afi) && new_select && - (!new_select->extra || !new_select->extra->parent)) { + if (advertise_type5_routes(bgp, afi) && + new_select && + is_route_injectable_into_evpn(new_select)) { /* apply the route-map */ if (bgp->adv_cmd_rmap[afi][safi].map) { @@ -2461,6 +2491,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, bgp_evpn_advertise_type5_route( bgp, &rn->p, new_select->attr, afi, safi); + else + bgp_evpn_withdraw_type5_route( + bgp, &rn->p, afi, safi); } else { bgp_evpn_advertise_type5_route(bgp, &rn->p, @@ -2468,8 +2501,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, afi, safi); } - } else if (advertise_type5_routes(bgp, afi) && old_select && - (!old_select->extra || !old_select->extra->parent)) + } else if (advertise_type5_routes(bgp, afi) && + old_select && + is_route_injectable_into_evpn(old_select)) bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi); } @@ -3062,7 +3096,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, goto filtered; } - if (bgp_mac_entry_exists(p)) { + if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) { reason = "self mac;"; goto filtered; } @@ -3251,7 +3285,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, extra = bgp_path_info_extra_get(pi); if (extra->label != label) { memcpy(&extra->label, label, - num_labels * sizeof(mpls_label_t)); + num_labels * sizeof(mpls_label_t)); extra->num_labels = num_labels; } if (!(afi == AFI_L2VPN && safi == SAFI_EVPN)) @@ -3423,7 +3457,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, if (has_valid_label) { extra = bgp_path_info_extra_get(new); if (extra->label != label) { - memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t)); + memcpy(&extra->label, label, + num_labels * sizeof(mpls_label_t)); extra->num_labels = num_labels; } if (!(afi == AFI_L2VPN && safi == SAFI_EVPN)) @@ -4160,6 +4195,26 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) } } +int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter) +{ + if (peer->sort == BGP_PEER_EBGP + && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter) + || FILTER_LIST_OUT_NAME(filter) + || DISTRIBUTE_OUT_NAME(filter))) + return 1; + return 0; +} + +int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter) +{ + if (peer->sort == BGP_PEER_EBGP + && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter) + || FILTER_LIST_IN_NAME(filter) + || DISTRIBUTE_IN_NAME(filter))) + return 1; + return 0; +} + static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, safi_t safi) { @@ -4415,10 +4470,10 @@ static struct bgp_static *bgp_static_new(void) static void bgp_static_free(struct bgp_static *bgp_static) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); - if (bgp_static->eth_s_id) - XFREE(MTYPE_ATTR, bgp_static->eth_s_id); + XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); + route_map_counter_decrement(bgp_static->rmap.map); + + XFREE(MTYPE_ATTR, bgp_static->eth_s_id); XFREE(MTYPE_BGP_STATIC, bgp_static); } @@ -4978,17 +5033,21 @@ static int bgp_static_set(struct vty *vty, const char *negate, bgp_static->backdoor = backdoor; if (rmap) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + route_map_counter_decrement( + bgp_static->rmap.map); bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); bgp_static->rmap.map = route_map_lookup_by_name(rmap); + route_map_counter_increment( + bgp_static->rmap.map); } else { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + route_map_counter_decrement( + bgp_static->rmap.map); bgp_static->rmap.name = NULL; bgp_static->rmap.map = NULL; bgp_static->valid = 0; @@ -5004,13 +5063,16 @@ static int bgp_static_set(struct vty *vty, const char *negate, bgp_static->label_index = label_index; if (rmap) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); + XFREE(MTYPE_ROUTE_MAP_NAME, + bgp_static->rmap.name); + route_map_counter_decrement( + bgp_static->rmap.map); bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); bgp_static->rmap.map = route_map_lookup_by_name(rmap); + route_map_counter_increment( + bgp_static->rmap.map); } bgp_node_set_bgp_static_info(rn, bgp_static); } @@ -5286,13 +5348,13 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, bgp_static->prd = prd; if (rmap_str) { - if (bgp_static->rmap.name) - XFREE(MTYPE_ROUTE_MAP_NAME, - bgp_static->rmap.name); + XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); + route_map_counter_decrement(bgp_static->rmap.map); bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str); bgp_static->rmap.map = route_map_lookup_by_name(rmap_str); + route_map_counter_increment(bgp_static->rmap.map); } if (safi == SAFI_EVPN) { @@ -5393,13 +5455,14 @@ static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi, rmap = &bgp->table_map[afi][safi]; if (rmap_name) { - if (rmap->name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + route_map_counter_decrement(rmap->map); rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name); rmap->map = route_map_lookup_by_name(rmap_name); + route_map_counter_increment(rmap->map); } else { - if (rmap->name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + route_map_counter_decrement(rmap->map); rmap->name = NULL; rmap->map = NULL; } @@ -5417,8 +5480,8 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi, struct bgp_rmap *rmap; rmap = &bgp->table_map[afi][safi]; - if (rmap->name) - XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name); + route_map_counter_decrement(rmap->map); rmap->name = NULL; rmap->map = NULL; @@ -5513,33 +5576,6 @@ DEFPY(ipv6_bgp_network, label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX); } -/* Aggreagete address: - - advertise-map Set condition to advertise attribute - as-set Generate AS set path information - attribute-map Set attributes of aggregate - route-map Set parameters of aggregate - summary-only Filter more specific routes from updates - suppress-map Conditionally filter more specific routes from updates - - */ -struct bgp_aggregate { - /* Summary-only flag. */ - uint8_t summary_only; - - /* AS set generation. */ - uint8_t as_set; - - /* Route-map for aggregated route. */ - struct route_map *map; - - /* Suppress-count. */ - unsigned long count; - - /* SAFI configuration. */ - safi_t safi; -}; - static struct bgp_aggregate *bgp_aggregate_new(void) { return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate)); @@ -5665,8 +5701,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, - struct bgp_path_info *pinew, afi_t afi, - safi_t safi, struct bgp_path_info *del, + afi_t afi, safi_t safi, struct bgp_aggregate *aggregate) { struct bgp_table *table; @@ -5674,13 +5709,9 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, struct bgp_node *rn; uint8_t origin; struct aspath *aspath = NULL; - struct aspath *asmerge = NULL; struct community *community = NULL; - struct community *commerge = NULL; struct ecommunity *ecommunity = NULL; - struct ecommunity *ecommerge = NULL; struct lcommunity *lcommunity = NULL; - struct lcommunity *lcommerge = NULL; struct bgp_path_info *pi; unsigned long match = 0; uint8_t atomic_aggregate = 0; @@ -5709,9 +5740,6 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, if (BGP_PATH_HOLDDOWN(pi)) continue; - if (del && pi == del) - continue; - if (pi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) atomic_aggregate = 1; @@ -5742,8 +5770,18 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, * route MUST have the ORIGIN attribute with the value * EGP. */ - if (origin < pi->attr->origin) - origin = pi->attr->origin; + switch (pi->attr->origin) { + case BGP_ORIGIN_INCOMPLETE: + aggregate->incomplete_origin_count++; + break; + case BGP_ORIGIN_EGP: + aggregate->egp_origin_count++; + break; + default: + /*Do nothing. + */ + break; + } if (!aggregate->as_set) continue; @@ -5752,130 +5790,68 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, * as-set aggregate route generate origin, as path, * and community aggregation. */ - if (aspath) { - asmerge = aspath_aggregate(aspath, - pi->attr->aspath); - aspath_free(aspath); - aspath = asmerge; - } else - aspath = aspath_dup(pi->attr->aspath); - - if (pi->attr->community) { - if (community) { - commerge = community_merge( - community, pi->attr->community); - community = - community_uniq_sort(commerge); - community_free(&commerge); - } else - community = community_dup( - pi->attr->community); - } - - if (pi->attr->ecommunity) { - if (ecommunity) { - ecommerge = ecommunity_merge( - ecommunity, - pi->attr->ecommunity); - ecommunity = - ecommunity_uniq_sort(ecommerge); - ecommunity_free(&ecommerge); - } else - ecommunity = ecommunity_dup( - pi->attr->ecommunity); - } - - if (pi->attr->lcommunity) { - if (lcommunity) { - lcommerge = lcommunity_merge( - lcommunity, - pi->attr->lcommunity); - lcommunity = - lcommunity_uniq_sort(lcommerge); - lcommunity_free(&lcommerge); - } else - lcommunity = lcommunity_dup( - pi->attr->lcommunity); - } + /* Compute aggregate route's as-path. + */ + bgp_compute_aggregate_aspath(aggregate, + pi->attr->aspath); + + /* Compute aggregate route's community. + */ + if (pi->attr->community) + bgp_compute_aggregate_community( + aggregate, + pi->attr->community); + + /* Compute aggregate route's extended community. + */ + if (pi->attr->ecommunity) + bgp_compute_aggregate_ecommunity( + aggregate, + pi->attr->ecommunity); + + /* Compute aggregate route's large community. + */ + if (pi->attr->lcommunity) + bgp_compute_aggregate_lcommunity( + aggregate, + pi->attr->lcommunity); } if (match) bgp_process(bgp, rn, afi, safi); } bgp_unlock_node(top); - if (pinew) { - aggregate->count++; - if (aggregate->summary_only) - (bgp_path_info_extra_get(pinew))->suppress++; + if (aggregate->incomplete_origin_count > 0) + origin = BGP_ORIGIN_INCOMPLETE; + else if (aggregate->egp_origin_count > 0) + origin = BGP_ORIGIN_EGP; - if (origin < pinew->attr->origin) - origin = pinew->attr->origin; + if (aggregate->as_set) { + if (aggregate->aspath) + /* Retrieve aggregate route's as-path. + */ + aspath = aspath_dup(aggregate->aspath); - if (aggregate->as_set) { - if (aspath) { - asmerge = aspath_aggregate(aspath, - pinew->attr->aspath); - aspath_free(aspath); - aspath = asmerge; - } else - aspath = aspath_dup(pinew->attr->aspath); + if (aggregate->community) + /* Retrieve aggregate route's community. + */ + community = community_dup(aggregate->community); - if (pinew->attr->community) { - if (community) { - commerge = community_merge( - community, - pinew->attr->community); - community = - community_uniq_sort(commerge); - community_free(&commerge); - } else - community = community_dup( - pinew->attr->community); - } + if (aggregate->ecommunity) + /* Retrieve aggregate route's ecommunity. + */ + ecommunity = ecommunity_dup(aggregate->ecommunity); - if (pinew->attr->ecommunity) { - if (ecommunity) { - ecommerge = ecommunity_merge( - ecommunity, - pinew->attr->ecommunity); - ecommunity = - ecommunity_uniq_sort(ecommerge); - ecommunity_free(&ecommerge); - } else - ecommunity = ecommunity_dup( - pinew->attr->ecommunity); - } - - if (pinew->attr->lcommunity) { - if (lcommunity) { - lcommerge = lcommunity_merge( - lcommunity, - pinew->attr->lcommunity); - lcommunity = - lcommunity_uniq_sort(lcommerge); - lcommunity_free(&lcommerge); - } else - lcommunity = lcommunity_dup( - pinew->attr->lcommunity); - } - } + if (aggregate->lcommunity) + /* Retrieve aggregate route's lcommunity. + */ + lcommunity = lcommunity_dup(aggregate->lcommunity); } bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community, ecommunity, lcommunity, atomic_aggregate, aggregate); - - if (aggregate->count == 0) { - if (aspath) - aspath_free(aspath); - if (community) - community_free(&community); - if (ecommunity) - ecommunity_free(&ecommunity); - if (lcommunity) - lcommunity_free(&lcommunity); - } } static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, @@ -5914,6 +5890,41 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, } } aggregate->count--; + + if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE) + aggregate->incomplete_origin_count--; + else if (pi->attr->origin == BGP_ORIGIN_EGP) + aggregate->egp_origin_count--; + + if (aggregate->as_set) { + /* Remove as-path from aggregate. + */ + bgp_remove_aspath_from_aggregate( + aggregate, + pi->attr->aspath); + + if (pi->attr->community) + /* Remove community from aggregate. + */ + bgp_remove_community_from_aggregate( + aggregate, + pi->attr->community); + + if (pi->attr->ecommunity) + /* Remove ecommunity from aggregate. + */ + bgp_remove_ecommunity_from_aggregate( + aggregate, + pi->attr->ecommunity); + + if (pi->attr->lcommunity) + /* Remove lcommunity from aggregate. + */ + bgp_remove_lcommunity_from_aggregate( + aggregate, + pi->attr->lcommunity); + } + } /* If this node was suppressed, process the change. */ @@ -5923,6 +5934,210 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, bgp_unlock_node(top); } +static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p, + struct bgp_path_info *pinew, afi_t afi, + safi_t safi, + struct bgp_aggregate *aggregate) +{ + uint8_t origin; + struct aspath *aspath = NULL; + uint8_t atomic_aggregate = 0; + struct community *community = NULL; + struct ecommunity *ecommunity = NULL; + struct lcommunity *lcommunity = NULL; + + /* ORIGIN attribute: If at least one route among routes that are + * aggregated has ORIGIN with the value INCOMPLETE, then the + * aggregated route must have the ORIGIN attribute with the value + * INCOMPLETE. Otherwise, if at least one route among routes that + * are aggregated has ORIGIN with the value EGP, then the aggregated + * route must have the origin attribute with the value EGP. In all + * other case the value of the ORIGIN attribute of the aggregated + * route is INTERNAL. + */ + origin = BGP_ORIGIN_IGP; + + aggregate->count++; + + if (aggregate->summary_only) + (bgp_path_info_extra_get(pinew))->suppress++; + + switch (pinew->attr->origin) { + case BGP_ORIGIN_INCOMPLETE: + aggregate->incomplete_origin_count++; + break; + case BGP_ORIGIN_EGP: + aggregate->egp_origin_count++; + break; + default: + /* Do nothing. + */ + break; + } + + if (aggregate->incomplete_origin_count > 0) + origin = BGP_ORIGIN_INCOMPLETE; + else if (aggregate->egp_origin_count > 0) + origin = BGP_ORIGIN_EGP; + + if (aggregate->as_set) { + /* Compute aggregate route's as-path. + */ + bgp_compute_aggregate_aspath(aggregate, + pinew->attr->aspath); + + /* Compute aggregate route's community. + */ + if (pinew->attr->community) + bgp_compute_aggregate_community( + aggregate, + pinew->attr->community); + + /* Compute aggregate route's extended community. + */ + if (pinew->attr->ecommunity) + bgp_compute_aggregate_ecommunity( + aggregate, + pinew->attr->ecommunity); + + /* Compute aggregate route's large community. + */ + if (pinew->attr->lcommunity) + bgp_compute_aggregate_lcommunity( + aggregate, + pinew->attr->lcommunity); + + /* Retrieve aggregate route's as-path. + */ + if (aggregate->aspath) + aspath = aspath_dup(aggregate->aspath); + + /* Retrieve aggregate route's community. + */ + if (aggregate->community) + community = community_dup(aggregate->community); + + /* Retrieve aggregate route's ecommunity. + */ + if (aggregate->ecommunity) + ecommunity = ecommunity_dup(aggregate->ecommunity); + + /* Retrieve aggregate route's lcommunity. + */ + if (aggregate->lcommunity) + lcommunity = lcommunity_dup(aggregate->lcommunity); + } + + bgp_aggregate_install(bgp, afi, safi, aggr_p, origin, + aspath, community, ecommunity, + lcommunity, atomic_aggregate, aggregate); +} + +static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi, + safi_t safi, + struct bgp_path_info *pi, + struct bgp_aggregate *aggregate, + struct prefix *aggr_p) +{ + uint8_t origin; + struct aspath *aspath = NULL; + uint8_t atomic_aggregate = 0; + struct community *community = NULL; + struct ecommunity *ecommunity = NULL; + struct lcommunity *lcommunity = NULL; + unsigned long match = 0; + + if (BGP_PATH_HOLDDOWN(pi)) + return; + + if (pi->sub_type == BGP_ROUTE_AGGREGATE) + return; + + if (aggregate->summary_only + && pi->extra + && pi->extra->suppress > 0) { + pi->extra->suppress--; + + if (pi->extra->suppress == 0) { + bgp_path_info_set_flag(pi->net, pi, + BGP_PATH_ATTR_CHANGED); + match++; + } + } + + if (aggregate->count > 0) + aggregate->count--; + + if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE) + aggregate->incomplete_origin_count--; + else if (pi->attr->origin == BGP_ORIGIN_EGP) + aggregate->egp_origin_count--; + + if (aggregate->as_set) { + /* Remove as-path from aggregate. + */ + bgp_remove_aspath_from_aggregate(aggregate, + pi->attr->aspath); + + if (pi->attr->community) + /* Remove community from aggregate. + */ + bgp_remove_community_from_aggregate( + aggregate, + pi->attr->community); + + if (pi->attr->ecommunity) + /* Remove ecommunity from aggregate. + */ + bgp_remove_ecommunity_from_aggregate( + aggregate, + pi->attr->ecommunity); + + if (pi->attr->lcommunity) + /* Remove lcommunity from aggregate. + */ + bgp_remove_lcommunity_from_aggregate( + aggregate, + pi->attr->lcommunity); + } + + /* If this node was suppressed, process the change. */ + if (match) + bgp_process(bgp, pi->net, afi, safi); + + origin = BGP_ORIGIN_IGP; + if (aggregate->incomplete_origin_count > 0) + origin = BGP_ORIGIN_INCOMPLETE; + else if (aggregate->egp_origin_count > 0) + origin = BGP_ORIGIN_EGP; + + if (aggregate->as_set) { + /* Retrieve aggregate route's as-path. + */ + if (aggregate->aspath) + aspath = aspath_dup(aggregate->aspath); + + /* Retrieve aggregate route's community. + */ + if (aggregate->community) + community = community_dup(aggregate->community); + + /* Retrieve aggregate route's ecommunity. + */ + if (aggregate->ecommunity) + ecommunity = ecommunity_dup(aggregate->ecommunity); + + /* Retrieve aggregate route's lcommunity. + */ + if (aggregate->lcommunity) + lcommunity = lcommunity_dup(aggregate->lcommunity); + } + + bgp_aggregate_install(bgp, afi, safi, aggr_p, origin, + aspath, community, ecommunity, + lcommunity, atomic_aggregate, aggregate); +} + void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, struct bgp_path_info *pi, afi_t afi, safi_t safi) { @@ -5949,9 +6164,8 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) { aggregate = bgp_node_get_bgp_aggregate_info(rn); if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { - bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); - bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL, - aggregate); + bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi, + safi, aggregate); } } bgp_unlock_node(child); @@ -5980,9 +6194,8 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) { aggregate = bgp_node_get_bgp_aggregate_info(rn); if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { - bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); - bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del, - aggregate); + bgp_remove_route_from_aggregate(bgp, afi, safi, + del, aggregate, &rn->p); } } bgp_unlock_node(child); @@ -6024,6 +6237,59 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, /* Unlock aggregate address configuration. */ bgp_node_set_bgp_aggregate_info(rn, NULL); + + if (aggregate->community) + community_free(&aggregate->community); + + if (aggregate->community_hash) { + /* Delete all communities in the hash. + */ + hash_clean(aggregate->community_hash, + bgp_aggr_community_remove); + /* Free up the community_hash. + */ + hash_free(aggregate->community_hash); + } + + if (aggregate->ecommunity) + ecommunity_free(&aggregate->ecommunity); + + if (aggregate->ecommunity_hash) { + /* Delete all ecommunities in the hash. + */ + hash_clean(aggregate->ecommunity_hash, + bgp_aggr_ecommunity_remove); + /* Free up the ecommunity_hash. + */ + hash_free(aggregate->ecommunity_hash); + } + + if (aggregate->lcommunity) + lcommunity_free(&aggregate->lcommunity); + + if (aggregate->lcommunity_hash) { + /* Delete all lcommunities in the hash. + */ + hash_clean(aggregate->lcommunity_hash, + bgp_aggr_lcommunity_remove); + /* Free up the lcommunity_hash. + */ + hash_free(aggregate->lcommunity_hash); + } + + if (aggregate->aspath) + aspath_free(aggregate->aspath); + + if (aggregate->aspath_hash) { + /* Delete all as-paths in the hash. + */ + hash_clean(aggregate->aspath_hash, + bgp_aggr_aspath_remove); + /* Free up the aspath_hash. + */ + hash_free(aggregate->aspath_hash); + } + bgp_aggregate_free(aggregate); bgp_unlock_node(rn); bgp_unlock_node(rn); @@ -6077,7 +6343,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, bgp_node_set_bgp_aggregate_info(rn, aggregate); /* Aggregate address insert into BGP routing table. */ - bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate); + bgp_aggregate_route(bgp, &p, afi, safi, aggregate); return CMD_SUCCESS; } @@ -8387,11 +8653,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, json_pmsi = json_object_new_object(); json_object_string_add(json_pmsi, "tunnelType", str); + json_object_int_add(json_pmsi, + "label", + label2vni(&attr->label)); json_object_object_add(json_path, "pmsi", json_pmsi); } else - vty_out(vty, " PMSI Tunnel Type: %s\n", - str); + vty_out(vty, + " PMSI Tunnel Type: %s, label: %d\n", + str, label2vni(&attr->label)); } } @@ -11183,8 +11453,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, return CMD_WARNING_CONFIG_FAILED; } - if (bdistance->access_list) - XFREE(MTYPE_AS_LIST, bdistance->access_list); + XFREE(MTYPE_AS_LIST, bdistance->access_list); bgp_distance_free(bdistance); bgp_node_set_bgp_path_info(rn, NULL); @@ -11624,10 +11893,10 @@ DEFUN (clear_ip_bgp_dampening_address_mask, NULL, 0); } -static void show_bgp_peerhash_entry(struct hash_backet *backet, void *arg) +static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg) { struct vty *vty = arg; - struct peer *peer = backet->data; + struct peer *peer = bucket->data; char buf[SU_ADDRSTRLEN]; vty_out(vty, "\tPeer: %s %s\n", peer->host, @@ -11771,10 +12040,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, decode_label(&bgp_static->label), esi, buf2, macrouter); - if (macrouter) - XFREE(MTYPE_TMP, macrouter); - if (esi) - XFREE(MTYPE_TMP, esi); + XFREE(MTYPE_TMP, macrouter); + XFREE(MTYPE_TMP, esi); } } }