LCOV - code coverage report
Current view: top level - vnsw/agent/controller - controller_vrf_export.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 55 61 90.2 %
Date: 2026-11-09 02:10:49 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include <boost/uuid/uuid_io.hpp>
       7             : 
       8             : #include <cmn/agent_cmn.h>
       9             : #include <oper/route_common.h>
      10             : #include <oper/agent_route_walker.h>
      11             : #include <oper/vrf.h>
      12             : #include <oper/mirror_table.h>
      13             : 
      14             : #include <controller/controller_export.h>
      15             : #include <controller/controller_vrf_export.h>
      16             : #include <controller/controller_route_walker.h>
      17             : #include <controller/controller_peer.h>
      18             : #include <controller/controller_init.h>
      19             : #include <controller/controller_types.h>
      20             : 
      21          32 : VrfExport::State::State() : DBState(), exported_(false),
      22         128 :     force_chg_(false), rt_export_(), last_sequence_number_(0) {
      23          16 : };
      24             : 
      25          32 : VrfExport::State::~State() {
      26          32 : };
      27             : 
      28         716 : bool VrfExport::State::IsExportable(uint64_t sequence_number) {
      29             :     // Sequence number passed in argument is of channel to which this state
      30             :     // belongs. Once channel sends the vrf subscription after flap/fresh
      31             :     // connection, state's sequence number will be updated to that of channel.
      32             :     // After this all routes in this VRF become eligible for export.
      33             :     // This is needed as control-node mandates that VRF is subscribed before any
      34             :     // route is seen in same else it will again flap the
      35             :     // connection(intentionally).
      36             :     // Note: In case of flaps etc CN removes VRF subscription.
      37             :     // This sequence number macthing helps in making sure that VRF sub is
      38             :     // sent before any route is published.
      39         716 :     return (last_sequence_number_ != sequence_number);
      40             : }
      41             : 
      42        1222 : void VrfExport::Notify(const Agent *agent, AgentXmppChannel *bgp_xmpp_peer,
      43             :                        DBTablePartBase *partition, DBEntryBase *e) {
      44             : 
      45        1222 :     BgpPeer *bgp_peer = static_cast<BgpPeer *>(bgp_xmpp_peer->bgp_peer_id());
      46        1222 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
      47             :     //PBB VRF is implictly created, agent is not supposed to send RI
      48             :     //subscription message since control-node will not be aware of this RI
      49             :     //We still want to set a state and subscribe for bridge table for
      50             :     //building ingress replication tree
      51        1222 :     bool send_subscribe  = vrf->ShouldExportRoute();
      52             : 
      53        1222 :     uint32_t instance_id = vrf->rd();
      54             :     //Instance ID being zero is possible because of VN unavailability and VRF
      55             :     //ending up with NULL VRF. Reason being config sequence.
      56             :     //So seeing 0 instance_id delete the state so that resubscribe can be done
      57             :     //with new id and then re-export all route.
      58             :     //Note: Assumption is that instance id will never change from non zero to
      59             :     //some other non zero value.
      60             :     //Also Instance ID check is for TSN and TA only.
      61        1222 :     bool deleted = (vrf->IsDeleted()) || (instance_id == VrfEntry::kInvalidIndex);
      62             : 
      63        1222 :     if (deleted) {
      64        1050 :         bgp_peer->DeleteVrfState(partition, e);
      65        1050 :         if (!AgentXmppChannel::IsXmppChannelActive(agent, bgp_xmpp_peer)) {
      66           0 :             return;
      67             :         }
      68        1050 :         if (bgp_peer) {
      69        1050 :             CONTROLLER_TRACE(Trace, bgp_peer->GetName(), vrf->GetName(),
      70             :                              "VRF deleted, remove state");
      71        1050 :             bgp_peer->DeleteVrfState(partition, e);
      72             :         }
      73        1050 :         return;
      74             :     }
      75             : 
      76         172 :     if (!AgentXmppChannel::IsBgpPeerActive(agent, bgp_xmpp_peer))
      77         142 :         return;
      78             : 
      79          30 :     DBTableBase::ListenerId id = bgp_peer->GetVrfExportListenerId();
      80          30 :     State *state = static_cast<State *>(vrf->GetState(partition->parent(), id));
      81             :     uint8_t table_type;
      82          30 :     if (state == NULL) {
      83          16 :         state = new State();
      84          16 :         state->exported_ = false;
      85          16 :         state->mcast_exported_ = false;
      86          16 :         state->force_chg_ = true;
      87          16 :         vrf->SetState(partition->parent(), id, state);
      88             : 
      89             :             // Dont export routes belonging to Fabric VRF table
      90          16 :         for (table_type = (Agent::INVALID + 1);
      91         112 :                 table_type < Agent::ROUTE_TABLE_MAX; table_type++) {
      92         192 :             state->rt_export_[table_type] =
      93          96 :                 RouteExport::Init(
      94             :                         static_cast<AgentRouteTable *>
      95             :                         (vrf->GetRouteTable(table_type)),
      96             :                         bgp_xmpp_peer);
      97             :         }
      98             :    }
      99             : 
     100          30 :     if (state->last_sequence_number_ == bgp_xmpp_peer->sequence_number()) {
     101          14 :         state->force_chg_ = false;
     102             :     } else {
     103          16 :         state->last_sequence_number_ = bgp_xmpp_peer->sequence_number();
     104             :     }
     105             : 
     106          30 :     if (send_subscribe == false) {
     107           0 :         state->force_chg_ = false;
     108             :     }
     109             : 
     110          30 :     if (send_subscribe && ((state->exported_ == false) ||
     111          14 :                           (state->force_chg_ == true))) {
     112          16 :         if (AgentXmppChannel::ControllerSendSubscribe(bgp_xmpp_peer, vrf,
     113             :                                                       true)) {
     114          16 :             CONTROLLER_TRACE(Trace, bgp_peer->GetName(), vrf->GetName(),
     115             :                              "Subscribe");
     116             : 
     117          16 :             state->exported_ = true;
     118          16 :             if (state->force_chg_ == true) {
     119          16 :                 bgp_peer->route_walker()->StartRouteWalk(vrf, true,
     120             :                                           ControllerRouteWalker::NOTIFYALL);
     121          16 :                 state->force_chg_ = false;
     122             : 
     123          16 :                 if (Agent::GetInstance()->mulitcast_builder() == bgp_xmpp_peer) {
     124          16 :                     state->mcast_exported_ = true;
     125             :                 } else {
     126           0 :                     state->mcast_exported_ = false;
     127             :                 }
     128             :             }
     129          16 :             return;
     130             :         }
     131             :     } else {
     132          14 :         if (send_subscribe &&
     133          28 :             (Agent::GetInstance()->mulitcast_builder() == bgp_xmpp_peer) &&
     134          14 :             !state->mcast_exported_) {
     135             :             // When Agent switches to a new multicast builder, we have to
     136             :             // send multicast subscribe to the new multicast builder. Otherwise,
     137             :             // Agent can get stuck with old multicast tree affecting BUM
     138             :             // traffic.
     139           0 :             bgp_peer->route_walker()->StartRouteWalk(vrf, true,
     140             :                                   ControllerRouteWalker::NOTIFYMULTICAST);
     141           0 :             state->mcast_exported_ = true;
     142          28 :         } else if (send_subscribe &&
     143          14 :                    Agent::GetInstance()->mulitcast_builder() != bgp_xmpp_peer) {
     144             :             // If it is not the multicast builder, mark the flag false so that
     145             :             // if it becomes multicast builder we notify mutlcast routes
     146           0 :             state->mcast_exported_ = false;
     147             :         } else {
     148          14 :             CONTROLLER_TRACE(Trace, bgp_peer->GetName(), vrf->GetName(),
     149             :                              "Already subscribed");
     150             :         }
     151             :     }
     152             : }

Generated by: LCOV version 1.14