Skip to content

Commit 651ffb4

Browse files
aronovicdcaugher
authored andcommitted
[SmartSwitch] Restore dash smartswitch vnet after protobuf updates and pr 19700 merge (sonic-net#20998)
Description of PR This change restores the functionality of the dash smartswitch vnet testing after the latest changes to the proto buffers and pr 19700 The issue was that the vnet smartswitch test was failing becase the dash parser is now using the same method as for private link but is missing some cases used when parsing config templates for vnet. Also some of the configurations from templates need to be updated based on the latest dash proto updates.
1 parent 33566f5 commit 651ffb4

File tree

8 files changed

+124
-70
lines changed

8 files changed

+124
-70
lines changed

tests/common/plugins/conditional_mark/tests_mark_conditions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ dash/test_dash_smartswitch_vnet.py:
697697
reason: "Currently dash tests are not supported on KVM or non-smartswitch T1s"
698698
conditions:
699699
- "asic_type in ['vs'] and https://github.com/sonic-net/sonic-mgmt/issues/16407"
700-
- "hwsku not in ['Cisco-8102-28FH-DPU-O-T1', 'Mellanox-SN4280-O8C40', 'Mellanox-SN4280-O28']"
700+
- "hwsku not in ['Cisco-8102-28FH-DPU-O-T1', 'Mellanox-SN4280-O8C40', 'Mellanox-SN4280-O28', 'Cisco-8102-28FH-DPU-O']"
701701

702702
dash/test_dash_vnet.py:
703703
skip:

tests/dash/packets.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ def outbound_smartswitch_vnet_packets(
511511
ip_src=dash_config_info[LOCAL_PA_IP],
512512
ip_dst=dash_config_info[LOOPBACK_IP],
513513
udp_dport=vxlan_udp_dport,
514+
udp_sport=VXLAN_UDP_BASE_SRC_PORT,
514515
with_udp_chksum=False,
515516
vxlan_vni=dash_config_info[VNET1_VNI],
516517
ip_ttl=64,

tests/dash/proto_utils.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
from ipaddress import ip_address
77

88
from dash_api.appliance_pb2 import Appliance
9-
from dash_api.eni_pb2 import Eni
9+
from dash_api.eni_pb2 import Eni, State # noqa: F401
1010
from dash_api.eni_route_pb2 import EniRoute
1111
from dash_api.route_group_pb2 import RouteGroup
1212
from dash_api.route_pb2 import Route
13-
from dash_api.route_type_pb2 import ActionType, RouteType, RouteTypeItem
13+
from dash_api.route_type_pb2 import ActionType, RouteType, RouteTypeItem, EncapType, RoutingType # noqa: F401
1414
from dash_api.vnet_mapping_pb2 import VnetMapping
1515
from dash_api.vnet_pb2 import Vnet
1616
from dash_api.meter_policy_pb2 import MeterPolicy
@@ -92,6 +92,11 @@ def parse_dash_proto(key: str, proto_dict: dict):
9292
table_name = re.search(r"DASH_(\w+)_TABLE", key).group(1)
9393
message = PB_CLASS_MAP[table_name]()
9494
field_map = message.DESCRIPTOR.fields_by_name
95+
96+
if table_name == "ROUTING_TYPE":
97+
pb = routing_type_from_json(proto_dict)
98+
return pb
99+
95100
new_dict = {}
96101
for key, value in proto_dict.items():
97102
if field_map[key].type == field_map[key].TYPE_MESSAGE:
@@ -111,6 +116,12 @@ def parse_dash_proto(key: str, proto_dict: dict):
111116
elif field_map[key].type == field_map[key].TYPE_BYTES:
112117
new_dict[key] = parse_byte_field(value)
113118

119+
elif field_map[key].type == field_map[key].TYPE_ENUM:
120+
if isinstance(value, int):
121+
new_dict[key] = value
122+
else:
123+
new_dict[key] = get_enum_type_from_str(field_map[key].enum_type.name, value)
124+
114125
elif field_map[key].type in PB_INT_TYPES:
115126
new_dict[key] = int(value)
116127

@@ -139,24 +150,21 @@ def get_enum_type_from_str(enum_type_str, enum_name_str):
139150

140151
def routing_type_from_json(json_obj):
141152
pb = RouteType()
142-
if isinstance(json_obj, list):
143-
for item in json_obj:
144-
pbi = RouteTypeItem()
145-
pbi.action_name = item["action_name"]
153+
route_type_items = json_obj['items']
154+
for item in route_type_items:
155+
pbi = RouteTypeItem()
156+
pbi.action_name = item["action_name"]
157+
if isinstance(item.get("action_type"), int):
158+
pbi.action_type = item.get("action_type")
159+
else:
146160
pbi.action_type = get_enum_type_from_str('ActionType', item.get("action_type"))
147-
if item.get("encap_type") is not None:
161+
if item.get("encap_type") is not None:
162+
if isinstance(item.get("encap_type"), int):
163+
pbi.encap_type = item.get("encap_type")
164+
else:
148165
pbi.encap_type = get_enum_type_from_str('EncapType', item.get("encap_type"))
149-
if item.get("vni") is not None:
150-
pbi.vni = int(item["vni"])
151-
pb.items.append(pbi)
152-
else:
153-
pbi = RouteTypeItem()
154-
pbi.action_name = json_obj["action_name"]
155-
pbi.action_type = get_enum_type_from_str('ActionType', json_obj.get("action_type"))
156-
if json_obj.get("encap_type") is not None:
157-
pbi.encap_type = get_enum_type_from_str('EncapType', json_obj.get("encap_type"))
158-
if json_obj.get("vni") is not None:
159-
pbi.vni = int(json_obj["vni"])
166+
if item.get("vni") is not None:
167+
pbi.vni = int(item["vni"])
160168
pb.items.append(pbi)
161169
return pb
162170

tests/dash/templates/dash_smartswitch_vnet_0.j2

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"DASH_APPLIANCE_TABLE:123" : {
44
"sip":"{{ loopback_ip }}",
55
"vm_vni":"{{ vm_vni }}",
6-
"local_region_id":"{{ local_region_id }}"
6+
"local_region_id":"{{ local_region_id }}",
7+
"trusted_vnis": "100"
78
},
89
"OP": "{{ op }}"
910
}

tests/dash/templates/dash_smartswitch_vnet_1.j2

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
11
[
22
{
3-
"DASH_ROUTING_TYPE_TABLE:vnet": {
4-
"action_name": "action1",
5-
"action_type": "maprouting"
6-
},
3+
"DASH_ROUTING_TYPE_TABLE:vnet": { "items": [
4+
{
5+
"action_name": "action1",
6+
"action_type": "maprouting"
7+
}
8+
]},
79
"OP": "{{ op }}"
810
},
911
{
10-
"DASH_ROUTING_TYPE_TABLE:vnet_direct": {
11-
"action_name": "action1",
12-
"action_type": "maprouting"
13-
},
12+
"DASH_ROUTING_TYPE_TABLE:vnet_direct": { "items": [
13+
{
14+
"action_name": "action1",
15+
"action_type": "maprouting"
16+
}
17+
]},
1418
"OP": "{{ op }}"
1519
},
1620
{
17-
"DASH_ROUTING_TYPE_TABLE:vnet_encap": {
18-
"action_name": "action1",
19-
"action_type": "staticencap",
20-
"encap_type": "vxlan"
21-
},
21+
"DASH_ROUTING_TYPE_TABLE:vnet_encap": { "items": [
22+
{
23+
"action_name": "action1",
24+
"action_type": "staticencap",
25+
"encap_type": "vxlan"
26+
}
27+
]},
2228
"OP": "{{ op }}"
2329
},
2430
{

tests/dash/templates/dash_smartswitch_vnet_2.j2

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
"mac_address":"{{ local_eni_mac }}",
66
"underlay_ip":"{{ local_pa_ip }}",
77
"admin_state":"enabled",
8-
"vnet":"{{ vnet1_name }}",
9-
"qos":"qos100"
8+
"vnet":"{{ vnet1_name }}"
109
},
1110
"OP": "{{ op }}"
1211
},

tests/dash/templates/dash_smartswitch_vnet_3.j2

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,7 @@
44
"routing_type":"vnet_encap",
55
"underlay_ip":"{{ remote_pa_ip }}",
66
"mac_address":"{{ remote_eni_mac }}",
7-
"use_dst_vni":"true"
8-
},
9-
"OP": "{{ op }}"
10-
},
11-
{
12-
"DASH_QOS_TABLE:qos100" : {
13-
"qos_id":"100",
14-
"bw":"4000000000",
15-
"cps":"10000000",
16-
"flows":"50000000"
7+
"use_dst_vni":true
178
},
189
"OP": "{{ op }}"
1910
},

tests/dash/test_dash_smartswitch_vnet.py

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22
import pytest
33
import ptf.testutils as testutils
44
import packets
5+
import time
6+
import json
57

6-
from constants import LOCAL_PTF_INTF, REMOTE_PA_IP, REMOTE_PTF_RECV_INTF, REMOTE_DUT_INTF
8+
from constants import LOCAL_PTF_INTF, REMOTE_PA_IP, REMOTE_PTF_RECV_INTF, REMOTE_DUT_INTF, \
9+
VXLAN_UDP_BASE_SRC_PORT, VXLAN_UDP_SRC_PORT_MASK
710
from gnmi_utils import apply_gnmi_file
811
from dash_utils import render_template_to_host, apply_swssconfig_file
912
from tests.dash.conftest import get_interface_ip
13+
from tests.common import config_reload
1014

1115
APPLIANCE_VIP = "10.1.0.5"
1216
ENABLE_GNMI_API = True
@@ -21,47 +25,100 @@
2125

2226
"""
2327
Test prerequisites:
24-
- DPU needs the Appliance VIP configured as its loopback IP
2528
- Assign IPs to DPU-NPU dataplane interfaces
26-
- Default route on DPU to NPU
2729
"""
2830

2931

3032
@pytest.fixture(scope="module", autouse=True)
31-
def add_dpu_static_route(duthost, dpu_ip):
32-
cmd = f"ip route replace {APPLIANCE_VIP}/32 via {dpu_ip}"
33-
duthost.shell(cmd)
33+
def dpu_setup_vnet(duthost, dpuhosts, dpu_index, skip_config):
34+
if skip_config:
3435

35-
yield
36+
return
37+
dpuhost = dpuhosts[dpu_index]
38+
# explicitly add mgmt IP route so the default route doesn't disrupt SSH access
39+
dpuhost.shell(f'ip route replace {duthost.mgmt_ip}/32 via 169.254.200.254')
40+
intfs = dpuhost.shell("show ip int")["stdout"]
41+
dpu_cmds = list()
42+
if "Loopback0" not in intfs:
43+
dpu_cmds.append("config loopback add Loopback0")
44+
dpu_cmds.append(f"config int ip add Loopback0 {APPLIANCE_VIP}/32")
3645

37-
duthost.shell(f"ip route del {APPLIANCE_VIP}/32 via {dpu_ip}")
46+
dpu_cmds.append(f"ip route replace default via {dpuhost.npu_data_port_ip}")
47+
dpuhost.shell_cmds(cmds=dpu_cmds)
3848

3949

4050
@pytest.fixture(scope="module", autouse=True)
41-
def add_npu_static_routes(duthost, dpu_ip, dash_smartswitch_vnet_config, skip_config, skip_cleanup):
51+
def add_npu_static_routes_vnet(duthost, dash_smartswitch_vnet_config, skip_config, skip_cleanup, dpu_index, dpuhosts):
4252
if not skip_config:
53+
dpuhost = dpuhosts[dpu_index]
4354
cmds = []
4455
pe_nexthop_ip = get_interface_ip(duthost, dash_smartswitch_vnet_config[REMOTE_DUT_INTF]).ip + 1
4556
cmds.append(f"ip route replace {dash_smartswitch_vnet_config[REMOTE_PA_IP]}/32 via {pe_nexthop_ip}")
57+
cmds.append(f"ip route replace {APPLIANCE_VIP}/32 via {dpuhost.dpu_data_port_ip}")
4658
logger.info(f"Adding static routes: {cmds}")
4759
duthost.shell_cmds(cmds=cmds)
4860

4961
yield
5062

5163
if not skip_config and not skip_cleanup:
64+
dpuhost = dpuhosts[dpu_index]
5265
cmds = []
5366
cmds.append(f"ip route del {dash_smartswitch_vnet_config[REMOTE_PA_IP]}/32 via {pe_nexthop_ip}")
67+
cmds.append(f"ip route del {APPLIANCE_VIP}/32 via {dpuhost.dpu_data_port_ip}")
5468
logger.info(f"Removing static routes: {cmds}")
5569
duthost.shell_cmds(cmds=cmds)
5670

5771

58-
@pytest.fixture(autouse=True)
59-
def common_setup_teardown(localhost, duthost, ptfhost, dpu_index, dash_smartswitch_vnet_config, skip_config):
72+
@pytest.fixture(scope="module", autouse=True)
73+
def set_vxlan_udp_sport_range(dpuhosts, dpu_index):
74+
"""
75+
Configure VXLAN UDP source port range in dpu configuration.
76+
"""
77+
dpuhost = dpuhosts[dpu_index]
78+
vxlan_sport_config = [
79+
{
80+
"SWITCH_TABLE:switch": {
81+
"vxlan_sport": VXLAN_UDP_BASE_SRC_PORT,
82+
"vxlan_mask": VXLAN_UDP_SRC_PORT_MASK
83+
},
84+
"OP": "SET"
85+
}
86+
]
87+
88+
logger.info(f"Setting VXLAN source port config: {vxlan_sport_config}")
89+
config_path = "/tmp/vxlan_sport_config.json"
90+
dpuhost.copy(content=json.dumps(vxlan_sport_config, indent=4), dest=config_path, verbose=False)
91+
apply_swssconfig_file(dpuhost, config_path)
92+
if 'pensando' in dpuhost.facts['asic_type']:
93+
logger.warning("Applying Pensando DPU VXLAN sport workaround")
94+
dpuhost.shell("pdsctl debug update device --vxlan-port 4789 --vxlan-src-ports 5120-5247")
95+
yield
96+
if str(VXLAN_UDP_BASE_SRC_PORT) in dpuhost.shell("redis-cli -n 0 hget SWITCH_TABLE:switch vxlan_sport")['stdout']:
97+
config_reload(dpuhost, safe_reload=True, yang_validate=False)
98+
99+
100+
@pytest.fixture(scope="module", autouse=True)
101+
def common_setup_teardown(
102+
localhost,
103+
duthost,
104+
ptfhost,
105+
dpu_index,
106+
dash_smartswitch_vnet_config,
107+
skip_config,
108+
dpuhosts,
109+
add_npu_static_routes_vnet,
110+
dpu_setup_vnet,
111+
set_vxlan_udp_sport_range):
60112
if skip_config:
61113
return
62114

63-
host = f"dpu{dpu_index}"
115+
dpuhost = dpuhosts[dpu_index]
116+
host = f"dpu{dpuhost.dpu_index}"
64117
op = "SET"
118+
# Until this fix and related are in 202506 release this workaround is needed
119+
# Issue observed is that first set of DASH objects is not configured
120+
# https://github.com/sonic-net/sonic-swss-common/pull/1068
121+
time.sleep(180)
65122
for i in range(0, 4):
66123
config = f"dash_smartswitch_vnet_{i}"
67124
template_name = "{}.j2".format(config)
@@ -74,29 +131,20 @@ def common_setup_teardown(localhost, duthost, ptfhost, dpu_index, dash_smartswit
74131

75132
yield
76133

77-
op = "DEL"
78-
for i in reversed(range(0, 4)):
79-
config = f"dash_smartswitch_vnet_{i}"
80-
template_name = "{}.j2".format(config)
81-
dest_path = "/tmp/{}.json".format(config)
82-
render_template_to_host(template_name, duthost, dest_path, dash_smartswitch_vnet_config, op=op)
83-
if ENABLE_GNMI_API:
84-
apply_gnmi_file(localhost, duthost, ptfhost, dest_path, None, 5, 1024, host)
85-
else:
86-
apply_swssconfig_file(duthost, dest_path)
134+
# Route rule removal is broken so config reload to cleanup for now
135+
# https://github.com/sonic-net/sonic-buildimage/issues/23590
136+
config_reload(dpuhost, safe_reload=True, yang_validate=False)
87137

88138

89139
def test_smartswitch_outbound_vnet(
90140
ptfadapter,
91141
dash_smartswitch_vnet_config,
92142
skip_dataplane_checking,
93-
inner_packet_type,
94-
vxlan_udp_dport):
143+
inner_packet_type):
95144

96145
if skip_dataplane_checking:
97146
return
98147
_, vxlan_packet, expected_packet = packets.outbound_smartswitch_vnet_packets(dash_smartswitch_vnet_config,
99-
vxlan_udp_dport=vxlan_udp_dport,
100148
inner_packet_type=inner_packet_type)
101149
ptfadapter.dataplane.flush()
102150
testutils.send(ptfadapter, dash_smartswitch_vnet_config[LOCAL_PTF_INTF], vxlan_packet, 1)

0 commit comments

Comments
 (0)