Skip to content

Commit 802e5dd

Browse files
Sudharsan D.Glguohan
authored andcommitted
add dynamic transceiver tuning support (sonic-net#821)
1 parent 95db5e5 commit 802e5dd

4 files changed

Lines changed: 202 additions & 0 deletions

File tree

doc/swss-schema.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ Stores information for physical switch ports managed by the switch chip. Ports t
2424
mtu = 1*4DIGIT ; port MTU
2525
fec = 1*64VCHAR ; port fec mode
2626
autoneg = BIT ; auto-negotiation mode
27+
preemphasis = 1*8HEXDIG *( "," 1*8HEXDIG) ; list of hex values, one per lane
28+
idriver = 1*8HEXDIG *( "," 1*8HEXDIG) ; list of hex values, one per lane
29+
ipredriver = 1*8HEXDIG *( "," 1*8HEXDIG) ; list of hex values, one per lane
2730

2831
;QOS Mappings
2932
map_dscp_to_tc = ref_hash_key_reference

orchagent/portsorch.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,9 @@ void PortsOrch::doPortTask(Consumer &consumer)
15191519
if (op == SET_COMMAND)
15201520
{
15211521
set<int> lane_set;
1522+
vector<uint32_t> pre_emphasis;
1523+
vector<uint32_t> idriver;
1524+
vector<uint32_t> ipredriver;
15221525
string admin_status;
15231526
string fec_mode;
15241527
string pfc_asym;
@@ -1575,6 +1578,24 @@ void PortsOrch::doPortTask(Consumer &consumer)
15751578
{
15761579
an = (int)stoul(fvValue(i));
15771580
}
1581+
1582+
/* Set port serdes Pre-emphasis */
1583+
if (fvField(i) == "preemphasis")
1584+
{
1585+
getPortSerdesVal(fvValue(i), pre_emphasis);
1586+
}
1587+
1588+
/* Set port serdes idriver */
1589+
if (fvField(i) == "idriver")
1590+
{
1591+
getPortSerdesVal(fvValue(i), idriver);
1592+
}
1593+
1594+
/* Set port serdes ipredriver */
1595+
if (fvField(i) == "ipredriver")
1596+
{
1597+
getPortSerdesVal(fvValue(i), ipredriver);
1598+
}
15781599
}
15791600

15801601
/* Collect information about all received ports */
@@ -1855,6 +1876,51 @@ void PortsOrch::doPortTask(Consumer &consumer)
18551876
}
18561877
}
18571878

1879+
if (pre_emphasis.size() != 0)
1880+
{
1881+
if (setPortSerdesAttribute(p.m_port_id, SAI_PORT_ATTR_SERDES_PREEMPHASIS, pre_emphasis))
1882+
{
1883+
SWSS_LOG_NOTICE("Set port %s preemphasis is success", alias.c_str());
1884+
}
1885+
else
1886+
{
1887+
SWSS_LOG_ERROR("Failed to set port %s pre-emphasis", alias.c_str());
1888+
it++;
1889+
continue;
1890+
}
1891+
1892+
}
1893+
1894+
if (idriver.size() != 0)
1895+
{
1896+
if (setPortSerdesAttribute(p.m_port_id, SAI_PORT_ATTR_SERDES_IDRIVER, idriver))
1897+
{
1898+
SWSS_LOG_NOTICE("Set port %s idriver is success", alias.c_str());
1899+
}
1900+
else
1901+
{
1902+
SWSS_LOG_ERROR("Failed to set port %s idriver", alias.c_str());
1903+
it++;
1904+
continue;
1905+
}
1906+
1907+
}
1908+
1909+
if (ipredriver.size() != 0)
1910+
{
1911+
if (setPortSerdesAttribute(p.m_port_id, SAI_PORT_ATTR_SERDES_IPREDRIVER, ipredriver))
1912+
{
1913+
SWSS_LOG_NOTICE("Set port %s ipredriver is success", alias.c_str());
1914+
}
1915+
else
1916+
{
1917+
SWSS_LOG_ERROR("Failed to set port %s ipredriver", alias.c_str());
1918+
it++;
1919+
continue;
1920+
}
1921+
1922+
}
1923+
18581924
/* Last step set port admin status */
18591925
if (!admin_status.empty() && (p.m_admin_state_up != (admin_status == "up")))
18601926
{
@@ -3297,3 +3363,41 @@ bool PortsOrch::removeAclTableGroup(const Port &p)
32973363
return true;
32983364
}
32993365

3366+
bool PortsOrch::setPortSerdesAttribute(sai_object_id_t port_id, sai_attr_id_t attr_id,
3367+
vector<uint32_t> &serdes_val)
3368+
{
3369+
SWSS_LOG_ENTER();
3370+
3371+
sai_attribute_t attr;
3372+
3373+
memset(&attr, 0, sizeof(attr));
3374+
attr.id = attr_id;
3375+
3376+
attr.value.u32list.count = (uint32_t)serdes_val.size();
3377+
attr.value.u32list.list = serdes_val.data();
3378+
3379+
sai_status_t status = sai_port_api->set_port_attribute(port_id, &attr);
3380+
if (status != SAI_STATUS_SUCCESS)
3381+
{
3382+
SWSS_LOG_ERROR("Failed to set serdes attribute %d to port pid:%lx",
3383+
attr_id, port_id);
3384+
return false;
3385+
}
3386+
return true;
3387+
}
3388+
3389+
void PortsOrch::getPortSerdesVal(const std::string& val_str,
3390+
std::vector<uint32_t> &lane_values)
3391+
{
3392+
SWSS_LOG_ENTER();
3393+
3394+
uint32_t lane_val;
3395+
std::string lane_str;
3396+
std::istringstream iss(val_str);
3397+
3398+
while (std::getline(iss, lane_str, ','))
3399+
{
3400+
lane_val = (uint32_t)std::stoul(lane_str, NULL, 16);
3401+
lane_values.push_back(lane_val);
3402+
}
3403+
}

orchagent/portsorch.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ class PortsOrch : public Orch, public Subject
189189

190190
bool getPortOperStatus(const Port& port, sai_port_oper_status_t& status) const;
191191
void updatePortOperStatus(Port &port, sai_port_oper_status_t status);
192+
193+
void getPortSerdesVal(const std::string& s, std::vector<uint32_t> &lane_values);
194+
195+
bool setPortSerdesAttribute(sai_object_id_t port_id, sai_attr_id_t attr_id,
196+
vector<uint32_t> &serdes_val);
192197
};
193198
#endif /* SWSS_PORTSORCH_H */
194199

tests/test_port.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,93 @@ def test_PortFec(dvs, testlog):
125125
for fv in fvs:
126126
if fv[0] == "SAI_PORT_ATTR_FEC_MODE":
127127
assert fv[1] == "SAI_PORT_FEC_MODE_RS"
128+
129+
def test_PortPreemp(dvs, testlog):
130+
131+
pre_name = 'preemphasis'
132+
pre_val = [0x1234,0x2345,0x3456,0x4567]
133+
pre_val_str = str(hex(pre_val[0])) + "," + str(hex(pre_val[1]))+ "," + \
134+
str(hex(pre_val[2]))+ "," + str(hex(pre_val[3]))
135+
136+
pre_val_asic = '4:' + str(pre_val[0]) + "," + str(pre_val[1]) + "," + \
137+
str(pre_val[2]) + "," + str(pre_val[3])
138+
fvs = swsscommon.FieldValuePairs([(pre_name, pre_val_str)])
139+
db = swsscommon.DBConnector(0, dvs.redis_sock, 0)
140+
adb = swsscommon.DBConnector(1, dvs.redis_sock, 0)
141+
142+
tbl = swsscommon.Table(db, "PORT_TABLE")
143+
ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE")
144+
atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
145+
146+
ptbl.set("Ethernet0", fvs)
147+
148+
149+
time.sleep(1)
150+
151+
# get fec
152+
(status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"])
153+
assert status == True
154+
155+
for fv in fvs:
156+
if fv[0] == "SAI_PORT_ATTR_SERDES_PREEMPHASIS":
157+
assert fv[1] == pre_val_asic
158+
159+
def test_PortIdriver(dvs, testlog):
160+
161+
idrv_name = 'idriver'
162+
idrv_val = [0x1,0x1,0x2,0x2]
163+
idrv_val_str = str(hex(idrv_val[0])) + "," + str(hex(idrv_val[1]))+ "," + \
164+
str(hex(idrv_val[2]))+ "," + str(hex(idrv_val[3]))
165+
166+
idrv_val_asic = '4:' + str(idrv_val[0]) + "," + str(idrv_val[1]) + "," + \
167+
str(idrv_val[2]) + "," + str(idrv_val[3])
168+
fvs = swsscommon.FieldValuePairs([(idrv_name, idrv_val_str)])
169+
db = swsscommon.DBConnector(0, dvs.redis_sock, 0)
170+
adb = swsscommon.DBConnector(1, dvs.redis_sock, 0)
171+
172+
tbl = swsscommon.Table(db, "PORT_TABLE")
173+
ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE")
174+
atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
175+
176+
ptbl.set("Ethernet0", fvs)
177+
178+
179+
time.sleep(1)
180+
181+
# get fec
182+
(status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"])
183+
assert status == True
184+
185+
for fv in fvs:
186+
if fv[0] == "SAI_PORT_ATTR_SERDES_IDRIVER":
187+
assert fv[1] == idrv_val_asic
188+
189+
def test_PortIpredriver(dvs, testlog):
190+
191+
ipre_name = 'ipredriver'
192+
ipre_val = [0x2,0x3,0x4,0x5]
193+
ipre_val_str = str(hex(ipre_val[0])) + "," + str(hex(ipre_val[1]))+ "," + \
194+
str(hex(ipre_val[2]))+ "," + str(hex(ipre_val[3]))
195+
196+
ipre_val_asic = '4:' + str(ipre_val[0]) + "," + str(ipre_val[1]) + "," + \
197+
str(ipre_val[2]) + "," + str(ipre_val[3])
198+
fvs = swsscommon.FieldValuePairs([(ipre_name, ipre_val_str)])
199+
db = swsscommon.DBConnector(0, dvs.redis_sock, 0)
200+
adb = swsscommon.DBConnector(1, dvs.redis_sock, 0)
201+
202+
tbl = swsscommon.Table(db, "PORT_TABLE")
203+
ptbl = swsscommon.ProducerStateTable(db, "PORT_TABLE")
204+
atbl = swsscommon.Table(adb, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
205+
206+
ptbl.set("Ethernet0", fvs)
207+
208+
209+
time.sleep(1)
210+
211+
# get fec
212+
(status, fvs) = atbl.get(dvs.asicdb.portnamemap["Ethernet0"])
213+
assert status == True
214+
215+
for fv in fvs:
216+
if fv[0] == "SAI_PORT_ATTR_SERDES_IPREDRIVER":
217+
assert fv[1] == ipre_val_asic

0 commit comments

Comments
 (0)