Skip to content

Commit

Permalink
bgp: add initial test topologies
Browse files Browse the repository at this point in the history
Add two basic BGP test topologies, including iBGP and eBGP sessions,
route redistribution and ECMP. These topologies should serve as a
foundation for upcoming conformance tests.

In a first moment, modify holo-bgp to skip relaying `PolicyApply`
messages to the test framework. This is necessary because the `nbr_tx`
task is also relaying messages to the test framework, so the order in
which those messages are collected is non-deterministic. A proper fix
will be implemented later.

Signed-off-by: Renato Westphal <[email protected]>
  • Loading branch information
rwestphal committed Apr 7, 2024
1 parent 8b34b69 commit a8cd5d4
Show file tree
Hide file tree
Showing 57 changed files with 8,937 additions and 8 deletions.
1 change: 1 addition & 0 deletions holo-bgp/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ impl ProtocolInputChannelsTx {
impl MessageReceiver<ProtocolInputMsg> for ProtocolInputChannelsRx {
async fn recv(&mut self) -> Option<ProtocolInputMsg> {
tokio::select! {
biased;
msg = self.tcp_accept.recv() => {
msg.map(ProtocolInputMsg::TcpAccept)
}
Expand Down
15 changes: 7 additions & 8 deletions holo-bgp/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,22 @@ pub mod messages {
nbr_addr: IpAddr,
afi_safi: AfiSafi,
routes: Vec<(IpNetwork, RoutePolicyInfo)>,
#[serde(skip)]
policies: Vec<Arc<Policy>>,
#[serde(skip)]
match_sets: Arc<MatchSets>,
#[serde(skip)]
default_policy: DefaultPolicyType,
},
Redistribute {
afi_safi: AfiSafi,
prefix: IpNetwork,
route: RoutePolicyInfo,
#[serde(skip)]
policies: Vec<Arc<Policy>>,
#[serde(skip)]
match_sets: Arc<MatchSets>,
#[serde(skip)]
default_policy: DefaultPolicyType,
},
}
Expand Down Expand Up @@ -480,14 +486,7 @@ pub(crate) fn policy_apply(
}
#[cfg(feature = "testing")]
{
let proto_output_tx = proto_output_tx.clone();
Task::spawn_blocking(move || {
// Relay message to the test framework.
while let Ok(msg) = policy_applyc.recv() {
let msg = messages::ProtocolOutputMsg::PolicyApply(msg);
let _ = proto_output_tx.blocking_send(msg);
}
})
Task::spawn_blocking(move || {})
}
}

Expand Down
7 changes: 7 additions & 0 deletions holo-bgp/tests/conformance/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//
// Copyright (c) The Holo Core Contributors
//
// SPDX-License-Identifier: MIT
//

mod topologies;
24 changes: 24 additions & 0 deletions holo-bgp/tests/conformance/topologies/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// Copyright (c) The Holo Core Contributors
//
// SPDX-License-Identifier: MIT
//

use holo_bgp::instance::Instance;
use holo_protocol::test::stub::run_test_topology;

#[tokio::test]
async fn topology1_1() {
for rt_num in 1..=4 {
let rt_name = format!("rt{}", rt_num);
run_test_topology::<Instance>("topo1-1", &rt_name).await;
}
}

#[tokio::test]
async fn topology2_1() {
for rt_num in 1..=6 {
let rt_name = format!("rt{}", rt_num);
run_test_topology::<Instance>("topo2-1", &rt_name).await;
}
}
25 changes: 25 additions & 0 deletions holo-bgp/tests/conformance/topologies/topo1-1/description.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
+---------+ +---------+
| | | |
| RT1 |eth-rt2 eth-rt1| RT2 |
| 1.1.1.1 +---------------------+ 2.2.2.2 |
| | 10.0.1.0/24 | |
+---------+ +---------+
|eth-rt3 |eth-rt4
| |
|10.0.2.0/24 |10.0.3.0/24
| |
|eth-rt1 |eth-rt2
+---------+ +---------+
| | | |
| RT3 | 172.16.1.0/24 | RT4 |
| 3.3.3.3 +---------------------+ 4.4.4.4 |
| |eth-rt4 eth-rt3| |
+---------+ +---------+

eBGP:
* rt1 (AS 65100) <-> rt2 (AS 65101)
* rt1 (AS 65100) <-> rt3 (AS 65000)
* rt2 (AS 65101) <-> rt4 (AS 65000)

iBGP + OSPF:
* rt3 <-> rt4 (AS 65000)
136 changes: 136 additions & 0 deletions holo-bgp/tests/conformance/topologies/topo1-1/rt1/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"ietf-interfaces:interfaces": {
"interface": [
{
"name": "lo",
"type": "iana-if-type:ethernetCsmacd",
"ietf-ip:ipv4": {}
},
{
"name": "eth-rt2",
"type": "iana-if-type:ethernetCsmacd",
"ietf-ip:ipv4": {}
},
{
"name": "eth-rt3",
"type": "iana-if-type:ethernetCsmacd",
"ietf-ip:ipv4": {}
}
]
},
"ietf-routing:routing": {
"control-plane-protocols": {
"control-plane-protocol": [
{
"type": "ietf-bgp:bgp",
"name": "test",
"ietf-bgp:bgp": {
"global": {
"as": 65100,
"identifier": "1.1.1.1",
"afi-safis": {
"afi-safi": [
{
"name": "iana-bgp-types:ipv4-unicast",
"apply-policy": {
"import-policy": [
"REDIST"
]
},
"ipv4-unicast": {
"holo-bgp:redistribution": [
{
"type": "ietf-routing:direct"
}
]
}
}
]
}
},
"neighbors": {
"neighbor": [
{
"remote-address": "10.0.1.2",
"peer-as": 65101,
"afi-safis": {
"afi-safi": [
{
"name": "iana-bgp-types:ipv4-unicast",
"enabled": true,
"apply-policy": {
"default-import-policy": "accept-route",
"default-export-policy": "accept-route"
}
}
]
}
},
{
"remote-address": "10.0.2.3",
"peer-as": 65000,
"afi-safis": {
"afi-safi": [
{
"name": "iana-bgp-types:ipv4-unicast",
"enabled": true,
"apply-policy": {
"default-import-policy": "accept-route",
"default-export-policy": "accept-route"
}
}
]
}
}
]
}
}
}
]
}
},
"ietf-routing-policy:routing-policy": {
"defined-sets": {
"prefix-sets": {
"prefix-set": [
{
"name": "LOOPBACK",
"mode": "ipv4",
"prefixes": {
"prefix-list": [
{
"ip-prefix": "1.1.1.1/32",
"mask-length-lower": 32,
"mask-length-upper": 32
}
]
}
}
]
}
},
"policy-definitions": {
"policy-definition": [
{
"name": "REDIST",
"statements": {
"statement": [
{
"name": "1",
"conditions": {
"match-prefix-set": {
"prefix-set": "LOOPBACK"
}
},
"actions": {
"policy-result": "accept-route"
}
}
]
}
}
]
}
}
}

64 changes: 64 additions & 0 deletions holo-bgp/tests/conformance/topologies/topo1-1/rt1/events.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{"Ibus":"RouterIdQuery"}
{"Ibus":{"RouterIdUpdate":"1.1.1.1"}}
{"Ibus":{"PolicyMatchSetsUpd":{"prefixes":[[["LOOPBACK","Ipv4"],{"name":"LOOPBACK","mode":"Ipv4","prefixes":[{"prefix":"1.1.1.1/32","masklen_lower":32,"masklen_upper":32}]}]],"neighbors":{},"tags":{},"bgp":{"as_paths":{},"comms":{},"ext_comms":{},"extv6_comms":{},"large_comms":{},"nexthops":{}}}}}
{"Ibus":{"PolicyUpd":{"name":"REDIST","stmts":{"1":{"name":"1","prefix_set_match_type":"Any","tag_set_match_type":"Any","conditions":[["MatchPrefixSet",{"MatchPrefixSet":"LOOPBACK"}]],"actions":[["Accept",{"Accept":true}]]}}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Ibus":{"RouteRedistributeDump":{"protocol":"direct","af":"Ipv4"}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"direct","prefix":"1.1.1.1/32","distance":0,"metric":0,"tag":null,"nexthops":[{"Interface":{"ifindex":1}}]}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"direct","prefix":"10.0.1.0/24","distance":0,"metric":0,"tag":null,"nexthops":[{"Interface":{"ifindex":3}}]}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"direct","prefix":"10.0.2.0/24","distance":0,"metric":0,"tag":null,"nexthops":[{"Interface":{"ifindex":5}}]}}}
{"Protocol":{"PolicyResult":{"Redistribute":{"afi_safi":"Ipv4Unicast","prefix":"1.1.1.1/32","result":{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","opaque_attrs":"None","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Redistribute":{"afi_safi":"Ipv4Unicast","prefix":"10.0.1.0/24","result":"Reject"}}}}
{"Protocol":{"PolicyResult":{"Redistribute":{"afi_safi":"Ipv4Unicast","prefix":"10.0.2.0/24","result":"Reject"}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.1.1","local_port":179,"remote_addr":"10.0.1.2","remote_port":39828}}}}
{"Protocol":{"NbrTimer":{"nbr_addr":"10.0.2.3","timer":"AutoStart"}}}
{"Protocol":{"NbrTimer":{"nbr_addr":"10.0.1.2","timer":"AutoStart"}}}
{"Protocol":{"TcpConnect":{"conn_info":{"local_addr":"10.0.1.1","local_port":40492,"remote_addr":"10.0.1.2","remote_port":179}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Err":{"TcpConnClosed":"10.0.1.2"}}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.1.1","local_port":179,"remote_addr":"10.0.1.2","remote_port":39836}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Open":{"version":4,"my_as":65101,"holdtime":90,"identifier":"2.2.2.2","capabilities":[{"MultiProtocol":{"afi":"Ipv4","safi":"Unicast"}},{"FourOctetAsNumber":{"asn":65101}},"RouteRefresh"]}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Keepalive":{}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["2.2.2.2/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["1.1.1.1/32",{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}]]}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["2.2.2.2/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
{"Ibus":{"NexthopTrack":"10.0.1.2"}}
{"Ibus":{"NexthopUpd":{"addr":"10.0.1.2","metric":0}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"2.2.2.2/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[]}}]}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"2.2.2.2/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[{"Address":{"ifindex":3,"addr":"10.0.1.2","labels":[]}}]}}]}}}
{"Protocol":{"TcpConnect":{"conn_info":{"local_addr":"10.0.2.1","local_port":52856,"remote_addr":"10.0.2.3","remote_port":179}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Err":{"TcpConnClosed":"10.0.2.3"}}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["1.1.1.1/32",{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}]]}}}}
{"Protocol":{"TcpAccept":{"conn_info":{"local_addr":"10.0.2.1","local_port":179,"remote_addr":"10.0.2.3","remote_port":54870}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Open":{"version":4,"my_as":65000,"holdtime":90,"identifier":"3.3.3.3","capabilities":[{"MultiProtocol":{"afi":"Ipv4","safi":"Unicast"}},{"FourOctetAsNumber":{"asn":65000}},"RouteRefresh"]}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Keepalive":{}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.2.3","afi_safi":"Ipv4Unicast","routes":[["1.1.1.1/32",{"Accept":{"origin":{"Protocol":"direct"},"route_type":"Internal","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[]}}}}}],["2.2.2.2/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Update":{"reach":{"prefixes":["3.3.3.3/32"],"nexthop":"10.0.2.3"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.2.3","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"NexthopTrack":"10.0.2.3"}}
{"Ibus":{"NexthopUpd":{"addr":"10.0.2.3","metric":0}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"3.3.3.3/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"3.3.3.3/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[{"Address":{"ifindex":5,"addr":"10.0.2.3","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["4.4.4.4/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[]}}]}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[{"Address":{"ifindex":3,"addr":"10.0.1.2","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Update":{"reach":{"prefixes":["4.4.4.4/32"],"nexthop":"10.0.2.3"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.2.3","afi_safi":"Ipv4Unicast","routes":[["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Ibus":{"RouteIpAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["4.4.4.4/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Ibus":{"RouteRedistributeAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[{"Address":{"ifindex":5,"addr":"10.0.2.3","labels":[]}}]}}]}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Update":{"reach":{"prefixes":["3.3.3.3/32"],"nexthop":"10.0.1.2"},"attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]}}}}}}}}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Import","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"2.2.2.2","remote_addr":"10.0.1.2"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65101,65000]}]},"nexthop":"10.0.1.2"}}}}]]}}}}
{"Protocol":{"TriggerDecisionProcess":null}}
{"Protocol":{"PolicyResult":{"Neighbor":{"policy_type":"Export","nbr_addr":"10.0.1.2","afi_safi":"Ipv4Unicast","routes":[["3.3.3.3/32",{"Accept":{"origin":{"Neighbor":{"identifier":"3.3.3.3","remote_addr":"10.0.2.3"}},"route_type":"External","attrs":{"base":{"origin":"Incomplete","as_path":{"segments":[{"seg_type":"Sequence","members":[65000]}]},"nexthop":"10.0.2.3"}}}}]]}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.1.2","msg":{"Ok":{"Keepalive":{}}}}}}
{"Protocol":{"NbrRx":{"nbr_addr":"10.0.2.3","msg":{"Ok":{"Keepalive":{}}}}}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"RouterIdQuery"
{"RouteRedistributeDump":{"protocol":"direct","af":"Ipv4"}}
{"NexthopTrack":"10.0.1.2"}
{"RouteIpAdd":{"protocol":"bgp","prefix":"2.2.2.2/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[]}}]}}
{"NexthopTrack":"10.0.2.3"}
{"RouteIpAdd":{"protocol":"bgp","prefix":"3.3.3.3/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}
{"RouteIpAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.1.2","labels":[],"resolved":[]}}]}}
{"RouteIpAdd":{"protocol":"bgp","prefix":"4.4.4.4/32","distance":20,"metric":0,"tag":null,"nexthops":[{"Recursive":{"addr":"10.0.2.3","labels":[],"resolved":[]}}]}}
Loading

0 comments on commit a8cd5d4

Please sign in to comment.