Skip to content

Commit

Permalink
Add support for recreate host interfaces tap devices on warm start (s…
Browse files Browse the repository at this point in the history
  • Loading branch information
kcudnik authored and lguohan committed Dec 3, 2018
1 parent b4a7160 commit cd97c60
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 16 deletions.
12 changes: 12 additions & 0 deletions vslib/inc/sai_vs_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,15 @@ typedef struct _fdb_info_t

} fdb_info_t;

extern std::string sai_vs_serialize_fdb_info(
_In_ const fdb_info_t& fdb_info);

extern void sai_vs_deserialize_fdb_info(
_In_ const std::string& data,
_Out_ fdb_info_t& fdb_info);

#define SAI_VS_FDB_INFO "SAI_VS_FDB_INFO"

extern std::set<fdb_info_t> g_fdb_info_set;

class SwitchState
Expand Down Expand Up @@ -268,6 +277,9 @@ void vs_clear_switch_ids();
void vs_free_real_object_id(
_In_ sai_object_id_t switch_id);

sai_status_t vs_recreate_hostif_tap_interfaces(
_In_ sai_object_id_t switch_id);

sai_object_id_t vs_create_real_object_id(
_In_ sai_object_type_t object_type,
_In_ sai_object_id_t switch_id);
Expand Down
33 changes: 32 additions & 1 deletion vslib/src/sai_vs_generic_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,28 @@ std::shared_ptr<SwitchState> vs_read_switch_database_for_warm_restart(
std::string str_attr_id;
std::string str_attr_value;

iss >> str_object_type >> str_object_id >> str_attr_id >> str_attr_value;
iss >> str_object_type >> str_object_id;

if (str_object_type == SAI_VS_FDB_INFO)
{
/*
* If we read line from fdb info set and use tap device is enabled
* just parse line and repopulate fdb info set.
*/

if (g_vs_hostif_use_tap_device)
{
fdb_info_t fi;

sai_vs_deserialize_fdb_info(str_object_id, fi);

g_fdb_info_set.insert(fi);
}

continue;
}

iss >> str_attr_id >> str_attr_value;

sai_object_meta_key_t meta_key;

Expand Down Expand Up @@ -362,6 +383,11 @@ std::shared_ptr<SwitchState> vs_read_switch_database_for_warm_restart(

dumpFile.close();

if (g_vs_hostif_use_tap_device)
{
SWSS_LOG_NOTICE("loaded %zu fdb infos", g_fdb_info_set.size());
}

SWSS_LOG_NOTICE("loaded %zu objects from: %s", count, g_warm_boot_read_file);

return ss;
Expand Down Expand Up @@ -580,6 +606,11 @@ sai_status_t internal_vs_generic_create(
vs_update_real_object_ids(warmBootState);

vs_update_local_metadata(switch_id);

if (g_vs_hostif_use_tap_device)
{
vs_recreate_hostif_tap_interfaces(switch_id);
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions vslib/src/sai_vs_generic_get.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ sai_status_t internal_vs_generic_get(
{
SWSS_LOG_ENTER();

if (g_switch_state_map.find(switch_id) == g_switch_state_map.end())
{
SWSS_LOG_ERROR("failed to find switch %s in switch state map", sai_serialize_object_id(switch_id).c_str());

return SAI_STATUS_FAILURE;
}

auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(object_type);

auto it = objectHash.find(serialized_object_id);
Expand Down
15 changes: 15 additions & 0 deletions vslib/src/sai_vs_generic_remove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ void vs_dump_switch_database_for_warm_restart(
}
}

if (g_vs_hostif_use_tap_device)
{
/*
* If user is using tap devices we also need to dump local fdb info
* data and restore it on warm start.
*/

for (auto fi: g_fdb_info_set)
{
dumpFile << SAI_VS_FDB_INFO << " " << sai_vs_serialize_fdb_info(fi) << std::endl;
}

SWSS_LOG_NOTICE("dumped %zu fdb infos", g_fdb_info_set.size());
}

dumpFile.close();

SWSS_LOG_NOTICE("dumped %zu objects to %s", count, g_warm_boot_write_file);
Expand Down
120 changes: 107 additions & 13 deletions vslib/src/sai_vs_hostintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <net/if_arp.h>
#include <linux/if_ether.h>

#include "swss/json.hpp"

using json = nlohmann::json;

// TODO on hostif remove we should stop threads

typedef struct _hostif_info_t
Expand All @@ -45,6 +49,43 @@ std::map<std::string, std::shared_ptr<hostif_info_t>> hostif_info_map;

std::set<fdb_info_t> g_fdb_info_set;

std::string sai_vs_serialize_fdb_info(
_In_ const fdb_info_t& fi)
{
SWSS_LOG_ENTER();

json j;

j["port_id"] = sai_serialize_object_id(fi.port_id);
j["vlan_id"] = sai_serialize_vlan_id(fi.vlan_id);
j["bridge_port_id"] = sai_serialize_object_id(fi.bridge_port_id);
j["fdb_entry"] = sai_serialize_fdb_entry(fi.fdb_entry);
j["timestamp"] = sai_serialize_number(fi.timestamp);

SWSS_LOG_INFO("item: %s", j.dump().c_str());

return j.dump();
}

void sai_vs_deserialize_fdb_info(
_In_ const std::string& data,
_Out_ fdb_info_t& fi)
{
SWSS_LOG_ENTER();

SWSS_LOG_INFO("item: %s", data.c_str());

const json& j = json::parse(data);

memset(&fi, 0, sizeof(fi));

sai_deserialize_object_id(j["port_id"], fi.port_id);
sai_deserialize_vlan_id(j["vlan_id"], fi.vlan_id);
sai_deserialize_object_id(j["bridge_port_id"], fi.bridge_port_id);
sai_deserialize_fdb_entry(j["fdb_entry"], fi.fdb_entry);
sai_deserialize_number(j["timestamp"], fi.timestamp);
}

void updateLocalDB(
_In_ const sai_fdb_event_notification_data_t &data,
_In_ sai_fdb_event_t fdb_event)
Expand Down Expand Up @@ -961,24 +1002,13 @@ bool hostif_create_tap_veth_forwarding(
return true;
}

sai_status_t vs_create_hostif_int(
_In_ sai_object_type_t object_type,
_Out_ sai_object_id_t *hostif_id,
sai_status_t vs_create_hostif_tap_interface(
_In_ sai_object_id_t switch_id,
_In_ uint32_t attr_count,
_In_ const sai_attribute_t *attr_list)
{
SWSS_LOG_ENTER();

if (g_vs_hostif_use_tap_device == false)
{
return vs_generic_create(object_type,
hostif_id,
switch_id,
attr_count,
attr_list);
}

// validate SAI_HOSTIF_ATTR_TYPE

auto attr_type = sai_metadata_get_attr_by_id(SAI_HOSTIF_ATTR_TYPE, attr_count, attr_list);
Expand Down Expand Up @@ -1061,6 +1091,8 @@ sai_status_t vs_create_hostif_int(

sai_attribute_t attr;

memset(&attr, 0, sizeof(attr));

attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS;

sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr);
Expand Down Expand Up @@ -1105,7 +1137,69 @@ sai_status_t vs_create_hostif_int(

SWSS_LOG_INFO("created tap interface %s", name.c_str());

return vs_generic_create(object_type,
return SAI_STATUS_SUCCESS;
}

sai_status_t vs_recreate_hostif_tap_interfaces(
_In_ sai_object_id_t switch_id)
{
SWSS_LOG_ENTER();

if (g_vs_hostif_use_tap_device == false)
{
return SAI_STATUS_SUCCESS;
}

if (g_switch_state_map.find(switch_id) == g_switch_state_map.end())
{
SWSS_LOG_ERROR("failed to find switch %s in switch state map", sai_serialize_object_id(switch_id).c_str());

return SAI_STATUS_FAILURE;
}

auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_HOSTIF);

SWSS_LOG_NOTICE("attempt to recreate %zu tap devices for host interfaces", objectHash.size());

for (auto okvp: objectHash)
{
std::vector<sai_attribute_t> attrs;

for (auto akvp: okvp.second)
{
attrs.push_back(*akvp.second->getAttr());
}

vs_create_hostif_tap_interface(switch_id, (uint32_t)attrs.size(), attrs.data());
}

return SAI_STATUS_SUCCESS;
}

sai_status_t vs_create_hostif_int(
_In_ sai_object_type_t object_type,
_Out_ sai_object_id_t *hostif_id,
_In_ sai_object_id_t switch_id,
_In_ uint32_t attr_count,
_In_ const sai_attribute_t *attr_list)
{
SWSS_LOG_ENTER();

if (g_vs_hostif_use_tap_device == true)
{
sai_status_t status = vs_create_hostif_tap_interface(
switch_id,
attr_count,
attr_list);

if (status != SAI_STATUS_SUCCESS)
{
return status;
}
}

return vs_generic_create(
object_type,
hostif_id,
switch_id,
attr_count,
Expand Down
3 changes: 3 additions & 0 deletions vslib/src/sai_vs_interfacequery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,8 @@ void processFdbEntriesForAging()
return;
}

SWSS_LOG_INFO("fdb infos to process: %zu", g_fdb_info_set.size());

uint32_t current = (uint32_t)time(NULL);

// find aged fdb entries
Expand Down Expand Up @@ -716,6 +718,7 @@ sai_status_t sai_api_initialize(

g_fdbAgingThreadRun = true;

// TODO should this be moved to create switch and SwitchState?
g_fdbAgingThread = std::make_shared<std::thread>(std::thread(fdbAgingThreadProc));

g_api_initialized = true;
Expand Down
2 changes: 0 additions & 2 deletions vslib/src/sai_vs_switch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,6 @@ void vs_create_netlink_message_listener(
std::shared_ptr<std::thread> linkThread =
std::make_shared<std::thread>(linkmsg_thread, switch_id);

linkThread->detach();

sw->setLinkThread(linkThread);
}

Expand Down

0 comments on commit cd97c60

Please sign in to comment.