Merge pull request #9649 from proelbtn/add-support-for-end-dt4

add support for SRv6 IPv4 L3VPN
This commit is contained in:
Russ White 2022-02-08 08:30:02 -05:00 committed by GitHub
commit e735c8073c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 1588 additions and 1 deletions

View File

@ -26,6 +26,7 @@ enum {
SEG6_LOCAL_IIF,
SEG6_LOCAL_OIF,
SEG6_LOCAL_BPF,
SEG6_LOCAL_VRFTABLE,
__SEG6_LOCAL_MAX,
};
#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)

View File

@ -427,7 +427,8 @@ DEFPY (install_seg6local_routes,
End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table>\
End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table>\
(1-1000000)$routes [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
@ -446,6 +447,8 @@ DEFPY (install_seg6local_routes,
"V4 Nexthop address to use\n"
"SRv6 End.DT6 function to use\n"
"Redirect table id to use\n"
"SRv6 End.DT4 function to use\n"
"Redirect table id to use\n"
"How many to create\n"
"Should we repeat this command\n"
"How many times to repeat this command\n")
@ -496,6 +499,9 @@ DEFPY (install_seg6local_routes,
} else if (seg6l_enddt6) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
ctx.table = seg6l_enddt6_table;
} else if (seg6l_enddt4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
ctx.table = seg6l_enddt4_table;
} else {
action = ZEBRA_SEG6_LOCAL_ACTION_END;
}

View File

@ -0,0 +1,8 @@
frr defaults traditional
!
hostname ce1
password zebra
!
log stdout notifications
log commands
log file bgpd.log

View File

@ -0,0 +1,58 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"protocol": "static",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 1,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 73,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "192.168.1.1",
"afi": "ipv4",
"interfaceName": "eth0",
"active": true,
"weight": 1
}
]
}
],
"192.168.1.0/24": [
{
"prefix": "192.168.1.0/24",
"protocol": "connected",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,14 @@
log file zebra.log
!
hostname ce1
!
interface eth0
ip address 192.168.1.2/24
!
ip forwarding
ipv6 forwarding
!
ip route 0.0.0.0/0 192.168.1.1
!
line vty
!

View File

@ -0,0 +1,8 @@
frr defaults traditional
!
hostname ce2
password zebra
!
log stdout notifications
log commands
log file bgpd.log

View File

@ -0,0 +1,58 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"protocol": "static",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 1,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 73,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "192.168.2.1",
"afi": "ipv4",
"interfaceName": "eth0",
"active": true,
"weight": 1
}
]
}
],
"192.168.2.0/24": [
{
"prefix": "192.168.2.0/24",
"protocol": "connected",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,14 @@
log file zebra.log
!
hostname ce2
!
interface eth0
ip address 192.168.2.2/24
!
ip forwarding
ipv6 forwarding
!
ip route 0.0.0.0/0 192.168.2.1
!
line vty
!

View File

@ -0,0 +1,8 @@
frr defaults traditional
!
hostname ce3
password zebra
!
log stdout notifications
log commands
log file bgpd.log

View File

@ -0,0 +1,58 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"protocol": "static",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 1,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 73,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "192.168.3.1",
"afi": "ipv4",
"interfaceName": "eth0",
"active": true,
"weight": 1
}
]
}
],
"192.168.3.0/24": [
{
"prefix": "192.168.3.0/24",
"protocol": "connected",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,14 @@
log file zebra.log
!
hostname ce3
!
interface eth0
ip address 192.168.3.2/24
!
ip forwarding
ipv6 forwarding
!
ip route 0.0.0.0/0 192.168.3.1
!
line vty
!

View File

@ -0,0 +1,8 @@
frr defaults traditional
!
hostname ce4
password zebra
!
log stdout notifications
log commands
log file bgpd.log

View File

@ -0,0 +1,58 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"protocol": "static",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 1,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 73,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "192.168.4.1",
"afi": "ipv4",
"interfaceName": "eth0",
"active": true,
"weight": 1
}
]
}
],
"192.168.4.0/24": [
{
"prefix": "192.168.4.0/24",
"protocol": "connected",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,14 @@
log file zebra.log
!
hostname ce4
!
interface eth0
ip address 192.168.4.2/24
!
ip forwarding
ipv6 forwarding
!
ip route 0.0.0.0/0 192.168.4.1
!
line vty
!

View File

@ -0,0 +1,8 @@
frr defaults traditional
!
hostname ce5
password zebra
!
log stdout notifications
log commands
log file bgpd.log

View File

@ -0,0 +1,58 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"protocol": "static",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 1,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 73,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "192.168.5.1",
"afi": "ipv4",
"interfaceName": "eth0",
"active": true,
"weight": 1
}
]
}
],
"192.168.5.0/24": [
{
"prefix": "192.168.5.0/24",
"protocol": "connected",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,14 @@
log file zebra.log
!
hostname ce5
!
interface eth0
ip address 192.168.5.2/24
!
ip forwarding
ipv6 forwarding
!
ip route 0.0.0.0/0 192.168.5.1
!
line vty
!

View File

@ -0,0 +1,8 @@
frr defaults traditional
!
hostname ce6
password zebra
!
log stdout notifications
log commands
log file bgpd.log

View File

@ -0,0 +1,58 @@
{
"0.0.0.0/0": [
{
"prefix": "0.0.0.0/0",
"protocol": "static",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 1,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 73,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"ip": "192.168.6.1",
"afi": "ipv4",
"interfaceName": "eth0",
"active": true,
"weight": 1
}
]
}
],
"192.168.6.0/24": [
{
"prefix": "192.168.6.0/24",
"protocol": "connected",
"vrfId": 0,
"vrfName": "default",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 254,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth0",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,14 @@
log file zebra.log
!
hostname ce6
!
interface eth0
ip address 192.168.6.2/24
!
ip forwarding
ipv6 forwarding
!
ip route 0.0.0.0/0 192.168.6.1
!
line vty
!

View File

@ -0,0 +1,66 @@
frr defaults traditional
!
hostname r1
password zebra
!
log stdout notifications
log monitor notifications
log commands
!
!debug bgp neighbor-events
!debug bgp zebra
!debug bgp vnc verbose
!debug bgp update-groups
!debug bgp updates in
!debug bgp updates out
!debug bgp vpn label
!debug bgp vpn leak-from-vrf
!debug bgp vpn leak-to-vrf
!debug bgp vpn rmap-event
!
router bgp 1
bgp router-id 1.1.1.1
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
neighbor 2001::2 remote-as 2
neighbor 2001::2 timers 3 10
neighbor 2001::2 timers connect 1
neighbor 2001::2 capability extended-nexthop
!
address-family ipv4 vpn
neighbor 2001::2 activate
exit-address-family
!
segment-routing srv6
locator loc1
!
!
router bgp 1 vrf vrf10
bgp router-id 1.1.1.1
no bgp ebgp-requires-policy
!
address-family ipv4 unicast
sid vpn export auto
nexthop vpn export 2001::1
rd vpn export 1:10
rt vpn both 99:99
import vpn
export vpn
redistribute connected
!
exit-address-family
!
router bgp 1 vrf vrf20
bgp router-id 1.1.1.1
no bgp ebgp-requires-policy
!
address-family ipv4 unicast
sid vpn export auto
nexthop vpn export 2001::1
rd vpn export 1:20
rt vpn both 88:88
import vpn
export vpn
redistribute connected
exit-address-family
!

View File

@ -0,0 +1,167 @@
{
"vrfId": 0,
"vrfName": "default",
"tableVersion": 2,
"routerId": "1.1.1.1",
"defaultLocPrf": 100,
"localAS": 1,
"routes": {
"routeDistinguishers": {
"1:10": {
"192.168.1.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.1.0",
"prefixLen": 24,
"network": "192.168.1.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"nhVrfName": "vrf10",
"nexthops": [
{
"ip": "2001::1",
"hostname": "r1",
"afi": "ipv6",
"used": true
}
]
}
],
"192.168.3.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.3.0",
"prefixLen": 24,
"network": "192.168.3.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"nhVrfName": "vrf10",
"nexthops": [
{
"ip": "2001::1",
"hostname": "r1",
"afi": "ipv6",
"used": true
}
]
}
]
},
"1:20": {
"192.168.5.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.5.0",
"prefixLen": 24,
"network": "192.168.5.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"nhVrfName": "vrf20",
"nexthops": [
{
"ip": "2001::1",
"hostname": "r1",
"afi": "ipv6",
"used": true
}
]
}
]
},
"2:10": {
"192.168.2.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.2.0",
"prefixLen": 24,
"network": "192.168.2.0/24",
"metric": 0,
"weight": 0,
"peerId": "2001::2",
"path": "2",
"origin": "incomplete",
"nexthops": [
{
"ip": "2001::2",
"hostname": "r2",
"afi": "ipv6",
"used": true
}
]
}
]
},
"2:20": {
"192.168.4.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.4.0",
"prefixLen": 24,
"network": "192.168.4.0/24",
"metric": 0,
"weight": 0,
"peerId": "2001::2",
"path": "2",
"origin": "incomplete",
"nexthops": [
{
"ip": "2001::2",
"hostname": "r2",
"afi": "ipv6",
"used": true
}
]
}
],
"192.168.6.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.6.0",
"prefixLen": 24,
"network": "192.168.6.0/24",
"metric": 0,
"weight": 0,
"peerId": "2001::2",
"path": "2",
"origin": "incomplete",
"nexthops": [
{
"ip": "2001::2",
"hostname": "r2",
"afi": "ipv6",
"used": true
}
]
}
]
}
}
}
}

View File

@ -0,0 +1,86 @@
{
"192.168.1.0/24": [
{
"prefix": "192.168.1.0/24",
"protocol": "connected",
"vrfName": "vrf10",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 10,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth1",
"active": true
}
]
}
],
"192.168.2.0/24": [
{
"prefix": "192.168.2.0/24",
"protocol": "bgp",
"vrfName": "vrf10",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 10,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"afi": "ipv6",
"interfaceName": "eth0",
"vrf": "default",
"active": true,
"weight": 1,
"seg6": {
"segs": "2001:db8:2:2:100::"
}
}
],
"asPath": "2"
}
],
"192.168.3.0/24": [
{
"prefix": "192.168.3.0/24",
"protocol": "connected",
"vrfName": "vrf10",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 10,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth2",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,92 @@
{
"192.168.4.0/24": [
{
"prefix": "192.168.4.0/24",
"protocol": "bgp",
"vrfName": "vrf20",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 20,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"afi": "ipv6",
"interfaceName": "eth0",
"vrf": "default",
"active": true,
"weight": 1,
"seg6": {
"segs": "2001:db8:2:2:200::"
}
}
],
"asPath": "2"
}
],
"192.168.5.0/24": [
{
"prefix": "192.168.5.0/24",
"protocol": "connected",
"vrfName": "vrf20",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 20,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth3",
"active": true
}
]
}
],
"192.168.6.0/24": [
{
"prefix": "192.168.6.0/24",
"protocol": "bgp",
"vrfName": "vrf20",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 20,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"afi": "ipv6",
"interfaceName": "eth0",
"vrf": "default",
"active": true,
"weight": 1,
"seg6": {
"segs": "2001:db8:2:2:200::"
}
}
],
"asPath": "2"
}
]
}

View File

@ -0,0 +1,41 @@
log file zebra.log
!
hostname r1
password zebra
!
log stdout notifications
log monitor notifications
log commands
!
debug zebra packet
debug zebra dplane
debug zebra kernel
!
interface eth0
ipv6 address 2001::1/64
!
interface eth1 vrf vrf10
ip address 192.168.1.1/24
ipv6 address 2001:1::1/64
!
interface eth2 vrf vrf10
ip address 192.168.3.1/24
!
interface eth3 vrf vrf20
ip address 192.168.5.1/24
!
segment-routing
srv6
locators
locator loc1
prefix 2001:db8:1:1::/64
!
!
!
ip forwarding
ipv6 forwarding
!
ipv6 route 2001:db8:2:2::/64 2001::2
!
line vty
!

View File

@ -0,0 +1,66 @@
frr defaults traditional
!
hostname r2
password zebra
!
log stdout notifications
log monitor notifications
log commands
!
!debug bgp neighbor-events
!debug bgp zebra
!debug bgp vnc verbose
!debug bgp update-groups
!debug bgp updates in
!debug bgp updates out
!debug bgp updates
!debug bgp vpn label
!debug bgp vpn leak-from-vrf
!debug bgp vpn leak-to-vrf
!debug bgp vpn rmap-event
!
router bgp 2
bgp router-id 2.2.2.2
no bgp ebgp-requires-policy
no bgp default ipv4-unicast
neighbor 2001::1 remote-as 1
neighbor 2001::1 timers 3 10
neighbor 2001::1 timers connect 1
neighbor 2001::1 capability extended-nexthop
!
address-family ipv4 vpn
neighbor 2001::1 activate
exit-address-family
!
segment-routing srv6
locator loc1
!
!
router bgp 2 vrf vrf10
bgp router-id 2.2.2.2
no bgp ebgp-requires-policy
!
address-family ipv4 unicast
sid vpn export auto
nexthop vpn export 2001::2
rd vpn export 2:10
rt vpn both 99:99
import vpn
export vpn
redistribute connected
exit-address-family
!
router bgp 2 vrf vrf20
bgp router-id 2.2.2.2
no bgp ebgp-requires-policy
!
address-family ipv4 unicast
sid vpn export auto
nexthop vpn export 2001::2
rd vpn export 2:20
rt vpn both 88:88
import vpn
export vpn
redistribute connected
exit-address-family
!

View File

@ -0,0 +1,167 @@
{
"vrfId": 0,
"vrfName": "default",
"tableVersion": 2,
"routerId": "2.2.2.2",
"defaultLocPrf": 100,
"localAS": 2,
"routes": {
"routeDistinguishers": {
"1:10": {
"192.168.1.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.1.0",
"prefixLen": 24,
"network": "192.168.1.0/24",
"metric": 0,
"weight": 0,
"peerId": "2001::1",
"path": "1",
"origin": "incomplete",
"nexthops": [
{
"ip": "2001::1",
"hostname": "r1",
"afi": "ipv6",
"used": true
}
]
}
],
"192.168.3.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.3.0",
"prefixLen": 24,
"network": "192.168.3.0/24",
"metric": 0,
"weight": 0,
"peerId": "2001::1",
"path": "1",
"origin": "incomplete",
"nexthops": [
{
"ip": "2001::1",
"hostname": "r1",
"afi": "ipv6",
"used": true
}
]
}
]
},
"1:20": {
"192.168.5.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.5.0",
"prefixLen": 24,
"network": "192.168.5.0/24",
"metric": 0,
"weight": 0,
"peerId": "2001::1",
"path": "1",
"origin": "incomplete",
"nexthops": [
{
"ip": "2001::1",
"hostname": "r1",
"afi": "ipv6",
"used": true
}
]
}
]
},
"2:10": {
"192.168.2.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.2.0",
"prefixLen": 24,
"network": "192.168.2.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"nhVrfName": "vrf10",
"nexthops": [
{
"ip": "2001::2",
"hostname": "r2",
"afi": "ipv6",
"used": true
}
]
}
]
},
"2:20": {
"192.168.4.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.4.0",
"prefixLen": 24,
"network": "192.168.4.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"nhVrfName": "vrf20",
"nexthops": [
{
"ip": "2001::2",
"hostname": "r2",
"afi": "ipv6",
"used": true
}
]
}
],
"192.168.6.0/24": [
{
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"pathFrom": "external",
"prefix": "192.168.6.0",
"prefixLen": 24,
"network": "192.168.6.0/24",
"metric": 0,
"weight": 32768,
"peerId": "(unspec)",
"path": "",
"origin": "incomplete",
"nhVrfName": "vrf20",
"nexthops": [
{
"ip": "2001::2",
"hostname": "r2",
"afi": "ipv6",
"used": true
}
]
}
]
}
}
}
}

View File

@ -0,0 +1,92 @@
{
"192.168.1.0/24": [
{
"prefix": "192.168.1.0/24",
"protocol": "bgp",
"vrfName": "vrf10",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 10,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"afi": "ipv6",
"interfaceName": "eth0",
"vrf": "default",
"active": true,
"weight": 1,
"seg6": {
"segs": "2001:db8:1:1:100::"
}
}
],
"asPath": "1"
}
],
"192.168.2.0/24": [
{
"prefix": "192.168.2.0/24",
"protocol": "connected",
"vrfName": "vrf10",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 10,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth1",
"active": true
}
]
}
],
"192.168.3.0/24": [
{
"prefix": "192.168.3.0/24",
"protocol": "bgp",
"vrfName": "vrf10",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 10,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"afi": "ipv6",
"interfaceName": "eth0",
"vrf": "default",
"active": true,
"weight": 1,
"seg6": {
"segs": "2001:db8:1:1:100::"
}
}
],
"asPath": "1"
}
]
}

View File

@ -0,0 +1,86 @@
{
"192.168.4.0/24": [
{
"prefix": "192.168.4.0/24",
"protocol": "connected",
"vrfName": "vrf20",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 20,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth2",
"active": true
}
]
}
],
"192.168.5.0/24": [
{
"prefix": "192.168.5.0/24",
"protocol": "bgp",
"vrfName": "vrf20",
"selected": true,
"destSelected": true,
"distance": 20,
"metric": 0,
"installed": true,
"table": 20,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"afi": "ipv6",
"interfaceName": "eth0",
"vrf": "default",
"active": true,
"weight": 1,
"seg6": {
"segs": "2001:db8:1:1:200::"
}
}
],
"asPath": "1"
}
],
"192.168.6.0/24": [
{
"prefix": "192.168.6.0/24",
"protocol": "connected",
"vrfName": "vrf20",
"selected": true,
"destSelected": true,
"distance": 0,
"metric": 0,
"installed": true,
"table": 20,
"internalStatus": 16,
"internalFlags": 8,
"internalNextHopNum": 1,
"internalNextHopActiveNum": 1,
"nexthops": [
{
"flags": 3,
"fib": true,
"directlyConnected": true,
"interfaceName": "eth3",
"active": true
}
]
}
]
}

View File

@ -0,0 +1,40 @@
log file zebra.log
!
hostname r2
password zebra
!
log stdout notifications
log monitor notifications
log commands
!
debug zebra packet
debug zebra dplane
debug zebra kernel
!
interface eth0
ipv6 address 2001::2/64
!
interface eth1 vrf vrf10
ip address 192.168.2.1/24
!
interface eth2 vrf vrf20
ip address 192.168.4.1/24
!
interface eth3 vrf vrf20
ip address 192.168.6.1/24
!
segment-routing
srv6
locators
locator loc1
prefix 2001:db8:2:2::/64
!
!
!
ip forwarding
ipv6 forwarding
!
ipv6 route 2001:db8:1:1::/64 2001::1
!
line vty
!

View File

@ -0,0 +1,171 @@
#!/usr/bin/env python
#
# Part of NetDEF Topology Tests
#
# Copyright (c) 2018, LabN Consulting, L.L.C.
# Authored by Lou Berger <lberger@labn.net>
#
# Permission to use, copy, modify, and/or distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice appear
# in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
#
import os
import re
import sys
import json
import functools
import pytest
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
tgen.add_router("r1")
tgen.add_router("r2")
tgen.add_router("ce1")
tgen.add_router("ce2")
tgen.add_router("ce3")
tgen.add_router("ce4")
tgen.add_router("ce5")
tgen.add_router("ce6")
tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "eth0", "eth0")
tgen.add_link(tgen.gears["ce1"], tgen.gears["r1"], "eth0", "eth1")
tgen.add_link(tgen.gears["ce2"], tgen.gears["r2"], "eth0", "eth1")
tgen.add_link(tgen.gears["ce3"], tgen.gears["r1"], "eth0", "eth2")
tgen.add_link(tgen.gears["ce4"], tgen.gears["r2"], "eth0", "eth2")
tgen.add_link(tgen.gears["ce5"], tgen.gears["r1"], "eth0", "eth3")
tgen.add_link(tgen.gears["ce6"], tgen.gears["r2"], "eth0", "eth3")
def setup_module(mod):
result = required_linux_kernel_version("5.15")
if result is not True:
pytest.skip("Kernel requirements are not met")
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
for rname, router in tgen.routers().items():
router.run("/bin/bash {}/{}/setup.sh".format(CWD, rname))
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)))
tgen.gears["r1"].run("sysctl net.vrf.strict_mode=1")
tgen.gears["r1"].run("ip link add vrf10 type vrf table 10")
tgen.gears["r1"].run("ip link set vrf10 up")
tgen.gears["r1"].run("ip link add vrf20 type vrf table 20")
tgen.gears["r1"].run("ip link set vrf20 up")
tgen.gears["r1"].run("ip link set eth1 master vrf10")
tgen.gears["r1"].run("ip link set eth2 master vrf10")
tgen.gears["r1"].run("ip link set eth3 master vrf20")
tgen.gears["r2"].run("sysctl net.vrf.strict_mode=1")
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 add vrf20 type vrf table 20")
tgen.gears["r2"].run("ip link set vrf20 up")
tgen.gears["r2"].run("ip link set eth1 master vrf10")
tgen.gears["r2"].run("ip link set eth2 master vrf20")
tgen.gears["r2"].run("ip link set eth3 master vrf20")
tgen.start_router()
def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
def open_json_file(filename):
try:
with open(filename, "r") as f:
return json.load(f)
except IOError:
assert False, "Could not read file {}".format(filename)
def check_ping(name, dest_addr, expect_connected):
def _check(name, dest_addr, match):
tgen = get_topogen()
output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
logger.info(output)
assert match in output, "ping fail"
match = "{} packet loss".format("0%" if expect_connected else "100%")
logger.info("[+] check {} {} {}".format(name, dest_addr, match))
tgen = get_topogen()
func = functools.partial(_check, name, dest_addr, match)
success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
assert result is None, "Failed"
def check_rib(name, cmd, expected_file):
def _check(name, dest_addr, match):
logger.info("polling")
tgen = get_topogen()
router = tgen.gears[name]
output = json.loads(router.vtysh_cmd(cmd))
expected = open_json_file("{}/{}".format(CWD, expected_file))
return topotest.json_cmp(output, expected)
logger.info("[+] check {} \"{}\" {}".format(name, cmd, expected_file))
tgen = get_topogen()
func = functools.partial(_check, name, cmd, expected_file)
success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
assert result is None, "Failed"
def test_rib():
check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib.json")
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib.json")
check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_rib.json")
check_rib("r1", "show ip route vrf vrf20 json", "r1/vrf20_rib.json")
check_rib("r2", "show ip route vrf vrf10 json", "r2/vrf10_rib.json")
check_rib("r2", "show ip route vrf vrf20 json", "r2/vrf20_rib.json")
check_rib("ce1", "show ip route json", "ce1/ip_rib.json")
check_rib("ce2", "show ip route json", "ce2/ip_rib.json")
check_rib("ce3", "show ip route json", "ce3/ip_rib.json")
check_rib("ce4", "show ip route json", "ce4/ip_rib.json")
check_rib("ce5", "show ip route json", "ce5/ip_rib.json")
check_rib("ce6", "show ip route json", "ce6/ip_rib.json")
def test_ping():
check_ping("ce1", "192.168.2.2", " 0% packet loss")
check_ping("ce1", "192.168.3.2", " 0% packet loss")
check_ping("ce1", "192.168.4.2", " 100% packet loss")
check_ping("ce1", "192.168.5.2", " 100% packet loss")
check_ping("ce1", "192.168.6.2", " 100% packet loss")
check_ping("ce4", "192.168.1.2", " 100% packet loss")
check_ping("ce4", "192.168.2.2", " 100% packet loss")
check_ping("ce4", "192.168.3.2", " 100% packet loss")
check_ping("ce4", "192.168.5.2", " 0% packet loss")
check_ping("ce4", "192.168.6.2", " 0% packet loss")
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))

View File

@ -438,6 +438,10 @@ parse_encap_seg6local(struct rtattr *tb,
if (tb_encap[SEG6_LOCAL_TABLE])
ctx->table = *(uint32_t *)RTA_DATA(tb_encap[SEG6_LOCAL_TABLE]);
if (tb_encap[SEG6_LOCAL_VRFTABLE])
ctx->table =
*(uint32_t *)RTA_DATA(tb_encap[SEG6_LOCAL_VRFTABLE]);
return act;
}
@ -1467,6 +1471,16 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
ctx->table))
return false;
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
if (!nl_attr_put32(nlmsg, req_size,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_DT4))
return false;
if (!nl_attr_put32(nlmsg, req_size,
SEG6_LOCAL_VRFTABLE,
ctx->table))
return false;
break;
default:
zlog_err("%s: unsupport seg6local behaviour action=%u",
__func__,
@ -2570,6 +2584,18 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
ctx->table))
return 0;
break;
case SEG6_LOCAL_ACTION_END_DT4:
if (!nl_attr_put32(
&req->n, buflen,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_DT4))
return 0;
if (!nl_attr_put32(
&req->n, buflen,
SEG6_LOCAL_VRFTABLE,
ctx->table))
return 0;
break;
default:
zlog_err("%s: unsupport seg6local behaviour action=%u",
__func__, action);