Skip to content

Commit e66d49a

Browse files
authored
[LLDP] Fix for LLDP advertisements being sent with wrong information. (sonic-net#5493)
* Fix for LLDP advertisments being sent with wrong information. Since lldpd is starting before lldpmgr, some advertisment packets might sent with default value, mac address as Port ID. This fix hold the packets from being sent by the lldpd until all interfaces are well configured by the lldpmgrd. Signed-off-by: Shlomi Bitton <[email protected]> * Fix comments * Fix unit-test output caused a failure during build * Add 'run_cmd' function and use it * Resume lldpd even if port init timeout reached
1 parent c14b41d commit e66d49a

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

dockers/docker-lldp/lldpd.conf.j2

+2
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ configure ports eth0 lldp portidsubtype local {{ mgmt_port_name }}
1010
configure system ip management pattern {{ ipv4 }}
1111
{% endif %}
1212
configure system hostname {{ DEVICE_METADATA['localhost']['hostname'] }}
13+
{# pause lldpd operations until all interfaces are well configured, resume command will run in lldpmgrd #}
14+
pause

dockers/docker-lldp/lldpmgrd

+39-4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ try:
1919
import subprocess
2020
import sys
2121

22+
import syslog
23+
import os.path
24+
import time
2225
from sonic_py_common import daemon_base
2326
from swsscommon import swsscommon
2427
except ImportError as err:
@@ -27,6 +30,7 @@ except ImportError as err:
2730
VERSION = "1.0"
2831

2932
SYSLOG_IDENTIFIER = "lldpmgrd"
33+
PORT_INIT_TIMEOUT = 300
3034

3135

3236
class LldpManager(daemon_base.DaemonBase):
@@ -130,16 +134,14 @@ class LldpManager(daemon_base.DaemonBase):
130134
for (port_name, cmd) in self.pending_cmds.iteritems():
131135
self.log_debug("Running command: '{}'".format(cmd))
132136

133-
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
134-
135-
(stdout, stderr) = proc.communicate()
137+
rc, stderr = run_cmd(self, cmd)
136138

137139
# If the command succeeds, add the port name to our to_delete list.
138140
# We will delete this command from self.pending_cmds below.
139141
# If the command fails, log a message, but don't delete the command
140142
# from self.pending_cmds, so that the command will be retried the
141143
# next time this method is called.
142-
if proc.returncode == 0:
144+
if rc == 0:
143145
to_delete.append(port_name)
144146
else:
145147
self.log_warning("Command failed '{}': {}".format(cmd, stderr))
@@ -166,6 +168,13 @@ class LldpManager(daemon_base.DaemonBase):
166168
# Set select timeout to 10 seconds
167169
SELECT_TIMEOUT_MS = 1000 * 10
168170

171+
# Daemon is paused on the configuration file to avoid lldp packets with wrong information
172+
# until all interfaces are well configured on lldpd
173+
port_init_done = False
174+
port_config_done = False
175+
resume_lldp_sent = False
176+
start_time = time.time()
177+
169178
sel = swsscommon.Select()
170179

171180
# Subscribe to PORT table notifications in the Config DB
@@ -204,9 +213,25 @@ class LldpManager(daemon_base.DaemonBase):
204213
else:
205214
self.pending_cmds.pop(key, None)
206215

216+
elif key == "PortInitDone":
217+
port_init_done = True
218+
elif key == "PortConfigDone":
219+
port_config_done = True
220+
207221
# Process all pending commands
208222
self.process_pending_cmds()
209223

224+
# Resume the daemon since all interfaces data updated and configured to the lldpd so no miss leading packets will be sent
225+
if not resume_lldp_sent:
226+
if check_timeout(self, start_time):
227+
port_init_done = port_config_done = True
228+
if port_init_done and port_config_done:
229+
port_init_done = port_config_done = False
230+
rc, stderr = run_cmd(self, "lldpcli resume")
231+
if rc != 0:
232+
self.log_error("Failed to resume lldpd with command: 'lldpcli resume': {}".format(stderr))
233+
sys.exit(1)
234+
resume_lldp_sent = True
210235

211236
# ============================= Functions =============================
212237

@@ -219,6 +244,16 @@ def main():
219244

220245
lldpmgr.run()
221246

247+
def run_cmd(self, cmd):
248+
proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
249+
(stdout, stderr) = proc.communicate()
250+
return proc.returncode, stderr
251+
252+
def check_timeout(self, start_time):
253+
if time.time() - start_time > PORT_INIT_TIMEOUT:
254+
self.log_error("Port init timeout reached ({} seconds), resuming lldpd...".format(PORT_INIT_TIMEOUT))
255+
return True
256+
return False
222257

223258
if __name__ == "__main__":
224259
main()
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
configure ports eth0 lldp portidsubtype local eth0
22
configure system ip management pattern 10.0.0.100
33
configure system hostname switch-t0
4+
pause
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
configure ports eth0 lldp portidsubtype local eth0
22
configure system ip management pattern 10.0.0.100
33
configure system hostname switch-t0
4+
pause

0 commit comments

Comments
 (0)