10
10
#include " swssnet.h"
11
11
#include " converter.h"
12
12
#include " mirrororch.h"
13
+ #include " tokenize.h"
13
14
14
15
#define MIRROR_SESSION_STATUS " status"
15
16
#define MIRROR_SESSION_STATUS_ACTIVE " active"
16
17
#define MIRROR_SESSION_STATUS_INACTIVE " inactive"
18
+ #define MIRROR_SESSION_NEXT_HOP_IP " next_hop_ip"
17
19
#define MIRROR_SESSION_SRC_IP " src_ip"
18
20
#define MIRROR_SESSION_DST_IP " dst_ip"
19
21
#define MIRROR_SESSION_GRE_TYPE " gre_type"
23
25
#define MIRROR_SESSION_DST_MAC_ADDRESS " dst_mac"
24
26
#define MIRROR_SESSION_MONITOR_PORT " monitor_port"
25
27
#define MIRROR_SESSION_ROUTE_PREFIX " route_prefix"
26
- #define MIRROR_SESSION_VLAN_HEADER_VALID " vlan_header_valid "
28
+ #define MIRROR_SESSION_VLAN_ID " vlan_id "
27
29
#define MIRROR_SESSION_POLICER " policer"
28
30
29
31
#define MIRROR_SESSION_DEFAULT_VLAN_PRI 0
@@ -58,6 +60,7 @@ MirrorEntry::MirrorEntry(const string& platform) :
58
60
}
59
61
60
62
nexthopInfo.prefix = IpPrefix (" 0.0.0.0/0" );
63
+ nexthopInfo.nexthop = IpAddress (" 0.0.0.0" );
61
64
}
62
65
63
66
MirrorOrch::MirrorOrch (TableConnector stateDbConnector, TableConnector confDbConnector,
@@ -75,6 +78,74 @@ MirrorOrch::MirrorOrch(TableConnector stateDbConnector, TableConnector confDbCon
75
78
m_fdbOrch->attach (this );
76
79
}
77
80
81
+ bool MirrorOrch::bake ()
82
+ {
83
+ SWSS_LOG_ENTER ();
84
+
85
+ // Freeze the route update during orchagent restoration
86
+ m_freeze = true ;
87
+
88
+ deque<KeyOpFieldsValuesTuple> entries;
89
+ vector<string> keys;
90
+ m_mirrorTable.getKeys (keys);
91
+ for (const auto &key : keys)
92
+ {
93
+ vector<FieldValueTuple> tuples;
94
+ m_mirrorTable.get (key, tuples);
95
+
96
+ bool active = false ;
97
+ string monitor_port;
98
+ string next_hop_ip;
99
+
100
+ for (const auto &tuple : tuples)
101
+ {
102
+ if (fvField (tuple) == MIRROR_SESSION_STATUS)
103
+ {
104
+ active = fvValue (tuple) == MIRROR_SESSION_STATUS_ACTIVE;
105
+ }
106
+ else if (fvField (tuple) == MIRROR_SESSION_MONITOR_PORT)
107
+ {
108
+ monitor_port = fvValue (tuple);
109
+ }
110
+ else if (fvField (tuple) == MIRROR_SESSION_NEXT_HOP_IP)
111
+ {
112
+ next_hop_ip = fvValue (tuple);
113
+ }
114
+ }
115
+
116
+ if (!active)
117
+ {
118
+ continue ;
119
+ }
120
+
121
+ SWSS_LOG_NOTICE (" Found mirror session %s active before warm reboot" ,
122
+ key.c_str ());
123
+
124
+ // Recover saved active session's monitor port
125
+ m_recoverySessionMap.emplace (
126
+ key, monitor_port + state_db_key_delimiter + next_hop_ip);
127
+ }
128
+
129
+ return Orch::bake ();
130
+ }
131
+
132
+ bool MirrorOrch::postBake ()
133
+ {
134
+ SWSS_LOG_ENTER ();
135
+
136
+ SWSS_LOG_NOTICE (" Start MirrorOrch post-baking" );
137
+
138
+ // Unfreeze the route update
139
+ m_freeze = false ;
140
+
141
+ Orch::doTask ();
142
+
143
+ // Clean up the recovery cache
144
+ m_recoverySessionMap.clear ();
145
+
146
+ return Orch::postBake ();
147
+ }
148
+
78
149
void MirrorOrch::update (SubjectType type, void *cntx)
79
150
{
80
151
SWSS_LOG_ENTER ();
@@ -320,10 +391,11 @@ void MirrorOrch::setSessionState(const string& name, const MirrorEntry& session,
320
391
{
321
392
SWSS_LOG_ENTER ();
322
393
323
- SWSS_LOG_INFO (" Setting mirroring sessions %s state\n " , name.c_str ());
394
+ SWSS_LOG_INFO (" Update mirroring sessions %s state" , name.c_str ());
324
395
325
396
vector<FieldValueTuple> fvVector;
326
397
string value;
398
+
327
399
if (attr.empty () || attr == MIRROR_SESSION_STATUS)
328
400
{
329
401
value = session.status ? MIRROR_SESSION_STATUS_ACTIVE : MIRROR_SESSION_STATUS_INACTIVE;
@@ -332,8 +404,9 @@ void MirrorOrch::setSessionState(const string& name, const MirrorEntry& session,
332
404
333
405
if (attr.empty () || attr == MIRROR_SESSION_MONITOR_PORT)
334
406
{
335
- value = sai_serialize_object_id (session.neighborInfo .portId );
336
- fvVector.emplace_back (MIRROR_SESSION_MONITOR_PORT, value);
407
+ Port port;
408
+ m_portsOrch->getPort (session.neighborInfo .portId , port);
409
+ fvVector.emplace_back (MIRROR_SESSION_MONITOR_PORT, port.m_alias );
337
410
}
338
411
339
412
if (attr.empty () || attr == MIRROR_SESSION_DST_MAC_ADDRESS)
@@ -348,10 +421,16 @@ void MirrorOrch::setSessionState(const string& name, const MirrorEntry& session,
348
421
fvVector.emplace_back (MIRROR_SESSION_ROUTE_PREFIX, value);
349
422
}
350
423
351
- if (attr.empty () || attr == MIRROR_SESSION_VLAN_HEADER_VALID)
424
+ if (attr.empty () || attr == MIRROR_SESSION_VLAN_ID)
425
+ {
426
+ value = to_string (session.neighborInfo .port .m_vlan_info .vlan_id );
427
+ fvVector.emplace_back (MIRROR_SESSION_VLAN_ID, value);
428
+ }
429
+
430
+ if (attr.empty () || attr == MIRROR_SESSION_NEXT_HOP_IP)
352
431
{
353
- value = to_string ( session.neighborInfo . port . m_type == Port::VLAN );
354
- fvVector.emplace_back (MIRROR_SESSION_VLAN_HEADER_VALID , value);
432
+ value = session.nexthopInfo . nexthop . to_string ( );
433
+ fvVector.emplace_back (MIRROR_SESSION_NEXT_HOP_IP , value);
355
434
}
356
435
357
436
m_mirrorTable.set (name, fvVector);
@@ -396,32 +475,68 @@ bool MirrorOrch::getNeighborInfo(const string& name, MirrorEntry& session)
396
475
return false ;
397
476
}
398
477
399
- // Get the firt member of the LAG
400
- Port member;
401
- const auto & first_member_alias = *session.neighborInfo .port .m_members .begin ();
402
- m_portsOrch->getPort (first_member_alias, member);
478
+ // Recover the LAG member monitor port picked before warm reboot
479
+ // to minimalize the data plane changes across warm reboot.
480
+ if (m_recoverySessionMap.find (name) != m_recoverySessionMap.end ())
481
+ {
482
+ string alias = tokenize (m_recoverySessionMap[name],
483
+ state_db_key_delimiter, 1 )[0 ];
484
+ Port member;
485
+ m_portsOrch->getPort (alias, member);
486
+
487
+ SWSS_LOG_NOTICE (" Recover mirror session %s with LAG member port %s" ,
488
+ name.c_str (), alias.c_str ());
489
+ session.neighborInfo .portId = member.m_port_id ;
490
+ }
491
+ else
492
+ {
493
+ // Get the firt member of the LAG
494
+ Port member;
495
+ string first_member_alias = *session.neighborInfo .port .m_members .begin ();
496
+ m_portsOrch->getPort (first_member_alias, member);
497
+
498
+ session.neighborInfo .portId = member.m_port_id ;
499
+ }
403
500
404
- session.neighborInfo .portId = member.m_port_id ;
405
501
return true ;
406
502
}
407
503
case Port::VLAN:
408
504
{
409
505
SWSS_LOG_NOTICE (" Get mirror session destination IP neighbor VLAN %d" ,
410
506
session.neighborInfo .port .m_vlan_info .vlan_id );
411
- Port member;
412
- if (!m_fdbOrch->getPort (session.neighborInfo .mac , session.neighborInfo .port .m_vlan_info .vlan_id , member))
507
+
508
+ // Recover the VLAN member monitor port picked before warm reboot
509
+ // since the FDB entries are not yet learned on the hardware
510
+ if (m_recoverySessionMap.find (name) != m_recoverySessionMap.end ())
413
511
{
414
- SWSS_LOG_NOTICE (" Waiting to get FDB entry MAC %s under VLAN %s" ,
415
- session.neighborInfo .mac .to_string ().c_str (),
416
- session.neighborInfo .port .m_alias .c_str ());
417
- return false ;
512
+ string alias = tokenize (m_recoverySessionMap[name],
513
+ state_db_key_delimiter, 1 )[0 ];
514
+ Port member;
515
+ m_portsOrch->getPort (alias, member);
516
+
517
+ SWSS_LOG_NOTICE (" Recover mirror session %s with VLAN member port %s" ,
518
+ name.c_str (), alias.c_str ());
519
+ session.neighborInfo .portId = member.m_port_id ;
418
520
}
419
521
else
420
522
{
421
- // Update monitor port
422
- session.neighborInfo .portId = member.m_port_id ;
423
- return true ;
523
+ Port member;
524
+ if (!m_fdbOrch->getPort (session.neighborInfo .mac ,
525
+ session.neighborInfo .port .m_vlan_info .vlan_id , member))
526
+ {
527
+ SWSS_LOG_NOTICE (" Waiting to get FDB entry MAC %s under VLAN %s" ,
528
+ session.neighborInfo .mac .to_string ().c_str (),
529
+ session.neighborInfo .port .m_alias .c_str ());
530
+ return false ;
531
+ }
532
+ else
533
+ {
534
+ // Update monitor port
535
+ session.neighborInfo .portId = member.m_port_id ;
536
+ }
424
537
}
538
+
539
+ return true ;
425
540
}
426
541
default :
427
542
{
@@ -741,7 +856,7 @@ bool MirrorOrch::updateSessionType(const string& name, MirrorEntry& session)
741
856
SWSS_LOG_NOTICE (" Update mirror session %s VLAN to %s" ,
742
857
name.c_str (), session.neighborInfo .port .m_alias .c_str ());
743
858
744
- setSessionState (name, session, MIRROR_SESSION_VLAN_HEADER_VALID );
859
+ setSessionState (name, session, MIRROR_SESSION_VLAN_ID );
745
860
746
861
return true ;
747
862
}
@@ -782,7 +897,35 @@ void MirrorOrch::updateNextHop(const NextHopUpdate& update)
782
897
783
898
if (update.nexthopGroup != IpAddresses ())
784
899
{
785
- session.nexthopInfo .nexthop = *update.nexthopGroup .getIpAddresses ().begin ();
900
+ SWSS_LOG_NOTICE (" next hop IPs: %s" , update.nexthopGroup .to_string ().c_str ());
901
+
902
+ // Recover the session based on the state database information
903
+ if (m_recoverySessionMap.find (name) != m_recoverySessionMap.end ())
904
+ {
905
+ IpAddress nexthop = IpAddress (tokenize (m_recoverySessionMap[name],
906
+ state_db_key_delimiter, 1 )[1 ]);
907
+
908
+ // Check if recovered next hop IP is within the update's next hop IPs
909
+ if (update.nexthopGroup .getIpAddresses ().count (nexthop))
910
+ {
911
+ SWSS_LOG_NOTICE (" Recover mirror session %s with next hop %s" ,
912
+ name.c_str (), nexthop.to_string ().c_str ());
913
+ session.nexthopInfo .nexthop = nexthop;
914
+ }
915
+ else
916
+ {
917
+ // Correct the next hop IP
918
+ SWSS_LOG_NOTICE (" Correct mirror session %s next hop from %s to %s" ,
919
+ name.c_str (), session.nexthopInfo .nexthop .to_string ().c_str (),
920
+ nexthop.to_string ().c_str ());
921
+ session.nexthopInfo .nexthop = *update.nexthopGroup .getIpAddresses ().begin ();
922
+ }
923
+ }
924
+ else
925
+ {
926
+ // Pick the first one from the next hop group
927
+ session.nexthopInfo .nexthop = *update.nexthopGroup .getIpAddresses ().begin ();
928
+ }
786
929
}
787
930
else
788
931
{
@@ -968,6 +1111,11 @@ void MirrorOrch::doTask(Consumer& consumer)
968
1111
{
969
1112
SWSS_LOG_ENTER ();
970
1113
1114
+ if (m_freeze)
1115
+ {
1116
+ return ;
1117
+ }
1118
+
971
1119
if (!gPortsOrch ->allPortsReady ())
972
1120
{
973
1121
return ;
@@ -991,7 +1139,7 @@ void MirrorOrch::doTask(Consumer& consumer)
991
1139
}
992
1140
else
993
1141
{
994
- SWSS_LOG_ERROR (" Unknown operation type %s\n " , op.c_str ());
1142
+ SWSS_LOG_ERROR (" Unknown operation type %s" , op.c_str ());
995
1143
}
996
1144
997
1145
consumer.m_toSync .erase (it++);
0 commit comments