Skip to content

Commit

Permalink
Add support for lane map in virtual switch (sonic-net#385)
Browse files Browse the repository at this point in the history
  • Loading branch information
kcudnik authored and lguohan committed Nov 20, 2018
1 parent 5ddafbc commit efdd86f
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/aspell.en.pws
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ EIO
encap
endl
enum
eth
ethernet
fdb
FDB
Expand Down
34 changes: 34 additions & 0 deletions tests/brcm/lanemap.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
; comment
# comment
eth0:29,30,31,32
eth1:25,26,27,28
eth2:37,38,39,40
eth3:33,34,35,36
eth4:41,42,43,44
eth5:45,46,47,48
eth6:5,6,7,8
eth7:1,2,3,4
eth8:9,10,11,12
eth9:13,14,15,16
eth10:21,22,23,24
eth11:17,18,19,20
eth12:249,50,51,52
eth13:353,54,55,56
eth14:461,62,63,64
eth15:557,58,59,60
eth16:665,66,67,68
eth17:769,70,71,72
eth18:877,78,79,80
eth19:973,74,75,76
eth20:105,106,107,108
eth21:109,110,111,112
eth22:117,118,119,120
eth23:113,114,115,116
eth24:121,122,123,124
eth25:125,126,127,128
eth26:85,86,87,88
eth27:81,82,83,84
eth28:89,90,91,92
eth29:93,94,95,96
eth30:97,98,99,100
eth31:101,102,103,104
1 change: 1 addition & 0 deletions tests/brcm/vsprofile.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SAI_WARM_BOOT_READ_FILE=/var/cache/sai_warmboot.bin
SAI_WARM_BOOT_WRITE_FILE=/var/cache/sai_warmboot.bin
SAI_VS_SWITCH_TYPE=SAI_VS_SWITCH_TYPE_BCM56850
SAI_VS_INTERFACE_LANE_MAP_FILE=brcm/lanemap.ini
18 changes: 18 additions & 0 deletions vslib/inc/sai_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@ extern "C" {
}

#include "swss/logger.h"
#include "swss/tokenize.h"
#include "meta/sai_meta.h"

#include <mutex>

#define SAI_KEY_VS_SWITCH_TYPE "SAI_VS_SWITCH_TYPE"

/**
* @def SAI_KEY_VS_INTERFACE_LANE_MAP_FILE
*
* If specified in profile.ini it should point to eth interface to lane map.
*
* Example:
* eth0:1,2,3,4
* eth1:5,6,7,8
*/
#define SAI_KEY_VS_INTERFACE_LANE_MAP_FILE "SAI_VS_INTERFACE_LANE_MAP_FILE"

/**
* @def SAI_KEY_VS_HOSTIF_USE_TAP_DEVICE
*
Expand Down Expand Up @@ -83,6 +95,12 @@ extern const char *g_boot_type;
extern const char *g_warm_boot_read_file;
extern const char *g_warm_boot_write_file;

extern const char *g_interface_lane_map_file;

extern std::map<uint32_t,std::string> g_lane_to_ifname;
extern std::map<std::string,std::vector<uint32_t>> g_ifname_to_lanes;
extern std::vector<uint32_t> g_lane_order;

extern const sai_acl_api_t vs_acl_api;
extern const sai_bfd_api_t vs_bfd_api;
extern const sai_bridge_api_t vs_bridge_api;
Expand Down
35 changes: 35 additions & 0 deletions vslib/src/sai_vs_hostintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,41 @@ bool hostif_create_tap_veth_forwarding(

std::string vethname = SAI_VS_VETH_PREFIX + tapname;

// check if user override interface names

{
sai_attribute_t attr;

uint32_t lanes[4];

attr.id = SAI_PORT_ATTR_HW_LANE_LIST;

attr.value.u32list.count = 4;
attr.value.u32list.list = lanes;

if (vs_generic_get(SAI_OBJECT_TYPE_PORT, port_id, 1, &attr) != SAI_STATUS_SUCCESS)
{
SWSS_LOG_WARN("failed to get port %s lanes, using veth: %s",
sai_serialize_object_id(port_id).c_str(),
vethname.c_str());
}
else
{
auto it = g_lane_to_ifname.find(lanes[0]);

if (it == g_lane_to_ifname.end())
{
SWSS_LOG_WARN("failed to get ifname from lane number %u", lanes[0]);
}
else
{
SWSS_LOG_NOTICE("using %s instead of %s", it->second.c_str(), vethname.c_str());

vethname = it->second;
}
}
}

int packet_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

if (packet_socket < 0)
Expand Down
136 changes: 136 additions & 0 deletions vslib/src/sai_vs_interfacequery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "sai_vs_state.h"
#include <string.h>
#include <unistd.h>
#include <net/if.h>

#include <algorithm>

Expand All @@ -25,10 +26,16 @@ std::shared_ptr<std::thread> g_fdbAgingThread;

int g_vs_boot_type = SAI_VS_COLD_BOOT;

std::map<uint32_t,std::string> g_lane_to_ifname;
std::map<std::string,std::vector<uint32_t>> g_ifname_to_lanes;
std::vector<uint32_t> g_lane_order;

const char *g_boot_type = NULL;
const char *g_warm_boot_read_file = NULL;
const char *g_warm_boot_write_file = NULL;

const char *g_interface_lane_map_file = NULL;

void channelOpEnableUnittests(
_In_ const std::string &key,
_In_ const std::vector<swss::FieldValueTuple> &values)
Expand Down Expand Up @@ -475,6 +482,131 @@ void clear_local_state()
vs_reset_id_counter();
}

bool check_ifname(
_In_ const std::string& name)
{
SWSS_LOG_ENTER();

size_t size = name.size();

if (size == 0 || size > IFNAMSIZ)
{
SWSS_LOG_ERROR("invalid interface name %s length: %zu", name.c_str(), size);
return false;
}

for (size_t i = 0; i < size; i++)
{
char c = name[i];

if (c >= '0' && c <= '9')
continue;

if (c >= 'a' && c <= 'z')
continue;

if (c >= 'A' && c <= 'Z')
continue;

SWSS_LOG_ERROR("invalid character '%c' in interface name %s", c, name.c_str());
return false;
}

// interface name is valid
return true;
}

void load_interface_lane_map()
{
SWSS_LOG_ENTER();

if (g_interface_lane_map_file == NULL)
{
SWSS_LOG_NOTICE("no interface lane map");
return;
}

std::ifstream lanemap(g_interface_lane_map_file);

if (!lanemap.is_open())
{
SWSS_LOG_ERROR("failed to open lane map file: %s", g_interface_lane_map_file);
return;
}

std::string line;

while(getline(lanemap, line))
{
if (line.size() > 0 && (line[0] == '#' || line[0] == ';'))
{
continue;
}

auto tokens = swss::tokenize(line, ':');

if (tokens.size() != 2)
{
SWSS_LOG_ERROR("expected 2 tokens in line %s, got %zu", line.c_str(), tokens.size());
continue;
}

auto ifname = tokens.at(0);
auto lanes = tokens.at(1);

if (!check_ifname(ifname))
{
continue;
}

if (g_ifname_to_lanes.find(ifname) != g_ifname_to_lanes.end())
{
SWSS_LOG_ERROR("interface %s was already defined", ifname.c_str());
continue;
}

tokens = swss::tokenize(lanes,',');

size_t n = tokens.size();

if (n != 1 && n != 2 && n != 4)
{
SWSS_LOG_ERROR("invalid number of lanes (%zu) assigned to interface %s", n, ifname.c_str());
continue;
}

std::vector<uint32_t> lanevec;

for (auto l: tokens)
{
uint32_t lanenumber;
if (sscanf(l.c_str(), "%u", &lanenumber) != 1)
{
SWSS_LOG_ERROR("failed to parse lane number: %s", l.c_str());
continue;
}

if (g_lane_to_ifname.find(lanenumber) != g_lane_to_ifname.end())
{
SWSS_LOG_ERROR("lane number %u used on %s was already defined on %s",
lanenumber,
ifname.c_str(),
g_lane_to_ifname.at(lanenumber).c_str());
continue;
}

lanevec.push_back(lanenumber);
g_lane_order.push_back(lanenumber);

g_lane_to_ifname[lanenumber] = ifname;
}

g_ifname_to_lanes[ifname] = lanevec;
}

SWSS_LOG_NOTICE("loaded %zu lanes and %zu interfaces", g_lane_to_ifname.size(), g_ifname_to_lanes.size());
}

sai_status_t sai_api_initialize(
_In_ uint64_t flags,
_In_ const sai_service_method_table_t *service_method_table)
Expand Down Expand Up @@ -511,6 +643,10 @@ sai_status_t sai_api_initialize(
return SAI_STATUS_FAILURE;
}

g_interface_lane_map_file = service_method_table->profile_get_value(0, SAI_KEY_VS_INTERFACE_LANE_MAP_FILE);

load_interface_lane_map();

g_boot_type = service_method_table->profile_get_value(0, SAI_KEY_BOOT_TYPE);
g_warm_boot_read_file = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE);
g_warm_boot_write_file = service_method_table->profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE);
Expand Down
16 changes: 16 additions & 0 deletions vslib/src/sai_vs_switch_BCM56850.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "sai_vs.h"
#include "sai_vs_state.h"
#include <net/if.h>

// TODO extra work may be needed on GET api if N on list will be > then actual

Expand Down Expand Up @@ -186,6 +187,21 @@ static sai_status_t create_ports()
101,102,103,104
};

if (g_lane_order.size() != port_count * 4)
{
SWSS_LOG_ERROR("only supported lane count is %d, using default", port_count * 4);
}
else if (g_ifname_to_lanes.size() != port_count)
{
SWSS_LOG_ERROR("only supported interface count is %d, using default", port_count);
}
else
{
SWSS_LOG_NOTICE("replacing lane numbers from %s", g_interface_lane_map_file);

memcpy(lanes, g_lane_order.data(), port_count * 4);
}

port_list.clear();

sai_object_id_t switch_object_id = ss->getSwitchId();
Expand Down
15 changes: 15 additions & 0 deletions vslib/src/sai_vs_switch_MLNX2700.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,21 @@ static sai_status_t create_ports()
4,5,6,7,
};

if (g_lane_order.size() != port_count * 4)
{
SWSS_LOG_ERROR("only supported lane count is %d, using default", port_count * 4);
}
else if (g_ifname_to_lanes.size() != port_count)
{
SWSS_LOG_ERROR("only supported interface count is %d, using default", port_count);
}
else
{
SWSS_LOG_NOTICE("replacing lane numbers from %s", g_interface_lane_map_file);

memcpy(lanes, g_lane_order.data(), port_count * 4);
}

port_list.clear();

sai_object_id_t switch_id = ss->getSwitchId();
Expand Down

0 comments on commit efdd86f

Please sign in to comment.