Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for platforms based on Barefoot Networks' device #452

Merged
merged 32 commits into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
475e2da
initial barefoot support october 2017
Nov 2, 2017
4a02a6f
add validate and get port speed APIs - cleanup deletes from earlier c…
Nov 3, 2017
9aa8377
Merge branch 'rel_6_0' into bf-master
Nov 3, 2017
c78f25f
missed changes from earlier
Nov 4, 2017
56d480e
missed integration delete
Nov 4, 2017
e0cad33
trying to get close to master version - and not break other vendor
Nov 5, 2017
1531771
set the port config in the ASIC_DB
Nov 6, 2017
0011df4
update hostif oper status besides the DB update
Nov 6, 2017
b5f5856
merge closer to master - including spaces and comments
Nov 8, 2017
1b347a4
fix typos
Nov 9, 2017
41cff68
Merge remote-tracking branch 'azure/master' into bf-master
Nov 13, 2017
8c1d488
cosmetic fix
Nov 13, 2017
c944692
Merge remote-tracking branch 'azure/master' into bf-master
Nov 18, 2017
f9d4999
Merge remote-tracking branch 'azure/master' into bf-master
Nov 21, 2017
2505270
fix the order of nexthop/neighbor delete
Nov 22, 2017
5a1db21
Merge remote-tracking branch 'origin/rel_6_1' into bf-master
Nov 22, 2017
5aabe44
Merge remote-tracking branch 'azure/master' into bf-master
Dec 11, 2017
34f5fdc
fix code merge issue
Dec 14, 2017
0b921c6
Merge remote-tracking branch 'azure/master' into bf-master
Dec 18, 2017
78a4866
Tests readme fixes (#419)
pavel-shirshov Dec 18, 2017
3e7243b
Merge remote-tracking branch 'azure/master' into bf-master
Dec 18, 2017
6ad7ece
add pfc_detect lua script
Dec 18, 2017
5374ea1
cleanup configure.ac to allow barefoot platform includes
Mar 5, 2018
7bf3da3
fix typo
Mar 6, 2018
870cf49
revert commented tunneldecap
Mar 6, 2018
041d82d
test selective tunneldecap
Mar 7, 2018
75aed6e
revert too ambitious an attempt and just push_back into vector!
Mar 7, 2018
f7df97f
change fec mode to string (from integer)
Mar 7, 2018
a12a2e5
cleanup based on review
Mar 12, 2018
5d049e8
closer to 201712 - cosmetic cleanup
Mar 13, 2018
933960f
address review comments
Mar 15, 2018
bc95cca
fix format
lguohan Mar 16, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ esac],[gtest=false])
AM_CONDITIONAL(GTEST, test x$gtest = xtrue)

CFLAGS_COMMON="-std=c++11 -Wall -fPIC -Wno-write-strings -I/usr/include/libnl3 -I/usr/include/swss"

AM_CONDITIONAL(sonic_asic_platform_barefoot, test x$CONFIGURED_PLATFORM = xbarefoot)
AM_COND_IF([sonic_asic_platform_barefoot],
[CFLAGS_COMMON+=" -I/opt/bfn/install/include/switchsai"])
Copy link
Contributor

@lguohan lguohan Mar 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rsunkad , why is this needed? I do not see it being used anywhere in your PR.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below is the compilation without the change: sai,h is always included from the install dir in our current debs.

libtool: link: g++ -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wl,-z -Wl,relro -o portsyncd portsyncd-portsyncd.o portsyncd-linksync.o -lnl-3 -lnl-route-3 -lswsscommon -lnl-genl-3 -lhiredis
make[4]: Leaving directory '/sonic/src/sonic-swss/portsyncd'
Making all in orchagent
make[4]: Entering directory '/sonic/src/sonic-swss/orchagent'
g++ -DHAVE_CONFIG_H -I. -I.. -I .. -g -DNDEBUG -std=c++11 -Wall -fPIC -Wno-write-strings -I/usr/include/libnl3 -I/usr/include/swss -Werror -Wno-reorder -Wcast-align -Wcast-qual -Wconversion -Wdisabled-optimization -Wextra -Wfloat-equal -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimport -Winit-self -Winvalid-pch -Wlong-long -Wmissing-field-initializers -Wmissing-format-attribute -Wno-aggregate-return -Wno-padded -Wno-switch-enum -Wno-unused-parameter -Wpacked -Wpointer-arith -Wredundant-decls -Wstack-protector -Wstrict-aliasing=3 -Wswitch -Wswitch-default -Wunreachable-code -Wunused -Wvariadic-macros -Wno-switch-default -Wno-long-long -Wno-redundant-decls -I /usr/include/sai -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -c -o orchagent-main.o test -f 'main.cpp' || echo './'main.cpp
main.cpp:2:17: fatal error: sai.h: No such file or directory
#include "sai.h"
^
compilation terminated.
Makefile:550: recipe for target 'orchagent-main.o' failed

Copy link
Contributor

@lguohan lguohan Mar 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I think it is because on other platforms, they have a libsaixxx-dev packages which installs SAI headers under /usr/include/sai. They install the package before compile swss, so they do not need this.


CFLAGS_COMMON+=" -Werror"
CFLAGS_COMMON+=" -Wno-reorder"
CFLAGS_COMMON+=" -Wcast-align"
Expand Down
1 change: 1 addition & 0 deletions orchagent/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ swssdir = $(datadir)/swss
dist_swss_DATA = \
pfc_detect_mellanox.lua \
pfc_detect_broadcom.lua \
pfc_detect_barefoot.lua \
pfc_restore.lua

bin_PROGRAMS = orchagent routeresync
Expand Down
1 change: 1 addition & 0 deletions orchagent/orch.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const char config_db_key_delimiter = '|';

#define MLNX_PLATFORM_SUBSTRING "mellanox"
#define BRCM_PLATFORM_SUBSTRING "broadcom"
#define BFN_PLATFORM_SUBSTRING "barefoot"

#define CONFIGDB_KEY_SEPARATOR "|"
#define DEFAULT_KEY_SEPARATOR ":"
Expand Down
91 changes: 91 additions & 0 deletions orchagent/pfc_detect_barefoot.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
-- KEYS - queue IDs
-- ARGV[1] - counters db index
-- ARGV[2] - counters table name
-- ARGV[3] - poll time interval
-- return queue Ids that satisfy criteria

local counters_db = ARGV[1]
local counters_table_name = ARGV[2]
local poll_time = tonumber(ARGV[3])

local rets = {}

redis.call('SELECT', counters_db)

-- Iterate through each queue
local n = table.getn(KEYS)
for i = n, 1, -1 do
local counter_keys = redis.call('HKEYS', counters_table_name .. ':' .. KEYS[i])
local counter_num = 0
local old_counter_num = 0
local is_deadlock = false
local pfc_wd_status = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'PFC_WD_STATUS')
local pfc_wd_action = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'PFC_WD_ACTION')
if pfc_wd_status == 'operational' or pfc_wd_action == 'alert' then
local detection_time = tonumber(redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'PFC_WD_DETECTION_TIME'))
local time_left = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'PFC_WD_DETECTION_TIME_LEFT')
if not time_left then
time_left = detection_time
else
time_left = tonumber(time_left)
end

local queue_index = redis.call('HGET', 'COUNTERS_QUEUE_INDEX_MAP', KEYS[i])
local port_id = redis.call('HGET', 'COUNTERS_QUEUE_PORT_MAP', KEYS[i])
local pfc_rx_pkt_key = 'SAI_PORT_STAT_PFC_' .. queue_index .. '_RX_PKTS'
local pfc_on2off_key = 'SAI_PORT_STAT_PFC_' .. queue_index .. '_ON2OFF_RX_PKTS'


-- Get all counters
local occupancy_bytes = tonumber(redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_STAT_CURR_OCCUPANCY_BYTES'))
local packets = tonumber(redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_STAT_PACKETS'))
local pfc_rx_packets = tonumber(redis.call('HGET', counters_table_name .. ':' .. port_id, pfc_rx_pkt_key))
local pfc_on2off = tonumber(redis.call('HGET', counters_table_name .. ':' .. port_id, pfc_on2off_key))
local queue_pause_status = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_ATTR_PAUSE_STATUS')

local packets_last = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_STAT_PACKETS_last')
local pfc_rx_packets_last = redis.call('HGET', counters_table_name .. ':' .. port_id, pfc_rx_pkt_key .. '_last')
local pfc_on2off_last = redis.call('HGET', counters_table_name .. ':' .. port_id, pfc_on2off_key .. '_last')
local queue_pause_status_last = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_ATTR_PAUSE_STATUS_last')

-- DEBUG CODE START. Uncomment to enable
local debug_storm = redis.call('HGET', counters_table_name .. ':' .. KEYS[i], 'DEBUG_STORM')
-- DEBUG CODE END.

-- If this is not a first run, then we have last values available
if packets_last and pfc_rx_packets_last and pfc_on2off_last and queue_pause_status_last then
packets_last = tonumber(packets_last)
pfc_rx_packets_last = tonumber(pfc_rx_packets_last)
pfc_on2off_last = tonumber(pfc_on2off_last)

-- Check actual condition of queue being in PFC storm
if (occupancy_bytes > 0 and packets - packets_last == 0 and pfc_rx_packets - pfc_rx_packets_last > 0) or
-- DEBUG CODE START. Uncomment to enable
(debug_storm == "enabled") or
-- DEBUG CODE END.
(occupancy_bytes == 0 and pfc_rx_packets - pfc_rx_packets_last > 0 and pfc_on2off - pfc_on2off_last == 0 and queue_pause_status_last == 'true' and queue_pause_status == 'true') then
if time_left <= poll_time then
redis.call('PUBLISH', 'PFC_WD', '["' .. KEYS[i] .. '","storm"]')
is_deadlock = true
time_left = detection_time
else
time_left = time_left - poll_time
end
else
if pfc_wd_action == 'alert' and pfc_wd_status ~= 'operational' then
redis.call('PUBLISH', 'PFC_WD', '["' .. KEYS[i] .. '","restore"]')
end
time_left = detection_time
end
end

-- Save values for next run
redis.call('HSET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_ATTR_PAUSE_STATUS_last', queue_pause_status)
redis.call('HSET', counters_table_name .. ':' .. KEYS[i], 'SAI_QUEUE_STAT_PACKETS_last', packets)
redis.call('HSET', counters_table_name .. ':' .. KEYS[i], 'PFC_WD_DETECTION_TIME_LEFT', time_left)
redis.call('HSET', counters_table_name .. ':' .. port_id, pfc_rx_pkt_key .. '_last', pfc_rx_packets)
redis.call('HSET', counters_table_name .. ':' .. port_id, pfc_on2off_key .. '_last', pfc_on2off)
end
end

return rets
69 changes: 62 additions & 7 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "converter.h"
#include "saiserialize.h"

#include "saiserialize.h"

extern sai_switch_api_t *sai_switch_api;
extern sai_bridge_api_t *sai_bridge_api;
Expand Down Expand Up @@ -665,7 +664,6 @@ bool PortsOrch::validatePortSpeed(sai_object_id_t port_id, sai_uint32_t speed)
bool PortsOrch::setPortSpeed(sai_object_id_t port_id, sai_uint32_t speed)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
sai_status_t status;

Expand Down Expand Up @@ -728,6 +726,33 @@ bool PortsOrch::getQueueType(sai_object_id_t queue_id, string &type)
return true;
}

bool PortsOrch::setPortAutoNeg(sai_object_id_t id, int an)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE;
switch(an) {
case 0: // leave it as is?
return true;
case 1:
attr.value.booldata = true;
break;
case 2:
attr.value.booldata = false;
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just bool? 0, 1 here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original idea was to support default/on/off. Default would imply SDK defaults. But SAI does not support that. The use case is to default to different settings based on the type of cable/transcievers/etc. I can revert this back to boolean, if you feel it won't be supported in the near future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to SAI, it seems is bool value, and the default value is false. If you feel that the default value is incorrect, then we should change in the sai spec.

I think it will be clear here to follow SAI standard.


sai_status_t status = sai_port_api->set_port_attribute(id, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to set AN %u to port pid:%lx", attr.value.u32, id);
return false;
}
SWSS_LOG_INFO("Set AN %u to port pid:%lx", attr.value.u32, id);
return true;
}

bool PortsOrch::setHostIntfsOperStatus(sai_object_id_t port_id, bool up)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -771,7 +796,7 @@ void PortsOrch::updateDbPortOperStatus(sai_object_id_t id, sai_port_oper_status_
}
}

bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed)
bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed, int an, string fec_mode)
{
SWSS_LOG_ENTER();

Expand All @@ -789,6 +814,18 @@ bool PortsOrch::addPort(const set<int> &lane_set, uint32_t speed)
attr.value.u32list.count = static_cast<uint32_t>(lanes.size());
attrs.push_back(attr);

if(an == true) {
attr.id = SAI_PORT_ATTR_AUTO_NEG_MODE;
attr.value.booldata = true;
attrs.push_back(attr);
}

if(fec_mode != "") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make brace in a separate line and leave a space between if and parenthesis.

attr.id = SAI_PORT_ATTR_FEC_MODE;
attr.value.u32 = fec_mode_map[fec_mode];
attrs.push_back(attr);
}

sai_object_id_t port_id;
sai_status_t status = sai_port_api->create_port(&port_id, gSwitchId, static_cast<uint32_t>(attrs.size()), attrs.data());
if (status != SAI_STATUS_SUCCESS)
Expand Down Expand Up @@ -939,6 +976,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
string fec_mode;
uint32_t mtu = 0;
uint32_t speed = 0;
int an = -1;

for (auto i : kfvFieldsValues(t))
{
Expand All @@ -953,6 +991,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
int lane = stoi(lane_str);
lane_set.insert(lane);
}

}

/* Set port admin status */
Expand All @@ -970,12 +1009,16 @@ void PortsOrch::doPortTask(Consumer &consumer)
/* Set port fec */
if (fvField(i) == "fec")
fec_mode = fvValue(i);

/* Set autoneg */
if (fvField(i) == "autoneg")
an = (int)stoul(fvValue(i));
}

/* Collect information about all received ports */
if (lane_set.size())
{
m_lanesAliasSpeedMap[lane_set] = make_tuple(alias, speed);
m_lanesAliasSpeedMap[lane_set] = make_tuple(alias, speed, an, fec_mode);
}

/* Once all ports received, go through the each port and perform appropriate actions:
Expand All @@ -990,7 +1033,7 @@ void PortsOrch::doPortTask(Consumer &consumer)
if (m_lanesAliasSpeedMap.find(it->first) == m_lanesAliasSpeedMap.end())
{
char *platform = getenv("platform");
if (platform && strstr(platform, MLNX_PLATFORM_SUBSTRING))
if (platform && (strstr(platform, BFN_PLATFORM_SUBSTRING) || strstr(platform, MLNX_PLATFORM_SUBSTRING)))
{
if (!removePort(it->second))
{
Expand Down Expand Up @@ -1019,9 +1062,9 @@ void PortsOrch::doPortTask(Consumer &consumer)
// work around to avoid syncd termination on SAI error due missing create_port SAI API
// can be removed when SAI redis return NotImplemented error
char *platform = getenv("platform");
if (platform && strstr(platform, MLNX_PLATFORM_SUBSTRING))
if (platform && (strstr(platform, BFN_PLATFORM_SUBSTRING) || strstr(platform, MLNX_PLATFORM_SUBSTRING)))
{
if (!addPort(it->first, get<1>(it->second)))
if (!addPort(it->first, get<1>(it->second), get<2>(it->second), get<3>(it->second)))
{
throw runtime_error("PortsOrch initialization failure.");
}
Expand Down Expand Up @@ -1138,6 +1181,18 @@ void PortsOrch::doPortTask(Consumer &consumer)
}
}


if(an != -1) {
if (setPortAutoNeg(p.m_port_id, an))
SWSS_LOG_NOTICE("Set port %s AN to %u", alias.c_str(), an);
else
{
SWSS_LOG_ERROR("Failed to set port %s AN to %u", alias.c_str(), an);
it++;
continue;
}
}

if (fec_mode != "")
{
if (fec_mode_map.find(fec_mode) != fec_mode_map.end())
Expand Down
8 changes: 6 additions & 2 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

typedef std::vector<sai_uint32_t> PortSupportedSpeeds;


static const map<sai_port_oper_status_t, string> oper_status_strings =
{
{ SAI_PORT_OPER_STATUS_UNKNOWN, "unknown" },
Expand Down Expand Up @@ -79,7 +80,7 @@ class PortsOrch : public Orch, public Subject
bool m_portConfigDone = false;
sai_uint32_t m_portCount;
map<set<int>, sai_object_id_t> m_portListLaneMap;
map<set<int>, tuple<string, uint32_t>> m_lanesAliasSpeedMap;
map<set<int>, tuple<string, uint32_t, int, string>> m_lanesAliasSpeedMap;
map<string, Port> m_portList;

void doTask(Consumer &consumer);
Expand Down Expand Up @@ -113,7 +114,7 @@ class PortsOrch : public Orch, public Subject
bool removeLagMember(Port &lag, Port &port);
void getLagMember(Port &lag, vector<Port> &portv);

bool addPort(const set<int> &lane_set, uint32_t speed);
bool addPort(const set<int> &lane_set, uint32_t speed, int an=0, string fec="");
bool removePort(sai_object_id_t port_id);
bool initPort(const string &alias, const set<int> &lane_set);

Expand All @@ -130,6 +131,9 @@ class PortsOrch : public Orch, public Subject
bool getPortSpeed(sai_object_id_t port_id, sai_uint32_t &speed);

bool getQueueType(sai_object_id_t queue_id, string &type);

bool setPortAutoNeg(sai_object_id_t id, int an);
bool setPortFecMode(sai_object_id_t id, int fec);
};
#endif /* SWSS_PORTSORCH_H */

14 changes: 13 additions & 1 deletion portsyncd/portsyncd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ void handlePortConfigFile(ProducerStateTable &p, string file)
throw "Port configuration file not found!";
}

list<string> header = {"name", "lanes", "alias", "speed"};
list<string> header = {"name", "lanes", "alias", "speed", "autoneg", "fec"};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the master branch, fec is coming from config. If we are going to support autoneg in master, it should also come from config db.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there a problem with config DB for initial port states - ports will come up as default and then potentially "flap" when this configuration from DB is applied? I thought the portconfig.ini is first played into the SAI library and then modified when the config DB is evaluated and it notices a change. I may be wrong on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ultimately, all the configurations should come from one place. we plan to consolidate all configurations into config db.

I think since we are using create port API with the attributes coming from config db, there should be no flap.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we can remove the portconfig.ini file and get the breakout, speeds and hostinterface name, index associations from the configuration DB. The problem we had was that at boot up - we come up with default configurations - if the default matches the portconfig.ini no changes are observed. If changes come later it causes the remote nodes to see another flap. If we can eliminate this it will be great. Currently, you can see that some of the device configurations use breakout, fec and AN in the default config files. If you want us to remove fec and autoneg in the 201712 branch, we can do it. But the devices will need to apply a patch to build for their platforms. Some of them have fixed breakout configuration and default to fec and AN settings (sonic-buildimage pull request). Let me know if you want me to revert the changes and I will do so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for the confusion, I am ok with this on 201712 branch. For master branch, we need to take a different approach.

string line;
while (getline(infile, line))
{
Expand Down Expand Up @@ -254,6 +254,18 @@ void handlePortConfigFile(ProducerStateTable &p, string file)
attrs.push_back(speed_attr);
}

if ((entry.find("autoneg") != entry.end()) && (entry["autoneg"] != ""))
{
FieldValueTuple autoneg_attr("autoneg", entry["autoneg"]);
attrs.push_back(autoneg_attr);
}

if ((entry.find("fec") != entry.end()) && (entry["fec"] != ""))
{
FieldValueTuple fec_attr("fec", entry["fec"]);
attrs.push_back(fec_attr);
}

p.set(entry["name"], attrs);

g_portSet.insert(entry["name"]);
Expand Down
3 changes: 2 additions & 1 deletion tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ SWSS Integration tests runs on docker-sonic-vs which runs on top of SAI virtual
sudo pip install --system pytest==3.3.0
```
- Compile and install swss common library
````
```
cd sonic-swss-common
./autogen.sh
dpkg-buildpackage -us -uc -b
dpkg -i ../libswsscommon_1.0.0_amd64.deb
dpkg -i ../python-swsscommon_1.0.0_amd64.deb
Expand Down