Skip to content

Commit 8eca19c

Browse files
kcudniklguohan
authored andcommitted
Add support for recreate host interfaces tap devices on warm start (sonic-net#392)
1 parent 799ad45 commit 8eca19c

7 files changed

+176
-16
lines changed

vslib/inc/sai_vs_state.h

+12
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,15 @@ typedef struct _fdb_info_t
135135

136136
} fdb_info_t;
137137

138+
extern std::string sai_vs_serialize_fdb_info(
139+
_In_ const fdb_info_t& fdb_info);
140+
141+
extern void sai_vs_deserialize_fdb_info(
142+
_In_ const std::string& data,
143+
_Out_ fdb_info_t& fdb_info);
144+
145+
#define SAI_VS_FDB_INFO "SAI_VS_FDB_INFO"
146+
138147
extern std::set<fdb_info_t> g_fdb_info_set;
139148

140149
class SwitchState
@@ -268,6 +277,9 @@ void vs_clear_switch_ids();
268277
void vs_free_real_object_id(
269278
_In_ sai_object_id_t switch_id);
270279

280+
sai_status_t vs_recreate_hostif_tap_interfaces(
281+
_In_ sai_object_id_t switch_id);
282+
271283
sai_object_id_t vs_create_real_object_id(
272284
_In_ sai_object_type_t object_type,
273285
_In_ sai_object_id_t switch_id);

vslib/src/sai_vs_generic_create.cpp

+32-1
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,28 @@ std::shared_ptr<SwitchState> vs_read_switch_database_for_warm_restart(
304304
std::string str_attr_id;
305305
std::string str_attr_value;
306306

307-
iss >> str_object_type >> str_object_id >> str_attr_id >> str_attr_value;
307+
iss >> str_object_type >> str_object_id;
308+
309+
if (str_object_type == SAI_VS_FDB_INFO)
310+
{
311+
/*
312+
* If we read line from fdb info set and use tap device is enabled
313+
* just parse line and repopulate fdb info set.
314+
*/
315+
316+
if (g_vs_hostif_use_tap_device)
317+
{
318+
fdb_info_t fi;
319+
320+
sai_vs_deserialize_fdb_info(str_object_id, fi);
321+
322+
g_fdb_info_set.insert(fi);
323+
}
324+
325+
continue;
326+
}
327+
328+
iss >> str_attr_id >> str_attr_value;
308329

309330
sai_object_meta_key_t meta_key;
310331

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

363384
dumpFile.close();
364385

386+
if (g_vs_hostif_use_tap_device)
387+
{
388+
SWSS_LOG_NOTICE("loaded %zu fdb infos", g_fdb_info_set.size());
389+
}
390+
365391
SWSS_LOG_NOTICE("loaded %zu objects from: %s", count, g_warm_boot_read_file);
366392

367393
return ss;
@@ -580,6 +606,11 @@ sai_status_t internal_vs_generic_create(
580606
vs_update_real_object_ids(warmBootState);
581607

582608
vs_update_local_metadata(switch_id);
609+
610+
if (g_vs_hostif_use_tap_device)
611+
{
612+
vs_recreate_hostif_tap_interfaces(switch_id);
613+
}
583614
}
584615
}
585616

vslib/src/sai_vs_generic_get.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ sai_status_t internal_vs_generic_get(
4141
{
4242
SWSS_LOG_ENTER();
4343

44+
if (g_switch_state_map.find(switch_id) == g_switch_state_map.end())
45+
{
46+
SWSS_LOG_ERROR("failed to find switch %s in switch state map", sai_serialize_object_id(switch_id).c_str());
47+
48+
return SAI_STATUS_FAILURE;
49+
}
50+
4451
auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(object_type);
4552

4653
auto it = objectHash.find(serialized_object_id);

vslib/src/sai_vs_generic_remove.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,21 @@ void vs_dump_switch_database_for_warm_restart(
9595
}
9696
}
9797

98+
if (g_vs_hostif_use_tap_device)
99+
{
100+
/*
101+
* If user is using tap devices we also need to dump local fdb info
102+
* data and restore it on warm start.
103+
*/
104+
105+
for (auto fi: g_fdb_info_set)
106+
{
107+
dumpFile << SAI_VS_FDB_INFO << " " << sai_vs_serialize_fdb_info(fi) << std::endl;
108+
}
109+
110+
SWSS_LOG_NOTICE("dumped %zu fdb infos", g_fdb_info_set.size());
111+
}
112+
98113
dumpFile.close();
99114

100115
SWSS_LOG_NOTICE("dumped %zu objects to %s", count, g_warm_boot_write_file);

vslib/src/sai_vs_hostintf.cpp

+107-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include <net/if_arp.h>
2222
#include <linux/if_ether.h>
2323

24+
#include "swss/json.hpp"
25+
26+
using json = nlohmann::json;
27+
2428
// TODO on hostif remove we should stop threads
2529

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

4650
std::set<fdb_info_t> g_fdb_info_set;
4751

52+
std::string sai_vs_serialize_fdb_info(
53+
_In_ const fdb_info_t& fi)
54+
{
55+
SWSS_LOG_ENTER();
56+
57+
json j;
58+
59+
j["port_id"] = sai_serialize_object_id(fi.port_id);
60+
j["vlan_id"] = sai_serialize_vlan_id(fi.vlan_id);
61+
j["bridge_port_id"] = sai_serialize_object_id(fi.bridge_port_id);
62+
j["fdb_entry"] = sai_serialize_fdb_entry(fi.fdb_entry);
63+
j["timestamp"] = sai_serialize_number(fi.timestamp);
64+
65+
SWSS_LOG_INFO("item: %s", j.dump().c_str());
66+
67+
return j.dump();
68+
}
69+
70+
void sai_vs_deserialize_fdb_info(
71+
_In_ const std::string& data,
72+
_Out_ fdb_info_t& fi)
73+
{
74+
SWSS_LOG_ENTER();
75+
76+
SWSS_LOG_INFO("item: %s", data.c_str());
77+
78+
const json& j = json::parse(data);
79+
80+
memset(&fi, 0, sizeof(fi));
81+
82+
sai_deserialize_object_id(j["port_id"], fi.port_id);
83+
sai_deserialize_vlan_id(j["vlan_id"], fi.vlan_id);
84+
sai_deserialize_object_id(j["bridge_port_id"], fi.bridge_port_id);
85+
sai_deserialize_fdb_entry(j["fdb_entry"], fi.fdb_entry);
86+
sai_deserialize_number(j["timestamp"], fi.timestamp);
87+
}
88+
4889
void updateLocalDB(
4990
_In_ const sai_fdb_event_notification_data_t &data,
5091
_In_ sai_fdb_event_t fdb_event)
@@ -961,24 +1002,13 @@ bool hostif_create_tap_veth_forwarding(
9611002
return true;
9621003
}
9631004

964-
sai_status_t vs_create_hostif_int(
965-
_In_ sai_object_type_t object_type,
966-
_Out_ sai_object_id_t *hostif_id,
1005+
sai_status_t vs_create_hostif_tap_interface(
9671006
_In_ sai_object_id_t switch_id,
9681007
_In_ uint32_t attr_count,
9691008
_In_ const sai_attribute_t *attr_list)
9701009
{
9711010
SWSS_LOG_ENTER();
9721011

973-
if (g_vs_hostif_use_tap_device == false)
974-
{
975-
return vs_generic_create(object_type,
976-
hostif_id,
977-
switch_id,
978-
attr_count,
979-
attr_list);
980-
}
981-
9821012
// validate SAI_HOSTIF_ATTR_TYPE
9831013

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

10621092
sai_attribute_t attr;
10631093

1094+
memset(&attr, 0, sizeof(attr));
1095+
10641096
attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS;
10651097

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

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

1108-
return vs_generic_create(object_type,
1140+
return SAI_STATUS_SUCCESS;
1141+
}
1142+
1143+
sai_status_t vs_recreate_hostif_tap_interfaces(
1144+
_In_ sai_object_id_t switch_id)
1145+
{
1146+
SWSS_LOG_ENTER();
1147+
1148+
if (g_vs_hostif_use_tap_device == false)
1149+
{
1150+
return SAI_STATUS_SUCCESS;
1151+
}
1152+
1153+
if (g_switch_state_map.find(switch_id) == g_switch_state_map.end())
1154+
{
1155+
SWSS_LOG_ERROR("failed to find switch %s in switch state map", sai_serialize_object_id(switch_id).c_str());
1156+
1157+
return SAI_STATUS_FAILURE;
1158+
}
1159+
1160+
auto &objectHash = g_switch_state_map.at(switch_id)->objectHash.at(SAI_OBJECT_TYPE_HOSTIF);
1161+
1162+
SWSS_LOG_NOTICE("attempt to recreate %zu tap devices for host interfaces", objectHash.size());
1163+
1164+
for (auto okvp: objectHash)
1165+
{
1166+
std::vector<sai_attribute_t> attrs;
1167+
1168+
for (auto akvp: okvp.second)
1169+
{
1170+
attrs.push_back(*akvp.second->getAttr());
1171+
}
1172+
1173+
vs_create_hostif_tap_interface(switch_id, (uint32_t)attrs.size(), attrs.data());
1174+
}
1175+
1176+
return SAI_STATUS_SUCCESS;
1177+
}
1178+
1179+
sai_status_t vs_create_hostif_int(
1180+
_In_ sai_object_type_t object_type,
1181+
_Out_ sai_object_id_t *hostif_id,
1182+
_In_ sai_object_id_t switch_id,
1183+
_In_ uint32_t attr_count,
1184+
_In_ const sai_attribute_t *attr_list)
1185+
{
1186+
SWSS_LOG_ENTER();
1187+
1188+
if (g_vs_hostif_use_tap_device == true)
1189+
{
1190+
sai_status_t status = vs_create_hostif_tap_interface(
1191+
switch_id,
1192+
attr_count,
1193+
attr_list);
1194+
1195+
if (status != SAI_STATUS_SUCCESS)
1196+
{
1197+
return status;
1198+
}
1199+
}
1200+
1201+
return vs_generic_create(
1202+
object_type,
11091203
hostif_id,
11101204
switch_id,
11111205
attr_count,

vslib/src/sai_vs_interfacequery.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ void processFdbEntriesForAging()
387387
return;
388388
}
389389

390+
SWSS_LOG_INFO("fdb infos to process: %zu", g_fdb_info_set.size());
391+
390392
uint32_t current = (uint32_t)time(NULL);
391393

392394
// find aged fdb entries
@@ -716,6 +718,7 @@ sai_status_t sai_api_initialize(
716718

717719
g_fdbAgingThreadRun = true;
718720

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

721724
g_api_initialized = true;

vslib/src/sai_vs_switch.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,6 @@ void vs_create_netlink_message_listener(
253253
std::shared_ptr<std::thread> linkThread =
254254
std::make_shared<std::thread>(linkmsg_thread, switch_id);
255255

256-
linkThread->detach();
257-
258256
sw->setLinkThread(linkThread);
259257
}
260258

0 commit comments

Comments
 (0)