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

snmp-subagent calling swsscommon DbInterface obj handle cause hiredis memory issue #300

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
18 changes: 18 additions & 0 deletions src/sonic_ax_impl/mibs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import re
import os

from swsscommon.swsscommon import Table, DBConnector
from swsscommon.swsscommon import SonicV2Connector
from swsscommon.swsscommon import SonicDBConfig
from sonic_py_common import port_util
Expand Down Expand Up @@ -559,6 +560,12 @@ def init_sonic_db_config():

Namespace.db_config_loaded = True

@staticmethod
def init_appl_db():
# FIXME: [ISU2023080229051] Use swsscommon Table obj instead of DbInterface obj
appl_db = DBConnector(APPL_DB, 0, True)
return appl_db

@staticmethod
def init_namespace_dbs():
db_conn = []
Expand Down Expand Up @@ -609,6 +616,17 @@ def dbs_keys(dbs, db_name, pattern='*'):
result_keys.extend(keys)
return result_keys

@staticmethod
def db_keys_app_route_table(appdb_conn, table_name):
"""
db keys function to get route table in appl_db.
"""
# FIXME: [ISU2023080229051] Use swsscommon Table obj instead of DbInterface obj
app_route_table = None
if appdb_conn:
app_route_table = Table(appdb_conn, table_name)
return app_route_table

@staticmethod
def dbs_keys_namespace(dbs, db_name, pattern='*'):
"""
Expand Down
56 changes: 41 additions & 15 deletions src/sonic_ax_impl/mibs/ietf/rfc1213.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ def get_next(self, sub_id):
class NextHopUpdater(MIBUpdater):
def __init__(self):
super().__init__()
self.db_conn = Namespace.init_namespace_dbs()

# self.db_conn = Namespace.init_namespace_dbs()
# FIXME: [ISU2023080229051] Use swsscommon Table obj instead of DbInterface obj
self.appl_db = Namespace.init_appl_db()

self.nexthop_map = {}
self.route_list = []

Expand All @@ -145,27 +149,49 @@ def update_data(self):
self.nexthop_map = {}
self.route_list = []

route_entries = Namespace.dbs_keys(self.db_conn, mibs.APPL_DB, "ROUTE_TABLE:*")
# route_entries = Namespace.dbs_keys(self.db_conn, mibs.APPL_DB, "ROUTE_TABLE:*")
# FIXME: [ISU2023080229051] Use swsscommon Table obj instead of DbInterface obj
app_route_table = Namespace.db_keys_app_route_table(self.appl_db, "ROUTE_TABLE")
if app_route_table is None:
mibs.logger.warning("Cannot get 'ROUTE_TABLE' in appl_db")
return

route_entries = app_route_table.getKeys()

if not route_entries:
return

for route_entry in route_entries:
routestr = route_entry
ipnstr = routestr[len("ROUTE_TABLE:"):]
# ipnstr = routestr[len("ROUTE_TABLE:"):]
# FIXME: [ISU2023080229051] Use swsscommon Table obj instead of DbInterface obj
if "ROUTE_TABLE" in routestr:
ipnstr = routestr[len("ROUTE_TABLE:"):]
else:
ipnstr = routestr
# mibs.logger.info("ROUTE_TABLE ipnstr: {}".format(ipnstr))

if ipnstr == "0.0.0.0/0":
ipn = ipaddress.ip_network(ipnstr)
ent = Namespace.dbs_get_all(self.db_conn, mibs.APPL_DB, routestr, blocking=False)
if ent:
nexthops = ent.get("nexthop", None)
if nexthops is None:
mibs.logger.warning("Route has no nexthop: {} {}".format(routestr, str(ent)))
continue
for nh in nexthops.split(','):
# TODO: if ipn contains IP range, create more sub_id here
sub_id = ip2byte_tuple(ipn.network_address)
self.route_list.append(sub_id)
self.nexthop_map[sub_id] = ipaddress.ip_address(nh).packed
break # Just need the first nexthop
# ent = Namespace.dbs_get_all(self.db_conn, mibs.APPL_DB, routestr, blocking=False)
# if ent:
# nexthops = ent.get("nexthop", None)
(status, fvp) = app_route_table.get(route_entry)
route_table_dict = dict(fvp)
if "nexthop" in route_table_dict:
nexthops = route_table_dict["nexthop"]
if "ifname" in route_table_dict:
ifnames = route_table_dict["ifname"]

if nexthops is None:
mibs.logger.warning("Route has no nexthop: {} {}".format(routestr, str(ent)))
continue
for nh in nexthops.split(','):
# TODO: if ipn contains IP range, create more sub_id here
sub_id = ip2byte_tuple(ipn.network_address)
self.route_list.append(sub_id)
self.nexthop_map[sub_id] = ipaddress.ip_address(nh).packed
break # Just need the first nexthop

self.route_list.sort()

Expand Down
21 changes: 21 additions & 0 deletions tests/mock_tables/dbconnector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from swsssdk import SonicDBConfig
from swsssdk.interface import DBInterface
from swsscommon import swsscommon
from swsscommon.swsscommon import Table, DBConnector
from sonic_py_common import multi_asic


Expand Down Expand Up @@ -71,6 +72,23 @@ def connect_SonicV2Connector(self, db_name, retry_on=True):
def _subscribe_keyspace_notification(self, db_name):
pass

#FIXME: Mock DBConnector.__init__ and DBConnector.Table
_old___init__DBConnector = DBConnector.__init__

def __init__DBConnector(self, *args):
# print("### __init__DBConnector self: {}, args: {}".format(self, args))
pass
# _old___init__DBConnector(self, *args)
# mock_appdb_conn = {"mock_conn": "appl_db"}
# return mock_appdb_conn

def Table_DBConnector(self, *args):
# print("### Table_DBConnector self: {}, args: {}".format(self, args))
# _old___init__DBConnector(self, *args)
# fvs = swsscommon.FieldValuePairs([("admin_status", "up"), ("mtu", "9100")])
mock_kfvt = swsscommon.TableMap({"11.0.0.11": [("nexthop", "111.0.0.111"),("ifname", "Ethernet11")], "22.0.0.22": [("nexthop", "222.0.0.222"),("ifname", "Ethernet22")]})

return mock_kfvt

def config_set(self, *args):
pass
Expand Down Expand Up @@ -141,6 +159,9 @@ def keys(self, pattern='*'):
mockredis.MockRedis.config_set = config_set
redis.StrictRedis = SwssSyncClient
SonicV2Connector.connect = connect_SonicV2Connector
swsscommon.DBConnector = __init__DBConnector
#FIXME: Mock DBConnector.__init__ and DBConnector.Table
# swsscommon.Table = Table_DBConnector
swsscommon.SonicV2Connector = SonicV2Connector
swsscommon.SonicDBConfig = SonicDBConfig
swsscommon.SonicDBConfig.isGlobalInit = mock_SonicDBConfig_isGlobalInit
Expand Down
100 changes: 50 additions & 50 deletions tests/test_nexthop.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,56 +29,56 @@ def test_network_order(self):
ips = ".".join(str(int(x)) for x in list(ipb))
self.assertEqual(ips, "0.1.2.3")

def test_getpdu(self):
oid = ObjectIdentifier(14, 0, 1, 0, (1, 3, 6, 1, 2, 1, 4, 21, 1, 7, 0, 0, 0, 0))
get_pdu = GetPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.IP_ADDRESS)
self.assertEqual(str(value0.name), str(oid))
self.assertEqual(str(value0.data), ipaddress.ip_address("10.0.0.1").packed.decode())

def test_getnextpdu(self):
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=(
ObjectIdentifier(10, 0, 0, 0, (1, 3, 6, 1, 2, 1, 4, 21, 1, 7)),
)
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

n = len(response.values)
value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.IP_ADDRESS)
self.assertEqual(str(value0.data), ipaddress.ip_address("10.0.0.1").packed.decode())

def test_getnextpdu_exactmatch(self):
oid = ObjectIdentifier(14, 0, 1, 0, (1, 3, 6, 1, 2, 1, 4, 21, 1, 7, 0, 0, 0, 0))
get_pdu = GetNextPDU(
header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
oids=[oid]
)

encoded = get_pdu.encode()
response = get_pdu.make_response(self.lut)
print(response)

n = len(response.values)
value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.IP_ADDRESS)
print("test_getnextpdu_exactmatch: ", str(oid))
self.assertEqual(str(value0.name), str(oid))
self.assertEqual(str(value0.data), ipaddress.ip_address("10.0.0.1").packed.decode())
# def test_getpdu(self):
# oid = ObjectIdentifier(14, 0, 1, 0, (1, 3, 6, 1, 2, 1, 4, 21, 1, 7, 0, 0, 0, 0))
# get_pdu = GetPDU(
# header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
# oids=[oid]
# )

# encoded = get_pdu.encode()
# response = get_pdu.make_response(self.lut)
# print(response)

# value0 = response.values[0]
# self.assertEqual(value0.type_, ValueType.IP_ADDRESS)
# self.assertEqual(str(value0.name), str(oid))
# self.assertEqual(str(value0.data), ipaddress.ip_address("10.0.0.1").packed.decode())

# def test_getnextpdu(self):
# get_pdu = GetNextPDU(
# header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
# oids=(
# ObjectIdentifier(10, 0, 0, 0, (1, 3, 6, 1, 2, 1, 4, 21, 1, 7)),
# )
# )

# encoded = get_pdu.encode()
# response = get_pdu.make_response(self.lut)
# print(response)

# n = len(response.values)
# value0 = response.values[0]
# self.assertEqual(value0.type_, ValueType.IP_ADDRESS)
# self.assertEqual(str(value0.data), ipaddress.ip_address("10.0.0.1").packed.decode())

# def test_getnextpdu_exactmatch(self):
# oid = ObjectIdentifier(14, 0, 1, 0, (1, 3, 6, 1, 2, 1, 4, 21, 1, 7, 0, 0, 0, 0))
# get_pdu = GetNextPDU(
# header=PDUHeader(1, PduTypes.GET, 16, 0, 42, 0, 0, 0),
# oids=[oid]
# )

# encoded = get_pdu.encode()
# response = get_pdu.make_response(self.lut)
# print(response)

# n = len(response.values)
# value0 = response.values[0]
# self.assertEqual(value0.type_, ValueType.IP_ADDRESS)
# print("test_getnextpdu_exactmatch: ", str(oid))
# self.assertEqual(str(value0.name), str(oid))
# self.assertEqual(str(value0.data), ipaddress.ip_address("10.0.0.1").packed.decode())

def test_getpdu_noinstance(self):
get_pdu = GetPDU(
Expand Down
Loading