diff options
Diffstat (limited to 'bgpd/bgp_route.c')
| -rw-r--r-- | bgpd/bgp_route.c | 1279 |
1 files changed, 581 insertions, 698 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 4637cef3eb..716ba26305 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -88,9 +88,6 @@ #include "bgpd/bgp_flowspec.h" #include "bgpd/bgp_flowspec_util.h" #include "bgpd/bgp_pbr.h" -#include "northbound.h" -#include "northbound_cli.h" -#include "bgpd/bgp_nb.h" #ifndef VTYSH_EXTRACT_PL #include "bgpd/bgp_route_clippy.c" @@ -221,6 +218,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) return; e = *extra; + if (e->damp_info) + bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi, + e->damp_info->safi); e->damp_info = NULL; if (e->parent) { @@ -3391,16 +3391,14 @@ static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi, /* apply dampening, if result is suppressed, we'll be retaining * the bgp_path_info in the RIB for historical reference. */ - if (peer->sort == BGP_PEER_EBGP) { - if (get_active_bdc_from_pi(pi, afi, safi)) { - if (bgp_damp_withdraw(pi, dest, afi, safi, 0) - == BGP_DAMP_SUPPRESSED) { - bgp_aggregate_decrement(peer->bgp, p, pi, afi, - safi); - return; - } + if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) + && peer->sort == BGP_PEER_EBGP) + if ((bgp_damp_withdraw(pi, dest, afi, safi, 0)) + == BGP_DAMP_SUPPRESSED) { + bgp_aggregate_decrement(peer->bgp, p, pi, afi, + safi); + return; } - } #ifdef ENABLE_BGP_VNC if (safi == SAFI_MPLS_VPN) { @@ -3604,6 +3602,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, afi_t nh_afi; uint8_t pi_type = 0; uint8_t pi_sub_type = 0; + bool force_evpn_import = false; if (frrtrace_enabled(frr_bgp, process_update)) { char pfxprint[PREFIX2STR_BUFFER]; @@ -3663,7 +3662,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (aspath_loop_check(attr->aspath, peer->change_local_as) > aspath_loop_count) { peer->stat_pfx_aspath_loop++; - reason = "as-path contains our own AS A;"; + reason = "as-path contains our own AS;"; goto filtered; } } @@ -3848,7 +3847,8 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, || memcmp(&(bgp_path_info_extra_get(pi))->label, label, num_labels * sizeof(mpls_label_t)) == 0)) { - if (get_active_bdc_from_pi(pi, afi, safi) + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { if (bgp_debug_update(peer, p, NULL, 1)) { @@ -3916,6 +3916,14 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, } bgp_path_info_restore(dest, pi); + + /* + * If the BGP_PATH_REMOVED flag is set, then EVPN + * routes would have been unimported already when a + * prior BGP withdraw processing happened. Such routes + * need to be imported again, so flag accordingly. + */ + force_evpn_import = true; } /* Received Logging. */ @@ -3942,11 +3950,11 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, bgp_aggregate_decrement(bgp, p, pi, afi, safi); /* Update bgp route dampening information. */ - if (get_active_bdc_from_pi(pi, afi, safi) + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) { /* This is implicit withdraw so we should update - * dampening information. - */ + dampening + information. */ if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) bgp_damp_withdraw(pi, dest, afi, safi, 1); } @@ -4069,7 +4077,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, #endif /* Update bgp route dampening information. */ - if (get_active_bdc_from_pi(pi, afi, safi) + if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) { /* Now we do normal update dampening. */ ret = bgp_damp_update(pi, dest, afi, safi); @@ -4103,7 +4111,8 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr); if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi, - safi, pi, NULL, connected) + safi, pi, NULL, connected, + p) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID); @@ -4137,7 +4146,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, #endif /* If this is an EVPN route and some attribute has changed, - * process + * or we are explicitly told to perform a route import, process * route for import. If the extended community has changed, we * would * have done the un-import earlier and the import would result @@ -4148,7 +4157,8 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, * updating * the attributes for the route in the VNI(s). */ - if (safi == SAFI_EVPN && !same_attr && + if (safi == SAFI_EVPN && + (!same_attr || force_evpn_import) && CHECK_FLAG(pi->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, pi); @@ -4244,7 +4254,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, nh_afi = BGP_ATTR_NH_AFI(afi, new->attr); if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL, - connected) + connected, p) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) bgp_path_info_set_flag(dest, new, BGP_PATH_VALID); else { @@ -5683,7 +5693,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p, if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi, pi, NULL, - 0)) + 0, p)) bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID); else { @@ -5735,7 +5745,8 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p, /* Nexthop reachability check. */ if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK) && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { - if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0)) + if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0, + p)) bgp_path_info_set_flag(dest, new, BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { @@ -6023,16 +6034,28 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p, /* Configure static BGP network. When user don't run zebra, static route should be installed as valid. */ -int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx, - afi_t afi, safi_t safi, const char *rmap, int backdoor, - uint32_t label_index, char *errmsg, size_t errmsg_len) +static int bgp_static_set(struct vty *vty, const char *negate, + const char *ip_str, afi_t afi, safi_t safi, + const char *rmap, int backdoor, uint32_t label_index) { + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; struct prefix p; struct bgp_static *bgp_static; struct bgp_dest *dest; uint8_t need_update = 0; - prefix_copy(&p, pfx); + /* Convert IP prefix string to struct prefix. */ + ret = str2prefix(ip_str, &p); + if (!ret) { + vty_out(vty, "%% Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) { + vty_out(vty, "%% Malformed prefix (link-local address)\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); if (negate) { @@ -6041,25 +6064,26 @@ int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx, dest = bgp_node_lookup(bgp->route[afi][safi], &p); if (!dest) { - snprintf(errmsg, errmsg_len, - "Can't find static route specified\n"); - return -1; + vty_out(vty, "%% Can't find static route specified\n"); + return CMD_WARNING_CONFIG_FAILED; } bgp_static = bgp_dest_get_bgp_static_info(dest); if ((label_index != BGP_INVALID_LABEL_INDEX) && (label_index != bgp_static->label_index)) { - snprintf(errmsg, errmsg_len, - "label-index doesn't match static route\n"); - return -1; + vty_out(vty, + "%% label-index doesn't match static route\n"); + bgp_dest_unlock_node(dest); + return CMD_WARNING_CONFIG_FAILED; } if ((rmap && bgp_static->rmap.name) && strcmp(rmap, bgp_static->rmap.name)) { - snprintf(errmsg, errmsg_len, - "route-map name doesn't match static route\n"); - return -1; + vty_out(vty, + "%% route-map name doesn't match static route\n"); + bgp_dest_unlock_node(dest); + return CMD_WARNING_CONFIG_FAILED; } /* Update BGP RIB. */ @@ -6080,9 +6104,8 @@ int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx, /* Configuration change. */ /* Label index cannot be changed. */ if (bgp_static->label_index != label_index) { - snprintf(errmsg, errmsg_len, - "cannot change label-index\n"); - return -1; + vty_out(vty, "%% cannot change label-index\n"); + return CMD_WARNING_CONFIG_FAILED; } /* Check previous routes are installed into BGP. */ @@ -6144,7 +6167,7 @@ int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx, bgp_static_update(bgp, &p, bgp_static, afi, safi); } - return 0; + return CMD_SUCCESS; } void bgp_static_add(struct bgp *bgp) @@ -6596,27 +6619,25 @@ DEFUN (no_bgp_table_map, argv[idx_word]->arg); } -DEFPY_YANG (bgp_network, bgp_network_cmd, - "[no] network \ - <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \ - [{route-map WORD$map_name|label-index (0-1048560)$label_index| \ - backdoor$backdoor}]", - NO_STR - "Specify a network to announce via BGP\n" - "IPv4 prefix\n" - "Network number\n" - "Network mask\n" - "Network mask\n" - "Route-map to modify the attributes\n" - "Name of the route map\n" - "Label index to associate with the prefix\n" - "Label index value\n" - "Specify a BGP backdoor route\n") -{ - char addr_prefix_str[PREFIX_STRLEN]; - char base_xpath[XPATH_MAXLEN]; - afi_t afi; - safi_t safi; +DEFPY(bgp_network, + bgp_network_cmd, + "[no] network \ + <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \ + [{route-map WORD$map_name|label-index (0-1048560)$label_index| \ + backdoor$backdoor}]", + NO_STR + "Specify a network to announce via BGP\n" + "IPv4 prefix\n" + "Network number\n" + "Network mask\n" + "Network mask\n" + "Route-map to modify the attributes\n" + "Name of the route map\n" + "Label index to associate with the prefix\n" + "Label index value\n" + "Specify a BGP backdoor route\n") +{ + char addr_prefix_str[BUFSIZ]; if (address_str) { int ret; @@ -6630,102 +6651,27 @@ DEFPY_YANG (bgp_network, bgp_network_cmd, } } - afi = bgp_node_afi(vty); - safi = bgp_node_safi(vty); - - if (no) { - nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - } else { - nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); - - if (map_name) - nb_cli_enqueue_change(vty, "./rmap-policy-export", - NB_OP_CREATE, map_name); - else - nb_cli_enqueue_change(vty, "./rmap-policy-export", - NB_OP_DESTROY, NULL); - - if (label_index_str) - nb_cli_enqueue_change(vty, "./label-index", - NB_OP_MODIFY, label_index_str); - - nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY, - backdoor ? "true" : "false"); - } - - snprintf( - base_xpath, sizeof(base_xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi), - address_str ? addr_prefix_str : prefix_str); - - return nb_cli_apply_changes(vty, base_xpath); -} - -DEFPY_YANG (ipv6_bgp_network, - ipv6_bgp_network_cmd, - "[no] network X:X::X:X/M$prefix \ - [{route-map WORD$map_name|label-index (0-1048560)$label_index}]", - NO_STR - "Specify a network to announce via BGP\n" - "IPv6 prefix\n" - "Route-map to modify the attributes\n" - "Name of the route map\n" - "Label index to associate with the prefix\n" - "Label index value\n") -{ - char base_xpath[XPATH_MAXLEN]; - afi_t afi; - safi_t safi; - - afi = bgp_node_afi(vty); - safi = bgp_node_safi(vty); - - if (no) { - nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - } else { - nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); - - if (map_name) - nb_cli_enqueue_change(vty, "./rmap-policy-export", - NB_OP_MODIFY, map_name); - else - nb_cli_enqueue_change(vty, "./rmap-policy-export", - NB_OP_DESTROY, NULL); - - if (label_index_str) - nb_cli_enqueue_change(vty, "./label-index", - NB_OP_MODIFY, label_index_str); - } - - snprintf( - base_xpath, sizeof(base_xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi), prefix_str); - - return nb_cli_apply_changes(vty, base_xpath); + return bgp_static_set( + vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP, + bgp_node_safi(vty), map_name, backdoor ? 1 : 0, + label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX); } -void cli_show_bgp_global_afi_safi_network_config(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults) +DEFPY(ipv6_bgp_network, + ipv6_bgp_network_cmd, + "[no] network X:X::X:X/M$prefix \ + [{route-map WORD$map_name|label-index (0-1048560)$label_index}]", + NO_STR + "Specify a network to announce via BGP\n" + "IPv6 prefix\n" + "Route-map to modify the attributes\n" + "Name of the route map\n" + "Label index to associate with the prefix\n" + "Label index value\n") { - vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix")); - - if (yang_dnode_exists(dnode, "./label-index")) - vty_out(vty, " label-index %s", - yang_dnode_get_string(dnode, "./label-index")); - - if (yang_dnode_exists(dnode, "./rmap-policy-export")) - vty_out(vty, " route-map %s", - yang_dnode_get_string(dnode, "./rmap-policy-export")); - - if (yang_dnode_get_bool(dnode, "./backdoor")) - vty_out(vty, " backdoor"); - - vty_out(vty, "\n"); + return bgp_static_set( + vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0, + label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX); } static struct bgp_aggregate *bgp_aggregate_new(void) @@ -7801,32 +7747,35 @@ static const char *bgp_rpki_validation2str(enum rpki_states v_state) return "ERROR"; } -int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi, - safi_t safi, char *errmsg, size_t errmsg_len) +static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, + afi_t afi, safi_t safi) { + VTY_DECLVAR_CONTEXT(bgp, bgp); + int ret; + struct prefix p; struct bgp_dest *dest; struct bgp_aggregate *aggregate; - /* If the bgp instance is being deleted or self peer is deleted - * then do not create aggregate route - */ - if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) - || (bgp->peer_self == NULL)) - return 0; + /* Convert string to prefix structure. */ + ret = str2prefix(prefix_str, &p); + if (!ret) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); - apply_mask(prefix); /* Old configuration check. */ - dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix); + dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p); if (!dest) { - snprintf(errmsg, errmsg_len, - "There is no aggregate-address configuration.\n"); - return -1; + vty_out(vty, + "%% There is no aggregate-address configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; } aggregate = bgp_dest_get_bgp_aggregate_info(dest); - bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate); - bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL, - 0, aggregate); + bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); + bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, + NULL, NULL, 0, aggregate); /* Unlock aggregate address configuration. */ bgp_dest_set_bgp_aggregate_info(dest, NULL); @@ -7887,53 +7836,55 @@ int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi, bgp_dest_unlock_node(dest); bgp_dest_unlock_node(dest); - return 0; + return CMD_SUCCESS; } -int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi, - safi_t safi, const char *rmap, uint8_t summary_only, - uint8_t as_set, uint8_t origin, bool match_med, - const char *suppress_map, - char *errmsg, size_t errmsg_len) +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, bool match_med, + const char *suppress_map) { + VTY_DECLVAR_CONTEXT(bgp, bgp); int ret; + struct prefix p; struct bgp_dest *dest; struct bgp_aggregate *aggregate; uint8_t as_set_new = as_set; - char buf[PREFIX2STR_BUFFER]; if (suppress_map && summary_only) { - snprintf(errmsg, errmsg_len, + vty_out(vty, "'summary-only' and 'suppress-map' can't be used at the same time\n"); - return -1; + return CMD_WARNING_CONFIG_FAILED; } - apply_mask(prefix); + /* Convert string to prefix structure. */ + ret = str2prefix(prefix_str, &p); + if (!ret) { + vty_out(vty, "Malformed prefix\n"); + return CMD_WARNING_CONFIG_FAILED; + } + apply_mask(&p); - if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN) - || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) { - snprintf( - errmsg, errmsg_len, - "Specified prefix: %s will not result in any useful aggregation, disallowing\n", - prefix2str(prefix, buf, PREFIX_STRLEN)); - return -1; + if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) || + (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) { + vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n", + prefix_str); + return CMD_WARNING_CONFIG_FAILED; } /* Old configuration check. */ - dest = bgp_node_get(bgp->aggregate[afi][safi], prefix); + dest = bgp_node_get(bgp->aggregate[afi][safi], &p); aggregate = bgp_dest_get_bgp_aggregate_info(dest); if (aggregate) { - snprintf(errmsg, errmsg_len, - "There is already same aggregate network.\n"); + vty_out(vty, "There is already same aggregate network.\n"); /* try to remove the old entry */ - ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg, - errmsg_len); + ret = bgp_aggregate_unset(vty, prefix_str, afi, safi); if (ret) { - snprintf(errmsg, errmsg_len, - "Error deleting aggregate.\n"); + vty_out(vty, "Error deleting aggregate.\n"); bgp_dest_unlock_node(dest); - return -1; + return CMD_WARNING_CONFIG_FAILED; } } @@ -7956,8 +7907,7 @@ int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi, zlog_warn( "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.", __func__); - snprintf( - errmsg, errmsg_len, + vty_out(vty, "Ignoring as-set because `bgp reject-as-sets` is enabled.\n"); } } @@ -7994,40 +7944,39 @@ int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi, bgp_dest_set_bgp_aggregate_info(dest, aggregate); /* Aggregate address insert into BGP routing table. */ - bgp_aggregate_route(bgp, prefix, afi, safi, aggregate); + bgp_aggregate_route(bgp, &p, afi, safi, aggregate); - return 0; + return CMD_SUCCESS; } -DEFPY_YANG( - 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" - "|suppress-map WORD$suppress_map" - "}]", - 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" - "Suppress the selected more specific routes\n" - "Route map with the route selectors\n") -{ - char base_xpath[XPATH_MAXLEN]; +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" + "|suppress-map WORD$suppress_map" + "}]", + 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" + "Suppress the selected more specific routes\n" + "Route map with the route selectors\n") +{ + const char *prefix_s = NULL; safi_t safi = bgp_node_safi(vty); + uint8_t origin = BGP_ORIGIN_UNSPECIFIED; + int as_set = AGGREGATE_AS_UNSET; char prefix_buf[PREFIX2STR_BUFFER]; if (addr_str) { @@ -8037,158 +7986,78 @@ DEFPY_YANG( vty_out(vty, "%% Inconsistent address and mask\n"); return CMD_WARNING_CONFIG_FAILED; } - } else { - strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf)); - } - - if (!no && origin_s) - nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s); - - if (!no && as_set_s) - nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true"); - else - nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false"); - - if (!no && summary_only) - nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY, - "true"); - else - nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY, - "false"); - - if (!no && match_med) - nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true"); - else - nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, - "false"); - - if (rmap_name) - nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY, - rmap_name); - else - nb_cli_enqueue_change(vty, "./rmap-policy-export", - NB_OP_DESTROY, NULL); + prefix_s = prefix_buf; + } else + prefix_s = prefix_str; - if (suppress_map) - nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY, - suppress_map); - else - nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY, - NULL); + if (origin_s) { + if (strcmp(origin_s, "egp") == 0) + origin = BGP_ORIGIN_EGP; + else if (strcmp(origin_s, "igp") == 0) + origin = BGP_ORIGIN_IGP; + else if (strcmp(origin_s, "incomplete") == 0) + origin = BGP_ORIGIN_INCOMPLETE; + } - snprintf( - base_xpath, sizeof(base_xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']", - yang_afi_safi_value2identity(AFI_IP, safi), - bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf); + if (as_set_s) + as_set = AGGREGATE_AS_SET; + /* Handle configuration removal, otherwise installation. */ if (no) - nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - else - nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); - - return nb_cli_apply_changes(vty, base_xpath); -} - -DEFPY_YANG(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" - "|suppress-map WORD$suppress_map" - "}]", - 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" - "Suppress the selected more specific routes\n" - "Route map with the route selectors\n") -{ - char base_xpath[XPATH_MAXLEN]; - safi_t safi = bgp_node_safi(vty); - - if (!no && origin_s) - nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s); - - if (!no && as_set_s) - nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true"); - else - nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false"); - - if (!no && summary_only) - nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY, - "true"); - else - nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY, - "false"); - - if (!no && match_med) - nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true"); - else - nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, - "false"); - - if (rmap_name) - nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY, - rmap_name); - - if (suppress_map) - nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY, - suppress_map); - else - nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY, - NULL); - - snprintf( - base_xpath, sizeof(base_xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']", - yang_afi_safi_value2identity(AFI_IP6, safi), - bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str); - + 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, suppress_map); +} + +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" + "|suppress-map WORD$suppress_map" + "}]", + 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" + "Suppress the selected more specific routes\n" + "Route map with the route selectors\n") +{ + uint8_t origin = BGP_ORIGIN_UNSPECIFIED; + int as_set = AGGREGATE_AS_UNSET; + + if (origin_s) { + if (strcmp(origin_s, "egp") == 0) + origin = BGP_ORIGIN_EGP; + else if (strcmp(origin_s, "igp") == 0) + origin = BGP_ORIGIN_IGP; + else if (strcmp(origin_s, "incomplete") == 0) + origin = BGP_ORIGIN_INCOMPLETE; + } + + if (as_set_s) + as_set = AGGREGATE_AS_SET; + + /* Handle configuration removal, otherwise installation. */ if (no) - nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); - else - nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); - - return nb_cli_apply_changes(vty, base_xpath); -} - -void cli_show_bgp_global_afi_safi_unicast_aggregate_route( - struct vty *vty, struct lyd_node *dnode, bool show_defaults) -{ - uint8_t origin; - - vty_out(vty, " aggregate-address %s", - yang_dnode_get_string(dnode, "./prefix")); - - if (yang_dnode_get_bool(dnode, "./as-set")) - vty_out(vty, " as-set"); - - if (yang_dnode_get_bool(dnode, "./summary-only")) - vty_out(vty, " summary-only"); - - if (yang_dnode_exists(dnode, "./rmap-policy-export")) - vty_out(vty, " route-map %s", - yang_dnode_get_string(dnode, "./rmap-policy-export")); - - origin = yang_dnode_get_enum(dnode, "./origin"); - if (origin != BGP_ORIGIN_UNSPECIFIED) - vty_out(vty, " origin %s", bgp_origin2str(origin)); - - if (yang_dnode_get_bool(dnode, "./match-med")) - vty_out(vty, " matching-MED-only"); + return bgp_aggregate_unset(vty, prefix_str, AFI_IP6, + SAFI_UNICAST); - vty_out(vty, "\n"); + return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST, + rmap_name, summary_only != NULL, as_set, + origin, match_med != NULL, suppress_map); } /* Redistribute route treatment. */ @@ -9517,14 +9386,18 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, static void damp_route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, afi_t afi, safi_t safi, bool use_json, - json_object *json) + json_object *json_paths) { - struct attr *attr; + struct attr *attr = path->attr; int len; char timebuf[BGP_UPTIME_LEN]; + json_object *json_path = NULL; + + if (use_json) + json_path = json_object_new_object(); /* short status lead text */ - route_vty_short_status_out(vty, path, p, json); + route_vty_short_status_out(vty, path, p, json_path); /* print prefix and mask */ if (!use_json) { @@ -9532,147 +9405,125 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p, route_vty_out_route(path->net, p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); - } - len = vty_out(vty, "%s", path->peer->host); - len = 17 - len; - if (len < 1) { - if (!use_json) + len = vty_out(vty, "%s", path->peer->host); + len = 17 - len; + + if (len < 1) vty_out(vty, "\n%*s", 34, " "); - } else { - if (use_json) - json_object_int_add(json, "peerHost", len); else vty_out(vty, "%*s", len, " "); - } - if (use_json) - bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi, - safi, use_json, json); - else vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi, safi, - use_json, json)); - - /* Print attribute */ - attr = path->attr; + use_json, NULL)); - /* Print aspath */ - if (attr->aspath) { - if (use_json) - json_object_string_add(json, "asPath", - attr->aspath->str); - else + if (attr->aspath) aspath_print_vty(vty, "%s", attr->aspath, " "); - } - /* Print origin */ - if (use_json) - json_object_string_add(json, "origin", - bgp_origin_str[attr->origin]); - else vty_out(vty, "%s", bgp_origin_str[attr->origin]); - if (!use_json) vty_out(vty, "\n"); + } else { + bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi, + safi, use_json, json_path); + + if (attr->aspath) + json_object_string_add(json_path, "asPath", + attr->aspath->str); + + json_object_string_add(json_path, "origin", + bgp_origin_str[attr->origin]); + json_object_string_add(json_path, "peerHost", path->peer->host); + + json_object_array_add(json_paths, json_path); + } } /* flap route */ static void flap_route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, afi_t afi, safi_t safi, bool use_json, - json_object *json) + json_object *json_paths) { - struct attr *attr; + struct attr *attr = path->attr; struct bgp_damp_info *bdi; char timebuf[BGP_UPTIME_LEN]; int len; + json_object *json_path = NULL; if (!path->extra) return; + if (use_json) + json_path = json_object_new_object(); + bdi = path->extra->damp_info; /* short status lead text */ - route_vty_short_status_out(vty, path, p, json); + route_vty_short_status_out(vty, path, p, json_path); - /* print prefix and mask */ if (!use_json) { if (!display) route_vty_out_route(path->net, p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); - } - len = vty_out(vty, "%s", path->peer->host); - len = 16 - len; - if (len < 1) { - if (!use_json) + len = vty_out(vty, "%s", path->peer->host); + len = 16 - len; + if (len < 1) vty_out(vty, "\n%*s", 33, " "); - } else { - if (use_json) - json_object_int_add(json, "peerHost", len); else vty_out(vty, "%*s", len, " "); - } - len = vty_out(vty, "%d", bdi->flap); - len = 5 - len; - if (len < 1) { - if (!use_json) + len = vty_out(vty, "%d", bdi->flap); + len = 5 - len; + if (len < 1) vty_out(vty, " "); - } else { - if (use_json) - json_object_int_add(json, "bdiFlap", len); else vty_out(vty, "%*s", len, " "); - } - if (use_json) - peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, - json); - else vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, NULL)); - if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) - && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) { - if (use_json) - bgp_damp_reuse_time_vty(vty, path, timebuf, - BGP_UPTIME_LEN, afi, safi, - use_json, json); - else + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi, - safi, use_json, json)); - } else { - if (!use_json) + safi, use_json, NULL)); + else vty_out(vty, "%*s ", 8, " "); - } - /* Print attribute */ - attr = path->attr; - - /* Print aspath */ - if (attr->aspath) { - if (use_json) - json_object_string_add(json, "asPath", - attr->aspath->str); - else + if (attr->aspath) aspath_print_vty(vty, "%s", attr->aspath, " "); - } - /* Print origin */ - if (use_json) - json_object_string_add(json, "origin", - bgp_origin_str[attr->origin]); - else vty_out(vty, "%s", bgp_origin_str[attr->origin]); - if (!use_json) vty_out(vty, "\n"); + } else { + json_object_string_add(json_path, "peerHost", path->peer->host); + json_object_int_add(json_path, "bdiFlap", bdi->flap); + + peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json, + json_path); + + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) + bgp_damp_reuse_time_vty(vty, path, timebuf, + BGP_UPTIME_LEN, afi, safi, + use_json, json_path); + + if (attr->aspath) + json_object_string_add(json_path, "asPath", + attr->aspath->str); + + json_object_string_add(json_path, "origin", + bgp_origin_str[attr->origin]); + + json_object_array_add(json_paths, json_path); + } } static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer, @@ -10587,7 +10438,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } if (path->extra && path->extra->damp_info) - bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path); + bgp_damp_info_vty(vty, path, afi, safi, json_path); /* Remote Label */ if (path->extra && bgp_is_valid_label(&path->extra->label[0]) @@ -10876,8 +10727,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, const char *com2alias = bgp_community2alias( communities[i]); - if (strncmp(alias, com2alias, - strlen(com2alias)) + if (strcmp(alias, com2alias) == 0) { found = true; break; @@ -10892,8 +10742,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, const char *com2alias = bgp_community2alias( communities[i]); - if (strncmp(alias, com2alias, - strlen(com2alias)) + if (strcmp(alias, com2alias) == 0) { found = true; break; @@ -11643,7 +11492,8 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, if (!table) continue; - if ((rm = bgp_node_match(table, &match)) == NULL) + rm = bgp_node_match(table, &match); + if (rm == NULL) continue; const struct prefix *rm_p = bgp_dest_get_prefix(rm); @@ -11735,7 +11585,8 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, json_object_free(json_paths); } } else { - if ((dest = bgp_node_match(rib, &match)) != NULL) { + dest = bgp_node_match(rib, &match); + if (dest != NULL) { const struct prefix *dest_p = bgp_dest_get_prefix(dest); if (!prefix_check || dest_p->prefixlen == match.prefixlen) { @@ -12192,7 +12043,7 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd, |route-filter-translated-v4] [exact-match]\ |rpki <invalid|valid|notfound>\ |version (1-4294967295)\ - |alias WORD\ + |alias ALIAS_NAME\ ] [json$uj [detail$detail] | wide$wide]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR @@ -14314,21 +14165,28 @@ static void bgp_distance_free(struct bgp_distance *bdistance) XFREE(MTYPE_BGP_DISTANCE, bdistance); } -int bgp_distance_set(uint8_t distance, const char *ip_str, - const char *access_list_str, afi_t afi, safi_t safi, - char *errmsg, size_t errmsg_len) +static int bgp_distance_set(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) { int ret; + afi_t afi; + safi_t safi; struct prefix p; + uint8_t distance; struct bgp_dest *dest; struct bgp_distance *bdistance; + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); + ret = str2prefix(ip_str, &p); if (ret == 0) { - snprintf(errmsg, errmsg_len, "Malformed prefix\n"); + vty_out(vty, "Malformed prefix\n"); return CMD_WARNING_CONFIG_FAILED; } + distance = atoi(distance_str); + /* Get BGP distance node. */ dest = bgp_node_get(bgp_distance_table[afi][safi], &p); bdistance = bgp_dest_get_bgp_distance_info(dest); @@ -14351,32 +14209,38 @@ int bgp_distance_set(uint8_t distance, const char *ip_str, return CMD_SUCCESS; } -int bgp_distance_unset(uint8_t distance, const char *ip_str, - const char *access_list_str, afi_t afi, safi_t safi, - char *errmsg, size_t errmsg_len) +static int bgp_distance_unset(struct vty *vty, const char *distance_str, + const char *ip_str, const char *access_list_str) { int ret; + afi_t afi; + safi_t safi; struct prefix p; + int distance; struct bgp_dest *dest; struct bgp_distance *bdistance; + afi = bgp_node_afi(vty); + safi = bgp_node_safi(vty); + ret = str2prefix(ip_str, &p); if (ret == 0) { - snprintf(errmsg, errmsg_len, "Malformed prefix\n"); + vty_out(vty, "Malformed prefix\n"); return CMD_WARNING_CONFIG_FAILED; } dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p); if (!dest) { - snprintf(errmsg, errmsg_len, "Can't find specified prefix\n"); + vty_out(vty, "Can't find specified prefix\n"); return CMD_WARNING_CONFIG_FAILED; } bdistance = bgp_dest_get_bgp_distance_info(dest); + distance = atoi(distance_str); if (bdistance->distance != distance) { - snprintf(errmsg, errmsg_len, - "Distance does not match configured\n"); + vty_out(vty, "Distance does not match configured\n"); + bgp_dest_unlock_node(dest); return CMD_WARNING_CONFIG_FAILED; } @@ -14463,8 +14327,9 @@ uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo, * we should tell ZEBRA update the routes for a specific * AFI/SAFI to reflect changes in RIB. */ -void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi, - safi_t update_safi) +static void bgp_announce_routes_distance_update(struct bgp *bgp, + afi_t update_afi, + safi_t update_safi) { afi_t afi; safi_t safi; @@ -14484,228 +14349,237 @@ void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi, } } -DEFUN_YANG(bgp_distance, bgp_distance_cmd, - "distance bgp (1-255) (1-255) (1-255)", - "Define an administrative distance\n" - "BGP distance\n" - "Distance for routes external to the AS\n" - "Distance for routes internal to the AS\n" - "Distance for local routes\n") +DEFUN (bgp_distance, + bgp_distance_cmd, + "distance bgp (1-255) (1-255) (1-255)", + "Define an administrative distance\n" + "BGP distance\n" + "Distance for routes external to the AS\n" + "Distance for routes internal to the AS\n" + "Distance for local routes\n") { + VTY_DECLVAR_CONTEXT(bgp, bgp); int idx_number = 2; int idx_number_2 = 3; int idx_number_3 = 4; + int distance_ebgp = atoi(argv[idx_number]->arg); + int distance_ibgp = atoi(argv[idx_number_2]->arg); + int distance_local = atoi(argv[idx_number_3]->arg); afi_t afi; safi_t safi; - char xpath[XPATH_MAXLEN]; afi = bgp_node_afi(vty); safi = bgp_node_safi(vty); - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg); - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, - argv[idx_number_2]->arg); - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); - - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, - argv[idx_number_3]->arg); - - return nb_cli_apply_changes(vty, NULL); -} - -DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd, - "no distance bgp [(1-255) (1-255) (1-255)]", - NO_STR - "Define an administrative distance\n" - "BGP distance\n" - "Distance for routes external to the AS\n" - "Distance for routes internal to the AS\n" - "Distance for local routes\n") -{ - afi_t afi; - safi_t safi; - char xpath[XPATH_MAXLEN]; - - afi = bgp_node_afi(vty); - safi = bgp_node_safi(vty); + if (bgp->distance_ebgp[afi][safi] != distance_ebgp + || bgp->distance_ibgp[afi][safi] != distance_ibgp + || bgp->distance_local[afi][safi] != distance_local) { + bgp->distance_ebgp[afi][safi] = distance_ebgp; + bgp->distance_ibgp[afi][safi] = distance_ibgp; + bgp->distance_local[afi][safi] = distance_local; + bgp_announce_routes_distance_update(bgp, afi, safi); + } + return CMD_SUCCESS; +} - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL); - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL); - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); - - nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL); - - return nb_cli_apply_changes(vty, NULL); -} - -void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults) -{ - uint8_t distance_ebgp, distance_ibgp, distance_local; - - distance_ebgp = yang_dnode_get_uint8(dnode, "./external"); - distance_ibgp = yang_dnode_get_uint8(dnode, "./internal"); - distance_local = yang_dnode_get_uint8(dnode, "./local"); - - vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp, - distance_local); -} - -DEFPY_YANG(bgp_distance_source, - bgp_distance_source_cmd, - "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]", - NO_STR - "Define an administrative distance\n" - "Distance value\n" - "IPv4 source prefix\n" - "IPv6 source prefix\n" - "Access list name\n") +DEFUN (no_bgp_distance, + no_bgp_distance_cmd, + "no distance bgp [(1-255) (1-255) (1-255)]", + NO_STR + "Define an administrative distance\n" + "BGP distance\n" + "Distance for routes external to the AS\n" + "Distance for routes internal to the AS\n" + "Distance for local routes\n") { + VTY_DECLVAR_CONTEXT(bgp, bgp); afi_t afi; safi_t safi; - char xpath[XPATH_MAXLEN]; afi = bgp_node_afi(vty); safi = bgp_node_safi(vty); - if (!no) { - nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); - nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY, - distance_str); - if (acl) - nb_cli_enqueue_change(vty, - "./access-list-policy-export", - NB_OP_CREATE, acl); - else - nb_cli_enqueue_change(vty, - "./access-list-policy-export", - NB_OP_DESTROY, NULL); - } else { - nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); + if (bgp->distance_ebgp[afi][safi] != 0 + || bgp->distance_ibgp[afi][safi] != 0 + || bgp->distance_local[afi][safi] != 0) { + bgp->distance_ebgp[afi][safi] = 0; + bgp->distance_ibgp[afi][safi] = 0; + bgp->distance_local[afi][safi] = 0; + bgp_announce_routes_distance_update(bgp, afi, safi); } + return CMD_SUCCESS; +} - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi), prefix_str); - return nb_cli_apply_changes(vty, xpath); +DEFUN (bgp_distance_source, + bgp_distance_source_cmd, + "distance (1-255) A.B.C.D/M", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + bgp_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } -void cli_show_bgp_global_afi_safi_unicast_admin_distance_route( - struct vty *vty, struct lyd_node *dnode, bool show_defaults) +DEFUN (no_bgp_distance_source, + no_bgp_distance_source_cmd, + "no distance (1-255) A.B.C.D/M", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") { - vty_out(vty, " distance %d %s %s\n", - yang_dnode_get_uint8(dnode, "./distance"), - yang_dnode_get_string(dnode, "./prefix"), - (yang_dnode_exists(dnode, "./access-list-policy-export")) - ? yang_dnode_get_string(dnode, - "./access-list-policy-export") - : ""); + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + bgp_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, NULL); + return CMD_SUCCESS; } -DEFPY_YANG( - bgp_dampening, bgp_dampening_cmd, - "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]", - NO_STR - "BGP Specific commands\n" - "Enable route-flap dampening\n" - "Half-life time for the penalty\n" - "Value to start reusing a route\n" - "Value to start suppressing a route\n" - "Maximum duration to suppress a stable route\n") +DEFUN (bgp_distance_source_access_list, + bgp_distance_source_access_list_cmd, + "distance (1-255) A.B.C.D/M WORD", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") { - afi_t afi; - safi_t safi; - char xpath[XPATH_MAXLEN]; + int idx_number = 1; + int idx_ipv4_prefixlen = 2; + int idx_word = 3; + bgp_distance_set(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; +} - afi = bgp_node_afi(vty); - safi = bgp_node_safi(vty); +DEFUN (no_bgp_distance_source_access_list, + no_bgp_distance_source_access_list_cmd, + "no distance (1-255) A.B.C.D/M WORD", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + int idx_number = 2; + int idx_ipv4_prefixlen = 3; + int idx_word = 4; + bgp_distance_unset(vty, argv[idx_number]->arg, + argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg); + return CMD_SUCCESS; +} - if (!no) { - nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true"); - if (argc == 6) { - nb_cli_enqueue_change(vty, "./reach-decay", - NB_OP_MODIFY, halflife_str); - nb_cli_enqueue_change(vty, "./reuse-above", - NB_OP_MODIFY, reuse_str); - nb_cli_enqueue_change(vty, "./suppress-above", - NB_OP_MODIFY, suppress_str); - nb_cli_enqueue_change(vty, "./unreach-decay", - NB_OP_MODIFY, max_suppress_str); - } if (argc == 3) { - nb_cli_enqueue_change(vty, "./reach-decay", - NB_OP_MODIFY, halflife_str); - } - } else { - nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false"); - } +DEFUN (ipv6_bgp_distance_source, + ipv6_bgp_distance_source_cmd, + "distance (1-255) X:X::X:X/M", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL); + return CMD_SUCCESS; +} - snprintf( - xpath, sizeof(xpath), - "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening", - yang_afi_safi_value2identity(afi, safi), - bgp_afi_safi_get_container_str(afi, safi)); +DEFUN (no_ipv6_bgp_distance_source, + no_ipv6_bgp_distance_source_cmd, + "no distance (1-255) X:X::X:X/M", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL); + return CMD_SUCCESS; +} - return nb_cli_apply_changes(vty, xpath); +DEFUN (ipv6_bgp_distance_source_access_list, + ipv6_bgp_distance_source_access_list_cmd, + "distance (1-255) X:X::X:X/M WORD", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg); + return CMD_SUCCESS; } -void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty, - struct lyd_node *dnode, - bool show_defaults) +DEFUN (no_ipv6_bgp_distance_source_access_list, + no_ipv6_bgp_distance_source_access_list_cmd, + "no distance (1-255) X:X::X:X/M WORD", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") { - if (!yang_dnode_get_bool(dnode, "./enable")) - return; + bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg); + return CMD_SUCCESS; +} +DEFUN (bgp_damp_set, + bgp_damp_set_cmd, + "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]", + "BGP Specific commands\n" + "Enable route-flap dampening\n" + "Half-life time for the penalty\n" + "Value to start reusing a route\n" + "Value to start suppressing a route\n" + "Maximum duration to suppress a stable route\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + int idx_half_life = 2; + int idx_reuse = 3; + int idx_suppress = 4; + int idx_max_suppress = 5; int half = DEFAULT_HALF_LIFE * 60; int reuse = DEFAULT_REUSE; int suppress = DEFAULT_SUPPRESS; - int max; - - half = yang_dnode_get_uint8(dnode, "../reach-decay"); - reuse = yang_dnode_get_uint16(dnode, "../reuse-above"); - suppress = yang_dnode_get_uint16(dnode, "../suppress-above"); - max = yang_dnode_get_uint8(dnode, "../unreach-decay"); - - if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE - && suppress == DEFAULT_SUPPRESS && max == half * 4) - vty_out(vty, " bgp dampening\n"); - else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE - && suppress == DEFAULT_SUPPRESS && max == half * 4) - vty_out(vty, " bgp dampening %u\n", half); - else - vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse, - suppress, max); + int max = 4 * half; + + if (argc == 6) { + half = atoi(argv[idx_half_life]->arg) * 60; + reuse = atoi(argv[idx_reuse]->arg); + suppress = atoi(argv[idx_suppress]->arg); + max = atoi(argv[idx_max_suppress]->arg) * 60; + } else if (argc == 3) { + half = atoi(argv[idx_half_life]->arg) * 60; + max = 4 * half; + } + + /* + * These can't be 0 but our SA doesn't understand the + * way our cli is constructed + */ + assert(reuse); + assert(half); + if (suppress < reuse) { + vty_out(vty, + "Suppress value cannot be less than reuse value \n"); + return 0; + } + + return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half, + reuse, suppress, max); +} + +DEFUN (bgp_damp_unset, + bgp_damp_unset_cmd, + "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]", + NO_STR + "BGP Specific commands\n" + "Enable route-flap dampening\n" + "Half-life time for the penalty\n" + "Value to start reusing a route\n" + "Value to start suppressing a route\n" + "Maximum duration to suppress a stable route\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty)); } /* Display specified route of BGP table. */ @@ -14758,7 +14632,8 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, table = bgp_dest_get_bgp_table_info(dest); if (!table) continue; - if ((rm = bgp_node_match(table, &match)) == NULL) + rm = bgp_node_match(table, &match); + if (rm == NULL) continue; const struct prefix *rm_p = bgp_dest_get_prefix(dest); @@ -14770,8 +14645,7 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; bgp_damp_info_free( - &pi->extra->damp_info, - &bgp->damp[afi][safi], + pi->extra->damp_info, 1, afi, safi); pi = pi_temp; } else @@ -14782,8 +14656,8 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, bgp_dest_unlock_node(rm); } } else { - if ((dest = bgp_node_match(bgp->rib[afi][safi], &match)) - != NULL) { + dest = bgp_node_match(bgp->rib[afi][safi], &match); + if (dest != NULL) { const struct prefix *dest_p = bgp_dest_get_prefix(dest); if (!prefix_check @@ -14792,24 +14666,8 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, while (pi) { if (pi->extra && pi->extra->damp_info) { pi_temp = pi->next; - struct bgp_damp_info *bdi = - pi->extra->damp_info; - if (bdi->lastrecord - == BGP_RECORD_UPDATE) { - bgp_aggregate_increment( - bgp, - &bdi->dest->p, - bdi->path, - bdi->afi, - bdi->safi); - bgp_process(bgp, - bdi->dest, - bdi->afi, - bdi->safi); - } bgp_damp_info_free( - &pi->extra->damp_info, - &bgp->damp[afi][safi], + pi->extra->damp_info, 1, afi, safi); pi = pi_temp; } else @@ -14832,9 +14690,7 @@ DEFUN (clear_ip_bgp_dampening, BGP_STR "Clear route flap dampening information\n") { - VTY_DECLVAR_CONTEXT(bgp, bgp); - bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP, - SAFI_UNICAST); + bgp_damp_info_clean(AFI_IP, SAFI_UNICAST); return CMD_SUCCESS; } @@ -15254,27 +15110,54 @@ void bgp_route_init(void) install_element(BGP_NODE, &bgp_distance_cmd); install_element(BGP_NODE, &no_bgp_distance_cmd); install_element(BGP_NODE, &bgp_distance_source_cmd); + install_element(BGP_NODE, &no_bgp_distance_source_cmd); + install_element(BGP_NODE, &bgp_distance_source_access_list_cmd); + install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd); install_element(BGP_IPV4_NODE, &bgp_distance_cmd); install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd); install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd); + install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); + install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); install_element(BGP_IPV4M_NODE, &bgp_distance_cmd); install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd); install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd); + install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); + install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); + install_element(BGP_IPV4M_NODE, + &no_bgp_distance_source_access_list_cmd); install_element(BGP_IPV6_NODE, &bgp_distance_cmd); install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd); - install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd); + install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6_NODE, + &ipv6_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV6_NODE, + &no_ipv6_bgp_distance_source_access_list_cmd); install_element(BGP_IPV6M_NODE, &bgp_distance_cmd); install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd); - install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd); + install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element(BGP_IPV6M_NODE, + &ipv6_bgp_distance_source_access_list_cmd); + install_element(BGP_IPV6M_NODE, + &no_ipv6_bgp_distance_source_access_list_cmd); /* BGP dampening */ - install_element(BGP_NODE, &bgp_dampening_cmd); - install_element(BGP_IPV4_NODE, &bgp_dampening_cmd); - install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd); - install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd); - install_element(BGP_IPV6_NODE, &bgp_dampening_cmd); - install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd); - install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd); + install_element(BGP_NODE, &bgp_damp_set_cmd); + install_element(BGP_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd); + install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd); + install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd); /* Large Communities */ install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd); |
