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

[test plan] 4-byte AS Translation #8973

Merged
merged 25 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e8fb9e1
Merge pull request #1 from sonic-net/master
Azarack Oct 11, 2022
7d37d5a
Merge pull request #3 from sonic-net/master
Azarack Oct 17, 2022
1597709
Merge branch 'sonic-net:master' into master
Azarack Oct 26, 2022
70bea76
Merge branch 'sonic-net:master' into master
Azarack Oct 27, 2022
d7182bc
Merge branch 'sonic-net:master' into master
Azarack Nov 9, 2022
cd5f77d
Merge branch 'sonic-net:master' into master
Azarack Nov 10, 2022
025d4f2
Merge branch 'sonic-net:master' into master
Azarack Mar 15, 2023
44449fb
Merge branch 'sonic-net:master' into master
Azarack Mar 16, 2023
e15ea86
Merge branch 'sonic-net:master' into master
Azarack Mar 21, 2023
8d81027
Merge branch 'sonic-net:master' into master
Azarack Mar 21, 2023
e5d2305
Merge branch 'sonic-net:master' into master
Azarack Mar 28, 2023
6149cb3
Merge branch 'sonic-net:master' into master
Azarack Apr 4, 2023
52dcf3f
Merge branch 'sonic-net:master' into master
Azarack Apr 7, 2023
954e1f4
Merge branch 'sonic-net:master' into master
Azarack Apr 21, 2023
fbbf6c9
Merge branch 'sonic-net:master' into master
Azarack May 10, 2023
5bf1157
Merge branch 'sonic-net:master' into master
Azarack May 16, 2023
a34389c
Merge branch 'sonic-net:master' into master
Azarack Jun 5, 2023
925b27b
Merge branch 'sonic-net:master' into master
Azarack Jun 26, 2023
5ded63d
Merge branch 'sonic-net:master' into master
Azarack Jul 10, 2023
71da2ba
adding test and test plan
Azarack Jul 13, 2023
145fef7
change to use random frontend dut
Azarack Dec 13, 2023
1cbc1cf
Merge branch 'sonic-net:master' into 4-byte_as_trans
Azarack Mar 19, 2024
ba54ccf
adding clarification for route-map and updating tor and namespace
Azarack Mar 19, 2024
6d3aea6
adding neighbor cli options
Azarack Mar 20, 2024
abb7a18
Updating name and overview
Azarack Jul 17, 2024
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
56 changes: 56 additions & 0 deletions docs/testplan/BGP-4-Byte_AS_Translation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
- [Overview](#overview)
- [Scope](#scope)
- [Testbed](#testbed)
- [Setup configuration](#setup-configuration)
- [Test cases](#test-cases)

# Test name

BGP Session Flaps
Copy link
Contributor

Choose a reason for hiding this comment

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

looks like the test name and overview is not aligned with test description. Can you check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@prsunny You are correct that this was a mistake. I have updated it to the proper name.


## Overview

The goal of this test is to verify that the CPU and memory do not spike during cycles of BGP sessions flapping.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this really meant to be a test for session flap and memory check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@prsunny You are correct that this was a mistake. I have updated it to the proper overview.


### Scope

The test is targeting a running SONIC system with fully functioning configuration. The purpose of the test is to test for 4-Byte AS translation.

### Related DUT CLI commands

| Command | Comment |
| ------- | ------- |
|Configuration commands|
| N/A | |
|Show commands|
| show ip bgp summary | Dispaly current memory statistics, can be done with ipv6 too |

### Related DUT configuration files

N/A

### Related SAI APIs

N/A

## Test structure
### Setup configuration

This test requires BGP neighbors to be configured and established.

### Configuration scripts

N/A

## Test cases
### Test case #1 - 4-byte AS Translation

#### Test objective

Have a single neighbor configured with 4-byte ASN.
Step 1: Configure DUT and neighbor with 4-Byte ASN
Step 2: Verify 4-byte BGP session between DUT and neighbor is established
Step 3: Verify BGP is established for 4-byte neighbor and down for 2-byte neighbors
Step 3: Configure DUT to use 2-byte local-ASN for 2-byte neighbors
Step 4: Verify BGP is now established for 4-byte neighbor AND 2-byte neighbors
Step 5: Verify 2-byte neighbors receive routes from upstream 4-byte routers
4 changes: 4 additions & 0 deletions tests/bgp/templates/bgp_id.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Value router_id (\d+.\d+.\d+.\d+)

Start
^BGP router identifier\s+${router_id}
284 changes: 284 additions & 0 deletions tests/bgp/test_bgp_4-byte_as_trans.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
'''

The test case will verify that the DUT supports 4-byte AS Number translation.

Step 1: Configure DUT and neighbor with 4-Byte ASN
Step 2: Verify 4-byte BGP session between DUT and neighbor is established
Step 3: Verify BGP is established for 4-byte neighbor and down for 2-byte neighbors
Step 3: Configure DUT to use 2-byte local-ASN for 2-byte neighbors
Step 4: Verify BGP is now established for 4-byte neighbor AND 2-byte neighbors
Step 5: Verify 2-byte neighbors receive routes from upstream 4-byte routers


'''
import logging

import pytest
import time
import textfsm
from tests.common.config_reload import config_reload

logger = logging.getLogger(__name__)
dut_4byte_asn = 400003
neighbor_4byte_asn = 400001
bgp_sleep = 60
bgp_id_textfsm = "./bgp/templates/bgp_id.template"

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


@pytest.fixture(scope='module')
def setup(tbinfo, nbrhosts, duthosts, enum_frontend_dut_hostname, enum_rand_one_frontend_asic_index, request):
# verify neighbors are type sonic
if request.config.getoption("neighbor_type") != "sonic":
pytest.skip("Neighbor type must be sonic")
duthost = duthosts[enum_frontend_dut_hostname]
asic_index = enum_rand_one_frontend_asic_index
namespace = duthost.get_namespace_from_asic_id(asic_index)
dut_asn = tbinfo['topo']['properties']['configuration_properties']['common']['dut_asn']
tor1 = duthost.shell("show lldp table")['stdout'].split("\n")[3].split()[1]
tor2 = duthost.shell("show lldp table")['stdout'].split("\n")[5].split()[1]

tor_neighbors = dict()
skip_hosts = duthost.get_asic_namespace_list()
bgp_facts = duthost.bgp_facts(instance_id=asic_index)['ansible_facts']
neigh_asn = dict()

# verify sessions are established and gather neighbor information
for k, v in bgp_facts['bgp_neighbors'].items():
if v['description'].lower() not in skip_hosts:
if v['description'] == tor1:
if v['ip_version'] == 4:
neigh_ip_v4 = k
peer_group_v4 = v['peer group']
elif v['ip_version'] == 6:
neigh_ip_v6 = k
peer_group_v6 = v['peer group']
if v['description'] == tor2:
if v['ip_version'] == 4:
neigh2_ip_v4 = k
elif v['ip_version'] == 6:
neigh2_ip_v6 = k
assert v['state'] == 'established'
neigh_asn[v['description']] = v['remote AS']
tor_neighbors[v['description']] = nbrhosts[v['description']]["host"]

dut_ip_v4 = tbinfo['topo']['properties']['configuration'][tor1]['bgp']['peers'][dut_asn][0]
dut_ip_v6 = tbinfo['topo']['properties']['configuration'][tor1]['bgp']['peers'][dut_asn][1]

dut_ip_bgp_sum = duthost.shell('show ip bgp summary')['stdout']
neigh_ip_bgp_sum = nbrhosts[tor1]["host"].shell('show ip bgp summary')['stdout']
neigh2_ip_bgp_sum = nbrhosts[tor1]["host"].shell('show ip bgp summary')['stdout']
with open(bgp_id_textfsm) as template:
fsm = textfsm.TextFSM(template)
dut_bgp_id = fsm.ParseText(dut_ip_bgp_sum)[0][0]
neigh_bgp_id = fsm.ParseText(neigh_ip_bgp_sum)[1][0]
neigh2_bgp_id = fsm.ParseText(neigh2_ip_bgp_sum)[1][0]

dut_ipv4_network = duthost.shell("show run bgp | grep 'ip prefix-list'")['stdout'].split()[6]
dut_ipv6_network = duthost.shell("show run bgp | grep 'ipv6 prefix-list'")['stdout'].split()[6]
neigh_ipv4_network = nbrhosts[tor1]["host"].shell("show run bgp | grep 'ip prefix-list'")['stdout'].split()[6]
neigh_ipv6_network = nbrhosts[tor1]["host"].shell("show run bgp | grep 'ipv6 prefix-list'")['stdout'].split()[6]

setup_info = {
'duthost': duthost,
'neighhost': tor_neighbors[tor1],
'neigh2host': tor_neighbors[tor2],
'tor1': tor1,
'tor2': tor2,
'dut_asn': dut_asn,
'neigh_asn': neigh_asn[tor1],
'neigh2_asn': neigh_asn[tor2],
'asn_dict': neigh_asn,
'neighbors': tor_neighbors,
'namespace': namespace,
'dut_ip_v4': dut_ip_v4,
'dut_ip_v6': dut_ip_v6,
'neigh_ip_v4': neigh_ip_v4,
'neigh_ip_v6': neigh_ip_v6,
'neigh2_ip_v4': neigh2_ip_v4,
'neigh2_ip_v6': neigh2_ip_v6,
'peer_group_v4': peer_group_v4,
'peer_group_v6': peer_group_v6,
'asic_index': asic_index,
'dut_bgp_id': dut_bgp_id,
'neigh_bgp_id': neigh_bgp_id,
'neigh2_bgp_id': neigh2_bgp_id,
'dut_ipv4_network': dut_ipv4_network,
'dut_ipv6_network': dut_ipv6_network,
'neigh_ipv4_network': neigh_ipv4_network,
'neigh_ipv6_network': neigh_ipv6_network
}

logger.info("DUT BGP Config: {}".format(duthost.shell("show run bgp", module_ignore_errors=True)['stdout']))
logger.info("Neighbor BGP Config: {}".format(nbrhosts[tor1]["host"].shell("show run bgp")['stdout']))
logger.info('Setup_info: {}'.format(setup_info))

yield setup_info

# restore config to original state
config_reload(duthost)
config_reload(tor_neighbors[tor1], is_dut=False)

# verify sessions are established
bgp_facts = duthost.bgp_facts(instance_id=asic_index)['ansible_facts']
for k, v in bgp_facts['bgp_neighbors'].items():
if v['description'].lower() not in skip_hosts:
logger.debug(v['description'])
assert v['state'] == 'established'


def test_4_byte_asn_translation(setup):
cmd = 'vtysh -n {} \
-c "config" \
-c "no router bgp {}" \
-c "router bgp {}" \
-c "bgp router-id {}" \
-c "bgp log-neighbor-changes" \
-c "no bgp ebgp-requires-policy" \
-c "no bgp default ipv4-unicast" \
-c "bgp bestpath as-path multipath-relax" \
-c "neighbor {} peer-group" \
-c "neighbor {} peer-group" \
-c "neighbor {} remote-as {}" \
-c "neighbor {} peer-group {}" \
-c "neighbor {} description {}" \
-c "neighbor {} timers 3 10" \
-c "neighbor {} timers connect 10" \
-c "neighbor {} remote-as {}" \
-c "neighbor {} peer-group {}" \
-c "neighbor {} description {}" \
-c "neighbor {} timers 3 10" \
-c "neighbor {} timers connect 10" \
-c "neighbor {} remote-as {}" \
-c "neighbor {} peer-group {}" \
-c "neighbor {} description {}" \
-c "neighbor {} timers 3 10" \
-c "neighbor {} timers connect 10" \
-c "neighbor {} remote-as {}" \
-c "neighbor {} peer-group {}" \
-c "neighbor {} description {}" \
-c "neighbor {} timers 3 10" \
-c "neighbor {} timers connect 10" \
-c "address-family ipv4 unicast" \
-c "network {}" \
-c "neighbor {} soft-reconfiguration inbound" \
-c "neighbor {} route-map FROM_BGP_PEER_V4 in" \

Choose a reason for hiding this comment

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

route-map define is missing in the file, what exactly the route-map contain, similar other route map in the files as well.

Copy link
Contributor Author

@Azarack Azarack Mar 19, 2024

Choose a reason for hiding this comment

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

@kishorekunal01 This is a pre-configured route map that is part of the T2 BGP configuration. I did add a comment specifying this at the start of the command block.

-c "neighbor {} route-map TO_BGP_PEER_V4 out" \
-c "neighbor {} activate" \
-c "neighbor {} activate" \
-c "maximum-paths 64" \
-c "exit-address-family" \
-c "address-family ipv6 unicast" \
-c "network {}" \
-c "neighbor {} soft-reconfiguration inbound" \
-c "neighbor {} route-map FROM_BGP_PEER_V6 in" \
-c "neighbor {} route-map TO_BGP_PEER_V6 out" \
-c "neighbor {} activate" \
-c "neighbor {} activate" \
-c "maximum-paths 64" \
-c "exit-address-family" \
'.format(setup['namespace'], setup['dut_asn'], dut_4byte_asn, setup['dut_bgp_id'],
setup['peer_group_v4'], setup['peer_group_v6'], setup['neigh_ip_v4'], neighbor_4byte_asn,
setup['neigh_ip_v4'], setup['peer_group_v4'], setup['neigh_ip_v4'], setup['tor1'], setup['neigh_ip_v4'],
setup['neigh_ip_v4'], setup['neigh_ip_v6'], neighbor_4byte_asn, setup['neigh_ip_v6'],
setup['peer_group_v6'], setup['neigh_ip_v6'], setup['tor1'], setup['neigh_ip_v6'], setup['neigh_ip_v6'],
setup['neigh2_ip_v4'], setup['neigh2_asn'], setup['neigh2_ip_v4'], setup['peer_group_v4'],
setup['neigh2_ip_v4'], setup['tor2'], setup['neigh2_ip_v4'], setup['neigh2_ip_v4'], setup['neigh2_ip_v6'],
setup['neigh2_asn'], setup['neigh2_ip_v6'], setup['peer_group_v6'], setup['neigh2_ip_v6'], setup['tor2'],
setup['neigh2_ip_v6'], setup['neigh2_ip_v6'], setup['dut_ipv4_network'], setup['peer_group_v4'],
setup['peer_group_v4'], setup['peer_group_v4'], setup['neigh_ip_v4'], setup['neigh2_ip_v4'],
setup['dut_ipv6_network'], setup['peer_group_v6'], setup['peer_group_v6'], setup['peer_group_v6'],
setup['neigh_ip_v6'], setup['neigh2_ip_v6'])
logger.debug(setup['duthost'].shell(cmd, module_ignore_errors=True))

cmd = 'vtysh \
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add the cli_options = "-n " + duthost.get_namespace_from_asic_id(asic_index) here also? T2 neighbor could be multi-asic

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I added cli options for the neighbor.

-c "config" \
-c "no router bgp {}" \
-c "router bgp {}" \
-c "bgp router-id {}" \
-c "bgp log-neighbor-changes" \
-c "no bgp ebgp-requires-policy" \
-c "no bgp default ipv4-unicast" \
-c "bgp bestpath as-path multipath-relax" \
-c "neighbor {} peer-group" \
-c "neighbor {} peer-group" \
-c "neighbor {} remote-as {}" \
-c "neighbor {} peer-group {}" \
-c "neighbor {} description {}" \
-c "neighbor {} timers 3 10" \
-c "neighbor {} timers connect 10" \
-c "neighbor {} remote-as {}" \
-c "neighbor {} peer-group {}" \
-c "neighbor {} description {}" \
-c "neighbor {} timers 3 10" \
-c "neighbor {} timers connect 10" \
-c "address-family ipv4 unicast" \
-c "network {}" \
-c "neighbor {} soft-reconfiguration inbound" \
-c "neighbor {} route-map FROM_BGP_PEER_V4 in" \
-c "neighbor {} route-map TO_BGP_PEER_V4 out" \
-c "neighbor {} activate" \
-c "maximum-paths 64" \
-c "exit-address-family" \
-c "address-family ipv6 unicast" \
-c "network {}" \
-c "neighbor {} soft-reconfiguration inbound" \
-c "neighbor {} route-map FROM_BGP_PEER_V6 in" \
-c "neighbor {} route-map TO_BGP_PEER_V6 out" \
-c "neighbor {} activate" \
-c "maximum-paths 64" \
-c "exit-address-family" \
'.format(setup['neigh_asn'], neighbor_4byte_asn, setup['neigh_bgp_id'],
setup['peer_group_v4'], setup['peer_group_v6'], setup['dut_ip_v4'], dut_4byte_asn, setup['dut_ip_v4'],
setup['peer_group_v4'], setup['dut_ip_v4'], 'DUT', setup['dut_ip_v4'], setup['dut_ip_v4'],
setup['dut_ip_v6'], dut_4byte_asn, setup['dut_ip_v6'], setup['peer_group_v6'], setup['dut_ip_v6'], 'DUT',
setup['dut_ip_v6'], setup['dut_ip_v6'], setup['neigh_ipv4_network'], setup['peer_group_v4'],
setup['peer_group_v4'], setup['peer_group_v4'], setup['dut_ip_v4'], setup['neigh_ipv6_network'],
setup['peer_group_v6'], setup['peer_group_v6'], setup['peer_group_v6'], setup['dut_ip_v6'])

logger.debug(setup['neighhost'].shell(cmd, module_ignore_errors=True))

logger.info("DUT BGP Config: {}".format(setup['duthost'].shell("show run bgp")['stdout']))
logger.info("Neighbor BGP Config: {}".format(setup['neighhost'].shell("show run bgp")['stdout']))

time.sleep(bgp_sleep)
Copy link
Contributor

Choose a reason for hiding this comment

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

could you elaborate on what the previous cmd is doing?
the sleep time could be different among T2s

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The previous command configures a 4-byte ASN on the neighbor device.
I'm not sure what you mean by the sleep time being different as this is a variable set in the script.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean how did you decide bgp_sleep?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is the standard amount of time we wait for our tests to allow BGP to converge. Then after running the test case if there is an issue it is extended.

Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM if this sleep time of 120 works well on T2


# verify session to 4-byte neighbor is established and 2-byte neighbor is down
bgp_facts = setup['duthost'].bgp_facts(instance_id=setup['asic_index'])['ansible_facts']
for k, v in bgp_facts['bgp_neighbors'].items():
if v['description'].lower() == setup['tor1']:
logger.debug(v['description'])
assert v['state'] == 'established'
elif v['description'].lower() == setup['tor2']:
logger.debug(v['description'])
assert v['state'] != 'established'

# Configure DUT to use 2-byte local-ASN for 2-byte neighbors
cmd = 'vtysh -n {} \
-c "config" \
-c "router bgp {}" \
-c "neighbor {} local-as {}" \
-c "neighbor {} local-as {}" \
'.format(setup['namespace'], dut_4byte_asn, setup['peer_group_v4'], setup['dut_asn'], setup['peer_group_v6'],
setup['dut_asn'])
logger.debug(setup['duthost'].shell(cmd, module_ignore_errors=True))
cmd = 'vtysh -n {} -c "clear bgp *"'.format(setup['namespace'])
logger.debug(setup['duthost'].shell(cmd, module_ignore_errors=True))

time.sleep(bgp_sleep)

# verify session to 4-byte and 2-byte neighbor is established
bgp_facts = setup['duthost'].bgp_facts(instance_id=setup['asic_index'])['ansible_facts']
for k, v in bgp_facts['bgp_neighbors'].items():
if v['description'].lower() == setup['tor1']:
logger.debug(v['description'])
assert v['state'] == 'established'
elif v['description'].lower() == setup['tor2']:
logger.debug(v['description'])
assert v['state'] == 'established'

cmd = 'vtysh -c "show bgp ipv4 all neighbors {}" received-routes'.format(setup['neigh_ipv4_network'])
logger.debug(setup['neigh2host'].shell(cmd, module_ignore_errors=True))