11#include " macsecorch.h"
2+ #include " macsecpost.h"
3+ #include " notifier.h"
24
35#include < macaddress.h>
46#include < sai_serialize.h>
@@ -599,6 +601,7 @@ MACsecOrch::MACsecOrch(
599601 const std::vector<std::string> &tables,
600602 PortsOrch *port_orch) : Orch(app_db, tables),
601603 m_port_orch(port_orch),
604+ m_state_db(state_db),
602605 m_state_macsec_port(state_db, STATE_MACSEC_PORT_TABLE_NAME),
603606 m_state_macsec_egress_sc(state_db, STATE_MACSEC_EGRESS_SC_TABLE_NAME),
604607 m_state_macsec_ingress_sc(state_db, STATE_MACSEC_INGRESS_SC_TABLE_NAME),
@@ -649,6 +652,53 @@ MACsecOrch::MACsecOrch(
649652 saiAclFieldSciMatchSupported = false ;
650653 }
651654 }
655+
656+ // Add handler for POST completion callback/notification.
657+ string post_state = getMacsecPostState (m_state_db);
658+ if (post_state == " switch-level-post-in-progress" ||
659+ post_state == " macsec-level-post-in-progress" )
660+ {
661+ m_notificationsDb = make_shared<DBConnector>(" ASIC_DB" , 0 );
662+ m_postCompletionNotificationConsumer = new swss::NotificationConsumer (m_notificationsDb.get (), " NOTIFICATIONS" );
663+ auto postCompletionNotificatier = new Notifier (m_postCompletionNotificationConsumer, this , " POST_COMPLETION__NOTIFICATIONS" );
664+ Orch::addExecutor (postCompletionNotificatier);
665+ }
666+
667+ if (post_state == " switch-level-post-in-progress" )
668+ {
669+ // POST was already enabled in switch init. The completion notification may have already been sent
670+ // before MACSecOrch is initialized. So query if POST is completed or not.
671+ sai_attribute_t attr;
672+ attr.id = SAI_SWITCH_ATTR_MACSEC_POST_STATUS;
673+ if (sai_switch_api->get_switch_attribute (gSwitchId , 1 , &attr) == SAI_STATUS_SUCCESS)
674+ {
675+ if (attr.value .s32 == SAI_SWITCH_MACSEC_POST_STATUS_PASS)
676+ {
677+ setMacsecPostState (m_state_db, " pass" );
678+ SWSS_LOG_NOTICE (" Switch MACSec POST passed" );
679+ }
680+ else if (attr.value .s32 == SAI_SWITCH_MACSEC_POST_STATUS_FAIL)
681+ {
682+ setMacsecPostState (m_state_db, " fail" );
683+ SWSS_LOG_ERROR (" Switch MACSec POST failed: oid %" PRIu64, gSwitchId );
684+ }
685+ else
686+ {
687+ SWSS_LOG_NOTICE (" Switch MACSec POST status: %d" , attr.value .s32 );
688+ }
689+ }
690+ else
691+ {
692+ SWSS_LOG_ERROR (" Failed to get MACSec POST status" );
693+ }
694+ }
695+ else if (post_state == " macsec-level-post-in-progress" )
696+ {
697+ // POST is only supported in MACSec init. Create MACSec and enable POST.
698+ m_enable_post = true ;
699+ initMACsecObject (gSwitchId );
700+ SWSS_LOG_NOTICE (" Init MACSec objects and enable POST" );
701+ }
652702}
653703
654704MACsecOrch::~MACsecOrch ()
@@ -661,6 +711,127 @@ MACsecOrch::~MACsecOrch()
661711 }
662712}
663713
714+ void MACsecOrch::doTask (NotificationConsumer &consumer)
715+ {
716+ SWSS_LOG_ENTER ();
717+
718+ if (&consumer != m_postCompletionNotificationConsumer)
719+ {
720+ return ;
721+ }
722+
723+ std::deque<KeyOpFieldsValuesTuple> entries;
724+ consumer.pops (entries);
725+ for (auto & entry : entries)
726+ {
727+ handleNotification (consumer, entry);
728+ }
729+ }
730+
731+ void MACsecOrch::handleNotification (NotificationConsumer &consumer, KeyOpFieldsValuesTuple& entry)
732+ {
733+ SWSS_LOG_ENTER ();
734+
735+ if (&consumer != m_postCompletionNotificationConsumer)
736+ {
737+ return ;
738+ }
739+
740+ auto op = kfvOp (entry);
741+ auto data = kfvKey (entry);
742+ SWSS_LOG_NOTICE (" Received SAI notification: op %s, data %s" , op.c_str (), data.c_str ());
743+
744+ if (op == " switch_macsec_post_status" )
745+ {
746+ sai_object_id_t switch_id;
747+ sai_switch_macsec_post_status_t switch_macsec_post_status;
748+ sai_deserialize_switch_macsec_post_status_ntf (data, switch_id, switch_macsec_post_status);
749+
750+ string post_state = getMacsecPostState (m_state_db);
751+ if (post_state == " switch-level-post-in-progress" )
752+ {
753+ // MACSec POST was enabled in switch init. SAI enables POST in all HW MACSec engines.
754+ // The returned POST status is the aggregated result for all HW MACSec engines.
755+
756+ if (switch_macsec_post_status == SAI_SWITCH_MACSEC_POST_STATUS_PASS)
757+ {
758+ setMacsecPostState (m_state_db, " pass" );
759+ SWSS_LOG_NOTICE (" Switch MACSec POST passed" );
760+ }
761+ else if (switch_macsec_post_status == SAI_SWITCH_MACSEC_POST_STATUS_FAIL)
762+ {
763+ setMacsecPostState (m_state_db, " fail" );
764+ SWSS_LOG_ERROR (" Switch MACSec POST failed" );
765+ }
766+ }
767+ else if (post_state == " macsec-level-post-in-progress" )
768+ {
769+ SWSS_LOG_ERROR (" POST enabled in MACSec init, but got notification from switch init" );
770+ }
771+ }
772+
773+ if (op == " macsec_post_status" )
774+ {
775+ sai_object_id_t macsec_id;
776+ sai_macsec_post_status_t macsec_post_status;
777+ sai_deserialize_macsec_post_status_ntf (data, macsec_id, macsec_post_status);
778+
779+ if (m_enable_post)
780+ {
781+ // MACSec POST was enabled in MACSec object init. Since two MACSec objects were created
782+ // (one for each direction), two POST status must be returend from SAI. POST is considered
783+ // pass only if POST passes in both MACSec objects.
784+
785+ string direction = " unknown" ;
786+ auto macsec_obj = m_macsec_objs.find (gSwitchId );
787+ if (macsec_obj->second .m_ingress_id == macsec_id)
788+ {
789+ direction = " ingress" ;
790+ }
791+ else if (macsec_obj->second .m_egress_id == macsec_id)
792+ {
793+ direction = " egress" ;
794+ }
795+
796+ if (macsec_post_status == SAI_MACSEC_POST_STATUS_PASS)
797+ {
798+ if (direction == " ingress" )
799+ {
800+ SWSS_LOG_NOTICE (" Ingress MACSec POST passed" );
801+ macsec_obj->second .m_ingress_post_passed = true ;
802+ }
803+ else if (direction == " egress" )
804+ {
805+ SWSS_LOG_NOTICE (" Egress MACSec POST passed" );
806+ macsec_obj->second .m_egress_post_passed = true ;
807+ }
808+
809+ // Check if POST passed on both MACSec objects.
810+ if (macsec_obj->second .m_ingress_post_passed && macsec_obj->second .m_egress_post_passed )
811+ {
812+ setMacsecPostState (m_state_db, " pass" );
813+ SWSS_LOG_NOTICE (" Ingress and egress MACSec POST passed" );
814+ }
815+ }
816+ else if (macsec_post_status == SAI_MACSEC_POST_STATUS_FAIL)
817+ {
818+ if (direction == " ingress" )
819+ {
820+ SWSS_LOG_ERROR (" Ingress MACSec POST failed" );
821+ }
822+ else if (direction == " egress" )
823+ {
824+ SWSS_LOG_ERROR (" Egress MACSec POST failed" );
825+ }
826+
827+ // Consider POST failed since it failed on one MACSec object.
828+ setMacsecPostState (m_state_db, " fail" );
829+ SWSS_LOG_ERROR (" MACSec POST failed" );
830+ }
831+ }
832+ }
833+ }
834+
664835void MACsecOrch::doTask (Consumer &consumer)
665836{
666837 SWSS_LOG_ENTER ();
@@ -1044,6 +1215,13 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id)
10441215 attr.value .booldata = true ;
10451216 attrs.push_back (attr);
10461217
1218+ if (m_enable_post)
1219+ {
1220+ attr.id = SAI_MACSEC_ATTR_ENABLE_POST;
1221+ attr.value .booldata = true ;
1222+ attrs.push_back (attr);
1223+ }
1224+
10471225 sai_status_t status = sai_macsec_api->create_macsec (
10481226 &macsec_obj.first ->second .m_egress_id ,
10491227 switch_id,
@@ -1069,6 +1247,13 @@ bool MACsecOrch::initMACsecObject(sai_object_id_t switch_id)
10691247 attr.value .booldata = true ;
10701248 attrs.push_back (attr);
10711249
1250+ if (m_enable_post)
1251+ {
1252+ attr.id = SAI_MACSEC_ATTR_ENABLE_POST;
1253+ attr.value .booldata = true ;
1254+ attrs.push_back (attr);
1255+ }
1256+
10721257 status = sai_macsec_api->create_macsec (
10731258 &macsec_obj.first ->second .m_ingress_id ,
10741259 switch_id,
0 commit comments