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

Generated by: LCOV version 1.14