diff options
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_route.c | 563 | ||||
-rw-r--r-- | bgpd/bgp_route.h | 19 |
2 files changed, 340 insertions, 242 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 15c1df847..43ba4ceef 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6240,6 +6240,13 @@ static void bgp_aggregate_install( && pi->sub_type == BGP_ROUTE_AGGREGATE) break; + /* + * If we have paths with different MEDs, then don't install + * (or uninstall) the aggregate route. + */ + if (aggregate->match_med && aggregate->med_mismatched) + goto uninstall_aggregate_route; + if (aggregate->count > 0) { /* * If the aggregate information has not changed @@ -6284,6 +6291,7 @@ static void bgp_aggregate_install( bgp_path_info_add(dest, new); bgp_process(bgp, dest, afi, safi); } else { + uninstall_aggregate_route: for (pi = orig; pi; pi = pi->next) if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP @@ -6300,6 +6308,189 @@ static void bgp_aggregate_install( bgp_dest_unlock_node(dest); } +/** + * Check if the current path has different MED than other known paths. + * + * \returns `true` if the MED matched the others else `false`. + */ +static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate, + struct bgp *bgp, struct bgp_path_info *pi) +{ + uint32_t cur_med = bgp_med_value(pi->attr, bgp); + + /* This is the first route being analyzed. */ + if (!aggregate->med_initialized) { + aggregate->med_initialized = true; + aggregate->med_mismatched = false; + aggregate->med_matched_value = cur_med; + } else { + /* Check if routes with different MED showed up. */ + if (cur_med != aggregate->med_matched_value) + aggregate->med_mismatched = true; + } + + return !aggregate->med_mismatched; +} + +/** + * Initializes and tests all routes in the aggregate address path for MED + * values. + * + * \returns `true` if all MEDs are the same otherwise `false`. + */ +static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate, + struct bgp *bgp, const struct prefix *p, + afi_t afi, safi_t safi) +{ + struct bgp_table *table = bgp->rib[afi][safi]; + const struct prefix *dest_p; + struct bgp_dest *dest, *top; + struct bgp_path_info *pi; + bool med_matched = true; + + aggregate->med_initialized = false; + + top = bgp_node_get(table, p); + for (dest = bgp_node_get(table, p); dest; + dest = bgp_route_next_until(dest, top)) { + dest_p = bgp_dest_get_prefix(dest); + if (dest_p->prefixlen <= p->prefixlen) + continue; + + for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { + if (BGP_PATH_HOLDDOWN(pi)) + continue; + if (pi->sub_type == BGP_ROUTE_AGGREGATE) + continue; + if (!bgp_aggregate_med_match(aggregate, bgp, pi)) { + med_matched = false; + break; + } + } + if (!med_matched) + break; + } + bgp_dest_unlock_node(top); + + return med_matched; +} + +/** + * Toggles the route suppression status for this aggregate address + * configuration. + */ +static void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate, + struct bgp *bgp, + const struct prefix *p, afi_t afi, + safi_t safi, bool suppress) +{ + struct bgp_table *table = bgp->rib[afi][safi]; + struct bgp_path_info_extra *pie; + const struct prefix *dest_p; + struct bgp_dest *dest, *top; + struct bgp_path_info *pi; + bool toggle_suppression; + + /* We've found a different MED we must revert any suppressed routes. */ + top = bgp_node_get(table, p); + for (dest = bgp_node_get(table, p); dest; + dest = bgp_route_next_until(dest, top)) { + dest_p = bgp_dest_get_prefix(dest); + if (dest_p->prefixlen <= p->prefixlen) + continue; + + toggle_suppression = false; + for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { + if (BGP_PATH_HOLDDOWN(pi)) + continue; + if (pi->sub_type == BGP_ROUTE_AGGREGATE) + continue; + + /* + * On installation it is possible that pi->extra is + * set to NULL, otherwise it must exists. + */ + assert(!suppress && pi->extra != NULL); + + /* We are toggling suppression back. */ + if (suppress) { + pie = bgp_path_info_extra_get(pi); + /* Suppress route if not suppressed already. */ + pie->suppress++; + bgp_path_info_set_flag(dest, pi, + BGP_PATH_ATTR_CHANGED); + toggle_suppression = true; + continue; + } + + pie = pi->extra; + assert(pie->suppress > 0); + pie->suppress--; + /* Install route if there is no more suppression. */ + if (pie->suppress == 0) { + bgp_path_info_set_flag(dest, pi, + BGP_PATH_ATTR_CHANGED); + toggle_suppression = true; + } + } + + if (toggle_suppression) + bgp_process(bgp, dest, afi, safi); + } + bgp_dest_unlock_node(top); +} + +/** + * Aggregate address MED matching incremental test: this function is called + * when the initial aggregation occurred and we are only testing a single + * new path. + * + * In addition to testing and setting the MED validity it also installs back + * suppressed routes (if summary is configured). + * + * Must not be called in `bgp_aggregate_route`. + */ +static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate, + struct bgp *bgp, const struct prefix *p, + afi_t afi, safi_t safi, + struct bgp_path_info *pi, bool is_adding) +{ + /* MED matching disabled. */ + if (!aggregate->match_med) + return; + + /* Aggregation with different MED, nothing to do. */ + if (aggregate->med_mismatched) + return; + + /* + * Test the current entry: + * + * is_adding == true: if the new entry doesn't match then we must + * install all suppressed routes. + * + * is_adding == false: if the entry being removed was the last + * unmatching entry then we can suppress all routes. + */ + if (!is_adding) { + if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) + && aggregate->summary_only) + bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, + safi, true); + } else + bgp_aggregate_med_match(aggregate, bgp, pi); + + /* No mismatches, just quit. */ + if (!aggregate->med_mismatched) + return; + + /* Route summarization is disabled. */ + if (!aggregate->summary_only) + return; + + bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false); +} + /* Update an aggregate as routes are added/removed from the BGP table */ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, safi_t safi, struct bgp_aggregate *aggregate) @@ -6323,6 +6514,10 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, || (bgp->peer_self == NULL)) return; + /* Initialize and test routes for MED difference. */ + if (aggregate->match_med) + bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi); + /* 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 @@ -6359,8 +6554,14 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, /* * summary-only aggregate route suppress * aggregated route announcements. + * + * MED matching: + * Don't create summaries if MED didn't match + * otherwise neither the specific routes and the + * aggregation will be announced. */ - if (aggregate->summary_only) { + if (aggregate->summary_only + && AGGREGATE_MED_VALID(aggregate)) { (bgp_path_info_extra_get(pi))->suppress++; bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED); @@ -6502,7 +6703,8 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi, if (pi->sub_type == BGP_ROUTE_AGGREGATE) continue; - if (aggregate->summary_only && pi->extra) { + if (aggregate->summary_only && pi->extra + && AGGREGATE_MED_VALID(aggregate)) { pi->extra->suppress--; if (pi->extra->suppress == 0) { @@ -6593,7 +6795,15 @@ static void bgp_add_route_to_aggregate(struct bgp *bgp, aggregate->count++; - if (aggregate->summary_only) + /* + * This must be called before `summary` check to avoid + * "suppressing" twice. + */ + if (aggregate->match_med) + bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, + pinew, true); + + if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate)) (bgp_path_info_extra_get(pinew))->suppress++; switch (pinew->attr->origin) { @@ -6690,9 +6900,8 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi, if (pi->sub_type == BGP_ROUTE_AGGREGATE) return; - if (aggregate->summary_only - && pi->extra - && pi->extra->suppress > 0) { + if (aggregate->summary_only && pi->extra && pi->extra->suppress > 0 + && AGGREGATE_MED_VALID(aggregate)) { pi->extra->suppress--; if (pi->extra->suppress == 0) { @@ -6702,6 +6911,14 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi, } } + /* + * This must be called after `summary` check to avoid + * "unsuppressing" twice. + */ + if (aggregate->match_med) + bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi, + true); + if (aggregate->count > 0) aggregate->count--; @@ -6958,7 +7175,7 @@ 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, const char *rmap, uint8_t summary_only, uint8_t as_set, - uint8_t origin) + uint8_t origin, bool match_med) { VTY_DECLVAR_CONTEXT(bgp, bgp); int ret; @@ -7000,6 +7217,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, /* Make aggregate address structure. */ aggregate = bgp_aggregate_new(); aggregate->summary_only = summary_only; + aggregate->match_med = match_med; /* Network operators MUST NOT locally generate any new * announcements containing AS_SET or AS_CONFED_SET. If they have @@ -7045,236 +7263,108 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi, return CMD_SUCCESS; } -DEFUN (aggregate_address, - aggregate_address_cmd, - "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]", - "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" - "Apply route map to aggregate network\n" - "Name of route map\n" - "BGP origin code\n" - "Remote EGP\n" - "Local IGP\n" - "Unknown heritage\n") -{ - int idx = 0; - argv_find(argv, argc, "A.B.C.D/M", &idx); - char *prefix = argv[idx]->arg; - char *rmap = NULL; +DEFPY(aggregate_addressv4, aggregate_addressv4_cmd, + "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {" + "as-set$as_set_s" + "|summary-only$summary_only" + "|route-map WORD$rmap_name" + "|origin <egp|igp|incomplete>$origin_s" + "|matching-MED-only$match_med" + "}", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n" + "Generate AS set path information\n" + "Filter more specific routes from updates\n" + "Apply route map to aggregate network\n" + "Route map name\n" + "BGP origin code\n" + "Remote EGP\n" + "Local IGP\n" + "Unknown heritage\n" + "Only aggregate routes with matching MED\n") +{ + const char *prefix_s = NULL; + safi_t safi = bgp_node_safi(vty); uint8_t origin = BGP_ORIGIN_UNSPECIFIED; - int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET - : AGGREGATE_AS_UNSET; - idx = 0; - int summary_only = argv_find(argv, argc, "summary-only", &idx) - ? AGGREGATE_SUMMARY_ONLY - : 0; - - idx = 0; - argv_find(argv, argc, "WORD", &idx); - if (idx) - rmap = argv[idx]->arg; - - idx = 0; - if (argv_find(argv, argc, "origin", &idx)) { - if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0) - origin = BGP_ORIGIN_IGP; - if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0) - origin = BGP_ORIGIN_EGP; - if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0) - origin = BGP_ORIGIN_INCOMPLETE; - } - - return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap, - summary_only, as_set, origin); -} + int as_set = AGGREGATE_AS_UNSET; + char prefix_buf[PREFIX2STR_BUFFER]; -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]>] [route-map WORD] [origin <egp|igp|incomplete>]", - "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" - "Apply route map to aggregate network\n" - "Name of route map\n" - "BGP origin code\n" - "Remote EGP\n" - "Local IGP\n" - "Unknown heritage\n") -{ - int idx = 0; - argv_find(argv, argc, "A.B.C.D", &idx); - char *prefix = argv[idx]->arg; - char *mask = argv[idx + 1]->arg; - bool rmap_found; - char *rmap = NULL; - uint8_t origin = BGP_ORIGIN_UNSPECIFIED; - int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET - : AGGREGATE_AS_UNSET; - idx = 0; - int summary_only = argv_find(argv, argc, "summary-only", &idx) - ? AGGREGATE_SUMMARY_ONLY - : 0; - - rmap_found = argv_find(argv, argc, "WORD", &idx); - if (rmap_found) - rmap = argv[idx]->arg; - - char prefix_str[BUFSIZ]; - int ret = netmask_str2prefix_str(prefix, mask, prefix_str); - - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } + if (addr_str) { + if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf) + == 0) { + vty_out(vty, "%% Inconsistent address and mask\n"); + return CMD_WARNING_CONFIG_FAILED; + } + prefix_s = prefix_buf; + } else + prefix_s = prefix_str; - idx = 0; - if (argv_find(argv, argc, "origin", &idx)) { - if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0) - origin = BGP_ORIGIN_IGP; - if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0) + if (origin_s) { + if (strcmp(origin_s, "egp") == 0) origin = BGP_ORIGIN_EGP; - if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0) + else if (strcmp(origin_s, "igp") == 0) + origin = BGP_ORIGIN_IGP; + else if (strcmp(origin_s, "incomplete") == 0) origin = BGP_ORIGIN_INCOMPLETE; } - return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty), - rmap, summary_only, as_set, origin); -} - -DEFUN (no_aggregate_address, - no_aggregate_address_cmd, - "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]", - NO_STR - "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" - "Apply route map to aggregate network\n" - "Name of route map\n" - "BGP origin code\n" - "Remote EGP\n" - "Local IGP\n" - "Unknown heritage\n") -{ - int idx = 0; - argv_find(argv, argc, "A.B.C.D/M", &idx); - char *prefix = argv[idx]->arg; - return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty)); -} - -DEFUN (no_aggregate_address_mask, - no_aggregate_address_mask_cmd, - "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]", - NO_STR - "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" - "Apply route map to aggregate network\n" - "Name of route map\n" - "BGP origin code\n" - "Remote EGP\n" - "Local IGP\n" - "Unknown heritage\n") + if (as_set_s) + as_set = AGGREGATE_AS_SET; + + /* Handle configuration removal, otherwise installation. */ + if (no) + return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi); + + return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name, + summary_only != NULL, as_set, origin, + match_med != NULL); +} + +DEFPY(aggregate_addressv6, aggregate_addressv6_cmd, + "[no] aggregate-address X:X::X:X/M$prefix {" + "as-set$as_set_s" + "|summary-only$summary_only" + "|route-map WORD$rmap_name" + "|origin <egp|igp|incomplete>$origin_s" + "|matching-MED-only$match_med" + "}", + NO_STR + "Configure BGP aggregate entries\n" + "Aggregate prefix\n" + "Generate AS set path information\n" + "Filter more specific routes from updates\n" + "Apply route map to aggregate network\n" + "Route map name\n" + "BGP origin code\n" + "Remote EGP\n" + "Local IGP\n" + "Unknown heritage\n" + "Only aggregate routes with matching MED\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 prefix_str[BUFSIZ]; - int ret = netmask_str2prefix_str(prefix, mask, prefix_str); - - if (!ret) { - vty_out(vty, "%% Inconsistent address and mask\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty)); -} - -DEFUN (ipv6_aggregate_address, - ipv6_aggregate_address_cmd, - "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]", - "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" - "Apply route map to aggregate network\n" - "Name of route map\n" - "BGP origin code\n" - "Remote EGP\n" - "Local IGP\n" - "Unknown heritage\n") -{ - int idx = 0; - argv_find(argv, argc, "X:X::X:X/M", &idx); - char *prefix = argv[idx]->arg; - char *rmap = NULL; - bool rmap_found; uint8_t origin = BGP_ORIGIN_UNSPECIFIED; - int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET - : AGGREGATE_AS_UNSET; - - idx = 0; - int sum_only = argv_find(argv, argc, "summary-only", &idx) - ? AGGREGATE_SUMMARY_ONLY - : 0; + int as_set = AGGREGATE_AS_UNSET; - rmap_found = argv_find(argv, argc, "WORD", &idx); - if (rmap_found) - rmap = argv[idx]->arg; - - idx = 0; - if (argv_find(argv, argc, "origin", &idx)) { - if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0) - origin = BGP_ORIGIN_IGP; - if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0) + if (origin_s) { + if (strcmp(origin_s, "egp") == 0) origin = BGP_ORIGIN_EGP; - if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0) + else if (strcmp(origin_s, "igp") == 0) + origin = BGP_ORIGIN_IGP; + else if (strcmp(origin_s, "incomplete") == 0) origin = BGP_ORIGIN_INCOMPLETE; } - return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap, - sum_only, as_set, origin); -} + if (as_set_s) + as_set = AGGREGATE_AS_SET; -DEFUN (no_ipv6_aggregate_address, - no_ipv6_aggregate_address_cmd, - "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]", - NO_STR - "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" - "Apply route map to aggregate network\n" - "Name of route map\n" - "BGP origin code\n" - "Remote EGP\n" - "Local IGP\n" - "Unknown heritage\n") -{ - int idx = 0; - argv_find(argv, argc, "X:X::X:X/M", &idx); - char *prefix = argv[idx]->arg; - return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST); + /* Handle configuration removal, otherwise installation. */ + if (no) + return bgp_aggregate_unset(vty, prefix_str, AFI_IP6, + SAFI_UNICAST); + + return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST, + rmap_name, summary_only != NULL, as_set, + origin, match_med != NULL); } /* Redistribute route treatment. */ @@ -13880,6 +13970,9 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, vty_out(vty, " origin %s", bgp_origin2str(bgp_aggregate->origin)); + if (bgp_aggregate->match_med) + vty_out(vty, " matching-MED-only"); + vty_out(vty, "\n"); } } @@ -13929,36 +14022,24 @@ void bgp_route_init(void) install_element(BGP_NODE, &bgp_network_cmd); install_element(BGP_NODE, &no_bgp_table_map_cmd); - install_element(BGP_NODE, &aggregate_address_cmd); - install_element(BGP_NODE, &aggregate_address_mask_cmd); - install_element(BGP_NODE, &no_aggregate_address_cmd); - install_element(BGP_NODE, &no_aggregate_address_mask_cmd); + install_element(BGP_NODE, &aggregate_addressv4_cmd); /* IPv4 unicast configuration. */ install_element(BGP_IPV4_NODE, &bgp_table_map_cmd); install_element(BGP_IPV4_NODE, &bgp_network_cmd); install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd); - install_element(BGP_IPV4_NODE, &aggregate_address_cmd); - install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd); - install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd); - install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd); + install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd); /* IPv4 multicast configuration. */ install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd); install_element(BGP_IPV4M_NODE, &bgp_network_cmd); install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd); - install_element(BGP_IPV4M_NODE, &aggregate_address_cmd); - install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd); - install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd); - install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd); + install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd); /* IPv4 labeled-unicast configuration. */ install_element(BGP_IPV4L_NODE, &bgp_network_cmd); - install_element(BGP_IPV4L_NODE, &aggregate_address_cmd); - install_element(BGP_IPV4L_NODE, &aggregate_address_mask_cmd); - install_element(BGP_IPV4L_NODE, &no_aggregate_address_cmd); - install_element(BGP_IPV4L_NODE, &no_aggregate_address_mask_cmd); + install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd); install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd); install_element(VIEW_NODE, &show_ip_bgp_cmd); @@ -14003,15 +14084,13 @@ void bgp_route_init(void) install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd); install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd); - install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd); - install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd); + install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd); install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd); /* IPv6 labeled unicast address family. */ install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd); - install_element(BGP_IPV6L_NODE, &ipv6_aggregate_address_cmd); - install_element(BGP_IPV6L_NODE, &no_ipv6_aggregate_address_cmd); + install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd); install_element(BGP_NODE, &bgp_distance_cmd); install_element(BGP_NODE, &no_bgp_distance_cmd); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 340788489..962a08608 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -379,6 +379,25 @@ struct bgp_aggregate { /* SAFI configuration. */ safi_t safi; + + /** Match only equal MED. */ + bool match_med; + /* MED matching state. */ + /** Did we get the first MED value? */ + bool med_initialized; + /** Are there MED mismatches? */ + bool med_mismatched; + /** MED value found in current group. */ + uint32_t med_matched_value; + + /** + * Test if aggregated address MED of all route match, otherwise + * returns `false`. This macro will also return `true` if MED + * matching is disabled. + */ +#define AGGREGATE_MED_VALID(aggregate) \ + (((aggregate)->match_med && !(aggregate)->med_mismatched) \ + || !(aggregate)->match_med) }; #define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \ |