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

[mlnx-sfp-plugin] enhancement to support transceiver sensor monitoring #1839

Merged
merged 4 commits into from
Aug 2, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
43 changes: 41 additions & 2 deletions device/mellanox/x86_64-mlnx_lssn2700-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))

# parameters for DB connection
REDIS_HOSTNAME = "localhost"
REDIS_PORT = 6379
REDIS_TIMEOUT_USECS = 0

class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""

PORT_START = 0
PORT_END = 31
PORTS_IN_BLOCK = 32
Expand All @@ -22,6 +25,12 @@ class SfpUtil(SfpUtilBase):

_port_to_eeprom_mapping = {}

db_sel = None
db_sel_timeout = None
db_sel_object = None
db_sel_tbl = None
state_db = None

@property
def port_start(self):
return self.PORT_START
Expand All @@ -39,7 +48,7 @@ def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

def __init__(self):
eeprom_path = "/bsp/qsfp/qsfp{0}"
eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0048/hwmon/hwmon7/qsfp{0}_eeprom"

for x in range(0, self.port_end + 1):
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET)
Expand Down Expand Up @@ -149,3 +158,33 @@ def reset(self, port_num):
return False

return False

def get_transceiver_change_event(self, timeout=0):
Copy link
Collaborator

Choose a reason for hiding this comment

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

get_transceiver_change_event [](start = 8, length = 28)

This is vendor independent code. Let's move it out of plugin.
Who is using it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@qiluo-msft this function is intended to let each vendor have their own implementation, because each vendor may have different ways to get the SFP plug in/out notification. Here is the implementation on mlnx platform.

Copy link
Collaborator

@qiluo-msft qiluo-msft Jul 9, 2018

Choose a reason for hiding this comment

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

I would argue https://github.com/Azure/SONiC/blob/gh-pages/doc/transceiver-monitor-hld.md is not a good design, at least for Mellanox platform.

Mellanox syncd docker could directly get SFP notification and write to STATE_DB. There is no benefit to write to redis once, blocking waiting on it in another container (pmon) and write redis again. The disadvantages are new dependencies (like in this file), fragile system, and hard to debug.

If this is true for Mellanox, how could it benefit other vendors?


In reply to: 200867307 [](ancestors = 200867307)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would agree with you if we only consider mlnx platform, and at the very beginning, my design is to post the transceiver info to DB from syncd since mlnx can get the sfp change event from there. But after discussing with Guohan and community, we should have a common solution for all the vendors, design as common sfp change event API and left it to be implemented by each vendor.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Totally understood. This is a perfect to time to revisit the design.


In reply to: 201230542 [](ancestors = 201230542)

Copy link
Contributor

Choose a reason for hiding this comment

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

Just checking in -- are we or are we not revisiting the design? I believe the current design is the common solution for all vendors that @keboliu mentioned above. Therefore, I don't believe there is a need to revisit the design.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jleveque Yes, this the common solution for all vendors that have discussed.
@qiluo-msft would like to get your view on this.
more background information about this, for other vendors, may possible to get this event from sysfs, which will be very easy for them to implement this common API since sysfs is accessible from pmon. you may check with Hui who have some investigation on other platforms.

phy_port_dict = {}
status = True

if self.db_sel == None:
from swsscommon import swsscommon
self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
REDIS_HOSTNAME,
REDIS_PORT,
REDIS_TIMEOUT_USECS)

# Subscribe to state table for SFP change notifications
self.db_sel = swsscommon.Select()
self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY')
self.db_sel.addSelectable(self.db_sel_tbl)
self.db_sel_timeout = swsscommon.Select.TIMEOUT
self.db_sel_object = swsscommon.Select.OBJECT

(state, c) = self.db_sel.select(timeout)
if state == self.db_sel_timeout:
status = True
elif state != self.db_sel_object:
status = False
else:
(key, op, fvp) = self.db_sel_tbl.pop()
phy_port_dict[key] = op

return status, phy_port_dict

43 changes: 41 additions & 2 deletions device/mellanox/x86_64-mlnx_msn2100-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))

# parameters for DB connection
REDIS_HOSTNAME = "localhost"
REDIS_PORT = 6379
REDIS_TIMEOUT_USECS = 0

class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""

PORT_START = 0
PORT_END = 15
PORTS_IN_BLOCK = 16
Expand All @@ -22,6 +25,12 @@ class SfpUtil(SfpUtilBase):

_port_to_eeprom_mapping = {}

db_sel = None
db_sel_timeout = None
db_sel_object = None
db_sel_tbl = None
state_db = None

@property
def port_start(self):
return self.PORT_START
Expand All @@ -39,7 +48,7 @@ def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

def __init__(self):
eeprom_path = "/bsp/qsfp/qsfp{0}"
eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0048/hwmon/hwmon4/qsfp{0}_eeprom"

for x in range(0, self.port_end + 1):
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET)
Expand Down Expand Up @@ -149,3 +158,33 @@ def reset(self, port_num):
return False

return False

def get_transceiver_change_event(self, timeout=0):
phy_port_dict = {}
status = True

if self.db_sel == None:
from swsscommon import swsscommon
self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
REDIS_HOSTNAME,
REDIS_PORT,
REDIS_TIMEOUT_USECS)

# Subscribe to state table for SFP change notifications
self.db_sel = swsscommon.Select()
self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY')
self.db_sel.addSelectable(self.db_sel_tbl)
self.db_sel_timeout = swsscommon.Select.TIMEOUT
self.db_sel_object = swsscommon.Select.OBJECT

(state, c) = self.db_sel.select(timeout)
if state == self.db_sel_timeout:
status = True
elif state != self.db_sel_object:
status = False
else:
(key, op, fvp) = self.db_sel_tbl.pop()
phy_port_dict[key] = op

return status, phy_port_dict

47 changes: 44 additions & 3 deletions device/mellanox/x86_64-mlnx_msn2410-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,28 @@
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))

# parameters for DB connection
REDIS_HOSTNAME = "localhost"
REDIS_PORT = 6379
REDIS_TIMEOUT_USECS = 0

class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""

PORT_START = 0
PORT_END = 55
PORTS_IN_BLOCK = 56
QSFP_PORT_START = 48

EEPROM_OFFSET = 1

_port_to_eeprom_mapping = {}

db_sel = None
db_sel_timeout = None
db_sel_object = None
db_sel_tbl = None
state_db = None

@property
def port_start(self):
return self.PORT_START
Expand All @@ -32,20 +42,21 @@ def port_end(self):

@property
def qsfp_ports(self):
return range(0, self.PORTS_IN_BLOCK + 1)
return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)

@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

def __init__(self):
eeprom_path = "/bsp/qsfp/qsfp{0}"
eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0048/hwmon/hwmon6/qsfp{0}_eeprom"

for x in range(0, self.port_end + 1):
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET)

SfpUtilBase.__init__(self)


def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
Expand Down Expand Up @@ -149,3 +160,33 @@ def reset(self, port_num):
return False

return False

def get_transceiver_change_event(self, timeout=0):
phy_port_dict = {}
status = True

if self.db_sel == None:
from swsscommon import swsscommon
self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
REDIS_HOSTNAME,
REDIS_PORT,
REDIS_TIMEOUT_USECS)

# Subscribe to state table for SFP change notifications
self.db_sel = swsscommon.Select()
self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY')
self.db_sel.addSelectable(self.db_sel_tbl)
self.db_sel_timeout = swsscommon.Select.TIMEOUT
self.db_sel_object = swsscommon.Select.OBJECT

(state, c) = self.db_sel.select(timeout)
if state == self.db_sel_timeout:
status = True
elif state != self.db_sel_object:
status = False
else:
(key, op, fvp) = self.db_sel_tbl.pop()
phy_port_dict[key] = op

return status, phy_port_dict

43 changes: 41 additions & 2 deletions device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))

# parameters for DB connection
REDIS_HOSTNAME = "localhost"
REDIS_PORT = 6379
REDIS_TIMEOUT_USECS = 0

class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""

PORT_START = 0
PORT_END = 31
PORTS_IN_BLOCK = 32
Expand All @@ -22,6 +25,12 @@ class SfpUtil(SfpUtilBase):

_port_to_eeprom_mapping = {}

db_sel = None
db_sel_timeout = None
db_sel_object = None
db_sel_tbl = None
state_db = None

@property
def port_start(self):
return self.PORT_START
Expand All @@ -39,7 +48,7 @@ def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

def __init__(self):
eeprom_path = "/bsp/qsfp/qsfp{0}"
eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0048/hwmon/hwmon7/qsfp{0}_eeprom"

for x in range(0, self.port_end + 1):
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET)
Expand Down Expand Up @@ -149,3 +158,33 @@ def reset(self, port_num):
return False

return False

def get_transceiver_change_event(self, timeout=0):
phy_port_dict = {}
status = True

if self.db_sel == None:
from swsscommon import swsscommon
self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
REDIS_HOSTNAME,
REDIS_PORT,
REDIS_TIMEOUT_USECS)

# Subscribe to state table for SFP change notifications
self.db_sel = swsscommon.Select()
self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY')
self.db_sel.addSelectable(self.db_sel_tbl)
self.db_sel_timeout = swsscommon.Select.TIMEOUT
self.db_sel_object = swsscommon.Select.OBJECT

(state, c) = self.db_sel.select(timeout)
if state == self.db_sel_timeout:
status = True
elif state != self.db_sel_object:
status = False
else:
(key, op, fvp) = self.db_sel_tbl.pop()
phy_port_dict[key] = op

return status, phy_port_dict

43 changes: 41 additions & 2 deletions device/mellanox/x86_64-mlnx_msn2740-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))

# parameters for DB connection
REDIS_HOSTNAME = "localhost"
REDIS_PORT = 6379
REDIS_TIMEOUT_USECS = 0

class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""

PORT_START = 0
PORT_END = 31
PORTS_IN_BLOCK = 32
Expand All @@ -22,6 +25,12 @@ class SfpUtil(SfpUtilBase):

_port_to_eeprom_mapping = {}

db_sel = None
db_sel_timeout = None
db_sel_object = None
db_sel_tbl = None
state_db = None

@property
def port_start(self):
return self.PORT_START
Expand All @@ -39,7 +48,7 @@ def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping

def __init__(self):
eeprom_path = "/bsp/qsfp/qsfp{0}"
eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0048/hwmon/hwmon6/qsfp{0}_eeprom"

for x in range(0, self.port_end + 1):
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + self.EEPROM_OFFSET)
Expand Down Expand Up @@ -149,3 +158,33 @@ def reset(self, port_num):
return False

return False

def get_transceiver_change_event(self, timeout=0):
phy_port_dict = {}
status = True

if self.db_sel == None:
from swsscommon import swsscommon
self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
REDIS_HOSTNAME,
REDIS_PORT,
REDIS_TIMEOUT_USECS)

# Subscribe to state table for SFP change notifications
self.db_sel = swsscommon.Select()
self.db_sel_tbl = swsscommon.NotificationConsumer(self.state_db, 'TRANSCEIVER_NOTIFY')
self.db_sel.addSelectable(self.db_sel_tbl)
self.db_sel_timeout = swsscommon.Select.TIMEOUT
self.db_sel_object = swsscommon.Select.OBJECT

(state, c) = self.db_sel.select(timeout)
if state == self.db_sel_timeout:
status = True
elif state != self.db_sel_object:
status = False
else:
(key, op, fvp) = self.db_sel_tbl.pop()
phy_port_dict[key] = op

return status, phy_port_dict