-
Notifications
You must be signed in to change notification settings - Fork 109
/
rfc4363.py
143 lines (122 loc) · 5.1 KB
/
rfc4363.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import json
from sonic_ax_impl import mibs
from sonic_ax_impl.mibs import Namespace
from ax_interface import MIBMeta, ValueType, MIBUpdater, SubtreeMIBEntry
from ax_interface.util import mac_decimals
from bisect import bisect_right
class FdbUpdater(MIBUpdater):
def __init__(self):
super().__init__()
self.db_conn = Namespace.init_namespace_dbs()
self.if_name_map = {}
self.if_alias_map = {}
self.if_id_map = {}
self.oid_name_map = {}
self.sai_lag_map = {}
self.vlanmac_ifindex_map = {}
self.vlanmac_ifindex_list = []
self.if_bpid_map = {}
self.bvid_vlan_map = {}
self.broken_fdbs = []
def fdb_vlanmac(self, fdb):
if 'vlan' in fdb:
vlan_id = fdb["vlan"]
elif 'bvid' in fdb:
if fdb["bvid"] in self.bvid_vlan_map:
vlan_id = self.bvid_vlan_map[fdb["bvid"]]
else:
vlan_id = Namespace.dbs_get_vlan_id_from_bvid(self.db_conn, fdb["bvid"])
if isinstance(vlan_id, bytes):
vlan_id = vlan_id.decode()
# only cache vlan_id if valid
if vlan_id is not None:
self.bvid_vlan_map[fdb["bvid"]] = vlan_id
else:
return None
if not isinstance(vlan_id, str):
return None
return (int(vlan_id),) + mac_decimals(fdb["mac"])
def reinit_connection(self):
Namespace.connect_namespace_dbs(self.db_conn)
def reinit_data(self):
"""
Subclass update interface information
"""
(
self.if_name_map,
self.if_alias_map,
self.if_id_map,
self.oid_name_map,
) = Namespace.get_sync_d_from_all_namespace(
mibs.init_sync_d_interface_tables, self.db_conn
)
self.lag_name_if_name_map, \
self.if_name_lag_name_map, \
self.oid_lag_name_map, \
_, self.sai_lag_map = Namespace.get_sync_d_from_all_namespace(mibs.init_sync_d_lag_tables, self.db_conn)
self.if_bpid_map = Namespace.dbs_get_bridge_port_map(self.db_conn, mibs.ASIC_DB)
self.bvid_vlan_map.clear()
self.broken_fdbs.clear()
def update_data(self):
"""
Update redis (caches config)
Pulls the table references for each interface.
"""
self.vlanmac_ifindex_map = {}
self.vlanmac_ifindex_list = []
fdb_strings = Namespace.dbs_keys(self.db_conn, mibs.ASIC_DB, "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*")
if not fdb_strings:
return
for s in fdb_strings:
fdb_str = s
try:
fdb = json.loads(fdb_str.split(":", maxsplit=2)[-1])
except ValueError as e: # includes simplejson.decoder.JSONDecodeError
mibs.logger.error("SyncD 'ASIC_DB' includes invalid FDB_ENTRY '{}': {}.".format(fdb_str, e))
continue
ent = Namespace.dbs_get_all(self.db_conn, mibs.ASIC_DB, s, blocking=False)
if not ent:
continue
bridge_port_id_attr = ""
try:
bridge_port_id_attr = ent["SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"]
except KeyError as e:
# Only write warning log once
if fdb_str not in self.broken_fdbs:
mibs.logger.warn("SyncD 'ASIC_DB' includes invalid FDB_ENTRY '{}': failed to get bridge_port_id, exception: {}".format(fdb_str, e))
self.broken_fdbs.append(fdb_str)
continue
# Example output: oid:0x3a000000000608
bridge_port_id = bridge_port_id_attr[6:]
if bridge_port_id not in self.if_bpid_map:
continue
port_id = self.if_bpid_map[bridge_port_id]
if port_id in self.if_id_map:
port_name = self.if_id_map[port_id]
port_index = mibs.get_index_from_str(port_name)
elif port_id in self.sai_lag_map:
port_name = self.sai_lag_map[port_id]
port_index = mibs.get_index_from_str(port_name)
else:
continue
vlanmac = self.fdb_vlanmac(fdb)
if not vlanmac:
mibs.logger.debug("SyncD 'ASIC_DB' includes invalid FDB_ENTRY '{}': failed in fdb_vlanmac().".format(fdb_str))
continue
self.vlanmac_ifindex_map[vlanmac] = port_index
self.vlanmac_ifindex_list.append(vlanmac)
self.vlanmac_ifindex_list.sort()
def fdb_ifindex(self, sub_id):
return self.vlanmac_ifindex_map.get(sub_id, None)
def get_next(self, sub_id):
right = bisect_right(self.vlanmac_ifindex_list, sub_id)
if right >= len(self.vlanmac_ifindex_list):
return None
return self.vlanmac_ifindex_list[right]
class QBridgeMIBObjects(metaclass=MIBMeta, prefix='.1.3.6.1.2.1.17.7.1'):
"""
'Forwarding Database' https://tools.ietf.org/html/rfc4363
"""
fdb_updater = FdbUpdater()
dot1qTpFdbPort = \
SubtreeMIBEntry('2.2.1.2', fdb_updater, ValueType.INTEGER, fdb_updater.fdb_ifindex)