mirror of
https://github.com/FRRouting/frr.git
synced 2025-05-01 05:57:15 +02:00
Merge pull request #15052 from louis-6wind/rpki-vrf-92
bgpd: add VRF support to RPKI
This commit is contained in:
commit
20ec72d7ca
|
@ -51,10 +51,16 @@
|
||||||
#include "bgpd/bgp_routemap_nb.h"
|
#include "bgpd/bgp_routemap_nb.h"
|
||||||
#include "bgpd/bgp_community_alias.h"
|
#include "bgpd/bgp_community_alias.h"
|
||||||
|
|
||||||
|
DEFINE_HOOK(bgp_hook_config_write_vrf, (struct vty *vty, struct vrf *vrf),
|
||||||
|
(vty, vrf));
|
||||||
|
|
||||||
#ifdef ENABLE_BGP_VNC
|
#ifdef ENABLE_BGP_VNC
|
||||||
#include "bgpd/rfapi/rfapi_backend.h"
|
#include "bgpd/rfapi/rfapi_backend.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEFINE_HOOK(bgp_hook_vrf_update, (struct vrf *vrf, bool enabled),
|
||||||
|
(vrf, enabled));
|
||||||
|
|
||||||
/* bgpd options, we use GNU getopt library. */
|
/* bgpd options, we use GNU getopt library. */
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{ "bgp_port", required_argument, NULL, 'p' },
|
{ "bgp_port", required_argument, NULL, 'p' },
|
||||||
|
@ -287,6 +293,7 @@ static int bgp_vrf_enable(struct vrf *vrf)
|
||||||
|
|
||||||
bgp_handle_socket(bgp, vrf, old_vrf_id, true);
|
bgp_handle_socket(bgp, vrf, old_vrf_id, true);
|
||||||
bgp_instance_up(bgp);
|
bgp_instance_up(bgp);
|
||||||
|
hook_call(bgp_hook_vrf_update, vrf, true);
|
||||||
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
|
||||||
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
|
||||||
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
|
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
|
||||||
|
@ -333,15 +340,36 @@ static int bgp_vrf_disable(struct vrf *vrf)
|
||||||
* "down". */
|
* "down". */
|
||||||
bgp_instance_down(bgp);
|
bgp_instance_down(bgp);
|
||||||
bgp_vrf_unlink(bgp, vrf);
|
bgp_vrf_unlink(bgp, vrf);
|
||||||
|
hook_call(bgp_hook_vrf_update, vrf, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: This is a callback, the VRF will be deleted by the caller. */
|
/* Note: This is a callback, the VRF will be deleted by the caller. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bgp_vrf_config_write(struct vty *vty)
|
||||||
|
{
|
||||||
|
struct vrf *vrf;
|
||||||
|
|
||||||
|
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
|
||||||
|
if (vrf->vrf_id == VRF_DEFAULT) {
|
||||||
|
vty_out(vty, "!\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vty_out(vty, "vrf %s\n", vrf->name);
|
||||||
|
|
||||||
|
hook_call(bgp_hook_config_write_vrf, vty, vrf);
|
||||||
|
|
||||||
|
vty_out(vty, "exit-vrf\n!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void bgp_vrf_init(void)
|
static void bgp_vrf_init(void)
|
||||||
{
|
{
|
||||||
vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
|
vrf_init(bgp_vrf_new, bgp_vrf_enable, bgp_vrf_disable, bgp_vrf_delete);
|
||||||
|
vrf_cmd_init(bgp_vrf_config_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bgp_vrf_terminate(void)
|
static void bgp_vrf_terminate(void)
|
||||||
|
|
1137
bgpd/bgp_rpki.c
1137
bgpd/bgp_rpki.c
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,8 @@
|
||||||
#ifndef __BGP_RPKI_H__
|
#ifndef __BGP_RPKI_H__
|
||||||
#define __BGP_RPKI_H__
|
#define __BGP_RPKI_H__
|
||||||
|
|
||||||
|
extern struct zebra_privs_t bgpd_privs;
|
||||||
|
|
||||||
enum rpki_states {
|
enum rpki_states {
|
||||||
RPKI_NOT_BEING_USED,
|
RPKI_NOT_BEING_USED,
|
||||||
RPKI_VALID,
|
RPKI_VALID,
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
#include "lib/bfd.h"
|
#include "lib/bfd.h"
|
||||||
|
|
||||||
|
DECLARE_HOOK(bgp_hook_config_write_vrf, (struct vty *vty, struct vrf *vrf),
|
||||||
|
(vty, vrf));
|
||||||
|
|
||||||
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
|
#define BGP_MAX_HOSTNAME 64 /* Linux max, is larger than most other sys */
|
||||||
#define BGP_PEER_MAX_HASH_SIZE 16384
|
#define BGP_PEER_MAX_HASH_SIZE 16384
|
||||||
|
|
||||||
|
@ -839,6 +842,8 @@ DECLARE_HOOK(bgp_inst_config_write,
|
||||||
(bgp, vty));
|
(bgp, vty));
|
||||||
DECLARE_HOOK(bgp_snmp_traps_config_write, (struct vty *vty), (vty));
|
DECLARE_HOOK(bgp_snmp_traps_config_write, (struct vty *vty), (vty));
|
||||||
DECLARE_HOOK(bgp_config_end, (struct bgp *bgp), (bgp));
|
DECLARE_HOOK(bgp_config_end, (struct bgp *bgp), (bgp));
|
||||||
|
DECLARE_HOOK(bgp_hook_vrf_update, (struct vrf *vrf, bool enabled),
|
||||||
|
(vrf, enabled));
|
||||||
|
|
||||||
/* Thread callback information */
|
/* Thread callback information */
|
||||||
struct afi_safi_info {
|
struct afi_safi_info {
|
||||||
|
|
|
@ -62,8 +62,9 @@ otherwise ``bgpd`` daemon won't startup.
|
||||||
This command enables the RPKI configuration mode. Most commands that start
|
This command enables the RPKI configuration mode. Most commands that start
|
||||||
with *rpki* can only be used in this mode.
|
with *rpki* can only be used in this mode.
|
||||||
|
|
||||||
When it is used in a telnet session, leaving of this mode cause rpki to be
|
This command is available either in *configure node* for default *vrf* or
|
||||||
initialized.
|
in *vrf node* for specific *vrf*. When it is used in a telnet session,
|
||||||
|
leaving of this mode cause rpki to be initialized.
|
||||||
|
|
||||||
Executing this command alone does not activate prefix validation. You need
|
Executing this command alone does not activate prefix validation. You need
|
||||||
to configure at least one reachable cache server. See section
|
to configure at least one reachable cache server. See section
|
||||||
|
@ -90,6 +91,9 @@ Examples of the error::
|
||||||
router(config)# rpki
|
router(config)# rpki
|
||||||
% [BGP] Unknown command: rpki
|
% [BGP] Unknown command: rpki
|
||||||
|
|
||||||
|
router(config-vrf)# rpki
|
||||||
|
% [BGP] Unknown command: rpki
|
||||||
|
|
||||||
Note that the RPKI commands will be available in vtysh when running
|
Note that the RPKI commands will be available in vtysh when running
|
||||||
``find rpki`` regardless of whether the module is loaded.
|
``find rpki`` regardless of whether the module is loaded.
|
||||||
|
|
||||||
|
@ -98,7 +102,14 @@ Note that the RPKI commands will be available in vtysh when running
|
||||||
Configuring RPKI/RTR Cache Servers
|
Configuring RPKI/RTR Cache Servers
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
The following commands are independent of a specific cache server.
|
RPKI/RTR can be configured independently, either in configure node, or in *vrf*
|
||||||
|
sub context. If configured in configure node, the core *bgp* instance of default
|
||||||
|
*vrf* is impacted by the configuration.
|
||||||
|
|
||||||
|
Each RPKI/RTR context is mapped to a *vrf* and can be made up of a specific list
|
||||||
|
of cache-servers, and specific settings.
|
||||||
|
|
||||||
|
The following commands are available for independent of a specific cache server.
|
||||||
|
|
||||||
.. clicmd:: rpki polling_period (1-3600)
|
.. clicmd:: rpki polling_period (1-3600)
|
||||||
|
|
||||||
|
@ -166,7 +177,7 @@ Validating BGP Updates
|
||||||
.. code-block:: frr
|
.. code-block:: frr
|
||||||
|
|
||||||
! Allow for invalid routes in route selection process
|
! Allow for invalid routes in route selection process
|
||||||
route bgp 60001
|
route bgp 65001
|
||||||
!
|
!
|
||||||
! Set local preference of invalid prefixes to 10
|
! Set local preference of invalid prefixes to 10
|
||||||
route-map rpki permit 10
|
route-map rpki permit 10
|
||||||
|
@ -200,39 +211,39 @@ Debugging
|
||||||
Displaying RPKI
|
Displaying RPKI
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
.. clicmd:: show rpki configuration [json]
|
.. clicmd:: show rpki configuration [vrf NAME] [json]
|
||||||
|
|
||||||
Display RPKI configuration state including timers values.
|
Display RPKI configuration state including timers values.
|
||||||
|
|
||||||
.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [json]
|
.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [vrf NAME] [json]
|
||||||
|
|
||||||
Display validated prefixes received from the cache servers filtered
|
Display validated prefixes received from the cache servers filtered
|
||||||
by the specified prefix.
|
by the specified prefix.
|
||||||
|
|
||||||
.. clicmd:: show rpki as-number ASN [json]
|
.. clicmd:: show rpki as-number ASN [vrf NAME] [json]
|
||||||
|
|
||||||
Display validated prefixes received from the cache servers filtered
|
Display validated prefixes received from the cache servers filtered
|
||||||
by ASN.
|
by ASN.
|
||||||
|
|
||||||
.. clicmd:: show rpki prefix-table [json]
|
.. clicmd:: show rpki prefix-table [vrf NAME] [json]
|
||||||
|
|
||||||
Display all validated prefix to origin AS mappings/records which have been
|
Display all validated prefix to origin AS mappings/records which have been
|
||||||
received from the cache servers and stored in the router. Based on this data,
|
received from the cache servers and stored in the router. Based on this data,
|
||||||
the router validates BGP Updates.
|
the router validates BGP Updates.
|
||||||
|
|
||||||
.. clicmd:: show rpki cache-server [json]
|
.. clicmd:: show rpki cache-server [vrf NAME] [json]
|
||||||
|
|
||||||
Display all configured cache servers, whether active or not.
|
Display all configured cache servers, whether active or not.
|
||||||
|
|
||||||
.. clicmd:: show rpki cache-connection [json]
|
.. clicmd:: show rpki cache-connection [vrf NAME] [json]
|
||||||
|
|
||||||
Display all cache connections, and show which is connected or not.
|
Display all cache connections, and show which is connected or not.
|
||||||
|
|
||||||
.. clicmd:: show bgp [afi] [safi] <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> rpki <valid|invalid|notfound>
|
.. clicmd:: show bgp [vrf NAME] [afi] [safi] <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> rpki <valid|invalid|notfound>
|
||||||
|
|
||||||
Display for the specified prefix or address the bgp paths that match the given rpki state.
|
Display for the specified prefix or address the bgp paths that match the given rpki state.
|
||||||
|
|
||||||
.. clicmd:: show bgp [afi] [safi] rpki <valid|invalid|notfound>
|
.. clicmd:: show bgp [vrf NAME] [afi] [safi] rpki <valid|invalid|notfound>
|
||||||
|
|
||||||
Display all prefixes that match the given rpki state.
|
Display all prefixes that match the given rpki state.
|
||||||
|
|
||||||
|
@ -248,25 +259,52 @@ RPKI Configuration Example
|
||||||
debug bgp keepalives
|
debug bgp keepalives
|
||||||
debug rpki
|
debug rpki
|
||||||
!
|
!
|
||||||
|
vrf VRF1
|
||||||
rpki
|
rpki
|
||||||
rpki polling_period 1000
|
rpki polling_period 1000
|
||||||
rpki timeout 10
|
rpki timeout 10
|
||||||
! SSH Example:
|
! SSH Example:
|
||||||
rpki cache example.com source 141.22.28.223 22 rtr-ssh ./ssh_key/id_rsa ./ssh_key/id_rsa.pub preference 1
|
rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1
|
||||||
! TCP Example:
|
! TCP Example:
|
||||||
rpki cache rpki-validator.realmv6.org 8282 preference 2
|
rpki cache rpki-validator.realmv6.org 8282 preference 2
|
||||||
exit
|
exit
|
||||||
!
|
!
|
||||||
router bgp 60001
|
exit-vrf
|
||||||
bgp router-id 141.22.28.223
|
!
|
||||||
network 192.168.0.0/16
|
rpki
|
||||||
neighbor 123.123.123.0 remote-as 60002
|
rpki polling_period 1000
|
||||||
neighbor 123.123.123.0 route-map rpki in
|
rpki timeout 10
|
||||||
neighbor 123.123.123.0 update-source 141.22.28.223
|
! SSH Example:
|
||||||
|
rpki cache example.com source 198.51.100.223 22 rtr-ssh ./ssh_key/id_rsa preference 1
|
||||||
|
! TCP Example:
|
||||||
|
rpki cache rpki-validator.realmv6.org 8282 preference 2
|
||||||
|
exit
|
||||||
|
!
|
||||||
|
router bgp 65001
|
||||||
|
bgp router-id 198.51.100.223
|
||||||
|
neighbor 203.0.113.1 remote-as 65002
|
||||||
|
neighbor 203.0.113.1 update-source 198.51.100.223
|
||||||
|
address-family ipv4
|
||||||
|
network 192.0.2.0/24
|
||||||
|
neighbor 203.0.113.1 route-map rpki in
|
||||||
|
exit-address-family
|
||||||
!
|
!
|
||||||
address-family ipv6
|
address-family ipv6
|
||||||
neighbor 123.123.123.0 activate
|
neighbor 203.0.113.1 activate
|
||||||
neighbor 123.123.123.0 route-map rpki in
|
neighbor 203.0.113.1 route-map rpki in
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
router bgp 65001 vrf VRF1
|
||||||
|
bgp router-id 198.51.100.223
|
||||||
|
neighbor 203.0.113.1 remote-as 65002
|
||||||
|
address-family ipv4
|
||||||
|
network 192.0.2.0/24
|
||||||
|
neighbor 203.0.113.1 route-map rpki in
|
||||||
|
exit-address-family
|
||||||
|
!
|
||||||
|
address-family ipv6
|
||||||
|
neighbor 203.0.113.1 activate
|
||||||
|
neighbor 203.0.113.1 route-map rpki in
|
||||||
exit-address-family
|
exit-address-family
|
||||||
!
|
!
|
||||||
route-map rpki permit 10
|
route-map rpki permit 10
|
||||||
|
|
|
@ -178,6 +178,7 @@ enum node_type {
|
||||||
ISIS_SRV6_NODE, /* ISIS SRv6 node */
|
ISIS_SRV6_NODE, /* ISIS SRv6 node */
|
||||||
ISIS_SRV6_NODE_MSD_NODE, /* ISIS SRv6 Node MSDs node */
|
ISIS_SRV6_NODE_MSD_NODE, /* ISIS SRv6 Node MSDs node */
|
||||||
MGMTD_NODE, /* MGMTD node. */
|
MGMTD_NODE, /* MGMTD node. */
|
||||||
|
RPKI_VRF_NODE, /* RPKI node for VRF */
|
||||||
NODE_TYPE_MAX, /* maximum */
|
NODE_TYPE_MAX, /* maximum */
|
||||||
};
|
};
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
ip route 192.0.2.1/32 192.168.1.1
|
ip route 192.0.2.1/32 192.168.1.1
|
||||||
|
!
|
||||||
|
vrf vrf10
|
||||||
|
ip route 192.0.2.3/32 192.168.2.3
|
||||||
|
!
|
||||||
|
|
|
@ -7,3 +7,6 @@ interface vrf10 vrf vrf10
|
||||||
interface r2-eth0
|
interface r2-eth0
|
||||||
ip address 192.168.1.2/24
|
ip address 192.168.1.2/24
|
||||||
!
|
!
|
||||||
|
interface r2-eth1 vrf vrf10
|
||||||
|
ip address 192.168.2.2/24
|
||||||
|
!
|
||||||
|
|
14
tests/topotests/bgp_rpki_topo1/r3/bgpd.conf
Normal file
14
tests/topotests/bgp_rpki_topo1/r3/bgpd.conf
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
router bgp 65530
|
||||||
|
no bgp ebgp-requires-policy
|
||||||
|
no bgp network import-check
|
||||||
|
neighbor 192.0.2.2 remote-as 65002
|
||||||
|
neighbor 192.0.2.2 timers 1 3
|
||||||
|
neighbor 192.0.2.2 timers connect 1
|
||||||
|
neighbor 192.0.2.2 ebgp-multihop 3
|
||||||
|
neighbor 192.0.2.2 update-source 192.0.2.3
|
||||||
|
address-family ipv4 unicast
|
||||||
|
network 198.51.100.0/24
|
||||||
|
network 203.0.113.0/24
|
||||||
|
network 10.0.0.0/24
|
||||||
|
exit-address-family
|
||||||
|
!
|
1
tests/topotests/bgp_rpki_topo1/r3/rtrd.py
Symbolic link
1
tests/topotests/bgp_rpki_topo1/r3/rtrd.py
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../r1/rtrd.py
|
1
tests/topotests/bgp_rpki_topo1/r3/staticd.conf
Normal file
1
tests/topotests/bgp_rpki_topo1/r3/staticd.conf
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ip route 192.0.2.2/32 192.168.2.2
|
1
tests/topotests/bgp_rpki_topo1/r3/vrps.csv
Symbolic link
1
tests/topotests/bgp_rpki_topo1/r3/vrps.csv
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../r1/vrps.csv
|
|
5
tests/topotests/bgp_rpki_topo1/r3/zebra.conf
Normal file
5
tests/topotests/bgp_rpki_topo1/r3/zebra.conf
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
interface lo
|
||||||
|
ip address 192.0.2.3/32
|
||||||
|
!
|
||||||
|
interface r3-eth0
|
||||||
|
ip address 192.168.2.3/24
|
|
@ -22,13 +22,17 @@ pytestmark = [pytest.mark.bgpd]
|
||||||
|
|
||||||
|
|
||||||
def build_topo(tgen):
|
def build_topo(tgen):
|
||||||
for routern in range(1, 3):
|
for routern in range(1, 4):
|
||||||
tgen.add_router("r{}".format(routern))
|
tgen.add_router("r{}".format(routern))
|
||||||
|
|
||||||
switch = tgen.add_switch("s1")
|
switch = tgen.add_switch("s1")
|
||||||
switch.add_link(tgen.gears["r1"])
|
switch.add_link(tgen.gears["r1"])
|
||||||
switch.add_link(tgen.gears["r2"])
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
|
||||||
|
switch = tgen.add_switch("s2")
|
||||||
|
switch.add_link(tgen.gears["r2"])
|
||||||
|
switch.add_link(tgen.gears["r3"])
|
||||||
|
|
||||||
|
|
||||||
def setup_module(mod):
|
def setup_module(mod):
|
||||||
tgen = Topogen(build_topo, mod.__name__)
|
tgen = Topogen(build_topo, mod.__name__)
|
||||||
|
@ -49,25 +53,34 @@ def setup_module(mod):
|
||||||
" -M bgpd_rpki" if rname == "r2" else "",
|
" -M bgpd_rpki" if rname == "r2" else "",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tgen.gears["r2"].run("ip link add vrf10 type vrf table 10")
|
||||||
|
tgen.gears["r2"].run("ip link set vrf10 up")
|
||||||
|
|
||||||
|
tgen.gears["r2"].run("ip link set r2-eth1 master vrf10")
|
||||||
|
|
||||||
tgen.start_router()
|
tgen.start_router()
|
||||||
|
|
||||||
global rtrd_process
|
global rtrd_process
|
||||||
|
rtrd_process = {}
|
||||||
|
|
||||||
rname = "r1"
|
for rname in ["r1", "r3"]:
|
||||||
|
|
||||||
rtr_path = os.path.join(CWD, rname)
|
rtr_path = os.path.join(CWD, rname)
|
||||||
log_dir = os.path.join(tgen.logdir, rname)
|
log_dir = os.path.join(tgen.logdir, rname)
|
||||||
log_file = os.path.join(log_dir, "rtrd.log")
|
log_file = os.path.join(log_dir, "rtrd.log")
|
||||||
|
|
||||||
tgen.gears[rname].cmd("chmod u+x {}/rtrd.py".format(rtr_path))
|
tgen.gears[rname].cmd("chmod u+x {}/rtrd.py".format(rtr_path))
|
||||||
rtrd_process = tgen.gears[rname].popen("{}/rtrd.py {}".format(rtr_path, log_file))
|
rtrd_process[rname] = tgen.gears[rname].popen(
|
||||||
|
"{}/rtrd.py {}".format(rtr_path, log_file)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def teardown_module(mod):
|
def teardown_module(mod):
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
|
|
||||||
logger.info("r1: sending SIGTERM to rtrd RPKI server")
|
for rname in ["r1", "r3"]:
|
||||||
rtrd_process.kill()
|
logger.info("{}: sending SIGTERM to rtrd RPKI server".format(rname))
|
||||||
|
rtrd_process[rname].kill()
|
||||||
|
|
||||||
tgen.stop_topology()
|
tgen.stop_topology()
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,7 +127,7 @@ def test_show_bgp_rpki_prefixes():
|
||||||
|
|
||||||
for rname in ["r1", "r3"]:
|
for rname in ["r1", "r3"]:
|
||||||
logger.info("{}: checking if rtrd is running".format(rname))
|
logger.info("{}: checking if rtrd is running".format(rname))
|
||||||
if rtrd_process.poll() is not None:
|
if rtrd_process[rname].poll() is not None:
|
||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
rname = "r2"
|
rname = "r2"
|
||||||
|
@ -156,7 +169,7 @@ def test_show_bgp_rpki_prefixes_no_rpki_cache():
|
||||||
|
|
||||||
for rname in ["r1", "r3"]:
|
for rname in ["r1", "r3"]:
|
||||||
logger.info("{}: checking if rtrd is running".format(rname))
|
logger.info("{}: checking if rtrd is running".format(rname))
|
||||||
if rtrd_process.poll() is not None:
|
if rtrd_process[rname].poll() is not None:
|
||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
def _show_rpki_no_connection(rname):
|
def _show_rpki_no_connection(rname):
|
||||||
|
@ -192,7 +205,7 @@ def test_show_bgp_rpki_prefixes_reconnect():
|
||||||
|
|
||||||
for rname in ["r1", "r3"]:
|
for rname in ["r1", "r3"]:
|
||||||
logger.info("{}: checking if rtrd is running".format(rname))
|
logger.info("{}: checking if rtrd is running".format(rname))
|
||||||
if rtrd_process.poll() is not None:
|
if rtrd_process[rname].poll() is not None:
|
||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
step("Restore RPKI server configuration")
|
step("Restore RPKI server configuration")
|
||||||
|
@ -241,7 +254,7 @@ def test_show_bgp_rpki_route_map():
|
||||||
|
|
||||||
for rname in ["r1", "r3"]:
|
for rname in ["r1", "r3"]:
|
||||||
logger.info("{}: checking if rtrd is running".format(rname))
|
logger.info("{}: checking if rtrd is running".format(rname))
|
||||||
if rtrd_process.poll() is not None:
|
if rtrd_process[rname].poll() is not None:
|
||||||
pytest.skip(tgen.errors)
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
step("Apply RPKI valid route-map on neighbor")
|
step("Apply RPKI valid route-map on neighbor")
|
||||||
|
@ -283,6 +296,112 @@ router bgp 65002
|
||||||
assert result is None, "Unexpected prefixes RPKI state on {}".format(rname)
|
assert result is None, "Unexpected prefixes RPKI state on {}".format(rname)
|
||||||
|
|
||||||
|
|
||||||
|
def test_show_bgp_rpki_prefixes_vrf():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
for rname in ["r1", "r3"]:
|
||||||
|
logger.info("{}: checking if rtrd is running".format(rname))
|
||||||
|
if rtrd_process[rname].poll() is not None:
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
step("Configure RPKI cache server on vrf10")
|
||||||
|
|
||||||
|
rname = "r2"
|
||||||
|
tgen.gears[rname].vtysh_cmd(
|
||||||
|
"""
|
||||||
|
configure
|
||||||
|
vrf vrf10
|
||||||
|
rpki
|
||||||
|
rpki cache 192.0.2.3 15432 preference 1
|
||||||
|
exit
|
||||||
|
exit
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
step("Check vrf10 RPKI prefix table")
|
||||||
|
|
||||||
|
expected = open(os.path.join(CWD, "{}/rpki_prefix_table.json".format(rname))).read()
|
||||||
|
expected_json = json.loads(expected)
|
||||||
|
test_func = functools.partial(show_rpki_prefixes, rname, expected_json, vrf="vrf10")
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Failed to see RPKI prefixes on {}".format(rname)
|
||||||
|
|
||||||
|
for rpki_state in ["valid", "notfound", None]:
|
||||||
|
if rpki_state:
|
||||||
|
step(
|
||||||
|
"Check RPKI state of prefixes in vrf10 BGP table: {}".format(rpki_state)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
step("Check prefixes in vrf10 BGP table")
|
||||||
|
expected = open(
|
||||||
|
os.path.join(
|
||||||
|
CWD,
|
||||||
|
"{}/bgp_table_rpki_{}.json".format(
|
||||||
|
rname, rpki_state if rpki_state else "any"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
).read()
|
||||||
|
expected_json = json.loads(expected)
|
||||||
|
test_func = functools.partial(
|
||||||
|
show_bgp_ipv4_table_rpki, rname, rpki_state, expected_json, vrf="vrf10"
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Unexpected prefixes RPKI state on {}".format(rname)
|
||||||
|
|
||||||
|
|
||||||
|
def test_show_bgp_rpki_route_map_vrf():
|
||||||
|
tgen = get_topogen()
|
||||||
|
|
||||||
|
if tgen.routers_have_failure():
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
for rname in ["r1", "r3"]:
|
||||||
|
logger.info("{}: checking if rtrd is running".format(rname))
|
||||||
|
if rtrd_process[rname].poll() is not None:
|
||||||
|
pytest.skip(tgen.errors)
|
||||||
|
|
||||||
|
step("Apply RPKI valid route-map on vrf10 neighbor")
|
||||||
|
|
||||||
|
rname = "r2"
|
||||||
|
tgen.gears[rname].vtysh_cmd(
|
||||||
|
"""
|
||||||
|
configure
|
||||||
|
router bgp 65002 vrf vrf10
|
||||||
|
address-family ipv4 unicast
|
||||||
|
neighbor 192.0.2.3 route-map RPKI in
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
for rpki_state in ["valid", "notfound", None]:
|
||||||
|
if rpki_state:
|
||||||
|
step(
|
||||||
|
"Check RPKI state of prefixes in vrf10 BGP table: {}".format(rpki_state)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
step("Check prefixes in vrf10 BGP table")
|
||||||
|
expected = open(
|
||||||
|
os.path.join(
|
||||||
|
CWD,
|
||||||
|
"{}/bgp_table_rmap_rpki_{}.json".format(
|
||||||
|
rname, rpki_state if rpki_state else "any"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
).read()
|
||||||
|
expected_json = json.loads(expected)
|
||||||
|
test_func = functools.partial(
|
||||||
|
show_bgp_ipv4_table_rpki,
|
||||||
|
rname,
|
||||||
|
rpki_state,
|
||||||
|
expected_json,
|
||||||
|
vrf="vrf10",
|
||||||
|
)
|
||||||
|
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, "Unexpected prefixes RPKI state on {}".format(rname)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = ["-s"] + sys.argv[1:]
|
args = ["-s"] + sys.argv[1:]
|
||||||
sys.exit(pytest.main(args))
|
sys.exit(pytest.main(args))
|
||||||
|
|
|
@ -1625,6 +1625,14 @@ static struct cmd_node rpki_node = {
|
||||||
.parent_node = CONFIG_NODE,
|
.parent_node = CONFIG_NODE,
|
||||||
.prompt = "%s(config-rpki)# ",
|
.prompt = "%s(config-rpki)# ",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct cmd_node rpki_vrf_node = {
|
||||||
|
.name = "rpki",
|
||||||
|
.node = RPKI_VRF_NODE,
|
||||||
|
.parent_node = VRF_NODE,
|
||||||
|
.prompt = "%s(config-vrf-rpki)# ",
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* HAVE_BGPD */
|
#endif /* HAVE_BGPD */
|
||||||
|
|
||||||
#if HAVE_BFDD > 0
|
#if HAVE_BFDD > 0
|
||||||
|
@ -1855,7 +1863,10 @@ DEFUNSH(VTYSH_BGPD,
|
||||||
"rpki",
|
"rpki",
|
||||||
"Enable rpki and enter rpki configuration mode\n")
|
"Enable rpki and enter rpki configuration mode\n")
|
||||||
{
|
{
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
vty->node = RPKI_NODE;
|
vty->node = RPKI_NODE;
|
||||||
|
else
|
||||||
|
vty->node = RPKI_VRF_NODE;
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5071,6 +5082,12 @@ void vtysh_init_vty(void)
|
||||||
install_element(VRF_NODE, &vtysh_exit_vrf_cmd);
|
install_element(VRF_NODE, &vtysh_exit_vrf_cmd);
|
||||||
install_element(VRF_NODE, &vtysh_quit_vrf_cmd);
|
install_element(VRF_NODE, &vtysh_quit_vrf_cmd);
|
||||||
|
|
||||||
|
install_node(&rpki_vrf_node);
|
||||||
|
install_element(VRF_NODE, &rpki_cmd);
|
||||||
|
install_element(RPKI_VRF_NODE, &rpki_exit_cmd);
|
||||||
|
install_element(RPKI_VRF_NODE, &rpki_quit_cmd);
|
||||||
|
install_element(RPKI_VRF_NODE, &vtysh_end_all_cmd);
|
||||||
|
|
||||||
install_element(CONFIG_NODE, &vtysh_affinity_map_cmd);
|
install_element(CONFIG_NODE, &vtysh_affinity_map_cmd);
|
||||||
install_element(CONFIG_NODE, &vtysh_no_affinity_map_cmd);
|
install_element(CONFIG_NODE, &vtysh_no_affinity_map_cmd);
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ extern struct event_loop *master;
|
||||||
VTYSH_EIGRPD | VTYSH_BABELD | VTYSH_PBRD | VTYSH_FABRICD | \
|
VTYSH_EIGRPD | VTYSH_BABELD | VTYSH_PBRD | VTYSH_FABRICD | \
|
||||||
VTYSH_VRRPD | VTYSH_MGMTD
|
VTYSH_VRRPD | VTYSH_MGMTD
|
||||||
#define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD
|
#define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD
|
||||||
#define VTYSH_VRF VTYSH_INTERFACE_SUBSET
|
#define VTYSH_VRF VTYSH_INTERFACE_SUBSET | RPKI_VRF_NODE
|
||||||
#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD
|
#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD
|
||||||
/* Daemons who can process nexthop-group configs */
|
/* Daemons who can process nexthop-group configs */
|
||||||
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
|
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
|
||||||
|
|
|
@ -315,11 +315,20 @@ void vtysh_config_parse_line(void *arg, const char *line)
|
||||||
} else if (!strncmp(line, " ip mroute",
|
} else if (!strncmp(line, " ip mroute",
|
||||||
strlen(" ip mroute"))) {
|
strlen(" ip mroute"))) {
|
||||||
config_add_line_uniq_end(config->line, line);
|
config_add_line_uniq_end(config->line, line);
|
||||||
|
} else if ((strncmp(line, " rpki", strlen(" rpki")) ==
|
||||||
|
0) &&
|
||||||
|
config->index == VRF_NODE) {
|
||||||
|
config_add_line(config->line, line);
|
||||||
|
config->index = RPKI_VRF_NODE;
|
||||||
} else if (config->index == RMAP_NODE ||
|
} else if (config->index == RMAP_NODE ||
|
||||||
config->index == INTERFACE_NODE ||
|
config->index == INTERFACE_NODE ||
|
||||||
config->index == VTY_NODE)
|
config->index == VTY_NODE)
|
||||||
config_add_line_uniq(config->line, line);
|
config_add_line_uniq(config->line, line);
|
||||||
else if (config->index == NH_GROUP_NODE) {
|
else if (config->index == RPKI_VRF_NODE &&
|
||||||
|
strncmp(line, " exit", strlen(" exit")) == 0) {
|
||||||
|
config_add_line(config->line, line);
|
||||||
|
config->index = VRF_NODE;
|
||||||
|
} else if (config->index == NH_GROUP_NODE) {
|
||||||
if (strncmp(line, " resilient",
|
if (strncmp(line, " resilient",
|
||||||
strlen(" resilient")) == 0)
|
strlen(" resilient")) == 0)
|
||||||
config_add_line_head(config->line,
|
config_add_line_head(config->line,
|
||||||
|
|
Loading…
Reference in a new issue