Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SRv6 uSID BGP L3VPN services #15510

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions docs/testplan/srv6/SRv6-testplan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SRv6 uSID Tests #

## Outline

- [Overview](#overview)
- [Scope](#scope)
- [Testbed](#testbed)
- [Setup configuration](#setup-configuration)
- [Test cases](#test-cases)

## Overview
The purpose of this test is to verify that FRR programs SRv6 SIDs and policies correctly into the SONiC dataplane.

### Scope
The test is targeting a running SONIC system with fully functioning configuration. The purpose of the test is to test SRv6 uSID functionality.

### Testbed
The test will run on t0 testbed.

## Setup configuration
The test requires to configure BGP neighborship between DUT and one neighbor.

## Test cases
### Test case # 1 - Verify SRv6 uSID BGP L3VPN services
* Configure a BGP session between DUT and one neighbor.
* Setup an SRv6 uSID L3VPN between the DUT and the neighbor.
* Verify that the DUT programs a SID list in the SONiC data plane.
* Verify that the DUT programs a route to steer VPN traffic over the SID list.
* Verify that the DUT programs an SRv6 uDT6 SID to decapsulate and forward the VPN traffic received from the neighbor.
170 changes: 170 additions & 0 deletions tests/srv6/test_srv6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import pytest
import logging
from tests.common.helpers.assertions import pytest_assert as py_assert

pytestmark = [
pytest.mark.topology('t0')
]

Logger = logging.getLogger(__name__)

V6_PREFIX_NBR = "2001:db8::"
V6_MASK_NBR = "64"

V6_PREFIX_DUT = "2001:db8:1::"
V6_MASK_DUT = "64"


@pytest.fixture(name="setUp", scope="module")
def fixture_setUp(nbrhosts, duthosts, enum_frontend_dut_hostname):

# pick dut
duthost = duthosts[enum_frontend_dut_hostname]

# pick one neighbor
nbr = None
nbrnames = list(nbrhosts.keys())
for name in nbrnames:
if 'T1' in name:
nbr = nbrhosts[name]
break
py_assert(nbr is not None, "No T1 neighbors")

yield (nbr, duthost)

Logger.info("Performing cleanup")

# cleanup neighbor
cmd = "config vrf del Vrf10"
nbr['host'].shell(cmd)

# cleanup dut
duthost = duthosts[enum_frontend_dut_hostname]
cmd = "config vrf del Vrf10"
duthost.shell(cmd)


def run_srv6(enum_frontend_dut_hostname, hosts):
""" Route added on All neighbor should be learned by the DUT"""
Logger.info("Adding routes on neighbors")

nbr = hosts[0]
duthost = hosts[1]

# configure bgp on neighbor
cmd = "config vrf add Vrf10"
nbr['host'].shell(cmd)
cmd = "config loopback add Loopback1"
nbr['host'].shell(cmd)
cmd = "config interface vrf bind Loopback1 Vrf10"
nbr['host'].shell(cmd)
cmd = "config interface ip add Loopback1 2001:db8:2::1"
nbr['host'].shell(cmd)
cmd = ("vtysh"
" -c 'configure'"
" -c 'ipv6 route {}/{} Loopback1'"
" -c 'segment-routing'"
" -c 'srv6'"
" -c 'locators'"
" -c 'locator MAIN'"
" -c 'prefix fcbb:bbbb:1::/48 block-len 32 node-len 16 func-bits 16'"
" -c 'exit'"
" -c 'exit'"
" -c 'exit'"
" -c 'exit'"
" -c 'router bgp 64600'"
Copy link
Contributor

Choose a reason for hiding this comment

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

Where do we configure the BGP session in this FRR config?

Copy link
Author

Choose a reason for hiding this comment

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

In the FRR config, the line below configures the BGP session with the other node.

 -c 'neighbor 2001:db8:2::1 remote-as 65100'

" -c 'address-family ipv6 unicast'"
" -c 'network {}/{}'"
" -c 'exit'"
" -c 'segment-routing srv6'"
" -c 'locator MAIN'"
" -c 'exit'"
" -c 'router bgp 64600 vrf Vrf10'"
" -c 'address-family ipv6 unicast'"
" -c 'sid vpn export auto'"
" -c 'rd vpn export 1:10'"
" -c 'rt vpn both 99:99'"
" -c 'import vpn'"
" -c 'export vpn'"
" -c 'redistribute connected'"
" -c 'exit'"
" -c 'exit'").format(V6_PREFIX_NBR, V6_MASK_NBR, V6_PREFIX_NBR, V6_MASK_NBR)
nbr['host'].shell(cmd)
Logger.info("Route %s added", V6_PREFIX_NBR)

# configure bgp on dut
cmd = "config vrf add Vrf10"
duthost.shell(cmd)
cmd = "config loopback add Loopback1"
duthost.shell(cmd)
cmd = "config interface vrf bind Loopback1 Vrf10"
duthost.shell(cmd)
cmd = "config interface ip add Loopback1 2001:db8:2::1"
Copy link
Contributor

Choose a reason for hiding this comment

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

although this may not have any functional impact, but we'd better use a different Loopback address for DUT instead of reusing the Loopback address.

Copy link
Author

Choose a reason for hiding this comment

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

I agree with your point. I assigned the neighbor a Loopback address different from the DUT

duthost.shell(cmd)
cmd = ("vtysh"
" -c 'configure'"
" -c 'ipv6 route {}/{} Loopback1'"
" -c 'segment-routing'"
" -c 'srv6'"
" -c 'locators'"
" -c 'locator MAIN'"
" -c 'prefix fcbb:bbbb:2::/48 block-len 32 node-len 16 func-bits 16'"
" -c 'exit'"
" -c 'exit'"
" -c 'exit'"
" -c 'exit'"
" -c 'router bgp 65100'"
" -c 'address-family ipv6 unicast'"
" -c 'network {}/{}'"
" -c 'exit'"
" -c 'segment-routing srv6'"
" -c 'locator MAIN'"
" -c 'exit'"
" -c 'router bgp 65100 vrf Vrf10'"
" -c 'address-family ipv6 unicast'"
" -c 'sid vpn export auto'"
" -c 'rd vpn export 2:10'"
" -c 'rt vpn both 99:99'"
" -c 'import vpn'"
" -c 'export vpn'"
" -c 'redistribute connected'"
" -c 'exit'"
" -c 'exit'").format(V6_PREFIX_DUT, V6_MASK_DUT, V6_PREFIX_DUT, V6_MASK_DUT)
duthost.shell(cmd)
Logger.info("Route %s added to :duthost", V6_PREFIX_DUT)

# check ROUTE_TABLE
Logger.info("checking DUT for route %s", V6_PREFIX_NBR)
cmd = "redis-cli -n 0 hgetall \"ROUTE_TABLE:Vrf10:{}\"".format(V6_PREFIX_NBR)
result = duthost.shell(cmd)
result = result['stdout']
Logger.info("Route table nexthops are %s", result)
py_assert(result != "", "The DUT did not program the SRv6 steering route")
py_assert("segments: Vrf10:2001:db8::/64" not in result,
"The DUT did not program the SRv6 steering route correctly, missing 'segments' field")
py_assert("source: fc00:0:1::1" not in result,
"The DUT did not program the SRv6 steering route correctly, missing 'source' field")

# check SRV6_SID_LIST_TABLE
Logger.info("checking DUT for route %s", V6_PREFIX_NBR)
cmd = "redis-cli -n 0 hgetall \"SRV6_SID_LIST_TABLE:Vrf10:{}\"".format(V6_PREFIX_NBR)
result = duthost.shell(cmd)
result = result['stdout']
Logger.info("Route table nexthops are %s", result)
Copy link
Contributor

Choose a reason for hiding this comment

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

The log statements seems to be not updated accordingly? You are checking SID_LIST_TABLE here right? The log statement for MY_SID table seems to be not correct as well.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, indeed the log statement was incorrect. I fixed it. Thanks.

py_assert(result != "", "The DUT did not program the SRv6 SID list")
py_assert("path: fcbb:bbbb:1:1::" not in result,
"The DUT did not program the SRv6 SID list correctly, missing 'path' field")

# check SRV6_MY_SID_TABLE
Logger.info("checking DUT for route %s", V6_PREFIX_NBR)
cmd = "redis-cli -n 0 hgetall \"SRV6_MY_SID_TABLE:32:16:16:0:fcbb:bbbb:2:1::\""
result = duthost.shell(cmd)
result = result['stdout']
Logger.info("Route table nexthops are %s", result)
py_assert(result != "", "The DUT did not program SRv6 MySid entry")
py_assert("action: udt6" not in result, "The DUT did not program SRv6 MySid entry, missing 'action' field")
Copy link
Contributor

Choose a reason for hiding this comment

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

where do you configure the udt6 action?

Copy link
Author

Choose a reason for hiding this comment

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

uDT6 SID is created automatically by BGP.

When you set sid vpn export auto under the address-family ipv6 unicast section in the FRR config, BGP automatically creates the uDT6 SID.

py_assert("vrf: Vrf10" not in result, "The DUT did not program SRv6 MySid entry correcly, missing 'vrf' field")


def test_srv6(enum_frontend_dut_hostname, setUp):
run_srv6(enum_frontend_dut_hostname, setUp)
Loading