55#include < sstream>
66#include < set>
77#include < algorithm>
8+ #include < tuple>
89
910#include < netinet/if_ether.h>
1011#include " net/if.h"
1112
1213#include " logger.h"
1314#include " schema.h"
15+ #include " converter.h"
1416
1517extern sai_switch_api_t *sai_switch_api;
1618extern sai_bridge_api_t *sai_bridge_api;
@@ -470,6 +472,107 @@ void PortsOrch::updateDbPortOperStatus(sai_object_id_t id, sai_port_oper_status_
470472 }
471473}
472474
475+ bool PortsOrch::addPort (const set<int > &lane_set, uint32_t speed)
476+ {
477+ SWSS_LOG_ENTER ();
478+
479+ vector<uint32_t > lanes (lane_set.begin (), lane_set.end ());
480+
481+ sai_attribute_t attr;
482+ vector<sai_attribute_t > attrs;
483+
484+ attr.id = SAI_PORT_ATTR_SPEED;
485+ attr.value .u32 = speed;
486+ attrs.push_back (attr);
487+
488+ attr.id = SAI_PORT_ATTR_HW_LANE_LIST;
489+ attr.value .u32list .list = lanes.data ();
490+ attr.value .u32list .count = static_cast <uint32_t >(lanes.size ());
491+ attrs.push_back (attr);
492+
493+ sai_object_id_t port_id;
494+ sai_status_t status = sai_port_api->create_port (&port_id, gSwitchId , static_cast <uint32_t >(attrs.size ()), attrs.data ());
495+ if (status != SAI_STATUS_SUCCESS)
496+ {
497+ SWSS_LOG_ERROR (" Failed to create port with the speed %u, rv:%d" , speed, status);
498+ return false ;
499+ }
500+
501+ m_portListLaneMap[lane_set] = port_id;
502+
503+ SWSS_LOG_NOTICE (" Create port %lx with the speed %u" , port_id, speed);
504+
505+ return true ;
506+ }
507+
508+ bool PortsOrch::removePort (sai_object_id_t port_id)
509+ {
510+ SWSS_LOG_ENTER ();
511+
512+ sai_status_t status = sai_port_api->remove_port (port_id);
513+ if (status != SAI_STATUS_SUCCESS)
514+ {
515+ SWSS_LOG_ERROR (" Failed to remove port %lx, rv:%d" , port_id, status);
516+ return false ;
517+ }
518+
519+ SWSS_LOG_NOTICE (" Remove port %lx" , port_id);
520+
521+ return true ;
522+ }
523+
524+ bool PortsOrch::initPort (const string &alias, const set<int > &lane_set)
525+ {
526+ SWSS_LOG_ENTER ();
527+
528+ /* Determine if the lane combination exists in switch */
529+ if (m_portListLaneMap.find (lane_set) != m_portListLaneMap.end ())
530+ {
531+ sai_object_id_t id = m_portListLaneMap[lane_set];
532+
533+ /* Determine if the port has already been initialized before */
534+ if (m_portList.find (alias) != m_portList.end () && m_portList[alias].m_port_id == id)
535+ {
536+ SWSS_LOG_INFO (" Port has already been initialized before alias:%s" , alias.c_str ());
537+ }
538+ else
539+ {
540+ Port p (alias, Port::PHY);
541+
542+ p.m_index = static_cast <int32_t >(m_portList.size ()); // TODO: Assume no deletion of physical port
543+ p.m_port_id = id;
544+
545+ /* Initialize the port and create router interface and host interface */
546+ if (initializePort (p))
547+ {
548+ /* Add port to port list */
549+ m_portList[alias] = p;
550+ /* Add port name map to counter table */
551+ std::stringstream ss;
552+ ss << hex << p.m_port_id ;
553+ FieldValueTuple tuple (p.m_alias , ss.str ());
554+ vector<FieldValueTuple> vector;
555+ vector.push_back (tuple);
556+ m_counterTable->set (" " , vector);
557+
558+ SWSS_LOG_NOTICE (" Initialized port %s" , alias.c_str ());
559+ }
560+ else
561+ {
562+ SWSS_LOG_ERROR (" Failed to initialize port %s" , alias.c_str ());
563+ return false ;
564+ }
565+ }
566+ }
567+ else
568+ {
569+ SWSS_LOG_ERROR (" Failed to locate port lane combination alias:%s" , alias.c_str ());
570+ return false ;
571+ }
572+
573+ return true ;
574+ }
575+
473576void PortsOrch::doPortTask (Consumer &consumer)
474577{
475578 SWSS_LOG_ENTER ();
@@ -482,21 +585,34 @@ void PortsOrch::doPortTask(Consumer &consumer)
482585 string alias = kfvKey (t);
483586 string op = kfvOp (t);
484587
588+ if (alias == " PortConfigDone" )
589+ {
590+ m_portConfigDone = true ;
591+
592+ for (auto i : kfvFieldsValues (t))
593+ {
594+ if (fvField (i) == " count" )
595+ {
596+ m_portCount = to_uint<uint32_t >(fvValue (i));
597+ }
598+ }
599+ }
600+
485601 /* Get notification from application */
486602 /* portsyncd application:
487- * When portsorch receives 'ConfigDone ' message, it indicates port initialization
603+ * When portsorch receives 'PortInitDone ' message, it indicates port initialization
488604 * procedure is done. Before port initialization procedure, none of other tasks
489605 * are executed.
490606 */
491- if (alias == " ConfigDone " )
607+ if (alias == " PortInitDone " )
492608 {
493609 /* portsyncd restarting case:
494610 * When portsyncd restarts, duplicate notifications may be received.
495611 */
496612 if (!m_initDone)
497613 {
498614 m_initDone = true ;
499- SWSS_LOG_INFO (" Get ConfigDone notification from portsyncd." );
615+ SWSS_LOG_INFO (" Get PortInitDone notification from portsyncd." );
500616 }
501617
502618 it = consumer.m_toSync .erase (it);
@@ -523,7 +639,6 @@ void PortsOrch::doPortTask(Consumer &consumer)
523639 int lane = stoi (lane_str);
524640 lane_set.insert (lane);
525641 }
526-
527642 }
528643
529644 /* Set port admin status */
@@ -539,47 +654,52 @@ void PortsOrch::doPortTask(Consumer &consumer)
539654 speed = (uint32_t )stoul (fvValue (i));
540655 }
541656
657+ /* Collect information about all received ports */
542658 if (lane_set.size ())
543659 {
544- /* Determine if the lane combination exists in switch */
545- if (m_portListLaneMap.find (lane_set) !=
546- m_portListLaneMap.end ())
547- {
548- sai_object_id_t id = m_portListLaneMap[lane_set];
660+ m_lanesAliasSpeedMap[lane_set] = make_tuple (alias, speed);
661+ }
549662
550- /* Determin if the port has already been initialized before */
551- if (m_portList.find (alias) != m_portList.end () && m_portList[alias].m_port_id == id)
663+ /* Once all ports received, go through the each port and perform appropriate actions:
664+ * 1. Remove ports which don't exist anymore
665+ * 2. Create new ports
666+ * 3. Initialize all ports
667+ */
668+ if (m_portConfigDone && (m_lanesAliasSpeedMap.size () == m_portCount))
669+ {
670+ for (auto it = m_portListLaneMap.begin (); it != m_portListLaneMap.end ();)
671+ {
672+ if (m_lanesAliasSpeedMap.find (it->first ) == m_lanesAliasSpeedMap.end ())
552673 {
553- SWSS_LOG_INFO (" Port has already been initialized before alias:%s" , alias.c_str ());
674+ if (!removePort (it->second ))
675+ {
676+ throw runtime_error (" PortsOrch initialization failure." );
677+ }
678+ it = m_portListLaneMap.erase (it);
554679 }
555680 else
556681 {
557- Port p (alias, Port::PHY);
558-
559- p.m_index = (uint32_t )m_portList.size (); // TODO: Assume no deletion of physical port
560- p.m_port_id = id;
682+ ++it;
683+ }
684+ }
561685
562- /* Initialize the port and create router interface and host interface */
563- if (initializePort (p))
686+ for (auto it = m_lanesAliasSpeedMap.begin (); it != m_lanesAliasSpeedMap.end ();)
687+ {
688+ if (m_portListLaneMap.find (it->first ) == m_portListLaneMap.end ())
689+ {
690+ if (!addPort (it->first , get<1 >(it->second )))
564691 {
565- /* Add port to port list */
566- m_portList[alias] = p;
567- /* Add port name map to counter table */
568- std::stringstream ss;
569- ss << hex << p.m_port_id ;
570- FieldValueTuple tuple (p.m_alias , ss.str ());
571- vector<FieldValueTuple> vector;
572- vector.push_back (tuple);
573- m_counterTable->set (" " , vector);
574-
575- SWSS_LOG_NOTICE (" Initialized port %s" , alias.c_str ());
692+ throw runtime_error (" PortsOrch initialization failure." );
576693 }
577- else
578- SWSS_LOG_ERROR (" Failed to initialize port %s" , alias.c_str ());
579694 }
695+
696+ if (!initPort (get<0 >(it->second ), it->first ))
697+ {
698+ throw runtime_error (" PortsOrch initialization failure." );
699+ }
700+
701+ it = m_lanesAliasSpeedMap.erase (it);
580702 }
581- else
582- SWSS_LOG_ERROR (" Failed to locate port lane combination alias:%s" , alias.c_str ());
583703 }
584704
585705 Port p;
0 commit comments