2020-11-06 12:15:06 -06:00
|
|
|
#!/usr/bin/env python3
|
2020-06-24 00:23:08 -05:00
|
|
|
|
|
|
|
import signal
|
2020-11-06 12:15:06 -06:00
|
|
|
import sys
|
2020-06-24 00:23:08 -05:00
|
|
|
import traceback
|
2020-11-06 12:15:06 -06:00
|
|
|
from sonic_py_common.logger import Logger
|
|
|
|
from socket import if_nametoindex
|
2022-07-10 21:01:10 -05:00
|
|
|
from sonic_py_common import port_util
|
2020-11-06 12:15:06 -06:00
|
|
|
from swsscommon import swsscommon
|
2020-06-24 00:23:08 -05:00
|
|
|
|
|
|
|
SYSLOG_IDENTIFIER = 'port_index_mapper'
|
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
# Global logger instance
|
|
|
|
logger = Logger(SYSLOG_IDENTIFIER)
|
|
|
|
logger.set_min_log_priority_info()
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2020-12-03 17:57:50 -06:00
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
class PortIndexMapper(object):
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
def __init__(self):
|
|
|
|
REDIS_TIMEOUT_MS = 0
|
|
|
|
# Update this list to support more interfaces
|
|
|
|
tbl_lst = [swsscommon.STATE_PORT_TABLE_NAME,
|
|
|
|
swsscommon.STATE_VLAN_TABLE_NAME]
|
|
|
|
self.appl_db = swsscommon.DBConnector("STATE_DB",
|
|
|
|
REDIS_TIMEOUT_MS,
|
|
|
|
True)
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2022-07-10 21:01:10 -05:00
|
|
|
self.state_db = swsscommon.SonicV2Connector(host='127.0.0.1', decode_responses=True)
|
2020-11-06 12:15:06 -06:00
|
|
|
self.state_db.connect(self.state_db.STATE_DB, False)
|
|
|
|
self.sel = swsscommon.Select()
|
2020-11-07 22:23:01 -06:00
|
|
|
self.tbls = [swsscommon.SubscriberStateTable(self.appl_db, t)
|
2020-11-06 12:15:06 -06:00
|
|
|
for t in tbl_lst]
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
self.cur_interfaces = {}
|
|
|
|
|
2020-11-07 22:23:01 -06:00
|
|
|
for t in self.tbls:
|
2020-11-06 12:15:06 -06:00
|
|
|
self.sel.addSelectable(t)
|
|
|
|
|
|
|
|
def set_port_index_table_entry(self, key, index, ifindex):
|
|
|
|
self.state_db.set(self.state_db.STATE_DB, key, 'index', index)
|
|
|
|
self.state_db.set(self.state_db.STATE_DB, key, 'ifindex', ifindex)
|
|
|
|
|
|
|
|
def update_db(self, ifname, op):
|
2020-06-24 00:23:08 -05:00
|
|
|
index = port_util.get_index_from_str(ifname)
|
2020-11-06 12:15:06 -06:00
|
|
|
if op == 'SET' and index is None:
|
|
|
|
return
|
[sflow] Exception handling for if_nametoindex (#11437) (#13567)
catch system error and log as warning level instead of
error level in case interface was already deleted.
Why I did it
sflow process exited when failed to convert the interface index from interface name
How I did it
Added exception handling code and logged when OSError exception.
How to verify it
Recreated the bug scenario #11437 and ensured that sflow process not exited.
Description for the changelog
catch system error and log as warning level instead of
error level in case interface was already deleted.
Logs
steps :
root@sonic:~# sudo config vlan member del 4094 PortChannel0001
root@sonic:~# sudo config vlan member del 4094 Ethernet2
root@sonic:~# sudo config vlan del 4094
root@sonic:~#
"WARNING sflow#port_index_mapper: no interface with this name" is seen but no crash is reported
syslogs :
Jan 23 09:17:24.420448 sonic NOTICE swss#orchagent: :- removeVlanMember: Remove member Ethernet2 from VLAN Vlan4094 lid:ffe vmid:27000000000a53
Jan 23 09:17:24.420710 sonic NOTICE swss#orchagent: :- flushFdbEntries: flush key: SAI_OBJECT_TYPE_FDB_FLUSH:oid:0x21000000000000, fields: 3
Jan 23 09:17:24.420847 sonic NOTICE swss#orchagent: :- recordFlushFdbEntries: flush key: SAI_OBJECT_TYPE_FDB_FLUSH:oid:0x21000000000000, fields: 3
Jan 23 09:17:24.426082 sonic NOTICE syncd#syncd: :- processFdbFlush: fdb flush succeeded, updating redis database
Jan 23 09:17:24.426242 sonic NOTICE syncd#syncd: :- processFlushEvent: received a flush port fdb event, portVid = oid:0x3a000000000a52, bvId = oid:0x26000000000a51
Jan 23 09:17:24.426374 sonic NOTICE syncd#syncd: :- processFlushEvent: pattern ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*oid:0x26000000000a51*, portStr oid:0x3a000000000a52
Jan 23 09:17:24.427104 sonic NOTICE bgp#fpmsyncd: :- onRouteMsg: RouteTable del msg for route with only one nh on eth0/docker0: fe80::/64 :: eth0
Jan 23 09:17:24.427182 sonic NOTICE bgp#fpmsyncd: :- onRouteMsg: RouteTable del msg for route with only one nh on eth0/docker0: fd00::/80 :: docker0
Jan 23 09:17:24.428502 sonic NOTICE swss#orchagent: :- meta_sai_on_fdb_flush_event_consolidated: processing consolidated fdb flush event of type: SAI_FDB_ENTRY_TYPE_DYNAMIC
Jan 23 09:17:24.429058 sonic NOTICE swss#orchagent: :- meta_sai_on_fdb_flush_event_consolidated: fdb flush took 0.000606 sec
Jan 23 09:17:24.431496 sonic NOTICE swss#orchagent: :- setHostIntfsStripTag: Set SAI_HOSTIF_VLAN_TAG_STRIP to host interface: Ethernet2
Jan 23 09:17:24.431675 sonic NOTICE swss#orchagent: :- flushFdbEntries: flush key: SAI_OBJECT_TYPE_FDB_FLUSH:oid:0x21000000000000, fields: 2
Jan 23 09:17:24.431797 sonic NOTICE swss#orchagent: :- recordFlushFdbEntries: flush key: SAI_OBJECT_TYPE_FDB_FLUSH:oid:0x21000000000000, fields: 2
Jan 23 09:17:24.437009 sonic NOTICE swss#orchagent: :- meta_sai_on_fdb_flush_event_consolidated: processing consolidated fdb flush event of type: SAI_FDB_ENTRY_TYPE_DYNAMIC
Jan 23 09:17:24.437532 sonic NOTICE swss#orchagent: :- meta_sai_on_fdb_flush_event_consolidated: fdb flush took 0.000514 sec
Jan 23 09:17:24.437942 sonic NOTICE syncd#syncd: :- processFdbFlush: fdb flush succeeded, updating redis database
Jan 23 09:17:24.438065 sonic NOTICE syncd#syncd: :- processFlushEvent: received a flush port fdb event, portVid = oid:0x3a000000000a52, bvId = oid:0x0
Jan 23 09:17:24.438173 sonic NOTICE syncd#syncd: :- processFlushEvent: pattern ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*, portStr oid:0x3a000000000a52
Jan 23 09:17:24.440348 sonic NOTICE swss#orchagent: :- removeBridgePort: Remove bridge port Ethernet2 from default 1Q bridgeJan 23 09:17:29.782554 sonic NOTICE swss#orchagent: :- removeVlan: VLAN Vlan4094 still has 1 FDB entries
Jan 23 09:17:29.791373 sonic WARNING sflow#port_index_mapper: no interface with this name
Signed-off-by: Gokulnath-Raja <Gokulnath_R@dell.com>
2023-03-27 12:19:05 -05:00
|
|
|
|
|
|
|
# catch system error and log as warning level instead of
|
|
|
|
# error level in case interface was already deleted
|
|
|
|
ifindex = None
|
|
|
|
try:
|
|
|
|
ifindex = if_nametoindex(ifname)
|
|
|
|
except OSError as e:
|
|
|
|
logger.log_warning("%s" % str(e))
|
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
if op == 'SET' and ifindex is None:
|
2020-06-24 00:23:08 -05:00
|
|
|
return
|
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
# Check if ifname already exist or if index/ifindex changed due to
|
|
|
|
# syncd restart
|
|
|
|
if (ifname in self.cur_interfaces and
|
|
|
|
self.cur_interfaces[ifname] == (index, ifindex)):
|
|
|
|
return
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
_hash = '{}|{}'.format('PORT_INDEX_TABLE', ifname)
|
|
|
|
|
|
|
|
if op == 'SET':
|
|
|
|
self.cur_interfaces[ifname] = (index, ifindex)
|
|
|
|
self.set_port_index_table_entry(_hash, str(index), str(ifindex))
|
|
|
|
elif op == 'DEL':
|
|
|
|
del self.cur_interfaces[ifname]
|
|
|
|
self.state_db.delete(self.state_db.STATE_DB, _hash)
|
|
|
|
|
|
|
|
def listen(self):
|
|
|
|
SELECT_TIMEOUT_MS = -1 # Infinite wait
|
|
|
|
|
|
|
|
while True:
|
|
|
|
(state, c) = self.sel.select(SELECT_TIMEOUT_MS)
|
|
|
|
if state == swsscommon.Select.OBJECT:
|
2020-11-07 22:23:01 -06:00
|
|
|
for t in self.tbls:
|
2020-11-06 12:15:06 -06:00
|
|
|
(key, op, cfvs) = t.pop()
|
|
|
|
if op == 'DEL' and key in self.cur_interfaces:
|
|
|
|
self.update_db(key, op)
|
|
|
|
elif (op == 'SET' and key != 'PortInitDone' and
|
2020-11-07 22:23:01 -06:00
|
|
|
key != 'PortConfigDone' and
|
2020-11-06 12:15:06 -06:00
|
|
|
key not in self.cur_interfaces):
|
|
|
|
self.update_db(key, op)
|
|
|
|
elif state == swsscomm.Select.ERROR:
|
|
|
|
logger.log_error("Receieved error from select()")
|
|
|
|
break
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
def populate(self):
|
|
|
|
SELECT_TIMEOUT_MS = 0
|
2020-06-24 00:23:08 -05:00
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
while True:
|
|
|
|
(state, c) = self.sel.select(SELECT_TIMEOUT_MS)
|
|
|
|
if state == swsscommon.Select.OBJECT:
|
2020-11-07 22:23:01 -06:00
|
|
|
for t in self.tbls:
|
2020-11-06 12:15:06 -06:00
|
|
|
(key, op, cfvs) = t.pop()
|
2020-11-07 22:23:01 -06:00
|
|
|
if (key and key != 'PortInitDone' and
|
|
|
|
key != 'PortConfigDone'):
|
2020-11-06 12:15:06 -06:00
|
|
|
self.update_db(key, op)
|
|
|
|
else:
|
|
|
|
break
|
2020-06-24 00:23:08 -05:00
|
|
|
|
|
|
|
|
|
|
|
def signal_handler(signum, frame):
|
2020-11-06 12:15:06 -06:00
|
|
|
logger.log_notice("got signal {}".format(signum))
|
2020-06-24 00:23:08 -05:00
|
|
|
sys.exit(0)
|
|
|
|
|
2020-11-06 12:15:06 -06:00
|
|
|
|
|
|
|
def main():
|
|
|
|
port_mapper = PortIndexMapper()
|
|
|
|
port_mapper.populate()
|
|
|
|
port_mapper.listen()
|
|
|
|
|
2020-12-03 17:57:50 -06:00
|
|
|
|
2020-06-24 00:23:08 -05:00
|
|
|
if __name__ == '__main__':
|
|
|
|
rc = 0
|
|
|
|
try:
|
|
|
|
signal.signal(signal.SIGTERM, signal_handler)
|
|
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
|
|
main()
|
2020-11-06 12:15:06 -06:00
|
|
|
except Exception as e:
|
|
|
|
tb = sys.exc_info()[2]
|
|
|
|
traceback.print_tb(tb)
|
|
|
|
logger.log_error("%s" % str(e))
|
2020-06-24 00:23:08 -05:00
|
|
|
rc = -1
|
|
|
|
finally:
|
|
|
|
sys.exit(rc)
|