Skip to content
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
1 change: 1 addition & 0 deletions bgpd/bgp_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ struct attr {
#define BATTR_RMAP_L3VPN_ACCEPT_GRE (1 << 8)
#define BATTR_RMAP_VPNV4_NHOP_CHANGED (1 << 9)
#define BATTR_RMAP_VPNV6_GLOBAL_NHOP_CHANGED (1 << 10)
#define BATTR_RMAP_L3VPN_ACCEPT_GRETAP (1 << 11)

/* Router Reflector related structure. */
struct cluster_list {
Expand Down
30 changes: 18 additions & 12 deletions bgpd/bgp_nht.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,18 @@ static int bgp_isvalid_nexthop_for_mplsovergre(struct bgp_nexthop_cache *bnc,
? bnc->ifindex_ipv6_ll
: nexthop->ifindex,
bnc->bgp->vrf_id);
if (ifp && (ifp->ll_type == ZEBRA_LLT_IPGRE ||
ifp->ll_type == ZEBRA_LLT_IP6GRE))
break;
if (!ifp)
continue;
if ((ifp->zif_type == ZEBRA_IF_GRE || ifp->zif_type == ZEBRA_IF_IP6GRE) &&
CHECK_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE))
return true;
if ((ifp->zif_type == ZEBRA_IF_GRETAP ||
ifp->zif_type == ZEBRA_IF_IP6GRETAP) &&
CHECK_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_L3VPN_ACCEPT_GRETAP))
return true;
}
}
if (!ifp)
return false;

if (CHECK_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_L3VPN_ACCEPT_GRE))
return true;

return false;
}

Expand Down Expand Up @@ -481,13 +481,19 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, afi_
path_nh_map(pi, bnc, true);

bpi_ultimate = bgp_get_imported_bpi_ultimate(pi);
if (bpi_ultimate != pi && safi == SAFI_UNICAST &&
(CHECK_FLAG(bgp_route->af_flags[afi][SAFI_UNICAST],
BGP_CONFIG_VRF_TO_VRF_IMPORT) ||
CHECK_FLAG(bgp_route->af_flags[afi][SAFI_UNICAST],
BGP_CONFIG_VRF_TO_VRF_EXPORT)))
/* import does not require any valid MPLS label */
SET_FLAG(bnc->flags, BGP_NEXTHOP_ULTIMATE);

if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
(bgp_path_info_extra_get(bpi_ultimate))->igpmetric =
bnc->metric;
else if (bpi_ultimate->extra)
bpi_ultimate->extra->igpmetric = 0;

SET_FLAG(bnc->flags, BGP_NEXTHOP_ULTIMATE);
} else if (peer) {
/*
* Let's not accidentally save the peer data for a peer
Expand Down
25 changes: 16 additions & 9 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2283,7 +2283,7 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {

/* Set nexthop to object */
struct rmap_l3vpn_nexthop_encapsulation_set {
uint8_t protocol;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we completely dropping the protocol?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About protocol, I need to think..

Link layer protocol is not precise enough to know I am over a GRETAP (LLT ETHERNET) or a GRE interface (LLT_IPGRE).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it was storing protocol and allowing matches against it, who have you broken with this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The IP protocol of the 'rmap_l3vpn_nexthop_encapsulation_set'
structure is replaced by the zif_type, as interfaces used as backbone
for mpls ca either be ptp L3 GRE interfaces or ptp L2 GRE (GRETAP)
interfaces.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was considering IP6GRE and GRE equal for BGP.
I will use the same mechanism for IP6GRETAP and GRETAP interfaces.
So one new keywords: gretap

enum zebra_iftype zif_type;
};

static enum route_map_cmd_result_t
Expand All @@ -2295,10 +2295,11 @@ route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,

path = object;

if (rins->protocol != IPPROTO_GRE)
return RMAP_OKAY;
if (rins->zif_type == ZEBRA_IF_GRE)
SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
if (rins->zif_type == ZEBRA_IF_GRETAP)
SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRETAP);

SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
return RMAP_OKAY;
}

Expand All @@ -2310,8 +2311,13 @@ static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));

/* XXX ALL GRE modes are accepted for now: gre or ip6gre */
rins->protocol = IPPROTO_GRE;
/* GRE IPv4 and IPv6 modes are covered under gre keyword
* GRETAP IPv4 and IPv6 modes are covered under gretap keyword
*/
if (strmatch(arg, "gretap"))
rins->zif_type = ZEBRA_IF_GRETAP;
else
rins->zif_type = ZEBRA_IF_GRE;

return rins;
}
Expand Down Expand Up @@ -6337,12 +6343,13 @@ DEFUN_YANG (no_set_distance,
}

DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
"[no] set l3vpn next-hop encapsulation gre",
"[no] set l3vpn next-hop encapsulation <gre|gretap>$ziftype",
NO_STR SET_STR
"L3VPN operations\n"
"Next hop Information\n"
"Encapsulation options (for BGP only)\n"
"Accept L3VPN traffic over GRE encapsulation\n")
"Accept L3VPN traffic over GRE encapsulation\n"
"Accept L3VPN traffic over GRETAP encapsulation\n")
{
const char *xpath =
"./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
Expand All @@ -6359,7 +6366,7 @@ DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
if (operation == NB_OP_DESTROY)
return nb_cli_apply_changes(vty, NULL);

nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, ziftype);

return nb_cli_apply_changes(vty, NULL);
}
Expand Down
12 changes: 6 additions & 6 deletions doc/user/bgp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3169,15 +3169,15 @@ that check when the path chosen by the next-hop uses a GRE interface, and
there is a route-map configured at inbound side of ipv4-vpn or ipv6-vpn
address family with following syntax:

.. clicmd:: set l3vpn next-hop encapsulation gre
.. clicmd:: set l3vpn next-hop encapsulation <gre|gretap>
:daemon: bgp

The incoming BGP L3VPN entry is accepted, provided that the next hop of the
L3VPN entry uses a path that takes the GRE tunnel as outgoing interface. The
remote endpoint should be configured just behind the GRE tunnel; remote
device configuration may vary depending whether it acts at edge endpoint or
not: in any case, the expectation is that incoming MPLS traffic received at
this endpoint should be considered as a valid path for L3VPN.
L3VPN entry uses a path that takes chosen tunnel kind. The remote endpoint
should be configured just behind the tunnel; remote device configuration may
vary depending whether it acts at edge endpoint or not: in any case, the
expectation is that incoming MPLS traffic received at this endpoint should
be considered as a valid path for L3VPN.

.. _bgp-vrf-route-leaking:

Expand Down
21 changes: 21 additions & 0 deletions lib/if.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,23 @@ enum zebra_link_type {
ZEBRA_LLT_IEEE802154_PHY,
};

/* interface type - ones of interest. */
enum zebra_iftype {
ZEBRA_IF_OTHER = 0, /* Anything else */
ZEBRA_IF_VXLAN, /* VxLAN interface */
ZEBRA_IF_VRF, /* VRF device */
ZEBRA_IF_BRIDGE, /* bridge device */
ZEBRA_IF_VLAN, /* VLAN sub-interface */
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
ZEBRA_IF_VETH, /* VETH interface*/
ZEBRA_IF_BOND, /* Bond */
ZEBRA_IF_GRE, /* GRE interface */
ZEBRA_IF_IP6GRE, /* IP6GRE interface */
ZEBRA_IF_GRETAP, /* GRETAP interface */
ZEBRA_IF_IP6GRETAP, /* IP6GRETAP interface */
ZEBRA_IF_DUMMY, /* Dummy interface */
};

/*
Interface name length.

Expand Down Expand Up @@ -264,6 +281,10 @@ struct interface {

/* Link-layer information and hardware address */
enum zebra_link_type ll_type;

/* Zebra interface type */
enum zebra_iftype zif_type;

uint8_t hw_addr[INTERFACE_HWADDR_MAX];
int hw_addr_len;

Expand Down
1 change: 1 addition & 0 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -3068,6 +3068,7 @@ static void zebra_interface_if_set_value(struct stream *s,
STREAM_GETL(s, ifp->mtu6);
STREAM_GETL(s, ifp->bandwidth);
STREAM_GETL(s, ifp->link_ifindex);
STREAM_GETL(s, ifp->zif_type);
STREAM_GETL(s, ifp->ll_type);
STREAM_GETL(s, ifp->hw_addr_len);
if (ifp->hw_addr_len)
Expand Down
3 changes: 3 additions & 0 deletions tests/topotests/bgp_srv6l3vpn_sid/r1/bgpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ log commands
!debug bgp vpn leak-to-vrf
!debug bgp vpn rmap-event
!
interface eth0
mpls bgp forwarding
!
router bgp 1
bgp router-id 192.0.2.1
no bgp ebgp-requires-policy
Expand Down
3 changes: 3 additions & 0 deletions tests/topotests/bgp_srv6l3vpn_sid/r2/bgpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ log commands
!debug bgp vpn leak-to-vrf
!debug bgp vpn rmap-event
!
interface eth0
mpls bgp forwarding
!
router bgp 2
bgp router-id 192.0.2.2
no bgp ebgp-requires-policy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
!
interface r1-eth0
ip address 192.168.179.4/24
mpls bgp forwarding
exit
!
router bgp 65001
Expand Down
27 changes: 27 additions & 0 deletions tests/topotests/bgp_vpnv4_gre/r1/bgpd_gretap.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
router bgp 65500
bgp router-id 192.0.2.1
neighbor 192.0.2.2 remote-as 65500
neighbor 192.0.2.2 update-source 192.0.2.1
address-family ipv4 unicast
no neighbor 192.0.2.2 activate
exit-address-family
address-family ipv4 vpn
neighbor 192.0.2.2 activate
neighbor 192.0.2.2 route-map rmap in
exit-address-family
!
router bgp 65500 vrf vrf1
bgp router-id 192.0.2.1
address-family ipv4 unicast
redistribute connected
distance bgp 21 201 41
label vpn export 101
rd vpn export 444:1
rt vpn both 52:100
export vpn
import vpn
exit-address-family
!
route-map rmap permit 1
set l3vpn next-hop encapsulation gretap
!
62 changes: 48 additions & 14 deletions tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#

"""
test_bgp_vpnv4_gre.py: Test the FRR BGP daemon with BGP IPv6 interface
with route advertisements on a separate netns.
test_bgp_vpnv4_gre.py: Test the FRR BGP daemon with BGP IPv6 interface
with route advertisements on a separate netns.
"""

import os
Expand All @@ -27,13 +27,16 @@
# Import topogen and topotest helpers
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import retry
from lib.topolog import logger

# Required to instantiate the topology builder class.


pytestmark = [pytest.mark.bgpd]

TUNNEL_TYPE = None


def build_topo(tgen):
"Build function"
Expand All @@ -53,29 +56,37 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])


def _populate_iface():
def _populate_iface(mod):
global TUNNEL_TYPE

tgen = get_topogen()

if "gretap" in mod.__name__:
TUNNEL_TYPE = "gretap"
else:
TUNNEL_TYPE = "gre"

cmds_list = [
"ip link add vrf1 type vrf table 10",
"echo 10 > /proc/sys/net/mpls/platform_labels",
"ip link set dev vrf1 up",
"ip link set dev {0}-eth1 master vrf1",
"echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input",
"ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}",
"ip link add {0}-gre0 type {3} ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}",
"ip link set dev {0}-gre0 up",
"echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input",
]

for cmd in cmds_list:
input = cmd.format("r1", "1", "2")
logger.info("input: " + cmd)
output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2"))
input = cmd.format("r1", "1", "2", TUNNEL_TYPE)
logger.info("input: " + input)
output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2", TUNNEL_TYPE))
logger.info("output: " + output)

for cmd in cmds_list:
input = cmd.format("r2", "2", "1")
logger.info("input: " + cmd)
output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1"))
input = cmd.format("r2", "2", "1", TUNNEL_TYPE)
logger.info("input: " + input)
output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1", TUNNEL_TYPE))
logger.info("output: " + output)


Expand All @@ -85,15 +96,18 @@ def setup_module(mod):
tgen.start_topology()

router_list = tgen.routers()
_populate_iface()
_populate_iface(mod)

for rname, router in router_list.items():
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))
bgp_config = (
f"{rname}/bgpd_{TUNNEL_TYPE}.conf"
if rname == "r1"
else f"{rname}/bgpd.conf"
)
router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, bgp_config))

# Initialize all routers.
tgen.start_router()
Expand All @@ -106,6 +120,19 @@ def teardown_module(_mod):
tgen.stop_topology()


@retry(retry_timeout=10)
def _check_show_bgp_mpls_not_selected(router, vrf, ipv4prefix):
valid = True
output = json.loads(router.vtysh_cmd(f"show bgp vrf {vrf} ipv4 {ipv4prefix} json"))
paths = output["paths"]
for path in paths:
if "remoteLabel" in path.keys():
valid = path.get("valid", False)
if not valid:
return True
return f"MPLS path to {ipv4prefix} in vrf {vrf} not found or considered as valid"


def test_protocols_convergence():
"""
Assert that all protocols have converged
Expand Down Expand Up @@ -148,7 +175,7 @@ def test_protocols_convergence():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg

# Check BGP IPv4 routing tables on r2 not installed
# Check BGP IPv4 convergence on r2
logger.info("Checking BGP IPv4 routes for convergence on r2")
router = tgen.gears["r2"]
json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
Expand All @@ -166,6 +193,13 @@ def test_protocols_convergence():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg

# Check BGP IPv4 route 10.201.0.0/24 on r2 not installed
logger.info("Checking BGP IPv4 route 10.201.0.0/24 for invalidity on r2")
success = _check_show_bgp_mpls_not_selected(
tgen.gears["r2"], "vrf1", "10.201.0.0/24"
)
assert success is True, "network 10.201.0.0/24 invalid for MPLS: not found on r2"


def test_memory_leak():
"Run the memory leak test and report results."
Expand Down
Loading
Loading