@@ -13,10 +13,12 @@ using namespace swss;
13
13
14
14
#define DOT1Q_BRIDGE_NAME " Bridge"
15
15
#define VLAN_PREFIX " Vlan"
16
+ #define SWITCH_STR " switch"
16
17
#define LAG_PREFIX " PortChannel"
17
18
#define DEFAULT_VLAN_ID " 1"
18
19
#define DEFAULT_MTU_STR " 9100"
19
20
#define VLAN_HLEN 4
21
+ #define MAX_VLAN_ID 4095
20
22
21
23
extern MacAddress gMacAddress ;
22
24
@@ -28,6 +30,8 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c
28
30
m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME),
29
31
m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME),
30
32
m_stateVlanMemberTable(stateDb, STATE_VLAN_MEMBER_TABLE_NAME),
33
+ m_appFdbTableProducer(appDb, APP_FDB_TABLE_NAME),
34
+ m_appSwitchTableProducer(appDb, APP_SWITCH_TABLE_NAME),
31
35
m_appVlanTableProducer(appDb, APP_VLAN_TABLE_NAME),
32
36
m_appVlanMemberTableProducer(appDb, APP_VLAN_MEMBER_TABLE_NAME)
33
37
{
@@ -88,6 +92,10 @@ VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c
88
92
89
93
EXEC_WITH_ERROR_THROW (echo_cmd_backup, res);
90
94
}
95
+ /* vlan state notification from portsorch */
96
+ m_VlanStateNotificationConsumer = new swss::NotificationConsumer (appDb, " VLANSTATE" );
97
+ auto vlanStatusNotificatier = new Notifier (m_VlanStateNotificationConsumer, this , " VLANSTATE" );
98
+ Orch::addExecutor (vlanStatusNotificatier);
91
99
}
92
100
93
101
bool VlanMgr::addHostVlan (int vlan_id)
@@ -101,7 +109,7 @@ bool VlanMgr::addHostVlan(int vlan_id)
101
109
+ BASH_CMD + " -c \" "
102
110
+ BRIDGE_CMD + " vlan add vid " + std::to_string (vlan_id) + " dev " + DOT1Q_BRIDGE_NAME + " self && "
103
111
+ IP_CMD + " link add link " + DOT1Q_BRIDGE_NAME
104
- + " up "
112
+ + " down "
105
113
+ " name " + VLAN_PREFIX + std::to_string (vlan_id)
106
114
+ " address " + gMacAddress .to_string ()
107
115
+ " type vlan id " + std::to_string (vlan_id) + " \" " ;
@@ -179,14 +187,29 @@ bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const str
179
187
// /bin/bash -c "/sbin/ip link set {{port_alias}} master Bridge &&
180
188
// /sbin/bridge vlan del vid 1 dev {{ port_alias }} &&
181
189
// /sbin/bridge vlan add vid {{vlan_id}} dev {{port_alias}} {{tagging_mode}}"
182
- ostringstream cmds, inner;
183
- inner << IP_CMD " link set " << shellquote (port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
184
- BRIDGE_CMD " vlan del vid " DEFAULT_VLAN_ID " dev " << shellquote (port_alias) << " && "
185
- BRIDGE_CMD " vlan add vid " + std::to_string (vlan_id) + " dev " << shellquote (port_alias) << " " + tagging_cmd;
186
- cmds << BASH_CMD " -c " << shellquote (inner.str ());
190
+
191
+ const std::string key = std::string (" " ) + " Vlan1|" + port_alias;
187
192
188
- std::string res;
189
- EXEC_WITH_ERROR_THROW (cmds.str (), res);
193
+ if (isVlanMemberStateOk (key)) {
194
+ ostringstream cmds, inner;
195
+ inner << IP_CMD " link set " << shellquote (port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
196
+ BRIDGE_CMD " vlan add vid " + std::to_string (vlan_id) + " dev " << shellquote (port_alias) << " " + tagging_cmd;
197
+ cmds << BASH_CMD " -c " << shellquote (inner.str ());
198
+
199
+ std::string res;
200
+ EXEC_WITH_ERROR_THROW (cmds.str (), res);
201
+ }
202
+ else
203
+ {
204
+ ostringstream cmds, inner;
205
+ inner << IP_CMD " link set " << shellquote (port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
206
+ BRIDGE_CMD " vlan del vid " DEFAULT_VLAN_ID " dev " << shellquote (port_alias) << " && "
207
+ BRIDGE_CMD " vlan add vid " + std::to_string (vlan_id) + " dev " << shellquote (port_alias) << " " + tagging_cmd;
208
+ cmds << BASH_CMD " -c " << shellquote (inner.str ());
209
+
210
+ std::string res;
211
+ EXEC_WITH_ERROR_THROW (cmds.str (), res);
212
+ }
190
213
191
214
return true ;
192
215
}
@@ -224,6 +247,137 @@ bool VlanMgr::isVlanMacOk()
224
247
return !!gMacAddress ;
225
248
}
226
249
250
+ void VlanMgr::doSwitchTask (Consumer &consumer)
251
+ {
252
+ SWSS_LOG_ENTER ();
253
+ auto it = consumer.m_toSync .begin ();
254
+
255
+ while (it != consumer.m_toSync .end ())
256
+ {
257
+ KeyOpFieldsValuesTuple t = it->second ;
258
+
259
+ string key = kfvKey (t);
260
+ string op = kfvOp (t);
261
+
262
+ /* Ensure the key starts with "switch" otherwise ignore */
263
+ if (key != SWITCH_STR)
264
+ {
265
+ SWSS_LOG_NOTICE (" Ignoring SWITCH key %s" , key.c_str ());
266
+ it = consumer.m_toSync .erase (it);
267
+ continue ;
268
+ }
269
+
270
+ SWSS_LOG_DEBUG (" key:switch" );
271
+
272
+ for (auto i : kfvFieldsValues (t))
273
+ {
274
+ if (fvField (i) == " fdb_aging_time" )
275
+ {
276
+ long agingTime = 0 ;
277
+ SWSS_LOG_DEBUG (" attribute:fdb_aging_time" );
278
+ if (op == SET_COMMAND)
279
+ {
280
+ SWSS_LOG_DEBUG (" operation:set" );
281
+ agingTime = strtol (fvValue (i).c_str (), NULL , 0 );
282
+ if (agingTime < 0 )
283
+ {
284
+ SWSS_LOG_ERROR (" Invalid fdb_aging_time %s" , fvValue (i).c_str ());
285
+ break ;
286
+ }
287
+ SWSS_LOG_DEBUG (" value:%s" ,fvValue (i).c_str ());
288
+ }
289
+ else if (op == DEL_COMMAND)
290
+ {
291
+ SWSS_LOG_DEBUG (" operation:del" );
292
+ agingTime = 0 ;
293
+ }
294
+ else
295
+ {
296
+ SWSS_LOG_ERROR (" Unknown operation type %s" , op.c_str ());
297
+ break ;
298
+ }
299
+
300
+ vector<FieldValueTuple> fvVector;
301
+ FieldValueTuple aging_time (" fdb_aging_time" , to_string (agingTime));
302
+ fvVector.push_back (aging_time);
303
+ m_appSwitchTableProducer.set (key, fvVector);
304
+ break ;
305
+ }
306
+ }
307
+
308
+ it = consumer.m_toSync .erase (it);
309
+ }
310
+ }
311
+
312
+ void VlanMgr::doFdbTask (Consumer &consumer)
313
+ {
314
+ auto it = consumer.m_toSync .begin ();
315
+
316
+ while (it != consumer.m_toSync .end ())
317
+ {
318
+ KeyOpFieldsValuesTuple t = it->second ;
319
+
320
+ /* format: <VLAN_name>|<MAC_address> */
321
+ vector<string> keys = tokenize (kfvKey (t), config_db_key_delimiter, 1 );
322
+ /* keys[0] is vlan as (Vlan10) and keys[1] is mac as (00-00-00-00-00-00) */
323
+ string op = kfvOp (t);
324
+
325
+ /* Ensure the key starts with "Vlan" otherwise ignore */
326
+ if (strncmp (keys[0 ].c_str (), VLAN_PREFIX, 4 ))
327
+ {
328
+ SWSS_LOG_ERROR (" Invalid key format. No 'Vlan' prefix: %s" , keys[0 ].c_str ());
329
+ it = consumer.m_toSync .erase (it);
330
+ continue ;
331
+ }
332
+
333
+ unsigned long vlan_id;
334
+ vlan_id = strtoul (keys[0 ].substr (strlen (VLAN_PREFIX)).c_str (), NULL , 0 );
335
+
336
+ if ((vlan_id <= 0 ) || (vlan_id > MAX_VLAN_ID))
337
+ {
338
+ SWSS_LOG_ERROR (" Invalid key format. Vlan is out of range: %s" , keys[0 ].c_str ());
339
+ it = consumer.m_toSync .erase (it);
340
+ continue ;
341
+ }
342
+
343
+ MacAddress mac = MacAddress (keys[1 ]);
344
+
345
+ string key = VLAN_PREFIX + to_string (vlan_id);
346
+ key += DEFAULT_KEY_SEPARATOR;
347
+ key += mac.to_string ();
348
+
349
+ if (op == SET_COMMAND)
350
+ {
351
+ string port;
352
+ for (auto i : kfvFieldsValues (t))
353
+ {
354
+ if (fvField (i) == " port" )
355
+ {
356
+ port = fvValue (i);
357
+ break ;
358
+ }
359
+ }
360
+
361
+ vector<FieldValueTuple> fvVector;
362
+ FieldValueTuple p (" port" , port);
363
+ fvVector.push_back (p);
364
+ FieldValueTuple t (" type" , " static" );
365
+ fvVector.push_back (t);
366
+
367
+ m_appFdbTableProducer.set (key, fvVector);
368
+ }
369
+ else if (op == DEL_COMMAND)
370
+ {
371
+ m_appFdbTableProducer.del (key);
372
+ }
373
+ else
374
+ {
375
+ SWSS_LOG_ERROR (" Unknown operation type %s" , op.c_str ());
376
+ }
377
+ it = consumer.m_toSync .erase (it);
378
+ }
379
+ }
380
+
227
381
void VlanMgr::doVlanTask (Consumer &consumer)
228
382
{
229
383
if (!isVlanMacOk ())
@@ -296,12 +450,12 @@ void VlanMgr::doVlanTask(Consumer &consumer)
296
450
{
297
451
/* Set vlan admin status */
298
452
if (fvField (i) == " admin_status" )
299
- {
300
- admin_status = fvValue (i);
301
- setHostVlanAdminState (vlan_id, admin_status);
302
- fvVector.push_back (i);
303
- }
304
- /* Set vlan mtu */
453
+ {
454
+ admin_status = fvValue (i);
455
+ setHostVlanAdminState (vlan_id, admin_status);
456
+ fvVector.push_back (i);
457
+ }
458
+ /* Set vlan mtu */
305
459
else if (fvField (i) == " mtu" )
306
460
{
307
461
mtu = fvValue (i);
@@ -593,9 +747,47 @@ void VlanMgr::doTask(Consumer &consumer)
593
747
{
594
748
doVlanMemberTask (consumer);
595
749
}
750
+ else if (table_name == CFG_FDB_TABLE_NAME)
751
+ {
752
+ doFdbTask (consumer);
753
+ }
754
+ else if (table_name == CFG_SWITCH_TABLE_NAME)
755
+ {
756
+ SWSS_LOG_DEBUG (" Table:SWITCH" );
757
+ doSwitchTask (consumer);
758
+ }
596
759
else
597
760
{
598
761
SWSS_LOG_ERROR (" Unknown config table %s " , table_name.c_str ());
599
762
throw runtime_error (" VlanMgr doTask failure." );
600
763
}
601
764
}
765
+
766
+ void VlanMgr::doTask (NotificationConsumer &consumer)
767
+ {
768
+ std::string op;
769
+ std::string data;
770
+ std::vector<swss::FieldValueTuple> values;
771
+
772
+ if (&consumer != m_VlanStateNotificationConsumer)
773
+ {
774
+ SWSS_LOG_WARN (" received incorrect notification message" );
775
+ return ;
776
+ }
777
+
778
+ consumer.pop (op, data, values);
779
+
780
+ unsigned long vlan_id = strtoul (data.substr (strlen (VLAN_PREFIX)).c_str (), NULL , 0 );
781
+
782
+ SWSS_LOG_NOTICE (" vlanmgr received port status notification state %s vlan %s" ,
783
+ op.c_str (), data.c_str ());
784
+
785
+ if (isVlanStateOk (data))
786
+ {
787
+ setHostVlanAdminState ((int )vlan_id, op);
788
+ }
789
+ else
790
+ {
791
+ SWSS_LOG_ERROR (" received state update for vlan %s not existing" , data.c_str ());
792
+ }
793
+ }
0 commit comments