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

[multi-asic][RFC1213]: Oper status of mgmt interface for multi-asic platform #209

Open
wants to merge 2 commits 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 38 additions & 1 deletion src/sonic_ax_impl/mibs/ietf/rfc1213.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import socket
from enum import unique, Enum
from bisect import bisect_right
import os

from sonic_ax_impl import mibs
from sonic_ax_impl.mibs import Namespace
Expand Down Expand Up @@ -184,6 +185,7 @@ class IpMib(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.4'):
class InterfacesUpdater(MIBUpdater):

RFC1213_MAX_SPEED = 4294967295
if_operstate_file = "/sys/class/net/{}/operstate"

def __init__(self):
super().__init__()
Expand All @@ -203,6 +205,7 @@ def __init__(self):
self.if_id_map = {}
self.oid_name_map = {}
self.namespace_db_map = Namespace.get_namespace_db_map(self.db_conn)
self.mgmt_oper_status = {}

def reinit_data(self):
"""
Expand Down Expand Up @@ -239,6 +242,14 @@ def update_data(self):
list(self.oid_lag_name_map.keys()) +
list(self.mgmt_oid_name_map.keys()))
self.if_range = [(i,) for i in self.if_range]
"""
For multi-asic platform, operstatus of
management iface is not stored in state db,
Retrieve oper status from sys/class/net
"""
if len(self.db_conn) > 1:
for mgmt_oid,if_name in self.mgmt_oid_name_map.items():
self.mgmt_oper_status[mgmt_oid] = self._get_mgmt_oper_status(if_name)

def get_next(self, sub_id):
"""
Expand Down Expand Up @@ -359,6 +370,20 @@ def _get_if_entry(self, sub_id):

return Namespace.dbs_get_all(self.db_conn, db, if_table, blocking=True)


def _get_mgmt_oper_status(self, if_name):
"""
:param if_name: mgmt interface name
:return: operation status string
"""
status = "unknown"
if_operstate_file = self.if_operstate_file.format(if_name)
if os.path.exists(if_operstate_file):
file = open(if_operstate_file, "r")
if file is not None:
status = file.readline().strip()
return status

def _get_if_entry_state_db(self, sub_id):
"""
:param oid: The 1-based sub-identifier query.
Expand All @@ -372,7 +397,19 @@ def _get_if_entry_state_db(self, sub_id):
db = mibs.STATE_DB
if oid in self.mgmt_oid_name_map:
mgmt_if_name = self.mgmt_oid_name_map[oid]
if_table = mibs.mgmt_if_entry_table_state_db(mgmt_if_name)
"""
For multi-asic platform, operstatus of
management iface is not stored in state db,
Retrieve oper status from sys/class/net
"""
if len(self.db_conn) > 1:
if oid in self.mgmt_oper_status:
state = self.mgmt_oper_status[oid]
return {"oper_status":state}
else:
return None
else:
if_table = mibs.mgmt_if_entry_table_state_db(mgmt_if_name)
else:
return None

Expand Down
1 change: 1 addition & 0 deletions tests/mock_tables/eth1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
up
107 changes: 103 additions & 4 deletions tests/namespace/test_interfaces.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import os
import sys
import importlib
import mock

# noinspection PyUnresolvedReferences
import tests.mock_tables.dbconnector

modules_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(modules_path, 'src'))
mgmt_iface_status = modules_path + "/mock_tables/{}"

from unittest import TestCase

Expand All @@ -18,17 +20,19 @@
from ax_interface.mib import MIBTable
from sonic_ax_impl.mibs.ietf import rfc1213
from sonic_ax_impl import mibs
from mock import patch

class TestGetNextPDU(TestCase):
@classmethod
def setUpClass(cls):
tests.mock_tables.dbconnector.load_namespace_config()
importlib.reload(rfc1213)
cls.lut = MIBTable(rfc1213.InterfacesMIB)
for updater in cls.lut.updater_instances:
updater.update_data()
updater.reinit_data()
updater.update_data()
with mock.patch('sonic_ax_impl.mibs.ietf.rfc1213.InterfacesUpdater.if_operstate_file', mgmt_iface_status):
for updater in cls.lut.updater_instances:
updater.update_data()
updater.reinit_data()
updater.update_data()

def test_getnextpdu_noneifindex(self):
# oid.include = 1
Expand Down Expand Up @@ -236,6 +240,101 @@ def test_if_type_portchannel(self):
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 3, 1001))))
self.assertEqual(value0.data, 161)

def test_mgmt_iface(self):
"""
Test that mgmt port is present in the MIB
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 10000))
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)

value0 = response.values[0]
self.assertEqual(value0.type_, ValueType.INTEGER)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 10001))))
self.assertEqual(value0.data, 10000)

def test_mgmt_iface_description(self):
"""
Test mgmt port description (which is simply an alias)
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 2, 10001))
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.OCTET_STRING)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 2, 10001))))
self.assertEqual(str(value0.data), 'mgmt1')

def test_mgmt_iface_oper_status(self):
"""
Test mgmt port operative status
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 8, 10001))
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.INTEGER)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 8, 10001))))
self.assertEqual(value0.data, 1)

def test_mgmt_iface_oper_status_unknown(self):
"""
Test mgmt port operative status
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 8, 10002))
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.INTEGER)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 8, 10002))))
self.assertEqual(value0.data, 4)

def test_mgmt_iface_admin_status(self):
"""
Test mgmt port admin status
"""
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 7, 10001))
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.INTEGER)
self.assertEqual(str(value0.name), str(ObjectIdentifier(11, 0, 1, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 7, 10001))))
self.assertEqual(value0.data, 1)

def test_getnextpdu_first_bp_ifindex(self):
oid = ObjectIdentifier(11, 0, 0, 0, (1, 3, 6, 1, 2, 1, 2, 2, 1, 1,1004))
get_pdu = GetNextPDU(
Expand Down