Skip to content

Commit e03d6e9

Browse files
jipanyanglguohan
authored andcommitted
Warm reboot: Support portsyncd process warm restart (sonic-net#549)
* Support portsyncd process warm restart Signed-off-by: Jipan Yang <[email protected]> * [VS]: add test case for portsyncd warm restart Signed-off-by: Jipan Yang <[email protected]> * Adapt to the new warm reboot schema Signed-off-by: Jipan Yang <[email protected]> * Remove unneccessary netlink dump for ports Signed-off-by: Jipan Yang <[email protected]> * Remove checkPortInitDone() which is optional Signed-off-by: Jipan Yang <[email protected]> * Remove test_warm_reboot.py for easy merge Signed-off-by: Jipan Yang <[email protected]> * Add back portsyncd warm restart test script Signed-off-by: Jipan Yang <[email protected]>
1 parent d7bd94f commit e03d6e9

File tree

4 files changed

+150
-40
lines changed

4 files changed

+150
-40
lines changed

portsyncd/Makefile.am

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
INCLUDES = -I $(top_srcdir)
1+
INCLUDES = -I $(top_srcdir) -I $(top_srcdir)/warmrestart
22

33
bin_PROGRAMS = portsyncd
44

@@ -8,7 +8,7 @@ else
88
DBGFLAGS = -g
99
endif
1010

11-
portsyncd_SOURCES = portsyncd.cpp linksync.cpp
11+
portsyncd_SOURCES = portsyncd.cpp linksync.cpp $(top_srcdir)/warmrestart/warm_restart.cpp $(top_srcdir)/warmrestart/warm_restart.h
1212

1313
portsyncd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
1414
portsyncd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)

portsyncd/linksync.cpp

+38-34
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "linkcache.h"
1515
#include "portsyncd/linksync.h"
16+
#include "warm_restart.h"
1617

1718
#include <iostream>
1819
#include <set>
@@ -41,52 +42,55 @@ LinkSync::LinkSync(DBConnector *appl_db, DBConnector *state_db) :
4142
m_portTable(appl_db, APP_PORT_TABLE_NAME),
4243
m_statePortTable(state_db, STATE_PORT_TABLE_NAME)
4344
{
44-
/* See the comments for g_portSet in portsyncd.cpp */
45-
for (string port : g_portSet)
45+
if (!WarmStart::isWarmStart())
4646
{
47-
vector<FieldValueTuple> temp;
48-
if (m_portTable.get(port, temp))
47+
/* See the comments for g_portSet in portsyncd.cpp */
48+
for (string port : g_portSet)
4949
{
50-
for (auto it : temp)
50+
vector<FieldValueTuple> temp;
51+
if (m_portTable.get(port, temp))
5152
{
52-
if (fvField(it) == "admin_status")
53+
for (auto it : temp)
5354
{
54-
g_portSet.erase(port);
55-
break;
55+
if (fvField(it) == "admin_status")
56+
{
57+
g_portSet.erase(port);
58+
break;
59+
}
5660
}
5761
}
5862
}
59-
}
60-
61-
struct if_nameindex *if_ni, *idx_p;
62-
if_ni = if_nameindex();
63-
if (if_ni == NULL)
64-
{
65-
return;
66-
}
6763

68-
for (idx_p = if_ni; ! (idx_p->if_index == 0 && idx_p->if_name == NULL); idx_p++)
69-
{
70-
string key = idx_p->if_name;
71-
if (key.compare(0, INTFS_PREFIX.length(), INTFS_PREFIX))
64+
struct if_nameindex *if_ni, *idx_p;
65+
if_ni = if_nameindex();
66+
if (if_ni == NULL)
7267
{
73-
continue;
68+
return;
7469
}
7570

76-
m_ifindexOldNameMap[idx_p->if_index] = key;
77-
78-
/* Bring down the existing kernel interfaces */
79-
string cmd, res;
80-
SWSS_LOG_INFO("Bring down old interface %s(%d)", key.c_str(), idx_p->if_index);
81-
cmd = "ip link set " + key + " down";
82-
try
83-
{
84-
swss::exec(cmd, res);
85-
}
86-
catch (...)
71+
for (idx_p = if_ni; ! (idx_p->if_index == 0 && idx_p->if_name == NULL); idx_p++)
8772
{
88-
/* Ignore error in this flow ; */
89-
SWSS_LOG_WARN("Failed to bring down old interface %s(%d)", key.c_str(), idx_p->if_index);
73+
string key = idx_p->if_name;
74+
if (key.compare(0, INTFS_PREFIX.length(), INTFS_PREFIX))
75+
{
76+
continue;
77+
}
78+
79+
m_ifindexOldNameMap[idx_p->if_index] = key;
80+
81+
/* Bring down the existing kernel interfaces */
82+
string cmd, res;
83+
SWSS_LOG_INFO("Bring down old interface %s(%d)", key.c_str(), idx_p->if_index);
84+
cmd = "ip link set " + key + " down";
85+
try
86+
{
87+
swss::exec(cmd, res);
88+
}
89+
catch (...)
90+
{
91+
/* Ignore error in this flow ; */
92+
SWSS_LOG_WARN("Failed to bring down old interface %s(%d)", key.c_str(), idx_p->if_index);
93+
}
9094
}
9195
}
9296
}

portsyncd/portsyncd.cpp

+21-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <set>
77
#include <map>
88
#include <list>
9+
#include <sys/stat.h>
910
#include "dbconnector.h"
1011
#include "select.h"
1112
#include "netdispatcher.h"
@@ -14,6 +15,7 @@
1415
#include "portsyncd/linksync.h"
1516
#include "subscriberstatetable.h"
1617
#include "exec.h"
18+
#include "warm_restart.h"
1719

1820
using namespace std;
1921
using namespace swss;
@@ -42,6 +44,7 @@ void handlePortConfigFile(ProducerStateTable &p, string file);
4244
void handlePortConfigFromConfigDB(ProducerStateTable &p, DBConnector &cfgDb);
4345
void handleVlanIntfFile(string file);
4446
void handlePortConfig(ProducerStateTable &p, map<string, KeyOpFieldsValuesTuple> &port_cfg_map);
47+
void checkPortInitDone(DBConnector *appl_db);
4548

4649
int main(int argc, char **argv)
4750
{
@@ -72,6 +75,15 @@ int main(int argc, char **argv)
7275
ProducerStateTable p(&appl_db, APP_PORT_TABLE_NAME);
7376
SubscriberStateTable portCfg(&cfgDb, CFG_PORT_TABLE_NAME);
7477

78+
WarmStart::checkWarmStart("portsyncd");
79+
if (WarmStart::isWarmStart())
80+
{
81+
/* clear the init port config buffer */
82+
cout << "portsyncd warm start" << endl;
83+
deque<KeyOpFieldsValuesTuple> vkco;
84+
portCfg.pops(vkco);
85+
}
86+
7587
LinkSync sync(&appl_db, &state_db);
7688
NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, &sync);
7789
NetDispatcher::getInstance().registerMessageHandler(RTM_DELLINK, &sync);
@@ -84,15 +96,20 @@ int main(int argc, char **argv)
8496
netlink.registerGroup(RTNLGRP_LINK);
8597
cout << "Listen to link messages..." << endl;
8698

87-
if (!port_config_file.empty())
99+
/* For portsyncd warm start, don't process init port config again */
100+
if (!WarmStart::isWarmStart())
88101
{
89-
handlePortConfigFile(p, port_config_file);
90-
} else {
91-
handlePortConfigFromConfigDB(p, cfgDb);
102+
if (!port_config_file.empty())
103+
{
104+
handlePortConfigFile(p, port_config_file);
105+
} else {
106+
handlePortConfigFromConfigDB(p, cfgDb);
107+
}
92108
}
93109

94110
s.addSelectable(&netlink);
95111
s.addSelectable(&portCfg);
112+
96113
while (true)
97114
{
98115
Selectable *temps;

tests/test_warm_reboot.py

+89
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,95 @@ def how_many_entries_exist(db, table):
8787
return len(tbl.getKeys())
8888

8989

90+
def test_PortSyncdWarmRestart(dvs):
91+
92+
conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
93+
appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
94+
state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0)
95+
96+
# enable warm restart
97+
# TODO: use cfg command to config it
98+
create_entry_tbl(
99+
conf_db,
100+
swsscommon.CFG_WARM_RESTART_TABLE_NAME, "swss",
101+
[
102+
("enable", "true"),
103+
]
104+
)
105+
106+
dvs.runcmd("ifconfig Ethernet16 up")
107+
dvs.runcmd("ifconfig Ethernet20 up")
108+
109+
time.sleep(1)
110+
111+
dvs.runcmd("ifconfig Ethernet16 11.0.0.1/29 up")
112+
dvs.runcmd("ifconfig Ethernet20 11.0.0.9/29 up")
113+
114+
dvs.servers[4].runcmd("ip link set down dev eth0") == 0
115+
dvs.servers[4].runcmd("ip link set up dev eth0") == 0
116+
dvs.servers[4].runcmd("ifconfig eth0 11.0.0.2/29")
117+
dvs.servers[4].runcmd("ip route add default via 11.0.0.1")
118+
119+
dvs.servers[5].runcmd("ip link set down dev eth0") == 0
120+
dvs.servers[5].runcmd("ip link set up dev eth0") == 0
121+
dvs.servers[5].runcmd("ifconfig eth0 11.0.0.10/29")
122+
dvs.servers[5].runcmd("ip route add default via 11.0.0.9")
123+
124+
time.sleep(1)
125+
126+
# Ethernet port oper status should be up
127+
check_port_oper_status(appl_db, "Ethernet16", "up")
128+
check_port_oper_status(appl_db, "Ethernet20", "up")
129+
130+
# Ping should work between servers via vs vlan interfaces
131+
ping_stats = dvs.servers[4].runcmd("ping -c 1 11.0.0.10")
132+
time.sleep(1)
133+
134+
neighTbl = swsscommon.Table(appl_db, "NEIGH_TABLE")
135+
(status, fvs) = neighTbl.get("Ethernet16:11.0.0.2")
136+
assert status == True
137+
138+
(status, fvs) = neighTbl.get("Ethernet20:11.0.0.10")
139+
assert status == True
140+
141+
restart_count = swss_get_RestartCount(state_db)
142+
143+
# restart portsyncd
144+
dvs.runcmd(['sh', '-c', 'pkill -x portsyncd; cp /var/log/swss/sairedis.rec /var/log/swss/sairedis.rec.b; echo > /var/log/swss/sairedis.rec'])
145+
dvs.runcmd(['sh', '-c', 'supervisorctl start portsyncd'])
146+
time.sleep(2)
147+
148+
# No create/set/remove operations should be passed down to syncd for portsyncd warm restart
149+
num = dvs.runcmd(['sh', '-c', 'grep \|c\| /var/log/swss/sairedis.rec | wc -l'])
150+
assert num == '0\n'
151+
num = dvs.runcmd(['sh', '-c', 'grep \|s\| /var/log/swss/sairedis.rec | wc -l'])
152+
assert num == '0\n'
153+
num = dvs.runcmd(['sh', '-c', 'grep \|r\| /var/log/swss/sairedis.rec | wc -l'])
154+
assert num == '0\n'
155+
156+
#new ip on server 5
157+
dvs.servers[5].runcmd("ifconfig eth0 11.0.0.11/29")
158+
159+
# Ping should work between servers via vs Ethernet interfaces
160+
ping_stats = dvs.servers[4].runcmd("ping -c 1 11.0.0.11")
161+
162+
# new neighbor learn on VS
163+
(status, fvs) = neighTbl.get("Ethernet20:11.0.0.11")
164+
assert status == True
165+
166+
# Port state change reflected in appDB correctly
167+
dvs.servers[6].runcmd("ip link set down dev eth0") == 0
168+
dvs.servers[6].runcmd("ip link set up dev eth0") == 0
169+
time.sleep(1)
170+
171+
check_port_oper_status(appl_db, "Ethernet16", "up")
172+
check_port_oper_status(appl_db, "Ethernet20", "up")
173+
check_port_oper_status(appl_db, "Ethernet24", "up")
174+
175+
176+
swss_app_check_RestartCount_single(state_db, restart_count, "portsyncd")
177+
178+
90179
def test_VlanMgrdWarmRestart(dvs):
91180

92181
conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)

0 commit comments

Comments
 (0)