Skip to content

Commit f258b93

Browse files
byu343dgsudharsan
authored andcommitted
[gearbox] Support setting tx taps on gearbox ports (sonic-net#2158)
What I did This change adds support for setting tx tap or tuning values on gearbox ports. It uses the SAI attributes such as SAI_PORT_SERDES_ATTR_TX_FIR_PRE1 to communicate with SAI-based gearbox drivers. For the values, they are provided in the format like "system_tx_fir_pre2": [1,1] for an interface from gearbox_config.json. Why I did it How I verified it We verified that values provided in sonic-net/sonic-buildimage#10084 are set to the chip with this change. Added test to tests/test_gearbox.py. The added test will not pass until the following two changes (which should be merged first) are merged: Support SAI_PORT_ATTR_PORT_SERDES_ID on vs gearbox: sonic-net/sonic-sairedis#1082 Add gearbox taps to vs gearbox_config.json: sonic-net/sonic-buildimage#11480 Updated handling of VRF_VNI mapping and VLAN_VNI mapping for same VNI ID fixed compile issues Updated code for the flow where VRF VNI mapping is processed first followed by VLAN VNI mapping
1 parent 872f7bf commit f258b93

File tree

10 files changed

+244
-12
lines changed

10 files changed

+244
-12
lines changed

gearsyncd/gearboxparser.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
#include "gearboxparser.h"
18+
#include "gearboxutils.h"
1819
#include "phyparser.h"
1920
#include <vector>
2021

@@ -42,7 +43,7 @@ bool GearboxParser::parse()
4243
return false;
4344
}
4445

45-
json phys, phy, interfaces, interface, val, lanes;
46+
json phys, phy, interfaces, interface, val, lanes, txFir;
4647

4748
std::vector<swss::FieldValueTuple> attrs;
4849

@@ -285,6 +286,27 @@ bool GearboxParser::parse()
285286
SWSS_LOG_ERROR("missing 'line_lanes' field in 'interfaces' item %d in gearbox configuration", iter);
286287
return false;
287288
}
289+
290+
for (std::string txFirKey: swss::tx_fir_strings)
291+
{
292+
if (interface.find(txFirKey) != interface.end())
293+
{
294+
txFir = interface[txFirKey]; // vec
295+
std::string txFirValuesStr("");
296+
for (uint32_t iter2 = 0; iter2 < txFir.size(); iter2++)
297+
{
298+
val = txFir[iter2];
299+
if (txFirValuesStr.length() > 0)
300+
{
301+
txFirValuesStr += ",";
302+
}
303+
txFirValuesStr += std::to_string(val.get<int>());
304+
}
305+
attr = std::make_pair(txFirKey, txFirValuesStr);
306+
attrs.push_back(attr);
307+
}
308+
}
309+
288310
std::string key;
289311
key = "interface:" + std::to_string(index);
290312
if (getWriteToDb() == true)

lib/gearboxutils.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ std::map<int, gearbox_interface_t> GearboxUtils::loadInterfaceMap(Table *gearbox
266266
}
267267
}
268268
}
269+
else if (tx_fir_strings.find(val.first) != tx_fir_strings.end())
270+
{
271+
SWSS_LOG_DEBUG("Parsed key:%s, val:%s", val.first.c_str(), val.second.c_str());
272+
interface.tx_firs[val.first] = val.second;
273+
}
269274
}
270275
gearboxInterfaceMap[interface.index] = interface;
271276
}

lib/gearboxutils.h

+19
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,24 @@
3030

3131
namespace swss {
3232

33+
static const std::set<std::string> tx_fir_strings =
34+
{
35+
"system_tx_fir_pre1",
36+
"system_tx_fir_pre2",
37+
"system_tx_fir_pre3",
38+
"system_tx_fir_post1",
39+
"system_tx_fir_post2",
40+
"system_tx_fir_post3",
41+
"system_tx_fir_main",
42+
"line_tx_fir_pre1",
43+
"line_tx_fir_pre2",
44+
"line_tx_fir_pre3",
45+
"line_tx_fir_post1",
46+
"line_tx_fir_post2",
47+
"line_tx_fir_post3",
48+
"line_tx_fir_main"
49+
};
50+
3351
typedef struct
3452
{
3553
int phy_id;
@@ -54,6 +72,7 @@ typedef struct
5472
int phy_id;
5573
std::set<int> line_lanes;
5674
std::set<int> system_lanes;
75+
std::map<std::string, std::string> tx_firs;
5776
} gearbox_interface_t;
5877

5978
typedef struct

orchagent/p4orch/tests/fake_portorch.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ void PortsOrch::updateDbPortOperSpeed(Port &port, sai_uint32_t speed)
644644
{
645645
}
646646

647-
void PortsOrch::getPortSerdesVal(const std::string &s, std::vector<uint32_t> &lane_values)
647+
void PortsOrch::getPortSerdesVal(const std::string &s, std::vector<uint32_t> &lane_values, int base)
648648
{
649649
}
650650

orchagent/portsorch.cpp

+50-5
Original file line numberDiff line numberDiff line change
@@ -3761,7 +3761,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
37613761
p.m_preemphasis = serdes_attr;
37623762
m_portList[alias] = p;
37633763
}
3764-
else if (setPortSerdesAttribute(p.m_port_id, serdes_attr))
3764+
else if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr))
37653765
{
37663766
SWSS_LOG_NOTICE("Set port %s preemphasis is success", alias.c_str());
37673767
p.m_preemphasis = serdes_attr;
@@ -6923,7 +6923,7 @@ bool PortsOrch::removeAclTableGroup(const Port &p)
69236923
return true;
69246924
}
69256925

6926-
bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id,
6926+
bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
69276927
map<sai_port_serdes_attr_t, vector<uint32_t>> &serdes_attr)
69286928
{
69296929
SWSS_LOG_ENTER();
@@ -6975,7 +6975,7 @@ bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id,
69756975
port_serdes_attr.value.u32list.list = it->second.data();
69766976
attr_list.emplace_back(port_serdes_attr);
69776977
}
6978-
status = sai_port_api->create_port_serdes(&port_serdes_id, gSwitchId,
6978+
status = sai_port_api->create_port_serdes(&port_serdes_id, switch_id,
69796979
static_cast<uint32_t>(serdes_attr.size()+1),
69806980
attr_list.data());
69816981

@@ -7026,7 +7026,8 @@ void PortsOrch::removePortSerdesAttribute(sai_object_id_t port_id)
70267026
}
70277027

70287028
void PortsOrch::getPortSerdesVal(const std::string& val_str,
7029-
std::vector<uint32_t> &lane_values)
7029+
std::vector<uint32_t> &lane_values,
7030+
int base)
70307031
{
70317032
SWSS_LOG_ENTER();
70327033

@@ -7036,7 +7037,7 @@ void PortsOrch::getPortSerdesVal(const std::string& val_str,
70367037

70377038
while (std::getline(iss, lane_str, ','))
70387039
{
7039-
lane_val = (uint32_t)std::stoul(lane_str, NULL, 16);
7040+
lane_val = (uint32_t)std::stoul(lane_str, NULL, base);
70407041
lane_values.push_back(lane_val);
70417042
}
70427043
}
@@ -7412,6 +7413,50 @@ bool PortsOrch::initGearboxPort(Port &port)
74127413

74137414
fields[0] = FieldValueTuple(port.m_alias + "_line", sai_serialize_object_id(linePort));
74147415
m_gbcounterTable->set("", fields);
7416+
7417+
/* Set serdes tx taps on system and line side */
7418+
map<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr;
7419+
typedef pair<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr_pair;
7420+
vector<uint32_t> attr_val;
7421+
for (auto pair: tx_fir_strings_system_side) {
7422+
if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) {
7423+
attr_val.clear();
7424+
getPortSerdesVal(m_gearboxInterfaceMap[port.m_index].tx_firs[pair.first], attr_val, 10);
7425+
serdes_attr.insert(serdes_attr_pair(pair.second, attr_val));
7426+
}
7427+
}
7428+
if (serdes_attr.size() != 0)
7429+
{
7430+
if (setPortSerdesAttribute(systemPort, phyOid, serdes_attr))
7431+
{
7432+
SWSS_LOG_NOTICE("Set port %s system side preemphasis is success", port.m_alias.c_str());
7433+
}
7434+
else
7435+
{
7436+
SWSS_LOG_ERROR("Failed to set port %s system side pre-emphasis", port.m_alias.c_str());
7437+
return false;
7438+
}
7439+
}
7440+
serdes_attr.clear();
7441+
for (auto pair: tx_fir_strings_line_side) {
7442+
if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) {
7443+
attr_val.clear();
7444+
getPortSerdesVal(m_gearboxInterfaceMap[port.m_index].tx_firs[pair.first], attr_val, 10);
7445+
serdes_attr.insert(serdes_attr_pair(pair.second, attr_val));
7446+
}
7447+
}
7448+
if (serdes_attr.size() != 0)
7449+
{
7450+
if (setPortSerdesAttribute(linePort, phyOid, serdes_attr))
7451+
{
7452+
SWSS_LOG_NOTICE("Set port %s line side preemphasis is success", port.m_alias.c_str());
7453+
}
7454+
else
7455+
{
7456+
SWSS_LOG_ERROR("Failed to set port %s line side pre-emphasis", port.m_alias.c_str());
7457+
return false;
7458+
}
7459+
}
74157460
}
74167461
}
74177462

orchagent/portsorch.h

+24-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,28 @@ static const unordered_map<string, sai_port_oper_status_t> string_oper_status =
4949
{ "not present", SAI_PORT_OPER_STATUS_NOT_PRESENT }
5050
};
5151

52+
static const std::map<std::string, sai_port_serdes_attr_t> tx_fir_strings_system_side =
53+
{
54+
{"system_tx_fir_pre1", SAI_PORT_SERDES_ATTR_TX_FIR_PRE1},
55+
{"system_tx_fir_pre2", SAI_PORT_SERDES_ATTR_TX_FIR_PRE2},
56+
{"system_tx_fir_pre3", SAI_PORT_SERDES_ATTR_TX_FIR_PRE3},
57+
{"system_tx_fir_post1", SAI_PORT_SERDES_ATTR_TX_FIR_POST1},
58+
{"system_tx_fir_post2", SAI_PORT_SERDES_ATTR_TX_FIR_POST2},
59+
{"system_tx_fir_post3", SAI_PORT_SERDES_ATTR_TX_FIR_POST3},
60+
{"system_tx_fir_main", SAI_PORT_SERDES_ATTR_TX_FIR_MAIN}
61+
};
62+
63+
static const std::map<std::string, sai_port_serdes_attr_t> tx_fir_strings_line_side =
64+
{
65+
{"line_tx_fir_pre1", SAI_PORT_SERDES_ATTR_TX_FIR_PRE1},
66+
{"line_tx_fir_pre2", SAI_PORT_SERDES_ATTR_TX_FIR_PRE2},
67+
{"line_tx_fir_pre3", SAI_PORT_SERDES_ATTR_TX_FIR_PRE3},
68+
{"line_tx_fir_post1", SAI_PORT_SERDES_ATTR_TX_FIR_POST1},
69+
{"line_tx_fir_post2", SAI_PORT_SERDES_ATTR_TX_FIR_POST2},
70+
{"line_tx_fir_post3", SAI_PORT_SERDES_ATTR_TX_FIR_POST3},
71+
{"line_tx_fir_main", SAI_PORT_SERDES_ATTR_TX_FIR_MAIN}
72+
};
73+
5274
struct PortUpdate
5375
{
5476
Port port;
@@ -389,12 +411,12 @@ class PortsOrch : public Orch, public Subject
389411
void refreshPortStateAutoNeg(const Port &port);
390412
void refreshPortStateLinkTraining(const Port &port);
391413

392-
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values);
414+
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values, int base = 16);
393415
bool getPortAdvSpeedsVal(const std::string &s, std::vector<uint32_t> &speed_values);
394416
bool getPortInterfaceTypeVal(const std::string &s, sai_port_interface_type_t &interface_type);
395417
bool getPortAdvInterfaceTypesVal(const std::string &s, std::vector<uint32_t> &type_values);
396418

397-
bool setPortSerdesAttribute(sai_object_id_t port_id,
419+
bool setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
398420
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> &serdes_attr);
399421

400422

orchagent/vrforch.h

+13
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,19 @@ class VRFOrch : public Orch2
155155
return (-1);
156156
}
157157
}
158+
159+
bool isL3VniVlan(const uint32_t vni) const
160+
{
161+
if (l3vni_table_.find(vni) != std::end(l3vni_table_))
162+
{
163+
return l3vni_table_.at(vni).l3_vni;
164+
}
165+
else
166+
{
167+
return false;
168+
}
169+
}
170+
158171
int updateL3VniVlan(uint32_t vni, uint16_t vlan_id);
159172
private:
160173
virtual bool addOperation(const Request& request);

orchagent/vxlanorch.cpp

+78-3
Original file line numberDiff line numberDiff line change
@@ -1903,6 +1903,7 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request)
19031903

19041904
sai_vlan_id_t vlan_id = (sai_vlan_id_t)request.getAttrVlan("vlan");
19051905
Port tempPort;
1906+
bool isL3Vni = false;
19061907

19071908
const auto full_tunnel_map_entry_name = request.getFullKey();
19081909
SWSS_LOG_INFO("Full name = %s",full_tunnel_map_entry_name.c_str());
@@ -1974,11 +1975,21 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request)
19741975
tunnel_obj->vlan_vrf_vni_count++;
19751976
SWSS_LOG_INFO("vni count increased to %d",tunnel_obj->vlan_vrf_vni_count);
19761977

1978+
VRFOrch* vrf_orch = gDirectory.get<VRFOrch*>();
1979+
isL3Vni = vrf_orch->isL3VniVlan(vni_id);
1980+
19771981
try
19781982
{
1979-
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
1980-
tunnel_map_id, vni_id, vlan_id);
1981-
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = tunnel_map_entry_id;
1983+
if (isL3Vni == false)
1984+
{
1985+
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
1986+
tunnel_map_id, vni_id, vlan_id);
1987+
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = tunnel_map_entry_id;
1988+
}
1989+
else
1990+
{
1991+
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = SAI_NULL_OBJECT_ID;
1992+
}
19821993
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].vlan_id = vlan_id;
19831994
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].vni_id = vni_id;
19841995
}
@@ -2124,9 +2135,13 @@ bool VxlanTunnelMapOrch::delOperation(const Request& request)
21242135
bool VxlanVrfMapOrch::addOperation(const Request& request)
21252136
{
21262137
SWSS_LOG_ENTER();
2138+
std::string vniVlanMapName;
2139+
uint32_t vlan_id = 0;
2140+
sai_object_id_t tnl_map_entry_id = SAI_NULL_OBJECT_ID;
21272141

21282142
auto tunnel_name = request.getKeyString(0);
21292143
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
2144+
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
21302145
if (!tunnel_orch->isTunnelExists(tunnel_name))
21312146
{
21322147
SWSS_LOG_WARN("Vxlan tunnel '%s' doesn't exist", tunnel_name.c_str());
@@ -2188,6 +2203,15 @@ bool VxlanVrfMapOrch::addOperation(const Request& request)
21882203
vrf_map_entry_t entry;
21892204
try
21902205
{
2206+
entry.isL2Vni = vxlan_tun_map_orch->isVniVlanMapExists(vni_id, vniVlanMapName, &tnl_map_entry_id, &vlan_id);
2207+
if (entry.isL2Vni)
2208+
{
2209+
entry.vniVlanMapName = vniVlanMapName;
2210+
entry.vlan_id = vlan_id;
2211+
entry.vni_id = vni_id;
2212+
remove_tunnel_map_entry(tnl_map_entry_id);
2213+
SWSS_LOG_DEBUG("remove_tunnel_map_entry name %s, vlan %d, vni %d\n", entry.vniVlanMapName.c_str(), entry.vlan_id, entry.vni_id);
2214+
}
21912215
/*
21922216
* Create encap and decap mapper
21932217
*/
@@ -2219,6 +2243,8 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
22192243
SWSS_LOG_ENTER();
22202244

22212245
VRFOrch* vrf_orch = gDirectory.get<VRFOrch*>();
2246+
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
2247+
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
22222248
const auto full_map_entry_name = request.getFullKey();
22232249

22242250
if (!isVrfMapExists(full_map_entry_name))
@@ -2241,6 +2267,9 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
22412267
return false;
22422268
}
22432269
SWSS_LOG_NOTICE("VxlanVrfMapOrch VRF VNI mapping '%s' remove vrf %s", full_map_entry_name.c_str(), vrf_name.c_str());
2270+
auto tunnel_name = request.getKeyString(0);
2271+
auto tunnel_obj = tunnel_orch->getVxlanTunnel(tunnel_name);
2272+
22442273
vrf_map_entry_t entry;
22452274
try
22462275
{
@@ -2256,6 +2285,20 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
22562285
vrf_orch->decreaseVrfRefCount(vrf_name);
22572286
remove_tunnel_map_entry(entry.decap_id);
22582287
vrf_orch->decreaseVrfRefCount(vrf_name);
2288+
2289+
if(entry.isL2Vni)
2290+
{
2291+
const auto tunnel_map_id = tunnel_obj->getDecapMapId(TUNNEL_MAP_T_VLAN);
2292+
SWSS_LOG_NOTICE("Adding tunnel map entry. Tunnel: %s %s",tunnel_name.c_str(),entry.vniVlanMapName.c_str());
2293+
2294+
SWSS_LOG_DEBUG("create_tunnel_map_entry vni %d, vlan %d\n", entry.vni_id, entry.vlan_id);
2295+
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
2296+
tunnel_map_id, entry.vni_id, (uint16_t)entry.vlan_id);
2297+
SWSS_LOG_DEBUG("updateTnlMapId name %s\n", entry.vniVlanMapName.c_str());
2298+
2299+
vxlan_tun_map_orch->updateTnlMapId(entry.vniVlanMapName, tunnel_map_entry_id);
2300+
}
2301+
22592302
vxlan_vrf_table_.erase(full_map_entry_name);
22602303
vxlan_vrf_tunnel_.erase(vrf_name);
22612304
}
@@ -2599,3 +2642,35 @@ bool EvpnNvoOrch::delOperation(const Request& request)
25992642

26002643
return true;
26012644
}
2645+
2646+
bool VxlanTunnelMapOrch::isVniVlanMapExists(uint32_t vni_id, std::string& vniVlanMapName, sai_object_id_t *tnl_map_entry_id, uint32_t *vlan_id)
2647+
{
2648+
SWSS_LOG_ENTER();
2649+
bool map_entry_exists = false;
2650+
std::map<std::string, tunnel_map_entry_t>::iterator it;
2651+
for(it = vxlan_tunnel_map_table_.begin(); it != vxlan_tunnel_map_table_.end(); it++)
2652+
{
2653+
auto full_tunnel_map_entry_name = it->first;
2654+
tunnel_map_entry_t tunnel_map_entry = it->second;
2655+
2656+
if (vni_id == tunnel_map_entry.vni_id)
2657+
{
2658+
vniVlanMapName = full_tunnel_map_entry_name;
2659+
*tnl_map_entry_id = tunnel_map_entry.map_entry_id;
2660+
*vlan_id = tunnel_map_entry.vlan_id;
2661+
map_entry_exists = true;
2662+
SWSS_LOG_NOTICE("vniVlanMapName %s, vlan %d\n", vniVlanMapName.c_str(), *vlan_id);
2663+
break;
2664+
}
2665+
}
2666+
2667+
return map_entry_exists;
2668+
}
2669+
2670+
void VxlanTunnelMapOrch::updateTnlMapId(std::string vniVlanMapName, sai_object_id_t tunnel_map_id)
2671+
{
2672+
SWSS_LOG_ENTER();
2673+
SWSS_LOG_NOTICE("name %s\n", vniVlanMapName.c_str());
2674+
vxlan_tunnel_map_table_[vniVlanMapName].map_entry_id = tunnel_map_id;
2675+
}
2676+

0 commit comments

Comments
 (0)