]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_vty.c
*: Rename thread.[ch] to event.[ch]
[mirror_frr.git] / bgpd / bgp_vty.c
index 0ea636764afcd020b6ee7d1c30503179eab9b318..3bc64c34991486945d164f22059729057357ada7 100644 (file)
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /* BGP VTY interface.
  * Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
@@ -31,7 +16,7 @@
 #include "buffer.h"
 #include "linklist.h"
 #include "stream.h"
-#include "thread.h"
+#include "event.h"
 #include "log.h"
 #include "memory.h"
 #include "lib_vty.h"
@@ -5661,8 +5646,32 @@ DEFUN (no_neighbor_capability_enhe,
                                   PEER_FLAG_CAPABILITY_ENHE);
 }
 
+/* neighbor capability software-version */
+DEFPY(neighbor_capability_software_version,
+      neighbor_capability_software_version_cmd,
+      "[no$no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor capability software-version",
+      NO_STR
+      NEIGHBOR_STR
+      NEIGHBOR_ADDR_STR2
+      "Advertise capability to the peer\n"
+      "Advertise Software Version capability to the peer\n")
+{
+       struct peer *peer;
+
+       peer = peer_and_group_lookup_vty(vty, neighbor);
+       if (peer && peer->conf_if)
+               return CMD_SUCCESS;
+
+       if (no)
+               return peer_flag_unset_vty(vty, neighbor,
+                                          PEER_FLAG_CAPABILITY_SOFT_VERSION);
+       else
+               return peer_flag_set_vty(vty, neighbor,
+                                        PEER_FLAG_CAPABILITY_SOFT_VERSION);
+}
+
 static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str,
-                                  afi_t afi, safi_t safi, uint32_t flag,
+                                  afi_t afi, safi_t safi, uint64_t flag,
                                   int set)
 {
        int ret;
@@ -5681,13 +5690,13 @@ static int peer_af_flag_modify_vty(struct vty *vty, const char *peer_str,
 }
 
 static int peer_af_flag_set_vty(struct vty *vty, const char *peer_str,
-                               afi_t afi, safi_t safi, uint32_t flag)
+                               afi_t afi, safi_t safi, uint64_t flag)
 {
        return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 1);
 }
 
 static int peer_af_flag_unset_vty(struct vty *vty, const char *peer_str,
-                                 afi_t afi, safi_t safi, uint32_t flag)
+                                 afi_t afi, safi_t safi, uint64_t flag)
 {
        return peer_af_flag_modify_vty(vty, peer_str, afi, safi, flag, 0);
 }
@@ -8884,7 +8893,7 @@ DEFPY(neighbor_path_attribute_discard,
 {
        struct peer *peer;
        int idx = 0;
-       const char *discard_attrs = NULL;
+       char *discard_attrs = NULL;
 
        peer = peer_and_group_lookup_vty(vty, neighbor);
        if (!peer)
@@ -8896,6 +8905,8 @@ DEFPY(neighbor_path_attribute_discard,
 
        bgp_path_attribute_discard_vty(vty, peer, discard_attrs, true);
 
+       XFREE(MTYPE_TMP, discard_attrs);
+
        return CMD_SUCCESS;
 }
 
@@ -8911,7 +8922,7 @@ DEFPY(no_neighbor_path_attribute_discard,
 {
        struct peer *peer;
        int idx = 0;
-       const char *discard_attrs = NULL;
+       char *discard_attrs = NULL;
 
        peer = peer_and_group_lookup_vty(vty, neighbor);
        if (!peer)
@@ -8923,6 +8934,65 @@ DEFPY(no_neighbor_path_attribute_discard,
 
        bgp_path_attribute_discard_vty(vty, peer, discard_attrs, false);
 
+       XFREE(MTYPE_TMP, discard_attrs);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(neighbor_path_attribute_treat_as_withdraw,
+      neighbor_path_attribute_treat_as_withdraw_cmd,
+      "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute treat-as-withdraw (1-255)...",
+      NEIGHBOR_STR
+      NEIGHBOR_ADDR_STR2
+      "Manipulate path attributes from incoming UPDATE messages\n"
+      "Treat-as-withdraw any incoming BGP UPDATE messages that contain the specified attribute\n"
+      "Attribute number\n")
+{
+       struct peer *peer;
+       int idx = 0;
+       char *withdraw_attrs = NULL;
+
+       peer = peer_and_group_lookup_vty(vty, neighbor);
+       if (!peer)
+               return CMD_WARNING_CONFIG_FAILED;
+
+       argv_find(argv, argc, "(1-255)", &idx);
+       if (idx)
+               withdraw_attrs = argv_concat(argv, argc, idx);
+
+       bgp_path_attribute_withdraw_vty(vty, peer, withdraw_attrs, true);
+
+       XFREE(MTYPE_TMP, withdraw_attrs);
+
+       return CMD_SUCCESS;
+}
+
+DEFPY(no_neighbor_path_attribute_treat_as_withdraw,
+      no_neighbor_path_attribute_treat_as_withdraw_cmd,
+      "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor path-attribute treat-as-withdraw (1-255)...",
+      NO_STR
+      NEIGHBOR_STR
+      NEIGHBOR_ADDR_STR2
+      "Manipulate path attributes from incoming UPDATE messages\n"
+      "Treat-as-withdraw any incoming BGP UPDATE messages that contain the specified attribute\n"
+      "Attribute number\n")
+{
+       struct peer *peer;
+       int idx = 0;
+       char *withdraw_attrs = NULL;
+
+       peer = peer_and_group_lookup_vty(vty, neighbor);
+       if (!peer)
+               return CMD_WARNING_CONFIG_FAILED;
+
+       argv_find(argv, argc, "(1-255)", &idx);
+       if (idx)
+               withdraw_attrs = argv_concat(argv, argc, idx);
+
+       bgp_path_attribute_withdraw_vty(vty, peer, withdraw_attrs, false);
+
+       XFREE(MTYPE_TMP, withdraw_attrs);
+
        return CMD_SUCCESS;
 }
 
@@ -9044,10 +9114,13 @@ DEFPY (af_rd_vpn_export,
                           bgp_get_default(), bgp);
 
        if (yes) {
+               bgp->vpn_policy[afi].tovpn_rd_pretty =
+                       XSTRDUP(MTYPE_BGP, rd_str);
                bgp->vpn_policy[afi].tovpn_rd = prd;
                SET_FLAG(bgp->vpn_policy[afi].flags,
                         BGP_VPN_POLICY_TOVPN_RD_SET);
        } else {
+               XFREE(MTYPE_BGP, bgp->vpn_policy[afi].tovpn_rd_pretty);
                UNSET_FLAG(bgp->vpn_policy[afi].flags,
                           BGP_VPN_POLICY_TOVPN_RD_SET);
        }
@@ -10868,6 +10941,9 @@ static void bgp_show_peer_reset(struct vty * vty, struct peer *peer,
                                       peer_down_str[(int)peer->last_reset]);
                json_object_int_add(json_peer, "lastResetCode",
                                    peer->last_reset);
+               json_object_string_add(json_peer, "softwareVersion",
+                                      peer->soft_version ? peer->soft_version
+                                                         : "n/a");
        } else {
                if (peer->last_reset == PEER_DOWN_NOTIFY_SEND
                    || peer->last_reset == PEER_DOWN_NOTIFY_RECEIVED) {
@@ -10886,8 +10962,10 @@ static void bgp_show_peer_reset(struct vty * vty, struct peer *peer,
                                                  BGP_NOTIFY_CEASE_HARD_RESET)
                                        : "");
                } else {
-                       vty_out(vty, " %s\n",
-                               peer_down_str[(int)peer->last_reset]);
+                       vty_out(vty, "  %s (%s)\n",
+                               peer_down_str[(int)peer->last_reset],
+                               peer->soft_version ? peer->soft_version
+                                                  : "n/a");
                }
        }
 }
@@ -11598,37 +11676,22 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
                                vty_out(vty, "4 ");
                                vty_out(vty, ASN_FORMAT_SPACE(bgp->asnotation),
                                        &peer->as);
-                               if (show_wide) {
+                               if (show_wide)
                                        vty_out(vty,
                                                ASN_FORMAT_SPACE(
                                                        bgp->asnotation),
                                                peer->change_local_as
                                                        ? &peer->change_local_as
                                                        : &peer->local_as);
-                                       vty_out(vty,
-                                               " %9u %9u %8" PRIu64
-                                               " %4zu %4zu %8s",
-                                               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,
-                                               " %9u %9u %8" PRIu64
-                                               " %4zu %4zu %8s",
-                                               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));
-                               }
+                               vty_out(vty,
+                                       " %9u %9u %8" PRIu64 " %4zu %4zu %8s",
+                                       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_established(peer)) {
                                        if (peer->afc_recv[afi][safi]) {
                                                if (CHECK_FLAG(
@@ -13905,6 +13968,27 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
                        json_object_object_add(json_cap, "hostName",
                                               json_hname);
 
+                       /* Software Version capability */
+                       json_object *json_soft_version = NULL;
+
+                       json_soft_version = json_object_new_object();
+
+                       if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_ADV))
+                               json_object_string_add(
+                                       json_soft_version,
+                                       "advertisedSoftwareVersion",
+                                       cmd_software_version_get());
+
+                       if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_RCV))
+                               json_object_string_add(
+                                       json_soft_version,
+                                       "receivedSoftwareVersion",
+                                       p->soft_version ? p->soft_version
+                                                       : "n/a");
+
+                       json_object_object_add(json_cap, "softwareVersion",
+                                              json_soft_version);
+
                        /* Graceful Restart */
                        if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) ||
                            CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)) {
@@ -14280,6 +14364,25 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
 
                        vty_out(vty, "\n");
 
+                       /* Software Version capability */
+                       vty_out(vty, "    Version Capability:");
+
+                       if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_ADV)) {
+                               vty_out(vty,
+                                       " advertised software version (%s)",
+                                       cmd_software_version_get());
+                       } else
+                               vty_out(vty, " not advertised");
+
+                       if (CHECK_FLAG(p->cap, PEER_CAP_SOFT_VERSION_RCV)) {
+                               vty_out(vty, " received software version (%s)",
+                                       p->soft_version ? p->soft_version
+                                                       : "n/a");
+                       } else
+                               vty_out(vty, " not received");
+
+                       vty_out(vty, "\n");
+
                        /* Graceful Restart */
                        if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV) ||
                            CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)) {
@@ -15576,10 +15679,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
                                                json_object_new_string(vname));
                        json_object_object_add(json, "exportToVrfs",
                                               json_export_vrfs);
-                       json_object_string_addf(json, "routeDistinguisher",
-                                               "%pRD",
-                                               &bgp->vpn_policy[afi].tovpn_rd);
-
+                       json_object_string_addf(
+                               json, "routeDistinguisher", "%s",
+                               bgp->vpn_policy[afi].tovpn_rd_pretty);
                        dir = BGP_VPN_POLICY_DIR_TOVPN;
                        if (bgp->vpn_policy[afi].rtlist[dir]) {
                                ecom_str = ecommunity_ecom2str(
@@ -17026,7 +17128,7 @@ static void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp,
 
 /* peer-group helpers for config-write */
 
-static bool peergroup_flag_check(struct peer *peer, uint64_t flag)
+bool peergroup_flag_check(struct peer *peer, uint64_t flag)
 {
        if (!peer_group_active(peer)) {
                if (CHECK_FLAG(peer->flags_invert, flag))
@@ -17045,7 +17147,7 @@ static bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
                if (CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
                        return !peer_af_flag_check(peer, afi, safi, flag);
                else
-                       return !!peer_af_flag_check(peer, afi, safi, flag);
+                       return peer_af_flag_check(peer, afi, safi, flag);
        }
 
        return !!CHECK_FLAG(peer->af_flags_override[afi][safi], flag);
@@ -17153,8 +17255,8 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
        }
 
        if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET))
-               vty_out(vty, "%*srd vpn export %pRD\n", indent, "",
-                       &bgp->vpn_policy[afi].tovpn_rd);
+               vty_out(vty, "%*srd vpn export %s\n", indent, "",
+                       bgp->vpn_policy[afi].tovpn_rd_pretty);
 
        if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
                       BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
@@ -17566,6 +17668,11 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
                                addr);
        }
 
+       /* capability software-version */
+       if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION))
+               vty_out(vty, " neighbor %s capability software-version\n",
+                       addr);
+
        /* dont-capability-negotiation */
        if (peergroup_flag_check(peer, PEER_FLAG_DONT_CAPABILITY))
                vty_out(vty, " neighbor %s dont-capability-negotiate\n", addr);
@@ -17592,6 +17699,16 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
                vty_out(vty, " neighbor %s path-attribute discard %s\n", addr,
                        discard_attrs_str);
 
+       /* path-attribute treat-as-withdraw */
+       char withdraw_attrs_str[BUFSIZ] = {0};
+       bool withdraw_attrs = bgp_path_attribute_treat_as_withdraw(
+               peer, withdraw_attrs_str, sizeof(withdraw_attrs_str));
+
+       if (withdraw_attrs)
+               vty_out(vty,
+                       " neighbor %s path-attribute treat-as-withdraw %s\n",
+                       addr, withdraw_attrs_str);
+
        if (!CHECK_FLAG(peer->peer_gr_new_status_flag,
                        PEER_GRACEFUL_RESTART_NEW_STATE_INHERIT)) {
 
@@ -19708,6 +19825,12 @@ void bgp_vty_init(void)
        install_element(BGP_NODE, &neighbor_path_attribute_discard_cmd);
        install_element(BGP_NODE, &no_neighbor_path_attribute_discard_cmd);
 
+       /* "neighbor path-attribute treat-as-withdraw" commands. */
+       install_element(BGP_NODE,
+                       &neighbor_path_attribute_treat_as_withdraw_cmd);
+       install_element(BGP_NODE,
+                       &no_neighbor_path_attribute_treat_as_withdraw_cmd);
+
        /* "neighbor passive" commands. */
        install_element(BGP_NODE, &neighbor_passive_cmd);
        install_element(BGP_NODE, &no_neighbor_passive_cmd);
@@ -19725,6 +19848,9 @@ void bgp_vty_init(void)
        install_element(BGP_NODE, &neighbor_capability_enhe_cmd);
        install_element(BGP_NODE, &no_neighbor_capability_enhe_cmd);
 
+       /* "neighbor capability software-version" commands.*/
+       install_element(BGP_NODE, &neighbor_capability_software_version_cmd);
+
        /* "neighbor capability orf prefix-list" commands.*/
        install_element(BGP_NODE, &neighbor_capability_orf_prefix_hidden_cmd);
        install_element(BGP_NODE,