Skip to content

Commit 6a12ca9

Browse files
authored
[Mellanox] [ECMP calculator] Add support for 4600/4600C/2201 platforms with different interface naming method (#13814) (#13931)
1 parent be51191 commit 6a12ca9

File tree

2 files changed

+99
-32
lines changed

2 files changed

+99
-32
lines changed

platform/mellanox/docker-syncd-mlnx/ecmp_calculator/ecmp_calc.py

+27-21
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,18 @@
2323
PORT, VPORT, VLAN, SX_ENTRY_NOT_FOUND
2424
from packet_scheme import PACKET_SCHEME
2525
from port_utils import sx_get_ports_map, is_lag
26+
from swsscommon.swsscommon import ConfigDBConnector, DBConnector, Table
2627

2728
IP_VERSION_IPV4 = 1
2829
IP_VERSION_IPV6 = 2
29-
PORT_CHANNEL_IDX = 1
30+
PORT_CHANNEL_IDX = 0
3031
VRF_NAME_IDX = 1
3132
IP_VERSION_MAX_MASK_LEN = {IP_VERSION_IPV4: 32, IP_VERSION_IPV6: 128}
3233

34+
APPL_DB_NAME = 'APPL_DB'
3335
INTF_TABLE = 'INTF_TABLE'
36+
VRF_TABLE = 'VRF_TABLE'
37+
LAG_MEMBER_TABLE = 'LAG_MEMBER_TABLE'
3438
HASH_CALC_PATH = '/usr/bin/sx_hash_calculator'
3539
HASH_CALC_INPUT_FILE = "/tmp/hash_calculator_input.json"
3640
HASH_CALC_OUTPUT_FILE = "/tmp/hash_calculator_output.json"
@@ -113,6 +117,8 @@ def __init__(self):
113117
self.egress_ports = []
114118
self.debug = False
115119

120+
self.config_db = ConfigDBConnector()
121+
self.appl_db = DBConnector(APPL_DB_NAME, 0)
116122
self.open_sdk_connection()
117123
self.init_ports_map()
118124
self.get_active_vrids()
@@ -137,7 +143,7 @@ def debug_print(self, *args, **kwargs):
137143
print(*args, **kwargs)
138144

139145
def init_ports_map(self):
140-
self.ports_map = sx_get_ports_map(self.handle)
146+
self.ports_map = sx_get_ports_map(self.handle, self.config_db)
141147

142148
def validate_ingress_port(self, interface):
143149
if interface not in self.ports_map.values():
@@ -156,16 +162,12 @@ def validate_args(self, interface, packet, vrf, debug):
156162
if not self.validate_vrf():
157163
raise ValueError("VRF validation failed: VRF {} does not exist".format(self.user_vrf))
158164

159-
def validate_vrf(self):
160-
query_output = exec_cmd(['/usr/bin/redis-cli', '-n', '0', 'keys','*VRF*']).strip()
161-
if not query_output:
162-
return False
165+
def validate_vrf(self):
166+
vrf_table = Table(self.appl_db, VRF_TABLE)
167+
vrf_table_keys = vrf_table.getKeys()
163168

164-
vrf_entries= query_output.split('\n')
165-
for entry in vrf_entries:
166-
vrf = entry.split(':')[VRF_NAME_IDX]
167-
if vrf == self.user_vrf:
168-
return True
169+
if self.user_vrf in vrf_table_keys:
170+
return True
169171

170172
return False
171173

@@ -289,26 +291,30 @@ def print_egress_port(self):
289291
def is_port_bind_to_user_vrf(self, port_type, port, vlan_id = 0):
290292
if port_type == PORT:
291293
# INTF_TABLE:Ethernet0
292-
entry = '{}:{}'.format(INTF_TABLE, port)
294+
entry = '{}'.format(port)
293295
elif port_type == VPORT:
294296
# INTF_TABLE:Ethernet0.300
295-
entry = '{}:{}.{}'.format(INTF_TABLE, port, vlan_id)
297+
entry = '{}.{}'.format(port, vlan_id)
296298
elif port_type == VLAN:
297299
# INTF_TABLE:Vlan300
298-
entry = '{}:Vlan{}'.format(INTF_TABLE, vlan_id)
300+
entry = 'Vlan{}'.format(vlan_id)
301+
302+
vrf_table = Table(self.appl_db, INTF_TABLE)
303+
(_, port_vrf) = vrf_table.hget(entry, 'vrf_name')
299304

300-
port_vrf = exec_cmd(['/usr/bin/redis-cli', '-n', '0', 'hget', entry, 'vrf_name'])
301305
if self.user_vrf == port_vrf.strip():
302306
return True
303307

304308
return False
305309

306310
# Get port-channel name for given port-channel member port
307-
def get_port_channel_name(self, port):
308-
query_output = exec_cmd(['/usr/bin/redis-cli', '-n', '0', 'keys','*LAG_MEMBER_TABLE*'])
309-
for line in query_output.split('\n'):
310-
if str(port) in line:
311-
port_channel = line.split(':')[PORT_CHANNEL_IDX]
311+
def get_port_channel_name(self, port):
312+
lag_member_table = Table(self.appl_db, LAG_MEMBER_TABLE)
313+
lag_member_table_keys = lag_member_table.getKeys()
314+
315+
for key in lag_member_table_keys:
316+
if port in key:
317+
port_channel = key.split(':')[PORT_CHANNEL_IDX]
312318
return port_channel
313319

314320
raise KeyError("Failed to get port-channel name for interface {}".format(port))
@@ -368,7 +374,7 @@ def get_lag_member(self, logical, flood_case = False):
368374
member_index = self.get_lag_member_index(len(lag_members), flood_case)
369375
lag_member = lag_members[member_index]
370376

371-
self.debug_print("Lag member from which trafic will egress: {}".format(lag_member))
377+
self.debug_print("Lag members: {}\nLag member from which trafic will egress: {}".format(lag_members, lag_member))
372378
return lag_member
373379

374380
def call_hash_calculator(self, input_dict):

platform/mellanox/docker-syncd-mlnx/lib/port_utils.py

+72-11
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,86 @@
22

33
from python_sdk_api.sx_api import *
44
import inspect
5+
import re
56

67
DEVICE_ID = 1
78
SWITCH_ID = 0
9+
PORT_TABLE = 'PORT'
10+
FIRST_LANE_INDEX = 0
811
ETHERNET_PREFIX = 'Ethernet'
9-
ASIC_MAX_LANES = {SX_CHIP_TYPE_SPECTRUM: 4, SX_CHIP_TYPE_SPECTRUM2: 4,
10-
SX_CHIP_TYPE_SPECTRUM3: 8, SX_CHIP_TYPE_SPECTRUM4: 8}
1112

12-
def sx_get_ports_map(handle):
13+
def get_ports_lanes_map(config_db):
14+
""" Get lane number of the first lane in use by port for all existing ports.
15+
16+
Args:
17+
config_db (ConfigDBConnector): Config DB connector
18+
19+
Returns:
20+
dict: key is lane number of the first lane in use by port, value is SONiC port index (124 for Ethernet124)
21+
"""
22+
lanes_map = {}
23+
config_db.connect()
24+
25+
ports_table = config_db.get_table(PORT_TABLE)
26+
if ports_table is None:
27+
raise Exception("Can't read {} table".format(PORT_TABLE))
28+
29+
ports_table_keys = config_db.get_keys(PORT_TABLE)
30+
for port in ports_table_keys:
31+
port_data = ports_table.get(port)
32+
if port_data is not None:
33+
lanes = port_data.get('lanes')
34+
first_lane = lanes.split(',')[FIRST_LANE_INDEX]
35+
port_idx = re.sub(r"\D", "", port)
36+
lanes_map[int(first_lane)] = int(port_idx)
37+
38+
return lanes_map
39+
40+
def get_port_max_width(handle):
41+
""" Get max number of lanes in port according to chip type
42+
43+
Args:
44+
handle (sx_api_handle_t): SDK handle
45+
46+
Returns:
47+
int: max lanes in port
48+
"""
49+
# Get chip type
50+
chip_type = sx_get_chip_type(handle)
51+
52+
limits = rm_resources_t()
53+
modes = rm_modes_t()
54+
55+
rc = rm_chip_limits_get(chip_type, limits)
56+
sx_check_rc(rc)
57+
max_width = limits.port_map_width_max
58+
59+
# SPC2 ports have 8 lanes but SONiC is using 4
60+
if chip_type == SX_CHIP_TYPE_SPECTRUM2:
61+
max_width = 4
62+
63+
return max_width
64+
65+
def sx_get_ports_map(handle, config_db):
1366
""" Get ports map from SDK logical index to SONiC index
1467
1568
Args:
1669
handle (sx_api_handle_t): SDK handle
17-
70+
config_db (ConfigDBConnector): Config DB connector
71+
1872
Returns:
19-
dict : Dictionary of ports indices. Key is SDK logical index, value is SONiC index (4 for Ethernet4)
73+
dict: key is SDK logical index, value is SONiC index (4 for Ethernet4)
2074
"""
2175
try:
2276
ports_map = {}
77+
port_attributes_list = None
78+
port_cnt_p = None
2379

24-
# Get chip type
25-
chip_type = sx_get_chip_type(handle)
80+
# Get lanes map
81+
lanes_map = get_ports_lanes_map(config_db)
82+
83+
# Get max number of lanes in port
84+
port_max_width = get_port_max_width(handle)
2685

2786
# Get ports count
2887
port_cnt_p = new_uint32_t_p()
@@ -45,10 +104,12 @@ def sx_get_ports_map(handle):
45104
continue
46105

47106
# Calculate sonic index (sonic index=4 for Ethernet4)
48-
lane_index = get_lane_index(lane_bmap, ASIC_MAX_LANES[chip_type])
107+
lane_index = get_lane_index(lane_bmap, port_max_width)
49108
assert lane_index != -1, "Failed to calculate port index"
50109

51-
sonic_index = label_port * ASIC_MAX_LANES[chip_type] + lane_index;
110+
first_lane = label_port * port_max_width + lane_index;
111+
sonic_index = lanes_map[first_lane]
112+
52113
sonic_interface = ETHERNET_PREFIX + str(sonic_index)
53114
ports_map[logical_port] = sonic_interface
54115

@@ -65,7 +126,7 @@ def sx_get_chip_type(handle):
65126
handle (sx_api_handle_t): SDK handle
66127
67128
Returns:
68-
sx_chip_types_t : Chip type
129+
sx_chip_types_t: Chip type
69130
"""
70131
try:
71132
device_info_cnt_p = new_uint32_t_p()
@@ -95,7 +156,7 @@ def get_lane_index(lane_bmap, max_lanes):
95156
max_lanes (int): Max lanes in module
96157
97158
Returns:
98-
int : index of the first bit set to 1 in lane_bmap
159+
int: index of the first bit set to 1 in lane_bmap
99160
"""
100161
for lane_idx in range(0, max_lanes):
101162
if (lane_bmap & 0x1 == 1):

0 commit comments

Comments
 (0)