diff options
Diffstat (limited to 'bgpd/bgp_vty.c')
| -rw-r--r-- | bgpd/bgp_vty.c | 890 |
1 files changed, 545 insertions, 345 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index b77c4b2297..f8ef5e2aa2 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -119,10 +119,15 @@ FRR_CFG_DEFAULT_BOOL(BGP_EBGP_REQUIRES_POLICY, { .val_bool = false, .match_version = "< 7.4", }, { .val_bool = true }, ) +FRR_CFG_DEFAULT_BOOL(BGP_SUPPRESS_DUPLICATES, + { .val_bool = false, .match_version = "< 7.6", }, + { .val_bool = true }, +) DEFINE_HOOK(bgp_inst_config_write, (struct bgp *bgp, struct vty *vty), (bgp, vty)) +DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp)) #define GR_NO_OPER \ "The Graceful Restart No Operation was executed as cmd same as previous one." @@ -209,34 +214,38 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi) static const char *get_afi_safi_vty_str(afi_t afi, safi_t safi) { - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "IPv4 Unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "IPv4 Multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "IPv4 Labeled Unicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "IPv4 VPN"; - else if (afi == AFI_IP && safi == SAFI_ENCAP) - return "IPv4 Encap"; - else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) - return "IPv4 Flowspec"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "IPv6 Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "IPv6 Multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "IPv6 Labeled Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "IPv6 VPN"; - else if (afi == AFI_IP6 && safi == SAFI_ENCAP) - return "IPv6 Encap"; - else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) - return "IPv6 Flowspec"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "L2VPN EVPN"; - else - return "Unknown"; + if (afi == AFI_IP) { + if (safi == SAFI_UNICAST) + return "IPv4 Unicast"; + if (safi == SAFI_MULTICAST) + return "IPv4 Multicast"; + if (safi == SAFI_LABELED_UNICAST) + return "IPv4 Labeled Unicast"; + if (safi == SAFI_MPLS_VPN) + return "IPv4 VPN"; + if (safi == SAFI_ENCAP) + return "IPv4 Encap"; + if (safi == SAFI_FLOWSPEC) + return "IPv4 Flowspec"; + } else if (afi == AFI_IP6) { + if (safi == SAFI_UNICAST) + return "IPv6 Unicast"; + if (safi == SAFI_MULTICAST) + return "IPv6 Multicast"; + if (safi == SAFI_LABELED_UNICAST) + return "IPv6 Labeled Unicast"; + if (safi == SAFI_MPLS_VPN) + return "IPv6 VPN"; + if (safi == SAFI_ENCAP) + return "IPv6 Encap"; + if (safi == SAFI_FLOWSPEC) + return "IPv6 Flowspec"; + } else if (afi == AFI_L2VPN) { + if (safi == SAFI_EVPN) + return "L2VPN EVPN"; + } + + return "Unknown"; } /* @@ -247,34 +256,38 @@ static const char *get_afi_safi_vty_str(afi_t afi, safi_t safi) */ static const char *get_afi_safi_json_str(afi_t afi, safi_t safi) { - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "ipv4Unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "ipv4Multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "ipv4LabeledUnicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "ipv4Vpn"; - else if (afi == AFI_IP && safi == SAFI_ENCAP) - return "ipv4Encap"; - else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) - return "ipv4Flowspec"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "ipv6Unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "ipv6Multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "ipv6LabeledUnicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "ipv6Vpn"; - else if (afi == AFI_IP6 && safi == SAFI_ENCAP) - return "ipv6Encap"; - else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) - return "ipv6Flowspec"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "l2VpnEvpn"; - else - return "Unknown"; + if (afi == AFI_IP) { + if (safi == SAFI_UNICAST) + return "ipv4Unicast"; + if (safi == SAFI_MULTICAST) + return "ipv4Multicast"; + if (safi == SAFI_LABELED_UNICAST) + return "ipv4LabeledUnicast"; + if (safi == SAFI_MPLS_VPN) + return "ipv4Vpn"; + if (safi == SAFI_ENCAP) + return "ipv4Encap"; + if (safi == SAFI_FLOWSPEC) + return "ipv4Flowspec"; + } else if (afi == AFI_IP6) { + if (safi == SAFI_UNICAST) + return "ipv6Unicast"; + if (safi == SAFI_MULTICAST) + return "ipv6Multicast"; + if (safi == SAFI_LABELED_UNICAST) + return "ipv6LabeledUnicast"; + if (safi == SAFI_MPLS_VPN) + return "ipv6Vpn"; + if (safi == SAFI_ENCAP) + return "ipv6Encap"; + if (safi == SAFI_FLOWSPEC) + return "ipv6Flowspec"; + } else if (afi == AFI_L2VPN) { + if (safi == SAFI_EVPN) + return "l2VpnEvpn"; + } + + return "Unknown"; } /* return string maps to afi-safi specific container names @@ -282,30 +295,34 @@ static const char *get_afi_safi_json_str(afi_t afi, safi_t safi) */ const char *bgp_afi_safi_get_container_str(afi_t afi, safi_t safi) { - if (afi == AFI_IP && safi == SAFI_UNICAST) - return "ipv4-unicast"; - else if (afi == AFI_IP && safi == SAFI_MULTICAST) - return "ipv4-multicast"; - else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) - return "ipv4-labeled-unicast"; - else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "l3vpn-ipv4-unicast"; - else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) - return "ipv4-flowspec"; - else if (afi == AFI_IP6 && safi == SAFI_UNICAST) - return "ipv6-unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) - return "ipv6-multicast"; - else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) - return "ipv6-labeled-unicast"; - else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) - return "l3vpn-ipv6-unicast"; - else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) - return "ipv6-flowspec"; - else if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return "l2vpn-evpn"; - else - return "Unknown"; + if (afi == AFI_IP) { + if (safi == SAFI_UNICAST) + return "ipv4-unicast"; + if (safi == SAFI_MULTICAST) + return "ipv4-multicast"; + if (safi == SAFI_LABELED_UNICAST) + return "ipv4-labeled-unicast"; + if (safi == SAFI_MPLS_VPN) + return "l3vpn-ipv4-unicast"; + if (safi == SAFI_FLOWSPEC) + return "ipv4-flowspec"; + } else if (afi == AFI_IP6) { + if (safi == SAFI_UNICAST) + return "ipv6-unicast"; + if (safi == SAFI_MULTICAST) + return "ipv6-multicast"; + if (safi == SAFI_LABELED_UNICAST) + return "ipv6-labeled-unicast"; + if (safi == SAFI_MPLS_VPN) + return "l3vpn-ipv6-unicast"; + if (safi == SAFI_FLOWSPEC) + return "ipv6-flowspec"; + } else if (afi == AFI_L2VPN) { + if (safi == SAFI_EVPN) + return "l2vpn-evpn"; + } + + return "Unknown"; } /* Utility function to get address family from current node. */ @@ -475,6 +492,8 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name, SET_FLAG((*bgp)->flags, BGP_FLAG_DETERMINISTIC_MED); if (DFLT_BGP_EBGP_REQUIRES_POLICY) SET_FLAG((*bgp)->flags, BGP_FLAG_EBGP_REQUIRES_POLICY); + if (DFLT_BGP_SUPPRESS_DUPLICATES) + SET_FLAG((*bgp)->flags, BGP_FLAG_SUPPRESS_DUPLICATES); ret = BGP_SUCCESS; } @@ -864,6 +883,7 @@ static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi, struct listnode **nnode, enum bgp_clear_type stype) { int ret = 0; + struct peer_af *paf; /* if afi/.safi not specified, spin thru all of them */ if ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC)) { @@ -871,6 +891,11 @@ static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi, safi_t tmp_safi; FOREACH_AFI_SAFI (tmp_afi, tmp_safi) { + paf = peer_af_find(peer, tmp_afi, tmp_safi); + if (paf && paf->subgroup) + SET_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_FORCE_UPDATES); + if (!peer->afc[tmp_afi][tmp_safi]) continue; @@ -889,6 +914,11 @@ static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi, if (!peer->afc[afi][tmp_safi]) continue; + paf = peer_af_find(peer, afi, tmp_safi); + if (paf && paf->subgroup) + SET_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_FORCE_UPDATES); + if (stype == BGP_CLEAR_SOFT_NONE) ret = peer_clear(peer, nnode); else @@ -900,6 +930,11 @@ static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi, if (!peer->afc[afi][safi]) return 1; + paf = peer_af_find(peer, afi, safi); + if (paf && paf->subgroup) + SET_FLAG(paf->subgroup->sflags, + SUBGRP_STATUS_FORCE_UPDATES); + if (stype == BGP_CLEAR_SOFT_NONE) ret = peer_clear(peer, nnode); else @@ -2543,6 +2578,37 @@ DEFUN_YANG(no_bgp_always_compare_med, return nb_cli_apply_changes(vty, NULL); } +DEFUN_YANG(bgp_suppress_duplicates, + bgp_suppress_duplicates_cmd, + "bgp suppress-duplicates", + "BGP specific commands\n" + "Suppress duplicate updates if the route actually not changed\n") +{ + nb_cli_enqueue_change(vty, "./global/suppress-duplicates", + NB_OP_MODIFY, "true"); + return nb_cli_apply_changes(vty, NULL); +} + +DEFUN_YANG(no_bgp_suppress_duplicates, + no_bgp_suppress_duplicates_cmd, + "no bgp suppress-duplicates", + NO_STR + "BGP specific commands\n" + "Suppress duplicate updates if the route actually not changed\n") +{ + nb_cli_enqueue_change(vty, "./global/suppress-duplicates", + NB_OP_MODIFY, "false"); + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_router_bgp_suppress_duplicates(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults) +{ + if (yang_dnode_get_bool(dnode, NULL) != SAVE_BGP_SUPPRESS_DUPLICATES) + vty_out(vty, " bgp suppress-duplicates\n"); +} + DEFUN_YANG(bgp_ebgp_requires_policy, bgp_ebgp_requires_policy_cmd, "bgp ebgp-requires-policy", @@ -4887,27 +4953,63 @@ ALIAS_HIDDEN(no_neighbor_activate, no_neighbor_activate_hidden_cmd, NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Enable the Address Family for this Neighbor\n") -DEFUN_YANG (neighbor_set_peer_group, - neighbor_set_peer_group_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Member of the peer-group\n" - "Peer-group name\n") +DEFUN (neighbor_set_peer_group, + neighbor_set_peer_group_cmd, + "neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Member of the peer-group\n" + "Peer-group name\n") { + VTY_DECLVAR_CONTEXT(bgp, bgp); int idx_peer = 1; int idx_word = 3; - char base_xpath[XPATH_MAXLEN]; + int ret; + as_t as; + union sockunion su; + struct peer *peer; + struct peer_group *group; - if (peer_and_group_lookup_nb(vty, argv[idx_peer]->arg, base_xpath, - sizeof(base_xpath), NULL) - < 0) + ret = str2sockunion(argv[idx_peer]->arg, &su); + if (ret < 0) { + peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg); + if (!peer) { + vty_out(vty, "%% Malformed address or name: %s\n", + argv[idx_peer]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + } else { + if (peer_address_self_check(bgp, &su)) { + vty_out(vty, + "%% Can not configure the local system as neighbor\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Disallow for dynamic neighbor. */ + peer = peer_lookup(bgp, &su); + if (peer && peer_dynamic_neighbor(peer)) { + vty_out(vty, + "%% Operation not allowed on a dynamic neighbor\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + group = peer_group_lookup(bgp, argv[idx_word]->arg); + if (!group) { + vty_out(vty, "%% Configure the peer-group first\n"); return CMD_WARNING_CONFIG_FAILED; + } - nb_cli_enqueue_change(vty, "./peer-group", NB_OP_MODIFY, - argv[idx_word]->arg); + ret = peer_group_bind(bgp, &su, peer, group, &as); - return nb_cli_apply_changes(vty, base_xpath); + if (ret == BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT) { + vty_out(vty, + "%% Peer with AS %u cannot be in this peer-group, members must be all internal or all external\n", + as); + return CMD_WARNING_CONFIG_FAILED; + } + + return bgp_vty_return(vty, ret); } ALIAS_HIDDEN(neighbor_set_peer_group, neighbor_set_peer_group_hidden_cmd, @@ -4918,7 +5020,7 @@ ALIAS_HIDDEN(neighbor_set_peer_group, neighbor_set_peer_group_hidden_cmd, DEFUN_YANG (no_neighbor_set_peer_group, no_neighbor_set_peer_group_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", + "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group [PGNAME]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -4939,7 +5041,7 @@ DEFUN_YANG (no_neighbor_set_peer_group, } ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group PGNAME", + "no neighbor <A.B.C.D|X:X::X:X|WORD> peer-group [PGNAME]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Member of the peer-group\n" "Peer-group name\n") @@ -5463,7 +5565,6 @@ DEFUN_YANG (neighbor_nexthop_self, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5502,7 +5603,6 @@ DEFUN_YANG(neighbor_nexthop_self_force, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5587,7 +5687,6 @@ DEFUN_YANG (no_neighbor_nexthop_self_force, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5745,7 +5844,6 @@ DEFUN_YANG (neighbor_remove_private_as_all, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5785,7 +5883,6 @@ DEFUN_YANG (neighbor_remove_private_as_replace_as, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5826,7 +5923,6 @@ DEFUN_YANG (neighbor_remove_private_as_all_replace_as, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5907,7 +6003,6 @@ DEFUN_YANG (no_neighbor_remove_private_as_all, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5948,7 +6043,6 @@ DEFUN_YANG (no_neighbor_remove_private_as_replace_as, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -5990,7 +6084,6 @@ DEFUN_YANG (no_neighbor_remove_private_as_all_replace_as, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -6280,7 +6373,6 @@ DEFUN_YANG (neighbor_soft_reconfiguration, afi_t afi = bgp_node_afi(vty); safi_t safi = bgp_node_safi(vty); - snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, yang_afi_safi_value2identity(afi, safi)); @@ -7667,69 +7759,44 @@ ALIAS_HIDDEN( "Filter outgoing updates\n") /* Set prefix list to the peer. */ -static int peer_prefix_list_set_vty(struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *name_str, - const char *direct_str) -{ - int ret; - int direct = FILTER_IN; - struct peer *peer; - - peer = peer_and_group_lookup_vty(vty, ip_str); - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - - /* Check filter direction. */ - if (strncmp(direct_str, "i", 1) == 0) - direct = FILTER_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = FILTER_OUT; - - ret = peer_prefix_list_set(peer, afi, safi, direct, name_str); - - return bgp_vty_return(vty, ret); -} - -static int peer_prefix_list_unset_vty(struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *direct_str) +DEFPY_YANG( + neighbor_prefix_list, neighbor_prefix_list_cmd, + "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor_str prefix-list WORD$prefix_str <in|out>$direction", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Filter updates to/from this neighbor\n" + "Name of a prefix list\n" + "Filter incoming updates\n" + "Filter outgoing updates\n") { - int ret; - struct peer *peer; - int direct = FILTER_IN; + char base_xpath[XPATH_MAXLEN]; + char af_xpath[XPATH_MAXLEN]; + char plist_xpath[XPATH_MAXLEN]; + afi_t afi = bgp_node_afi(vty); + safi_t safi = bgp_node_safi(vty); - peer = peer_and_group_lookup_vty(vty, ip_str); - if (!peer) + snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, + yang_afi_safi_value2identity(afi, safi)); + if (peer_and_group_lookup_nb(vty, neighbor_str, base_xpath, + sizeof(base_xpath), af_xpath) + < 0) return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp(direct_str, "i", 1) == 0) - direct = FILTER_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = FILTER_OUT; - - ret = peer_prefix_list_unset(peer, afi, safi, direct); + if (strmatch(direction, "in")) + snprintf(plist_xpath, sizeof(plist_xpath), + "./%s/filter-config/plist-import", + bgp_afi_safi_get_container_str(afi, safi)); + else if (strmatch(direction, "out")) + snprintf(plist_xpath, sizeof(plist_xpath), + "./%s/filter-config/plist-export", + bgp_afi_safi_get_container_str(afi, safi)); - return bgp_vty_return(vty, ret); -} + if (!no) + nb_cli_enqueue_change(vty, plist_xpath, NB_OP_MODIFY, + prefix_str); + else + nb_cli_enqueue_change(vty, plist_xpath, NB_OP_DESTROY, NULL); -DEFUN (neighbor_prefix_list, - neighbor_prefix_list_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "Name of a prefix list\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") -{ - int idx_peer = 1; - int idx_word = 3; - int idx_in_out = 4; - return peer_prefix_list_set_vty( - vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), - argv[idx_word]->arg, argv[idx_in_out]->arg); + return nb_cli_apply_changes(vty, base_xpath); } ALIAS_HIDDEN(neighbor_prefix_list, neighbor_prefix_list_hidden_cmd, @@ -7740,32 +7807,6 @@ ALIAS_HIDDEN(neighbor_prefix_list, neighbor_prefix_list_hidden_cmd, "Filter incoming updates\n" "Filter outgoing updates\n") -DEFUN (no_neighbor_prefix_list, - no_neighbor_prefix_list_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "Name of a prefix list\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") -{ - int idx_peer = 2; - int idx_in_out = 5; - return peer_prefix_list_unset_vty(vty, argv[idx_peer]->arg, - bgp_node_afi(vty), bgp_node_safi(vty), - argv[idx_in_out]->arg); -} - -ALIAS_HIDDEN(no_neighbor_prefix_list, no_neighbor_prefix_list_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> prefix-list WORD <in|out>", - NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 - "Filter updates to/from this neighbor\n" - "Name of a prefix list\n" - "Filter incoming updates\n" - "Filter outgoing updates\n") - static int peer_aslist_set_vty(struct vty *vty, const char *ip_str, afi_t afi, safi_t safi, const char *name_str, const char *direct_str) @@ -7926,106 +7967,54 @@ ALIAS_HIDDEN(neighbor_advertise_map, neighbor_advertise_map_hidden_cmd, "Name of the exist or non exist map\n") /* Set route-map to the peer. */ -static int peer_route_map_set_vty(struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, const char *name_str, - const char *direct_str) -{ - int ret; - struct peer *peer; - int direct = RMAP_IN; - struct route_map *route_map; - - peer = peer_and_group_lookup_vty(vty, ip_str); - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - - /* Check filter direction. */ - if (strncmp(direct_str, "in", 2) == 0) - direct = RMAP_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = RMAP_OUT; - - route_map = route_map_lookup_warn_noexist(vty, name_str); - ret = peer_route_map_set(peer, afi, safi, direct, name_str, route_map); - - return bgp_vty_return(vty, ret); -} - -static int peer_route_map_unset_vty(struct vty *vty, const char *ip_str, - afi_t afi, safi_t safi, - const char *direct_str) +DEFPY_YANG( + neighbor_route_map, neighbor_route_map_cmd, + "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor_str route-map WORD$rmap_str <in|out>$direction", + NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 + "Apply route map to neighbor\n" + "Name of route map\n" + "Apply map to incoming routes\n" + "Apply map to outbound routes\n") { - int ret; - struct peer *peer; - int direct = RMAP_IN; + char base_xpath[XPATH_MAXLEN]; + char af_xpath[XPATH_MAXLEN]; + char rmap_xpath[XPATH_MAXLEN]; + afi_t afi = bgp_node_afi(vty); + safi_t safi = bgp_node_safi(vty); - peer = peer_and_group_lookup_vty(vty, ip_str); - if (!peer) + snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, + yang_afi_safi_value2identity(afi, safi)); + if (peer_and_group_lookup_nb(vty, neighbor_str, base_xpath, + sizeof(base_xpath), af_xpath) + < 0) return CMD_WARNING_CONFIG_FAILED; - /* Check filter direction. */ - if (strncmp(direct_str, "in", 2) == 0) - direct = RMAP_IN; - else if (strncmp(direct_str, "o", 1) == 0) - direct = RMAP_OUT; - - ret = peer_route_map_unset(peer, afi, safi, direct); - - return bgp_vty_return(vty, ret); -} + if (strmatch(direction, "in")) + snprintf(rmap_xpath, sizeof(rmap_xpath), + "./%s/filter-config/rmap-import", + bgp_afi_safi_get_container_str(afi, safi)); + else if (strmatch(direction, "out")) + snprintf(rmap_xpath, sizeof(rmap_xpath), + "./%s/filter-config/rmap-export", + bgp_afi_safi_get_container_str(afi, safi)); -DEFUN (neighbor_route_map, - neighbor_route_map_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> route-map WORD <in|out>", - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Apply route map to neighbor\n" - "Name of route map\n" - "Apply map to incoming routes\n" - "Apply map to outbound routes\n") -{ - int idx_peer = 1; - int idx_word = 3; - int idx_in_out = 4; - return peer_route_map_set_vty( - vty, argv[idx_peer]->arg, bgp_node_afi(vty), bgp_node_safi(vty), - argv[idx_word]->arg, argv[idx_in_out]->arg); -} + if (!no) { + if (!yang_dnode_exists( + vty->candidate_config->dnode, + "/frr-route-map:lib/route-map[name='%s']", + rmap_str)) { + if (vty_shell_serv(vty)) + vty_out(vty, + "The route-map '%s' does not exist.\n", + rmap_str); + } + nb_cli_enqueue_change(vty, rmap_xpath, NB_OP_MODIFY, rmap_str); + } else + nb_cli_enqueue_change(vty, rmap_xpath, NB_OP_DESTROY, NULL); -ALIAS_HIDDEN(neighbor_route_map, neighbor_route_map_hidden_cmd, - "neighbor <A.B.C.D|X:X::X:X|WORD> route-map WORD <in|out>", - NEIGHBOR_STR NEIGHBOR_ADDR_STR2 - "Apply route map to neighbor\n" - "Name of route map\n" - "Apply map to incoming routes\n" - "Apply map to outbound routes\n") - -DEFUN (no_neighbor_route_map, - no_neighbor_route_map_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> route-map WORD <in|out>", - NO_STR - NEIGHBOR_STR - NEIGHBOR_ADDR_STR2 - "Apply route map to neighbor\n" - "Name of route map\n" - "Apply map to incoming routes\n" - "Apply map to outbound routes\n") -{ - int idx_peer = 2; - int idx_in_out = 5; - return peer_route_map_unset_vty(vty, argv[idx_peer]->arg, - bgp_node_afi(vty), bgp_node_safi(vty), - argv[idx_in_out]->arg); + return nb_cli_apply_changes(vty, base_xpath); } -ALIAS_HIDDEN(no_neighbor_route_map, no_neighbor_route_map_hidden_cmd, - "no neighbor <A.B.C.D|X:X::X:X|WORD> route-map WORD <in|out>", - NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 - "Apply route map to neighbor\n" - "Name of route map\n" - "Apply map to incoming routes\n" - "Apply map to outbound routes\n") - /* Set unsuppress-map to the peer. */ static int peer_unsuppress_map_set_vty(struct vty *vty, const char *ip_str, afi_t afi, safi_t safi, @@ -8831,6 +8820,93 @@ DEFPY( return CMD_SUCCESS; } +DEFPY(neighbor_damp, + neighbor_damp_cmd, + "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [(1-45)$half [(1-20000)$reuse (1-20000)$suppress (1-255)$max]]", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Enable neighbor 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") +{ + struct peer *peer = peer_and_group_lookup_vty(vty, neighbor); + + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + if (!half) + half = DEFAULT_HALF_LIFE; + if (!reuse) { + reuse = DEFAULT_REUSE; + suppress = DEFAULT_SUPPRESS; + max = half * 4; + } + if (suppress < reuse) { + vty_out(vty, + "Suppress value cannot be less than reuse value\n"); + return CMD_WARNING_CONFIG_FAILED; + } + bgp_peer_damp_enable(peer, bgp_node_afi(vty), bgp_node_safi(vty), + half * 60, reuse, suppress, max * 60); + return CMD_SUCCESS; +} + +DEFPY(no_neighbor_damp, + no_neighbor_damp_cmd, + "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [HALF [REUSE SUPPRESS MAX]]", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Enable neighbor 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") +{ + struct peer *peer = peer_and_group_lookup_vty(vty, neighbor); + + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + bgp_peer_damp_disable(peer, bgp_node_afi(vty), bgp_node_safi(vty)); + return CMD_SUCCESS; +} + +DEFPY (show_ip_bgp_neighbor_damp_param, + show_ip_bgp_neighbor_damp_param_cmd, + "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD>$neighbor dampening parameters [json]$json", + SHOW_STR + IP_STR + BGP_STR + BGP_AFI_HELP_STR + "Address Family modifier\n" + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Neighbor route-flap dampening information\n" + "Display detail of configured dampening parameters\n" + JSON_STR) +{ + bool use_json = false; + int idx = 0; + afi_t afi = AFI_IP; + safi_t safi = SAFI_UNICAST; + struct peer *peer; + + if (argv_find(argv, argc, "ip", &idx)) + afi = AFI_IP; + if (argv_find(argv, argc, "ipv4", &idx)) + afi = AFI_IP; + if (argv_find(argv, argc, "ipv6", &idx)) + afi = AFI_IP6; + peer = peer_and_group_lookup_vty(vty, neighbor); + if (!peer) + return CMD_WARNING; + if (json) + use_json = true; + bgp_show_peer_dampening_parameters(vty, peer, afi, safi, use_json); + return CMD_SUCCESS; +} + static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv, struct ecommunity **list, bool is_rt6) { @@ -9066,6 +9142,7 @@ DEFPY (af_label_vpn_export, vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(), bgp); + hook_call(bgp_snmp_update_last_changed, bgp); return CMD_SUCCESS; } @@ -10499,11 +10576,29 @@ static void bgp_show_failed_summary(struct vty *vty, struct bgp *bgp, } } +/* If the peer's description includes whitespaces + * then return the first occurrence. Also strip description + * to the given size if needed. + */ +static char *bgp_peer_description_stripped(char *desc, uint32_t size) +{ + static char stripped[BUFSIZ]; + char *pnt; + uint32_t len = size > strlen(desc) ? strlen(desc) : size; + + pnt = strchr(desc, ' '); + if (pnt) + len = size > (uint32_t)(pnt - desc) ? (uint32_t)(pnt - desc) + : size; + + strlcpy(stripped, desc, len + 1); + + return stripped; +} /* Show BGP peer's summary information. */ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, - bool show_failed, bool show_established, - bool use_json) + uint8_t show_flags) { struct peer *peer; struct listnode *node, *nnode; @@ -10519,6 +10614,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object *json_peers = NULL; struct peer_af *paf; struct bgp_filter *filter; + bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); + bool show_failed = CHECK_FLAG(show_flags, BGP_SHOW_OPT_FAILED); + bool show_established = + CHECK_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED); + bool show_wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE); /* labeled-unicast routes are installed in the unicast table so in order * to @@ -10815,10 +10915,13 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, vty_out(vty, "%*s", max_neighbor_width - 8, " "); if (show_failed) - vty_out(vty, "EstdCnt DropCnt ResetTime Reason\n"); + vty_out(vty, + BGP_SHOW_SUMMARY_HEADER_FAILED); else vty_out(vty, - "V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc\n"); + show_wide + ? BGP_SHOW_SUMMARY_HEADER_ALL_WIDE + : BGP_SHOW_SUMMARY_HEADER_ALL); } } @@ -10858,6 +10961,11 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, peer->domainname); json_object_int_add(json_peer, "remoteAs", peer->as); + json_object_int_add( + json_peer, "localAs", + peer->change_local_as + ? peer->change_local_as + : peer->local_as); json_object_int_add(json_peer, "version", 4); json_object_int_add(json_peer, "msgRcvd", PEER_TOTAL_RX(peer)); @@ -11014,14 +11122,33 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, &peer->ibuf->count, memory_order_relaxed); - vty_out(vty, - "4 %10u %9u %9u %8" PRIu64" %4zu %4zu %8s", - peer->as, PEER_TOTAL_RX(peer), - PEER_TOTAL_TX(peer), - peer->version[afi][safi], inq_count, - outq_count, - peer_uptime(peer->uptime, timebuf, - BGP_UPTIME_LEN, 0, NULL)); + if (show_wide) + vty_out(vty, + "4 %10u %10u %9u %9u %8" PRIu64 + " %4zu %4zu %8s", + peer->as, + peer->change_local_as + ? peer->change_local_as + : peer->local_as, + PEER_TOTAL_RX(peer), + PEER_TOTAL_TX(peer), + peer->version[afi][safi], + inq_count, outq_count, + peer_uptime(peer->uptime, + timebuf, + BGP_UPTIME_LEN, 0, + NULL)); + else + vty_out(vty, "4 %10u %9u %9u %8" PRIu64 + " %4zu %4zu %8s", + peer->as, PEER_TOTAL_RX(peer), + PEER_TOTAL_TX(peer), + peer->version[afi][safi], + inq_count, outq_count, + peer_uptime(peer->uptime, + timebuf, + BGP_UPTIME_LEN, 0, + NULL)); if (peer->status == Established) { if (peer->afc_recv[afi][safi]) { @@ -11039,7 +11166,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, [afi] [pfx_rcd_safi]); } else { - vty_out(vty, " NoNeg"); + vty_out(vty, " NoNeg"); } if (paf && PAF_SUBGRP(paf)) { @@ -11056,6 +11183,8 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, (PAF_SUBGRP( paf)) ->scount); + } else { + vty_out(vty, " NoNeg"); } } else { if (CHECK_FLAG(peer->flags, @@ -11075,7 +11204,10 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, vty_out(vty, " %8u", 0); } if (peer->desc) - vty_out(vty, " %s", peer->desc); + vty_out(vty, " %s", + bgp_peer_description_stripped( + peer->desc, + show_wide ? 64 : 20)); else vty_out(vty, " N/A"); vty_out(vty, "\n"); @@ -11115,14 +11247,14 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, } static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, - int safi, bool show_failed, - bool show_established, bool use_json) + int safi, uint8_t show_flags) { int is_first = 1; int afi_wildcard = (afi == AFI_MAX); int safi_wildcard = (safi == SAFI_MAX); int is_wildcard = (afi_wildcard || safi_wildcard); bool nbr_output = false; + bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); if (use_json && is_wildcard) vty_out(vty, "{\n"); @@ -11160,8 +11292,7 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, } } bgp_show_summary(vty, bgp, afi, safi, - show_failed, show_established, - use_json); + show_flags); } safi++; if (!safi_wildcard) @@ -11183,14 +11314,13 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, } static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, - safi_t safi, bool show_failed, - bool show_established, - bool use_json) + safi_t safi, uint8_t show_flags) { struct listnode *node, *nnode; struct bgp *bgp; int is_first = 1; bool nbr_output = false; + bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); if (use_json) vty_out(vty, "{\n"); @@ -11213,8 +11343,7 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, ? VRF_DEFAULT_NAME : bgp->name); } - bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_failed, - show_established, use_json); + bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_flags); } if (use_json) @@ -11224,16 +11353,15 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, } int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, - safi_t safi, bool show_failed, bool show_established, - bool use_json) + safi_t safi, uint8_t show_flags) { struct bgp *bgp; + bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); if (name) { if (strmatch(name, "all")) { - bgp_show_all_instances_summary_vty( - vty, afi, safi, show_failed, show_established, - use_json); + bgp_show_all_instances_summary_vty(vty, afi, safi, + show_flags); return CMD_SUCCESS; } else { bgp = bgp_lookup_by_name(name); @@ -11248,8 +11376,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, } bgp_show_summary_afi_safi(vty, bgp, afi, safi, - show_failed, show_established, - use_json); + show_flags); return CMD_SUCCESS; } } @@ -11257,8 +11384,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, bgp = bgp_get_default(); if (bgp) - bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_failed, - show_established, use_json); + bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_flags); else { if (use_json) vty_out(vty, "{}\n"); @@ -11273,7 +11399,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, /* `show [ip] bgp summary' commands. */ DEFPY (show_ip_bgp_summary, show_ip_bgp_summary_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] summary [established|failed] [json$uj]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] summary [established|failed] [wide] [json$uj]", SHOW_STR IP_STR BGP_STR @@ -11284,13 +11410,13 @@ DEFPY (show_ip_bgp_summary, "Summary of BGP neighbor status\n" "Show only sessions in Established state\n" "Show only sessions not in Established state\n" + "Increase table width for longer output\n" JSON_STR) { char *vrf = NULL; afi_t afi = AFI_MAX; safi_t safi = SAFI_MAX; - bool show_failed = false; - bool show_established = false; + uint8_t show_flags = 0; int idx = 0; @@ -11311,12 +11437,18 @@ DEFPY (show_ip_bgp_summary, } if (argv_find(argv, argc, "failed", &idx)) - show_failed = true; + SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED); + if (argv_find(argv, argc, "established", &idx)) - show_established = true; + SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED); - return bgp_show_summary_vty(vty, vrf, afi, safi, show_failed, - show_established, uj); + if (argv_find(argv, argc, "wide", &idx)) + SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE); + + if (argv_find(argv, argc, "json", &idx)) + SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); + + return bgp_show_summary_vty(vty, vrf, afi, safi, show_flags); } const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json) @@ -13088,6 +13220,37 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, "received"); } + /* Enhanced Route Refresh */ + if (CHECK_FLAG(p->cap, PEER_CAP_ENHANCED_RR_ADV) + || CHECK_FLAG(p->cap, + PEER_CAP_ENHANCED_RR_RCV)) { + if (CHECK_FLAG(p->cap, + PEER_CAP_ENHANCED_RR_ADV) + && CHECK_FLAG( + p->cap, + PEER_CAP_ENHANCED_RR_RCV)) + json_object_string_add( + json_cap, + "enhancedRouteRefresh", + "advertisedAndReceived"); + else if ( + CHECK_FLAG( + p->cap, + PEER_CAP_ENHANCED_RR_ADV)) + json_object_string_add( + json_cap, + "enhancedRouteRefresh", + "advertised"); + else if ( + CHECK_FLAG( + p->cap, + PEER_CAP_ENHANCED_RR_RCV)) + json_object_string_add( + json_cap, + "enhancedRouteRefresh", + "received"); + } + /* Multiprotocol Extensions */ json_object *json_multi = NULL; json_multi = json_object_new_object(); @@ -13460,6 +13623,28 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, vty_out(vty, "\n"); } + /* Enhanced Route Refresh */ + if (CHECK_FLAG(p->cap, PEER_CAP_ENHANCED_RR_ADV) + || CHECK_FLAG(p->cap, + PEER_CAP_ENHANCED_RR_RCV)) { + vty_out(vty, + " Enhanced Route Refresh:"); + if (CHECK_FLAG( + p->cap, + PEER_CAP_ENHANCED_RR_ADV)) + vty_out(vty, " advertised"); + if (CHECK_FLAG( + p->cap, + PEER_CAP_ENHANCED_RR_RCV)) + vty_out(vty, " %sreceived", + CHECK_FLAG( + p->cap, + PEER_CAP_REFRESH_ADV) + ? "and " + : ""); + vty_out(vty, "\n"); + } + /* Multiprotocol Extensions */ FOREACH_AFI_SAFI (afi, safi) if (p->afc_adv[afi][safi] @@ -16882,7 +17067,15 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, /* BGP flag dampening. */ if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) - bgp_config_write_damp(vty, afi, safi); + bgp_config_write_damp(vty, bgp, afi, safi); + for (ALL_LIST_ELEMENTS_RO(bgp->group, node, group)) + if (peer_af_flag_check(group->conf, afi, safi, + PEER_FLAG_CONFIG_DAMPENING)) + bgp_config_write_peer_damp(vty, group->conf, afi, safi); + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) + if (peer_af_flag_check(peer, afi, safi, + PEER_FLAG_CONFIG_DAMPENING)) + bgp_config_write_peer_damp(vty, peer, afi, safi); for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi); @@ -17019,6 +17212,16 @@ int bgp_config_write(struct vty *vty) if (bgp->reject_as_sets) vty_out(vty, " bgp reject-as-sets\n"); + /* Suppress duplicate updates if the route actually not changed + */ + if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES) + != SAVE_BGP_SUPPRESS_DUPLICATES) + vty_out(vty, " %sbgp suppress-duplicates\n", + CHECK_FLAG(bgp->flags, + BGP_FLAG_SUPPRESS_DUPLICATES) + ? "" + : "no "); + /* BGP default ipv4-unicast. */ if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4)) vty_out(vty, " no bgp default ipv4-unicast\n"); @@ -17602,6 +17805,10 @@ void bgp_vty_init(void) install_element(BGP_NODE, &bgp_ebgp_requires_policy_cmd); install_element(BGP_NODE, &no_bgp_ebgp_requires_policy_cmd); + /* bgp suppress-duplicates */ + install_element(BGP_NODE, &bgp_suppress_duplicates_cmd); + install_element(BGP_NODE, &no_bgp_suppress_duplicates_cmd); + /* bgp reject-as-sets */ install_element(BGP_NODE, &bgp_reject_as_sets_cmd); install_element(BGP_NODE, &no_bgp_reject_as_sets_cmd); @@ -18404,27 +18611,16 @@ void bgp_vty_init(void) /* "neighbor prefix-list" commands. */ install_element(BGP_NODE, &neighbor_prefix_list_hidden_cmd); - install_element(BGP_NODE, &no_neighbor_prefix_list_hidden_cmd); install_element(BGP_IPV4_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_IPV4_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_IPV4M_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_IPV4M_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_IPV4L_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_IPV4L_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_IPV6_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_IPV6_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_IPV6M_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_IPV6M_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_IPV6L_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_IPV6L_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_VPNV4_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_VPNV6_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_VPNV6_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_FLOWSPECV4_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_FLOWSPECV6_NODE, &neighbor_prefix_list_cmd); - install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_prefix_list_cmd); /* "neighbor filter-list" commands. */ install_element(BGP_NODE, &neighbor_filter_list_hidden_cmd); @@ -18451,30 +18647,17 @@ void bgp_vty_init(void) install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_filter_list_cmd); /* "neighbor route-map" commands. */ - install_element(BGP_NODE, &neighbor_route_map_hidden_cmd); - install_element(BGP_NODE, &no_neighbor_route_map_hidden_cmd); install_element(BGP_IPV4_NODE, &neighbor_route_map_cmd); - install_element(BGP_IPV4_NODE, &no_neighbor_route_map_cmd); install_element(BGP_IPV4M_NODE, &neighbor_route_map_cmd); - install_element(BGP_IPV4M_NODE, &no_neighbor_route_map_cmd); install_element(BGP_IPV4L_NODE, &neighbor_route_map_cmd); - install_element(BGP_IPV4L_NODE, &no_neighbor_route_map_cmd); install_element(BGP_IPV6_NODE, &neighbor_route_map_cmd); - install_element(BGP_IPV6_NODE, &no_neighbor_route_map_cmd); install_element(BGP_IPV6M_NODE, &neighbor_route_map_cmd); - install_element(BGP_IPV6M_NODE, &no_neighbor_route_map_cmd); install_element(BGP_IPV6L_NODE, &neighbor_route_map_cmd); - install_element(BGP_IPV6L_NODE, &no_neighbor_route_map_cmd); install_element(BGP_VPNV4_NODE, &neighbor_route_map_cmd); - install_element(BGP_VPNV4_NODE, &no_neighbor_route_map_cmd); install_element(BGP_VPNV6_NODE, &neighbor_route_map_cmd); - install_element(BGP_VPNV6_NODE, &no_neighbor_route_map_cmd); install_element(BGP_FLOWSPECV4_NODE, &neighbor_route_map_cmd); - install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_route_map_cmd); install_element(BGP_FLOWSPECV6_NODE, &neighbor_route_map_cmd); - install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_route_map_cmd); install_element(BGP_EVPN_NODE, &neighbor_route_map_cmd); - install_element(BGP_EVPN_NODE, &no_neighbor_route_map_cmd); /* "neighbor unsuppress-map" commands. */ install_element(BGP_NODE, &neighbor_unsuppress_map_hidden_cmd); @@ -18633,6 +18816,23 @@ void bgp_vty_init(void) install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd); install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd); + /* "neighbor dampening" commands. */ + install_element(BGP_NODE, &neighbor_damp_cmd); + install_element(BGP_NODE, &no_neighbor_damp_cmd); + install_element(BGP_IPV4_NODE, &neighbor_damp_cmd); + install_element(BGP_IPV4_NODE, &no_neighbor_damp_cmd); + install_element(BGP_IPV4M_NODE, &neighbor_damp_cmd); + install_element(BGP_IPV4M_NODE, &no_neighbor_damp_cmd); + install_element(BGP_IPV4L_NODE, &neighbor_damp_cmd); + install_element(BGP_IPV4L_NODE, &no_neighbor_damp_cmd); + install_element(BGP_IPV6_NODE, &neighbor_damp_cmd); + install_element(BGP_IPV6_NODE, &no_neighbor_damp_cmd); + install_element(BGP_IPV6M_NODE, &neighbor_damp_cmd); + install_element(BGP_IPV6M_NODE, &no_neighbor_damp_cmd); + install_element(BGP_IPV6L_NODE, &neighbor_damp_cmd); + install_element(BGP_IPV6L_NODE, &no_neighbor_damp_cmd); + install_element(VIEW_NODE, &show_ip_bgp_neighbor_damp_param_cmd); + /* address-family commands. */ install_element(BGP_NODE, &address_family_ipv4_safi_cmd); install_element(BGP_NODE, &address_family_ipv6_safi_cmd); |
