Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: Respect allowas-in value from the source VRF's peer #17800

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions bgpd/bgp_mplsvpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1951,7 +1951,7 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
* because of loop checking.
*/
if (new_info)
vpn_leak_to_vrf_update(from_bgp, new_info, NULL);
vpn_leak_to_vrf_update(from_bgp, new_info, NULL, path_vrf->peer);
else
bgp_dest_unlock_node(bn);
}
Expand Down Expand Up @@ -2143,10 +2143,10 @@ static struct bgp *bgp_lookup_by_rd(struct bgp_path_info *bpi,
return NULL;
}

static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
struct bgp *from_bgp, /* from */
struct bgp_path_info *path_vpn,
struct prefix_rd *prd)
struct bgp_path_info *path_vpn, struct prefix_rd *prd,
struct peer *from)
{
const struct prefix *p = bgp_dest_get_prefix(path_vpn->net);
afi_t afi = family2afi(p->family);
Expand Down Expand Up @@ -2231,6 +2231,12 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
/* Check if leaked route has our asn. If so, don't import it. */
if (CHECK_FLAG(peer->af_flags[afi][SAFI_MPLS_VPN], PEER_FLAG_ALLOWAS_IN))
aspath_loop_count = peer->allowas_in[afi][SAFI_MPLS_VPN];
else if (peer == peer->bgp->peer_self && from)
/* If this is an import from one VRF to another and the source
* VRF's peer has allowas-in applied, respect it.
*/
aspath_loop_count = from->allowas_in[afi][SAFI_UNICAST];

if (aspath_loop_check(path_vpn->attr->aspath, to_bgp->as) > aspath_loop_count) {
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
Expand Down Expand Up @@ -2511,9 +2517,8 @@ bool vpn_leak_to_vrf_no_retain_filter_check(struct bgp *from_bgp,
return true;
}

void vpn_leak_to_vrf_update(struct bgp *from_bgp,
struct bgp_path_info *path_vpn,
struct prefix_rd *prd)
void vpn_leak_to_vrf_update(struct bgp *from_bgp, struct bgp_path_info *path_vpn,
struct prefix_rd *prd, struct peer *peer)
{
struct listnode *mnode, *mnnode;
struct bgp *bgp;
Expand All @@ -2528,8 +2533,7 @@ void vpn_leak_to_vrf_update(struct bgp *from_bgp,
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
if (!path_vpn->extra || !path_vpn->extra->vrfleak ||
path_vpn->extra->vrfleak->bgp_orig != bgp) { /* no loop */
vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn,
prd);
vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn, prd, peer);
}
}
}
Expand Down Expand Up @@ -2728,8 +2732,8 @@ void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,
bpi->extra->vrfleak->bgp_orig == to_bgp)
continue;

vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from,
bpi, NULL);
vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from, bpi, NULL,
bpi->peer);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions bgpd/bgp_mplsvpn.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,8 @@ extern bool vpn_leak_to_vrf_no_retain_filter_check(struct bgp *from_bgp,
struct attr *attr,
afi_t afi);

extern void vpn_leak_to_vrf_update(struct bgp *from_bgp,
struct bgp_path_info *path_vpn,
struct prefix_rd *prd);
extern void vpn_leak_to_vrf_update(struct bgp *from_bgp, struct bgp_path_info *path_vpn,
struct prefix_rd *prd, struct peer *peer);

extern void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn);

Expand Down
9 changes: 4 additions & 5 deletions bgpd/bgp_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -5539,7 +5539,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
vpn_leak_to_vrf_update(bgp, pi, prd);
vpn_leak_to_vrf_update(bgp, pi, prd, peer);
}

#ifdef ENABLE_BGP_VNC
Expand Down Expand Up @@ -5633,7 +5633,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
vpn_leak_to_vrf_update(bgp, new, prd);
vpn_leak_to_vrf_update(bgp, new, prd, peer);
}
#ifdef ENABLE_BGP_VNC
if (SAFI_MPLS_VPN == safi) {
Expand Down Expand Up @@ -7142,8 +7142,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,

if (SAFI_MPLS_VPN == safi &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
vpn_leak_to_vrf_update(bgp, pi,
&bgp_static->prd);
vpn_leak_to_vrf_update(bgp, pi, &bgp_static->prd, NULL);
}
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
Expand Down Expand Up @@ -7207,7 +7206,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,

if (SAFI_MPLS_VPN == safi &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd);
vpn_leak_to_vrf_update(bgp, new, &bgp_static->prd, NULL);
}
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN)
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
!
interface r1-eth0
ip address 192.168.179.4/24
exit
!
router bgp 65001
!
router bgp 65001 vrf CUSTOMER-A
bgp router-id 192.168.179.4
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 192.168.179.5 remote-as external
!
address-family ipv4 unicast
neighbor 192.168.179.5 next-hop-self
neighbor 192.168.179.5 allowas-in 10
label vpn export auto
rd vpn export 100:1
rt vpn both 100:1 100:2
export vpn
import vpn
exit-address-family
!
router bgp 65001 vrf CUSTOMER-B
bgp router-id 192.168.0.1
no bgp ebgp-requires-policy
no bgp network import-check
!
address-family ipv4 unicast
label vpn export auto
rd vpn export 100:2
rt vpn import 100:1 100:2
export vpn
import vpn
exit-address-family
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
!
interface lo
ip address 10.10.10.10/32
!
interface r2-eth0
ip address 192.168.179.5/24
exit
!
interface r2-eth1
ip address 192.168.2.2/24
exit
!
router bgp 65002
!
router bgp 65002 vrf CUSTOMER-A
bgp router-id 192.168.179.5
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 192.168.179.4 remote-as external
!
address-family ipv4 unicast
neighbor 192.168.179.4 next-hop-self
neighbor 192.168.179.4 route-map r1 out
label vpn export auto
rd vpn export 100:1
rt vpn import 100:1 100:2
export vpn
import vpn
exit-address-family
!
router bgp 65002 vrf CUSTOMER-B
bgp router-id 192.168.0.2
no bgp ebgp-requires-policy
no bgp network import-check
!
address-family ipv4 unicast
redistribute connected
network 10.10.10.10/32
label vpn export auto
rd vpn export 100:2
rt vpn both 100:2
export vpn
import vpn
exit-address-family
!
route-map r1 permit 10
set as-path prepend 65001
!
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env python
# SPDX-License-Identifier: ISC

#
# Copyright (c) 2024 by
# Donatas Abraitis <[email protected]>
#

import os
import sys
import json
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, get_topogen

pytestmark = [pytest.mark.bgpd]


def build_topo(tgen):
tgen.add_router("r1")
tgen.add_router("r2")

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["r1"])

switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["r2"])


def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()

r1 = tgen.gears["r1"]
r2 = tgen.gears["r2"]

r1.run("ip link add CUSTOMER-A type vrf table 1001")
r1.run("ip link set up dev CUSTOMER-A")
r1.run("ip link set r1-eth0 master CUSTOMER-A")

r1.run("ip link add CUSTOMER-B type vrf table 1002")
r1.run("ip link set up dev CUSTOMER-B")
r1.run("ip link set r1-eth1 master CUSTOMER-B")

r2.run("ip link add CUSTOMER-A type vrf table 1001")
r2.run("ip link set up dev CUSTOMER-A")
r2.run("ip link set r2-eth0 master CUSTOMER-A")

r2.run("ip link add CUSTOMER-B type vrf table 1002")
r2.run("ip link set up dev CUSTOMER-B")
r2.run("ip link set r2-eth1 master CUSTOMER-B")

router_list = tgen.routers()

for _, (rname, router) in enumerate(router_list.items(), 1):
router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))

tgen.start_router()


def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()


def test_bgp_vpnv4_import_allowas_in_between_vrf():
tgen = get_topogen()

if tgen.routers_have_failure():
pytest.skip(tgen.errors)

r1 = tgen.gears["r1"]

def _bgp_converge():
output = json.loads(
r1.vtysh_cmd("show bgp vrf CUSTOMER-A ipv4 unicast 10.10.10.10/32 json")
)
expected = {
"paths": [
{
"aspath": {
"string": "65002 65001",
},
"valid": True,
}
]
}
return topotest.json_cmp(output, expected)

test_func = functools.partial(_bgp_converge)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Failed to see 10.10.10.10/32 with a valid next-hop"

def _vrf_route_imported_to_vrf():
output = json.loads(
r1.vtysh_cmd("show ip route vrf CUSTOMER-B 10.10.10.10/32 json")
)
expected = {
"10.10.10.10/32": [
{
"protocol": "bgp",
"vrfName": "CUSTOMER-B",
"selected": True,
"installed": True,
"table": 1002,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"fib": True,
"ip": "192.168.179.5",
"afi": "ipv4",
"interfaceName": "r1-eth0",
"vrf": "CUSTOMER-A",
"active": True,
}
],
}
]
}
return topotest.json_cmp(output, expected)

test_func = functools.partial(_vrf_route_imported_to_vrf)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert (
result is None
), "Failed to see 10.10.10.10/32 to be imported into CUSTOMER-B VRF (Zebra)"


if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
Loading