Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[docker-syncd-mlnx] add new mlnx-sfpd daemon to docker-syncd-mlnx #1841

Merged
merged 1 commit into from
Jul 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion platform/mellanox/docker-syncd-mlnx-rpc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

DOCKER_SYNCD_MLNX_RPC = docker-syncd-mlnx-rpc.gz
$(DOCKER_SYNCD_MLNX_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-mlnx-rpc
$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT)
$(DOCKER_SYNCD_MLNX_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) $(MLNX_SFPD)
$(DOCKER_SYNCD_MLNX_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_MLNX)
SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX_RPC)
ifeq ($(ENABLE_SYNCD_RPC),y)
Expand Down
2 changes: 1 addition & 1 deletion platform/mellanox/docker-syncd-mlnx.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

DOCKER_SYNCD_MLNX = docker-syncd-mlnx.gz
$(DOCKER_SYNCD_MLNX)_PATH = $(PLATFORM_PATH)/docker-syncd-mlnx
$(DOCKER_SYNCD_MLNX)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API)
$(DOCKER_SYNCD_MLNX)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) $(MLNX_SFPD)
$(DOCKER_SYNCD_MLNX)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE)
SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_MLNX)
ifneq ($(ENABLE_SYNCD_RPC),y)
Expand Down
2 changes: 2 additions & 0 deletions platform/mellanox/docker-syncd-mlnx/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ rm -f /var/run/rsyslogd.pid
supervisorctl start rsyslogd

supervisorctl start syncd

supervisorctl start mlnx-sfpd
8 changes: 8 additions & 0 deletions platform/mellanox/docker-syncd-mlnx/supervisord.conf
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog

[program:mlnx-sfpd]
command=/usr/bin/mlnx-sfpd
priority=4
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
5 changes: 5 additions & 0 deletions platform/mellanox/mlnx-sfpd.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# mlnx-sfpd (SONiC MLNX platform sfp event monitoring daemon) Debian package

MLNX_SFPD = python-mlnx-sfpd_1.0-1_all.deb
$(MLNX_SFPD)_SRC_PATH = $(PLATFORM_PATH)/mlnx-sfpd
SONIC_PYTHON_STDEB_DEBS += $(MLNX_SFPD)
199 changes: 199 additions & 0 deletions platform/mellanox/mlnx-sfpd/scripts/mlnx-sfpd
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#!/usr/bin/env python
'''
This code is for a mlnx platform specific daemon, mlnx-sfpd.
Which listen to the SDK for the SFP change event and post the event to DB.
'''

from __future__ import print_function
import sys, errno
import os
import time
import syslog
import signal
import json
from python_sdk_api.sx_api import *
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • [](start = 34, length = 1)

Don't import wildcard in prod code.

from swsssdk import SonicV2Connector

VERSION = '1.0'

SYSLOG_IDENTIFIER = "mlnx-sfpd"

REDIS_HOSTIP = "127.0.0.1"

SDK_SFP_STATE_IN = 0x1
SDK_SFP_STATE_OUT = 0x2
STATUS_PLUGIN = '1'
STATUS_PLUGOUT = '0'
STATUS_UNKNOWN = '2'

sfp_value_status_dict = {SDK_SFP_STATE_IN:STATUS_PLUGIN, SDK_SFP_STATE_OUT:STATUS_PLUGOUT}

#========================== Syslog wrappers ==========================

def log_info(msg, also_print_to_console=False):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_INFO, msg)
syslog.closelog()

if also_print_to_console:
print(msg)

def log_warning(msg, also_print_to_console=False):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_WARNING, msg)
syslog.closelog()

if also_print_to_console:
print(msg)

def log_error(msg, also_print_to_console=False):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_ERR, msg)
syslog.closelog()

if also_print_to_console:
print(msg)

#========================== Signal Handling ==========================

def signal_handler(sig, frame):
if sig == signal.SIGHUP:
log_info("Caught SIGHUP - ignoring...")
return
elif sig == signal.SIGINT:
log_info("Caught SIGINT - exiting...")
sys.exit(128 + sig)
elif sig == signal.SIGTERM:
log_info("Caught SIGTERM - exiting...")
sys.exit(128 + sig)
else:
log_warning("Caught unhandled signal '" + sig + "'")


def sx_recv(fd_p, handle):
# recv parameters
pkt_size = 2000
pkt_size_p = new_uint32_t_p()
uint32_t_p_assign(pkt_size_p, pkt_size)
pkt = new_uint8_t_arr(pkt_size)
recv_info_p = new_sx_receive_info_t_p()
pmpe_t = sx_event_pmpe_t()
logical_port_list = new_sx_port_log_id_t_arr(4)
port_attributes_list = new_sx_port_attributes_t_arr(64)
port_cnt_p = new_uint32_t_p()
uint32_t_p_assign(port_cnt_p,64)
label_port_list = []

rc = sx_lib_host_ifc_recv(fd_p, pkt, pkt_size_p, recv_info_p)
if rc != 0:
log_error("event receive exit with error, rc %d" % rc)
exit(rc)

pmpe_t = recv_info_p.event_info.pmpe
port_list_size = pmpe_t.list_size
logical_port_list = pmpe_t.log_port_list
module_state = pmpe_t.module_state

for i in range(0, port_list_size):
logical_port = sx_port_log_id_t_arr_getitem(logical_port_list, i)
rc = sx_api_port_device_get(handle, 1 , 0, port_attributes_list, port_cnt_p)
port_cnt = uint32_t_p_value(port_cnt_p)

for i in range(0,port_cnt):
port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list,i)
if port_attributes.log_port == logical_port:
lable_port = port_attributes.port_mapping.module_port
break
label_port_list.append(lable_port)

return label_port_list, module_state

def send_sfp_notification(db, interface, state):
sfp_notify = [interface,state]
msg = json.dumps(sfp_notify,separators=(',',':'))
db.publish('STATE_DB','TRANSCEIVER_NOTIFY', msg)
return

# main start
def main():
# Register our signal handlers
signal.signal(signal.SIGHUP, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

#open SDK handler
log_info("starting mlnx-sfpd...")
rc, handle = sx_api_open(None)
retry_time = 1
while rc != SX_STATUS_SUCCESS:
time.sleep(2**retry_time)
retry_time += 1
rc, handle = sx_api_open(None)
if retry_time > 20:
log_error("Failed to open api handle.\nPlease check that SDK is running.")
sys.exit(errno.EACCES)

#open recv fd
rx_fd_p = new_sx_fd_t_p()
rc = sx_api_host_ifc_open(handle, rx_fd_p)
if rc != 0:
log_error("sx_api_host_ifc_open exit with error, rc %d" % rc)
exit(rc)

# set up general host ifc parameters
swid = 0
cmd = SX_ACCESS_CMD_REGISTER
uc_p = new_sx_user_channel_t_p()
uc_p.type = SX_USER_CHANNEL_TYPE_FD
uc_p.channel.fd = rx_fd_p
trap_id = SX_TRAP_ID_PMPE

rc = sx_api_host_ifc_trap_id_register_set(handle, cmd, swid, trap_id, uc_p)
if rc != 0:
log_error("sx_api_host_ifc_trap_id_register_set exit with error, rc %d" % rc)
exit(rc)

#connect to state db for notification sending
state_db = SonicV2Connector(host=REDIS_HOSTIP)
state_db.connect(state_db.STATE_DB)

#main loop for sfp event listening
log_info("mlnx-sfpd started")
while True:
state = STATUS_UNKNOWN
port_list, module_state = sx_recv(rx_fd_p, handle)
if module_state in sfp_value_status_dict: state = sfp_value_status_dict[module_state]

if state != STATUS_UNKNOWN:
for port in port_list:
log_info("SFP on port %d state %s" % (port, state))
send_sfp_notification(state_db, str(port), state)

log_info("sfp change event handling done")

'''
# TODO: clean open handlers before exit, need find out which errors can be raised by SDK in this case.
# unregister trap id
cmd = SX_ACCESS_CMD_DEREGISTER
rc = sx_api_host_ifc_trap_id_register_set(handle, cmd, swid, trap_id, uc_p)
if rc != 0:
log_error("sx_api_host_ifc_trap_id_register_set exit with error, rc %d" % rc)
exit(rc)

# close read fp
rc = sx_api_host_ifc_close(handle, rx_fd_p)
if rc != 0:
log_error("sx_api_host_ifc_close exit with error, rc %d" % rc)
exit(rc)

# close sdk handler
rc = sx_api_close(handle)
if rc != 0:
log_error("exit with error, rc %d" % rc)
exit(rc)

log_info("mlnx-sfpd exited")
'''

if __name__ == '__main__':
main()
28 changes: 28 additions & 0 deletions platform/mellanox/mlnx-sfpd/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from setuptools import setup

setup(
name='mlnx-sfpd',
version='1.0',
description='SFP event mmonitoring daemon for SONiC on mellanox platform',
license='Apache 2.0',
author='SONiC Community',
url='https://github.com/Azure/sonic-buildimage/',
maintainer='Kebo Liu',
maintainer_email='kebol@mellanox.com',
scripts=[
'scripts/mlnx-sfpd',
],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: No Input/Output (Daemon)',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Apache Software License',
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 2.7',
'Topic :: System :: Hardware',
],
keywords='sonic SONiC SFP sfp MELLANOX mellanox daemon SFPD sfpd',
)
1 change: 1 addition & 0 deletions platform/mellanox/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ include $(PLATFORM_PATH)/one-image.mk
include $(PLATFORM_PATH)/libsaithrift-dev.mk
include $(PLATFORM_PATH)/python-saithrift.mk
include $(PLATFORM_PATH)/docker-ptf-mlnx.mk
include $(PLATFORM_PATH)/mlnx-sfpd.mk

SONIC_ALL += $(SONIC_ONE_IMAGE) \
$(DOCKER_FPM)
Expand Down