Skip to content

Commit

Permalink
[gearbox] Support setting tx taps on gearbox ports (sonic-net#2158)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
byu343 authored and dgsudharsan committed Dec 9, 2022
1 parent 872f7bf commit f258b93
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 12 deletions.
24 changes: 23 additions & 1 deletion gearsyncd/gearboxparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "gearboxparser.h"
#include "gearboxutils.h"
#include "phyparser.h"
#include <vector>

Expand Down Expand Up @@ -42,7 +43,7 @@ bool GearboxParser::parse()
return false;
}

json phys, phy, interfaces, interface, val, lanes;
json phys, phy, interfaces, interface, val, lanes, txFir;

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

Expand Down Expand Up @@ -285,6 +286,27 @@ bool GearboxParser::parse()
SWSS_LOG_ERROR("missing 'line_lanes' field in 'interfaces' item %d in gearbox configuration", iter);
return false;
}

for (std::string txFirKey: swss::tx_fir_strings)
{
if (interface.find(txFirKey) != interface.end())
{
txFir = interface[txFirKey]; // vec
std::string txFirValuesStr("");
for (uint32_t iter2 = 0; iter2 < txFir.size(); iter2++)
{
val = txFir[iter2];
if (txFirValuesStr.length() > 0)
{
txFirValuesStr += ",";
}
txFirValuesStr += std::to_string(val.get<int>());
}
attr = std::make_pair(txFirKey, txFirValuesStr);
attrs.push_back(attr);
}
}

std::string key;
key = "interface:" + std::to_string(index);
if (getWriteToDb() == true)
Expand Down
5 changes: 5 additions & 0 deletions lib/gearboxutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ std::map<int, gearbox_interface_t> GearboxUtils::loadInterfaceMap(Table *gearbox
}
}
}
else if (tx_fir_strings.find(val.first) != tx_fir_strings.end())
{
SWSS_LOG_DEBUG("Parsed key:%s, val:%s", val.first.c_str(), val.second.c_str());
interface.tx_firs[val.first] = val.second;
}
}
gearboxInterfaceMap[interface.index] = interface;
}
Expand Down
19 changes: 19 additions & 0 deletions lib/gearboxutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@

namespace swss {

static const std::set<std::string> tx_fir_strings =
{
"system_tx_fir_pre1",
"system_tx_fir_pre2",
"system_tx_fir_pre3",
"system_tx_fir_post1",
"system_tx_fir_post2",
"system_tx_fir_post3",
"system_tx_fir_main",
"line_tx_fir_pre1",
"line_tx_fir_pre2",
"line_tx_fir_pre3",
"line_tx_fir_post1",
"line_tx_fir_post2",
"line_tx_fir_post3",
"line_tx_fir_main"
};

typedef struct
{
int phy_id;
Expand All @@ -54,6 +72,7 @@ typedef struct
int phy_id;
std::set<int> line_lanes;
std::set<int> system_lanes;
std::map<std::string, std::string> tx_firs;
} gearbox_interface_t;

typedef struct
Expand Down
2 changes: 1 addition & 1 deletion orchagent/p4orch/tests/fake_portorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ void PortsOrch::updateDbPortOperSpeed(Port &port, sai_uint32_t speed)
{
}

void PortsOrch::getPortSerdesVal(const std::string &s, std::vector<uint32_t> &lane_values)
void PortsOrch::getPortSerdesVal(const std::string &s, std::vector<uint32_t> &lane_values, int base)
{
}

Expand Down
55 changes: 50 additions & 5 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3761,7 +3761,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
p.m_preemphasis = serdes_attr;
m_portList[alias] = p;
}
else if (setPortSerdesAttribute(p.m_port_id, serdes_attr))
else if (setPortSerdesAttribute(p.m_port_id, gSwitchId, serdes_attr))
{
SWSS_LOG_NOTICE("Set port %s preemphasis is success", alias.c_str());
p.m_preemphasis = serdes_attr;
Expand Down Expand Up @@ -6923,7 +6923,7 @@ bool PortsOrch::removeAclTableGroup(const Port &p)
return true;
}

bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id,
bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
map<sai_port_serdes_attr_t, vector<uint32_t>> &serdes_attr)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -6975,7 +6975,7 @@ bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id,
port_serdes_attr.value.u32list.list = it->second.data();
attr_list.emplace_back(port_serdes_attr);
}
status = sai_port_api->create_port_serdes(&port_serdes_id, gSwitchId,
status = sai_port_api->create_port_serdes(&port_serdes_id, switch_id,
static_cast<uint32_t>(serdes_attr.size()+1),
attr_list.data());

Expand Down Expand Up @@ -7026,7 +7026,8 @@ void PortsOrch::removePortSerdesAttribute(sai_object_id_t port_id)
}

void PortsOrch::getPortSerdesVal(const std::string& val_str,
std::vector<uint32_t> &lane_values)
std::vector<uint32_t> &lane_values,
int base)
{
SWSS_LOG_ENTER();

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

while (std::getline(iss, lane_str, ','))
{
lane_val = (uint32_t)std::stoul(lane_str, NULL, 16);
lane_val = (uint32_t)std::stoul(lane_str, NULL, base);
lane_values.push_back(lane_val);
}
}
Expand Down Expand Up @@ -7412,6 +7413,50 @@ bool PortsOrch::initGearboxPort(Port &port)

fields[0] = FieldValueTuple(port.m_alias + "_line", sai_serialize_object_id(linePort));
m_gbcounterTable->set("", fields);

/* Set serdes tx taps on system and line side */
map<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr;
typedef pair<sai_port_serdes_attr_t, vector<uint32_t>> serdes_attr_pair;
vector<uint32_t> attr_val;
for (auto pair: tx_fir_strings_system_side) {
if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) {
attr_val.clear();
getPortSerdesVal(m_gearboxInterfaceMap[port.m_index].tx_firs[pair.first], attr_val, 10);
serdes_attr.insert(serdes_attr_pair(pair.second, attr_val));
}
}
if (serdes_attr.size() != 0)
{
if (setPortSerdesAttribute(systemPort, phyOid, serdes_attr))
{
SWSS_LOG_NOTICE("Set port %s system side preemphasis is success", port.m_alias.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to set port %s system side pre-emphasis", port.m_alias.c_str());
return false;
}
}
serdes_attr.clear();
for (auto pair: tx_fir_strings_line_side) {
if (m_gearboxInterfaceMap[port.m_index].tx_firs.find(pair.first) != m_gearboxInterfaceMap[port.m_index].tx_firs.end() ) {
attr_val.clear();
getPortSerdesVal(m_gearboxInterfaceMap[port.m_index].tx_firs[pair.first], attr_val, 10);
serdes_attr.insert(serdes_attr_pair(pair.second, attr_val));
}
}
if (serdes_attr.size() != 0)
{
if (setPortSerdesAttribute(linePort, phyOid, serdes_attr))
{
SWSS_LOG_NOTICE("Set port %s line side preemphasis is success", port.m_alias.c_str());
}
else
{
SWSS_LOG_ERROR("Failed to set port %s line side pre-emphasis", port.m_alias.c_str());
return false;
}
}
}
}

Expand Down
26 changes: 24 additions & 2 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,28 @@ static const unordered_map<string, sai_port_oper_status_t> string_oper_status =
{ "not present", SAI_PORT_OPER_STATUS_NOT_PRESENT }
};

static const std::map<std::string, sai_port_serdes_attr_t> tx_fir_strings_system_side =
{
{"system_tx_fir_pre1", SAI_PORT_SERDES_ATTR_TX_FIR_PRE1},
{"system_tx_fir_pre2", SAI_PORT_SERDES_ATTR_TX_FIR_PRE2},
{"system_tx_fir_pre3", SAI_PORT_SERDES_ATTR_TX_FIR_PRE3},
{"system_tx_fir_post1", SAI_PORT_SERDES_ATTR_TX_FIR_POST1},
{"system_tx_fir_post2", SAI_PORT_SERDES_ATTR_TX_FIR_POST2},
{"system_tx_fir_post3", SAI_PORT_SERDES_ATTR_TX_FIR_POST3},
{"system_tx_fir_main", SAI_PORT_SERDES_ATTR_TX_FIR_MAIN}
};

static const std::map<std::string, sai_port_serdes_attr_t> tx_fir_strings_line_side =
{
{"line_tx_fir_pre1", SAI_PORT_SERDES_ATTR_TX_FIR_PRE1},
{"line_tx_fir_pre2", SAI_PORT_SERDES_ATTR_TX_FIR_PRE2},
{"line_tx_fir_pre3", SAI_PORT_SERDES_ATTR_TX_FIR_PRE3},
{"line_tx_fir_post1", SAI_PORT_SERDES_ATTR_TX_FIR_POST1},
{"line_tx_fir_post2", SAI_PORT_SERDES_ATTR_TX_FIR_POST2},
{"line_tx_fir_post3", SAI_PORT_SERDES_ATTR_TX_FIR_POST3},
{"line_tx_fir_main", SAI_PORT_SERDES_ATTR_TX_FIR_MAIN}
};

struct PortUpdate
{
Port port;
Expand Down Expand Up @@ -389,12 +411,12 @@ class PortsOrch : public Orch, public Subject
void refreshPortStateAutoNeg(const Port &port);
void refreshPortStateLinkTraining(const Port &port);

void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values);
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values, int base = 16);
bool getPortAdvSpeedsVal(const std::string &s, std::vector<uint32_t> &speed_values);
bool getPortInterfaceTypeVal(const std::string &s, sai_port_interface_type_t &interface_type);
bool getPortAdvInterfaceTypesVal(const std::string &s, std::vector<uint32_t> &type_values);

bool setPortSerdesAttribute(sai_object_id_t port_id,
bool setPortSerdesAttribute(sai_object_id_t port_id, sai_object_id_t switch_id,
std::map<sai_port_serdes_attr_t, std::vector<uint32_t>> &serdes_attr);


Expand Down
13 changes: 13 additions & 0 deletions orchagent/vrforch.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,19 @@ class VRFOrch : public Orch2
return (-1);
}
}

bool isL3VniVlan(const uint32_t vni) const
{
if (l3vni_table_.find(vni) != std::end(l3vni_table_))
{
return l3vni_table_.at(vni).l3_vni;
}
else
{
return false;
}
}

int updateL3VniVlan(uint32_t vni, uint16_t vlan_id);
private:
virtual bool addOperation(const Request& request);
Expand Down
81 changes: 78 additions & 3 deletions orchagent/vxlanorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1903,6 +1903,7 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request)

sai_vlan_id_t vlan_id = (sai_vlan_id_t)request.getAttrVlan("vlan");
Port tempPort;
bool isL3Vni = false;

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

VRFOrch* vrf_orch = gDirectory.get<VRFOrch*>();
isL3Vni = vrf_orch->isL3VniVlan(vni_id);

try
{
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
tunnel_map_id, vni_id, vlan_id);
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = tunnel_map_entry_id;
if (isL3Vni == false)
{
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
tunnel_map_id, vni_id, vlan_id);
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = tunnel_map_entry_id;
}
else
{
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].map_entry_id = SAI_NULL_OBJECT_ID;
}
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].vlan_id = vlan_id;
vxlan_tunnel_map_table_[full_tunnel_map_entry_name].vni_id = vni_id;
}
Expand Down Expand Up @@ -2124,9 +2135,13 @@ bool VxlanTunnelMapOrch::delOperation(const Request& request)
bool VxlanVrfMapOrch::addOperation(const Request& request)
{
SWSS_LOG_ENTER();
std::string vniVlanMapName;
uint32_t vlan_id = 0;
sai_object_id_t tnl_map_entry_id = SAI_NULL_OBJECT_ID;

auto tunnel_name = request.getKeyString(0);
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
if (!tunnel_orch->isTunnelExists(tunnel_name))
{
SWSS_LOG_WARN("Vxlan tunnel '%s' doesn't exist", tunnel_name.c_str());
Expand Down Expand Up @@ -2188,6 +2203,15 @@ bool VxlanVrfMapOrch::addOperation(const Request& request)
vrf_map_entry_t entry;
try
{
entry.isL2Vni = vxlan_tun_map_orch->isVniVlanMapExists(vni_id, vniVlanMapName, &tnl_map_entry_id, &vlan_id);
if (entry.isL2Vni)
{
entry.vniVlanMapName = vniVlanMapName;
entry.vlan_id = vlan_id;
entry.vni_id = vni_id;
remove_tunnel_map_entry(tnl_map_entry_id);
SWSS_LOG_DEBUG("remove_tunnel_map_entry name %s, vlan %d, vni %d\n", entry.vniVlanMapName.c_str(), entry.vlan_id, entry.vni_id);
}
/*
* Create encap and decap mapper
*/
Expand Down Expand Up @@ -2219,6 +2243,8 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
SWSS_LOG_ENTER();

VRFOrch* vrf_orch = gDirectory.get<VRFOrch*>();
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
const auto full_map_entry_name = request.getFullKey();

if (!isVrfMapExists(full_map_entry_name))
Expand All @@ -2241,6 +2267,9 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
return false;
}
SWSS_LOG_NOTICE("VxlanVrfMapOrch VRF VNI mapping '%s' remove vrf %s", full_map_entry_name.c_str(), vrf_name.c_str());
auto tunnel_name = request.getKeyString(0);
auto tunnel_obj = tunnel_orch->getVxlanTunnel(tunnel_name);

vrf_map_entry_t entry;
try
{
Expand All @@ -2256,6 +2285,20 @@ bool VxlanVrfMapOrch::delOperation(const Request& request)
vrf_orch->decreaseVrfRefCount(vrf_name);
remove_tunnel_map_entry(entry.decap_id);
vrf_orch->decreaseVrfRefCount(vrf_name);

if(entry.isL2Vni)
{
const auto tunnel_map_id = tunnel_obj->getDecapMapId(TUNNEL_MAP_T_VLAN);
SWSS_LOG_NOTICE("Adding tunnel map entry. Tunnel: %s %s",tunnel_name.c_str(),entry.vniVlanMapName.c_str());

SWSS_LOG_DEBUG("create_tunnel_map_entry vni %d, vlan %d\n", entry.vni_id, entry.vlan_id);
auto tunnel_map_entry_id = create_tunnel_map_entry(MAP_T::VNI_TO_VLAN_ID,
tunnel_map_id, entry.vni_id, (uint16_t)entry.vlan_id);
SWSS_LOG_DEBUG("updateTnlMapId name %s\n", entry.vniVlanMapName.c_str());

vxlan_tun_map_orch->updateTnlMapId(entry.vniVlanMapName, tunnel_map_entry_id);
}

vxlan_vrf_table_.erase(full_map_entry_name);
vxlan_vrf_tunnel_.erase(vrf_name);
}
Expand Down Expand Up @@ -2599,3 +2642,35 @@ bool EvpnNvoOrch::delOperation(const Request& request)

return true;
}

bool VxlanTunnelMapOrch::isVniVlanMapExists(uint32_t vni_id, std::string& vniVlanMapName, sai_object_id_t *tnl_map_entry_id, uint32_t *vlan_id)
{
SWSS_LOG_ENTER();
bool map_entry_exists = false;
std::map<std::string, tunnel_map_entry_t>::iterator it;
for(it = vxlan_tunnel_map_table_.begin(); it != vxlan_tunnel_map_table_.end(); it++)
{
auto full_tunnel_map_entry_name = it->first;
tunnel_map_entry_t tunnel_map_entry = it->second;

if (vni_id == tunnel_map_entry.vni_id)
{
vniVlanMapName = full_tunnel_map_entry_name;
*tnl_map_entry_id = tunnel_map_entry.map_entry_id;
*vlan_id = tunnel_map_entry.vlan_id;
map_entry_exists = true;
SWSS_LOG_NOTICE("vniVlanMapName %s, vlan %d\n", vniVlanMapName.c_str(), *vlan_id);
break;
}
}

return map_entry_exists;
}

void VxlanTunnelMapOrch::updateTnlMapId(std::string vniVlanMapName, sai_object_id_t tunnel_map_id)
{
SWSS_LOG_ENTER();
SWSS_LOG_NOTICE("name %s\n", vniVlanMapName.c_str());
vxlan_tunnel_map_table_[vniVlanMapName].map_entry_id = tunnel_map_id;
}

Loading

0 comments on commit f258b93

Please sign in to comment.