summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_open.c21
-rw-r--r--bgpd/bgp_vty.c63
-rw-r--r--bgpd/bgpd.c1
-rw-r--r--bgpd/bgpd.h1
-rw-r--r--doc/user/bgp.rst8
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/__init__.py0
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r1/bgpd.conf8
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r1/zebra.conf4
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r2/bgpd.conf9
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r3/bgpd.conf7
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r3/zebra.conf7
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r4/bgpd.conf7
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/r4/zebra.conf7
-rw-r--r--tests/topotests/bgp_disable_addpath_rx/test_disable_addpath_rx.py148
15 files changed, 291 insertions, 7 deletions
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 113017559e..f1dfebdc1b 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1534,6 +1534,11 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
FOREACH_AFI_SAFI (afi, safi) {
if (peer->afc[afi][safi]) {
+ bool adv_addpath_rx =
+ !CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+ uint8_t flags = 0;
+
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
&pkt_safi);
@@ -1541,19 +1546,25 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
stream_putw(s, pkt_afi);
stream_putc(s, pkt_safi);
- if (adv_addpath_tx) {
- stream_putc(s, BGP_ADDPATH_RX | BGP_ADDPATH_TX);
+ if (adv_addpath_rx) {
+ SET_FLAG(flags, BGP_ADDPATH_RX);
SET_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_RX_ADV);
+ } else {
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV);
+ }
+
+ if (adv_addpath_tx) {
+ SET_FLAG(flags, BGP_ADDPATH_TX);
SET_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_TX_ADV);
} else {
- stream_putc(s, BGP_ADDPATH_RX);
- SET_FLAG(peer->af_cap[afi][safi],
- PEER_CAP_ADDPATH_AF_RX_ADV);
UNSET_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_TX_ADV);
}
+
+ stream_putc(s, flags);
}
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 92b74dd7cc..1d67f5560a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -7968,6 +7968,48 @@ DEFUN (no_neighbor_ttl_security,
return bgp_vty_return(vty, peer_ttl_security_hops_unset(peer));
}
+/* disable-addpath-rx */
+DEFUN(neighbor_disable_addpath_rx,
+ neighbor_disable_addpath_rx_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD> disable-addpath-rx",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Do not accept additional paths\n")
+{
+ char *peer_str = argv[1]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return peer_af_flag_set_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+}
+
+DEFUN(no_neighbor_disable_addpath_rx,
+ no_neighbor_disable_addpath_rx_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD> disable-addpath-rx",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Do not accept additional paths\n")
+{
+ char *peer_str = argv[2]->arg;
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, peer_str);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
+ PEER_FLAG_DISABLE_ADDPATH_RX);
+}
+
DEFUN (neighbor_addpath_tx_all_paths,
neighbor_addpath_tx_all_paths_cmd,
"neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths",
@@ -16606,6 +16648,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
}
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DISABLE_ADDPATH_RX))
+ vty_out(vty, " neighbor %s disable-addpath-rx\n", addr);
+
/* ORF capability. */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|| peergroup_af_flag_check(peer, afi, safi,
@@ -18228,6 +18273,24 @@ void bgp_vty_init(void)
install_element(BGP_FLOWSPECV6_NODE,
&no_neighbor_route_server_client_cmd);
+ /* "neighbor disable-addpath-rx" commands. */
+ install_element(BGP_IPV4_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_disable_addpath_rx_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_disable_addpath_rx_cmd);
+
/* "neighbor addpath-tx-all-paths" commands.*/
install_element(BGP_NODE, &neighbor_addpath_tx_all_paths_hidden_cmd);
install_element(BGP_NODE, &no_neighbor_addpath_tx_all_paths_hidden_cmd);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 7236b9fe4b..ec91e7e229 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4208,6 +4208,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
{PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
+ {PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
{0, 0, 0}};
/* Proper action set. */
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index eb1a18edc4..ee8e511014 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1356,6 +1356,7 @@ struct peer {
#define PEER_FLAG_SEND_LARGE_COMMUNITY (1U << 26) /* Send large Communities */
#define PEER_FLAG_MAX_PREFIX_OUT (1U << 27) /* outgoing maximum prefix */
#define PEER_FLAG_MAX_PREFIX_FORCE (1U << 28) /* maximum-prefix <num> force */
+#define PEER_FLAG_DISABLE_ADDPATH_RX (1U << 29) /* disable-addpath-rx */
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 45bdaf05d7..5c9d96e32b 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1582,6 +1582,10 @@ Configuring Peers
Configure BGP to send best known paths to neighbor in order to preserve multi
path capabilities inside a network.
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> disable-addpath-rx
+
+ Do not accept additional paths from this neighbor.
+
.. clicmd:: neighbor PEER ttl-security hops NUMBER
This command enforces Generalized TTL Security Mechanism (GTSM), as
@@ -4375,8 +4379,8 @@ Show command json output:
BGP fast-convergence support
============================
Whenever BGP peer address becomes unreachable we must bring down the BGP
-session immediately. Currently only single-hop EBGP sessions are brought
-down immediately.IBGP and multi-hop EBGP sessions wait for hold-timer
+session immediately. Currently only single-hop EBGP sessions are brought
+down immediately.IBGP and multi-hop EBGP sessions wait for hold-timer
expiry to bring down the sessions.
This new configuration option helps user to teardown BGP sessions immediately
diff --git a/tests/topotests/bgp_disable_addpath_rx/__init__.py b/tests/topotests/bgp_disable_addpath_rx/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/__init__.py
diff --git a/tests/topotests/bgp_disable_addpath_rx/r1/bgpd.conf b/tests/topotests/bgp_disable_addpath_rx/r1/bgpd.conf
new file mode 100644
index 0000000000..1f3352131b
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r1/bgpd.conf
@@ -0,0 +1,8 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ address-family ipv4 unicast
+ neighbor 192.168.1.2 disable-addpath-rx
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r1/zebra.conf b/tests/topotests/bgp_disable_addpath_rx/r1/zebra.conf
new file mode 100644
index 0000000000..b29940f46a
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r1/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r2/bgpd.conf b/tests/topotests/bgp_disable_addpath_rx/r2/bgpd.conf
new file mode 100644
index 0000000000..92d95003e9
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r2/bgpd.conf
@@ -0,0 +1,9 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.2.3 remote-as external
+ neighbor 192.168.2.4 remote-as external
+ address-family ipv4 unicast
+ neighbor 192.168.1.1 addpath-tx-all-paths
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r2/zebra.conf b/tests/topotests/bgp_disable_addpath_rx/r2/zebra.conf
new file mode 100644
index 0000000000..e4a9074c32
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r2/zebra.conf
@@ -0,0 +1,7 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+int r2-eth1
+ ip address 192.168.2.2/24
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r3/bgpd.conf b/tests/topotests/bgp_disable_addpath_rx/r3/bgpd.conf
new file mode 100644
index 0000000000..f5731a1089
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r3/bgpd.conf
@@ -0,0 +1,7 @@
+router bgp 65003
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r3/zebra.conf b/tests/topotests/bgp_disable_addpath_rx/r3/zebra.conf
new file mode 100644
index 0000000000..417a4844a5
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r3/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ip address 172.16.16.254/32
+!
+int r3-eth0
+ ip address 192.168.2.3/24
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r4/bgpd.conf b/tests/topotests/bgp_disable_addpath_rx/r4/bgpd.conf
new file mode 100644
index 0000000000..527b8d3486
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r4/bgpd.conf
@@ -0,0 +1,7 @@
+router bgp 65004
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/r4/zebra.conf b/tests/topotests/bgp_disable_addpath_rx/r4/zebra.conf
new file mode 100644
index 0000000000..241e38693c
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/r4/zebra.conf
@@ -0,0 +1,7 @@
+!
+int lo
+ ip address 172.16.16.254/32
+!
+int r4-eth0
+ ip address 192.168.2.4/24
+!
diff --git a/tests/topotests/bgp_disable_addpath_rx/test_disable_addpath_rx.py b/tests/topotests/bgp_disable_addpath_rx/test_disable_addpath_rx.py
new file mode 100644
index 0000000000..2126d62262
--- /dev/null
+++ b/tests/topotests/bgp_disable_addpath_rx/test_disable_addpath_rx.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if AddPath RX direction is not negotiated via AddPath capability.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_disable_addpath_rx():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ step(
+ "Check if r2 advertised only 2 paths to r1 (despite addpath-tx-all-paths enabled on r2)."
+ )
+
+ def check_bgp_advertised_routes(router):
+ output = json.loads(
+ router.vtysh_cmd(
+ "show bgp ipv4 unicast neighbor 192.168.1.1 advertised-routes json"
+ )
+ )
+ expected = {
+ "advertisedRoutes": {
+ "172.16.16.254/32": {
+ "addrPrefix": "172.16.16.254",
+ "prefixLen": 32,
+ },
+ "192.168.2.0/24": {
+ "addrPrefix": "192.168.2.0",
+ "prefixLen": 24,
+ },
+ },
+ "totalPrefixCounter": 2,
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(check_bgp_advertised_routes, r2)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "AddPath TX not working."
+
+ step("Check if AddPath RX is disabled on r1 and we receive only 2 paths.")
+
+ def check_bgp_disabled_addpath_rx(router):
+ output = json.loads(router.vtysh_cmd("show bgp neighbor 192.168.1.2 json"))
+ expected = {
+ "192.168.1.2": {
+ "bgpState": "Established",
+ "neighborCapabilities": {
+ "addPath": {
+ "ipv4Unicast": {"txReceived": True, "rxReceived": True}
+ },
+ },
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(check_bgp_disabled_addpath_rx, r1)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "AddPath RX advertised, but should not."
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))