mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +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_community_alias.h"
|
||||
|
||||
DEFINE_HOOK(bgp_hook_config_write_vrf, (struct vty *vty, struct vrf *vrf),
|
||||
(vty, vrf));
|
||||
|
||||
#ifdef ENABLE_BGP_VNC
|
||||
#include "bgpd/rfapi/rfapi_backend.h"
|
||||
#endif
|
||||
|
||||
DEFINE_HOOK(bgp_hook_vrf_update, (struct vrf *vrf, bool enabled),
|
||||
(vrf, enabled));
|
||||
|
||||
/* bgpd options, we use GNU getopt library. */
|
||||
static const struct option longopts[] = {
|
||||
{ "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_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_IP6);
|
||||
vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
|
||||
|
@ -333,15 +340,36 @@ static int bgp_vrf_disable(struct vrf *vrf)
|
|||
* "down". */
|
||||
bgp_instance_down(bgp);
|
||||
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. */
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
|
1155
bgpd/bgp_rpki.c
1155
bgpd/bgp_rpki.c
File diff suppressed because it is too large
Load diff
|
@ -8,6 +8,8 @@
|
|||
#ifndef __BGP_RPKI_H__
|
||||
#define __BGP_RPKI_H__
|
||||
|
||||
extern struct zebra_privs_t bgpd_privs;
|
||||
|
||||
enum rpki_states {
|
||||
RPKI_NOT_BEING_USED,
|
||||
RPKI_VALID,
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
|
||||
#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_PEER_MAX_HASH_SIZE 16384
|
||||
|
||||
|
@ -839,6 +842,8 @@ DECLARE_HOOK(bgp_inst_config_write,
|
|||
(bgp, vty));
|
||||
DECLARE_HOOK(bgp_snmp_traps_config_write, (struct vty *vty), (vty));
|
||||
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 */
|
||||
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
|
||||
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
|
||||
initialized.
|
||||
This command is available either in *configure node* for default *vrf* or
|
||||
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
|
||||
to configure at least one reachable cache server. See section
|
||||
|
@ -90,6 +91,9 @@ Examples of the error::
|
|||
router(config)# 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
|
||||
``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
|
||||
----------------------------------
|
||||
|
||||
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)
|
||||
|
||||
|
@ -166,7 +177,7 @@ Validating BGP Updates
|
|||
.. code-block:: frr
|
||||
|
||||
! Allow for invalid routes in route selection process
|
||||
route bgp 60001
|
||||
route bgp 65001
|
||||
!
|
||||
! Set local preference of invalid prefixes to 10
|
||||
route-map rpki permit 10
|
||||
|
@ -200,39 +211,39 @@ Debugging
|
|||
Displaying RPKI
|
||||
---------------
|
||||
|
||||
.. clicmd:: show rpki configuration [json]
|
||||
.. clicmd:: show rpki configuration [vrf NAME] [json]
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
received from the cache servers and stored in the router. Based on this data,
|
||||
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.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. 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.
|
||||
|
||||
.. 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.
|
||||
|
||||
|
@ -248,25 +259,52 @@ RPKI Configuration Example
|
|||
debug bgp keepalives
|
||||
debug rpki
|
||||
!
|
||||
vrf VRF1
|
||||
rpki
|
||||
rpki polling_period 1000
|
||||
rpki timeout 10
|
||||
! SSH Example:
|
||||
rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1
|
||||
! TCP Example:
|
||||
rpki cache rpki-validator.realmv6.org 8282 preference 2
|
||||
exit
|
||||
!
|
||||
exit-vrf
|
||||
!
|
||||
rpki
|
||||
rpki polling_period 1000
|
||||
rpki timeout 10
|
||||
! 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 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 60001
|
||||
bgp router-id 141.22.28.223
|
||||
network 192.168.0.0/16
|
||||
neighbor 123.123.123.0 remote-as 60002
|
||||
neighbor 123.123.123.0 route-map rpki in
|
||||
neighbor 123.123.123.0 update-source 141.22.28.223
|
||||
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
|
||||
neighbor 123.123.123.0 activate
|
||||
neighbor 123.123.123.0 route-map rpki in
|
||||
neighbor 203.0.113.1 activate
|
||||
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
|
||||
!
|
||||
route-map rpki permit 10
|
||||
|
|
|
@ -178,6 +178,7 @@ enum node_type {
|
|||
ISIS_SRV6_NODE, /* ISIS SRv6 node */
|
||||
ISIS_SRV6_NODE_MSD_NODE, /* ISIS SRv6 Node MSDs node */
|
||||
MGMTD_NODE, /* MGMTD node. */
|
||||
RPKI_VRF_NODE, /* RPKI node for VRF */
|
||||
NODE_TYPE_MAX, /* maximum */
|
||||
};
|
||||
/* clang-format on */
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
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
|
||||
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):
|
||||
for routern in range(1, 3):
|
||||
for routern in range(1, 4):
|
||||
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"])
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
tgen = Topogen(build_topo, mod.__name__)
|
||||
|
@ -49,25 +53,34 @@ def setup_module(mod):
|
|||
" -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()
|
||||
|
||||
global rtrd_process
|
||||
rtrd_process = {}
|
||||
|
||||
rname = "r1"
|
||||
for rname in ["r1", "r3"]:
|
||||
rtr_path = os.path.join(CWD, rname)
|
||||
log_dir = os.path.join(tgen.logdir, rname)
|
||||
log_file = os.path.join(log_dir, "rtrd.log")
|
||||
|
||||
rtr_path = os.path.join(CWD, rname)
|
||||
log_dir = os.path.join(tgen.logdir, rname)
|
||||
log_file = os.path.join(log_dir, "rtrd.log")
|
||||
|
||||
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))
|
||||
tgen.gears[rname].cmd("chmod u+x {}/rtrd.py".format(rtr_path))
|
||||
rtrd_process[rname] = tgen.gears[rname].popen(
|
||||
"{}/rtrd.py {}".format(rtr_path, log_file)
|
||||
)
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
tgen = get_topogen()
|
||||
|
||||
logger.info("r1: sending SIGTERM to rtrd RPKI server")
|
||||
rtrd_process.kill()
|
||||
for rname in ["r1", "r3"]:
|
||||
logger.info("{}: sending SIGTERM to rtrd RPKI server".format(rname))
|
||||
rtrd_process[rname].kill()
|
||||
|
||||
tgen.stop_topology()
|
||||
|
||||
|
||||
|
@ -114,7 +127,7 @@ def test_show_bgp_rpki_prefixes():
|
|||
|
||||
for rname in ["r1", "r3"]:
|
||||
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)
|
||||
|
||||
rname = "r2"
|
||||
|
@ -156,7 +169,7 @@ def test_show_bgp_rpki_prefixes_no_rpki_cache():
|
|||
|
||||
for rname in ["r1", "r3"]:
|
||||
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)
|
||||
|
||||
def _show_rpki_no_connection(rname):
|
||||
|
@ -192,7 +205,7 @@ def test_show_bgp_rpki_prefixes_reconnect():
|
|||
|
||||
for rname in ["r1", "r3"]:
|
||||
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)
|
||||
|
||||
step("Restore RPKI server configuration")
|
||||
|
@ -241,7 +254,7 @@ def test_show_bgp_rpki_route_map():
|
|||
|
||||
for rname in ["r1", "r3"]:
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
||||
|
|
|
@ -1625,6 +1625,14 @@ static struct cmd_node rpki_node = {
|
|||
.parent_node = CONFIG_NODE,
|
||||
.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 */
|
||||
|
||||
#if HAVE_BFDD > 0
|
||||
|
@ -1855,7 +1863,10 @@ DEFUNSH(VTYSH_BGPD,
|
|||
"rpki",
|
||||
"Enable rpki and enter rpki configuration mode\n")
|
||||
{
|
||||
vty->node = RPKI_NODE;
|
||||
if (vty->node == CONFIG_NODE)
|
||||
vty->node = RPKI_NODE;
|
||||
else
|
||||
vty->node = RPKI_VRF_NODE;
|
||||
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_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_no_affinity_map_cmd);
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ extern struct event_loop *master;
|
|||
VTYSH_EIGRPD | VTYSH_BABELD | VTYSH_PBRD | VTYSH_FABRICD | \
|
||||
VTYSH_VRRPD | VTYSH_MGMTD
|
||||
#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
|
||||
/* Daemons who can process nexthop-group configs */
|
||||
#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",
|
||||
strlen(" ip mroute"))) {
|
||||
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 ||
|
||||
config->index == INTERFACE_NODE ||
|
||||
config->index == VTY_NODE)
|
||||
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",
|
||||
strlen(" resilient")) == 0)
|
||||
config_add_line_head(config->line,
|
||||
|
|
Loading…
Reference in a new issue