@@ -11,6 +11,7 @@ class PortChangeEvent:
11
11
PORT_REMOVE = 1
12
12
PORT_SET = 2
13
13
PORT_DEL = 3
14
+ PORT_EVENT = {}
14
15
15
16
def __init__ (self , port_name , port_index , asic_id , event_type , port_dict = None ):
16
17
# Logical port name, e.g. Ethernet0
@@ -105,11 +106,16 @@ def subscribe_port_config_change(namespaces):
105
106
sel .addSelectable (port_tbl )
106
107
return sel , asic_context
107
108
108
- def subscribe_port_update_event (namespaces ):
109
+ def subscribe_port_update_event (namespaces , logger ):
110
+ """
111
+ Subscribe to a particular DB's table and listen to only interested fields
112
+ Format :
113
+ { <DB name> : <Table name> , <field1>, <field2>, .. } where only field<n> update will be received
114
+ """
109
115
port_tbl_map = [
110
- {'APPL_DB ' : swsscommon .APP_PORT_TABLE_NAME },
116
+ {'CONFIG_DB ' : swsscommon .CFG_PORT_TABLE_NAME },
111
117
{'STATE_DB' : 'TRANSCEIVER_INFO' },
112
- {'STATE_DB' : 'PORT_TABLE' },
118
+ {'STATE_DB' : 'PORT_TABLE' , 'FILTER' : [ 'host_tx_ready' ] },
113
119
]
114
120
115
121
sel = swsscommon .Select ()
@@ -119,13 +125,18 @@ def subscribe_port_update_event(namespaces):
119
125
db = daemon_base .db_connect (list (d .keys ())[0 ], namespace = namespace )
120
126
asic_id = multi_asic .get_asic_index_from_namespace (namespace )
121
127
port_tbl = swsscommon .SubscriberStateTable (db , list (d .values ())[0 ])
128
+ port_tbl .db_name = list (d .keys ())[0 ]
129
+ port_tbl .table_name = list (d .values ())[0 ]
130
+ port_tbl .filter = d ['FILTER' ] if 'FILTER' in d else None
122
131
asic_context [port_tbl ] = asic_id
123
132
sel .addSelectable (port_tbl )
133
+ logger .log_warning ("subscribing to port_tbl {} - {} DB of namespace {} " .format (
134
+ port_tbl , list (d .values ())[0 ], namespace ))
124
135
return sel , asic_context
125
136
126
137
def handle_port_update_event (sel , asic_context , stop_event , logger , port_change_event_handler ):
127
138
"""
128
- Select PORT update events, notify the observers upon a port update in APPL_DB/ CONFIG_DB
139
+ Select PORT update events, notify the observers upon a port update in CONFIG_DB
129
140
or a XCVR insertion/removal in STATE_DB
130
141
"""
131
142
if not stop_event .is_set ():
@@ -135,6 +146,8 @@ def handle_port_update_event(sel, asic_context, stop_event, logger, port_change_
135
146
if state != swsscommon .Select .OBJECT :
136
147
logger .log_warning ('sel.select() did not return swsscommon.Select.OBJECT' )
137
148
return
149
+
150
+ port_event_cache = {}
138
151
for port_tbl in asic_context .keys ():
139
152
while True :
140
153
(key , op , fvp ) = port_tbl .pop ()
@@ -143,24 +156,56 @@ def handle_port_update_event(sel, asic_context, stop_event, logger, port_change_
143
156
if not validate_port (key ):
144
157
continue
145
158
fvp = dict (fvp ) if fvp is not None else {}
159
+ logger .log_warning ("$$$ {} handle_port_update_event() : op={} DB:{} Table:{} fvp {}" .format (
160
+ key , op , port_tbl .db_name , port_tbl .table_name , fvp ))
161
+
146
162
if 'index' not in fvp :
147
- fvp ['index' ] = '-1'
148
- port_index = int (fvp ['index' ])
149
- port_change_event = None
150
- if op == swsscommon .SET_COMMAND :
151
- port_change_event = PortChangeEvent (key ,
163
+ fvp ['index' ] = '-1'
164
+ fvp ['key' ] = key
165
+ fvp ['asic_id' ] = asic_context [port_tbl ]
166
+ fvp ['op' ] = op
167
+ fvp ['FILTER' ] = port_tbl .filter
168
+ # Soak duplicate events and consider only the last event
169
+ port_event_cache [key + port_tbl .db_name + port_tbl .table_name ] = fvp
170
+
171
+ # Now apply filter over soaked events
172
+ for key , fvp in port_event_cache .items ():
173
+ port_index = int (fvp ['index' ])
174
+ port_change_event = None
175
+ diff = {}
176
+ filter = fvp ['FILTER' ]
177
+ del fvp ['FILTER' ]
178
+ if key in PortChangeEvent .PORT_EVENT :
179
+ diff = dict (set (fvp .items ()) - set (PortChangeEvent .PORT_EVENT [key ].items ()))
180
+ # Ignore duplicate events
181
+ if not diff :
182
+ PortChangeEvent .PORT_EVENT [key ] = fvp
183
+ continue
184
+ # Ensure only interested field update gets through for processing
185
+ if filter is not None :
186
+ if not (set (filter ) & set (diff .keys ())):
187
+ PortChangeEvent .PORT_EVENT [key ] = fvp
188
+ continue
189
+ PortChangeEvent .PORT_EVENT [key ] = fvp
190
+
191
+ if fvp ['op' ] == swsscommon .SET_COMMAND :
192
+ port_change_event = PortChangeEvent (fvp ['key' ],
152
193
port_index ,
153
- asic_context [ port_tbl ],
194
+ fvp [ 'asic_id' ],
154
195
PortChangeEvent .PORT_SET ,
155
196
fvp )
156
- elif op == swsscommon .DEL_COMMAND :
157
- port_change_event = PortChangeEvent (key ,
197
+ elif fvp [ 'op' ] == swsscommon .DEL_COMMAND :
198
+ port_change_event = PortChangeEvent (fvp [ ' key' ] ,
158
199
port_index ,
159
- asic_context [ port_tbl ],
200
+ fvp [ 'asic_id' ],
160
201
PortChangeEvent .PORT_DEL ,
161
202
fvp )
162
- if port_change_event is not None :
163
- port_change_event_handler (port_change_event )
203
+ # This is the final event considered for processing
204
+ logger .log_warning ("*** {} handle_port_update_event() fvp {}" .format (
205
+ key , fvp ))
206
+ if port_change_event is not None :
207
+ port_change_event_handler (port_change_event )
208
+
164
209
165
210
def handle_port_config_change (sel , asic_context , stop_event , port_mapping , logger , port_change_event_handler ):
166
211
"""Select CONFIG_DB PORT table changes, once there is a port configuration add/remove, notify observers
0 commit comments