mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 15:10:38 +00:00
Merge pull request #9545 from ton31337/feature/disable-addpath-rx
bgpd: Add disable-addpath-rx knob
This commit is contained in:
commit
4250098311
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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
|
||||
|
0
tests/topotests/bgp_disable_addpath_rx/__init__.py
Normal file
0
tests/topotests/bgp_disable_addpath_rx/__init__.py
Normal file
8
tests/topotests/bgp_disable_addpath_rx/r1/bgpd.conf
Normal file
8
tests/topotests/bgp_disable_addpath_rx/r1/bgpd.conf
Normal file
@ -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
|
||||
!
|
4
tests/topotests/bgp_disable_addpath_rx/r1/zebra.conf
Normal file
4
tests/topotests/bgp_disable_addpath_rx/r1/zebra.conf
Normal file
@ -0,0 +1,4 @@
|
||||
!
|
||||
int r1-eth0
|
||||
ip address 192.168.1.1/24
|
||||
!
|
9
tests/topotests/bgp_disable_addpath_rx/r2/bgpd.conf
Normal file
9
tests/topotests/bgp_disable_addpath_rx/r2/bgpd.conf
Normal file
@ -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
|
||||
!
|
7
tests/topotests/bgp_disable_addpath_rx/r2/zebra.conf
Normal file
7
tests/topotests/bgp_disable_addpath_rx/r2/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
int r2-eth0
|
||||
ip address 192.168.1.2/24
|
||||
!
|
||||
int r2-eth1
|
||||
ip address 192.168.2.2/24
|
||||
!
|
7
tests/topotests/bgp_disable_addpath_rx/r3/bgpd.conf
Normal file
7
tests/topotests/bgp_disable_addpath_rx/r3/bgpd.conf
Normal file
@ -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
|
||||
!
|
7
tests/topotests/bgp_disable_addpath_rx/r3/zebra.conf
Normal file
7
tests/topotests/bgp_disable_addpath_rx/r3/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
int lo
|
||||
ip address 172.16.16.254/32
|
||||
!
|
||||
int r3-eth0
|
||||
ip address 192.168.2.3/24
|
||||
!
|
7
tests/topotests/bgp_disable_addpath_rx/r4/bgpd.conf
Normal file
7
tests/topotests/bgp_disable_addpath_rx/r4/bgpd.conf
Normal file
@ -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
|
||||
!
|
7
tests/topotests/bgp_disable_addpath_rx/r4/zebra.conf
Normal file
7
tests/topotests/bgp_disable_addpath_rx/r4/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
int lo
|
||||
ip address 172.16.16.254/32
|
||||
!
|
||||
int r4-eth0
|
||||
ip address 192.168.2.4/24
|
||||
!
|
@ -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))
|
Loading…
Reference in New Issue
Block a user