LCOV - code coverage report
Current view: top level - bgp/routing-instance - service_chaining.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 77 80 96.2 %
Date: 2026-11-09 02:10:49 Functions: 160 164 97.6 %
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             : #ifndef SRC_BGP_ROUTING_INSTANCE_SERVICE_CHAINING_H_
       7             : #define SRC_BGP_ROUTING_INSTANCE_SERVICE_CHAINING_H_
       8             : 
       9             : #include <boost/ptr_container/ptr_map.hpp>
      10             : #include <boost/shared_ptr.hpp>
      11             : 
      12             : #include <list>
      13             : #include <map>
      14             : #include <set>
      15             : #include <string>
      16             : #include <vector>
      17             : #include <mutex>
      18             : 
      19             : #include "base/lifetime.h"
      20             : #include "base/queue_task.h"
      21             : #include "bgp/bgp_condition_listener.h"
      22             : #include "bgp/inet/inet_route.h"
      23             : #include "bgp/inet6/inet6_route.h"
      24             : #include "bgp/evpn/evpn_route.h"
      25             : #include "bgp/routing-instance/iservice_chain_mgr.h"
      26             : 
      27             : class BgpRoute;
      28             : class BgpTable;
      29             : class RoutingInstance;
      30             : class BgpTable;
      31             : class BgpServer;
      32             : class InetVpnRoute;
      33             : class Inet6VpnRoute;
      34             : class SandeshResponse;
      35             : class ServiceChainConfig;
      36             : class ServiceChainGroup;
      37             : class ShowServicechainInfo;
      38             : 
      39             : template <typename T> class ServiceChainMgr;
      40             : 
      41             : template <typename T1, typename T2, typename T3, typename T4>
      42             : struct ServiceChainBase {
      43             :   typedef T1 RouteT;
      44             :   typedef T2 VpnRouteT;
      45             :   typedef T3 PrefixT;
      46             :   typedef T4 AddressT;
      47             : };
      48             : 
      49             : class ServiceChainInet : public ServiceChainBase<
      50             :     InetRoute, InetVpnRoute, Ip4Prefix, Ip4Address> {
      51             : };
      52             : 
      53             : class ServiceChainInet6 : public ServiceChainBase<
      54             :     Inet6Route, Inet6VpnRoute, Inet6Prefix, Ip6Address> {
      55             : };
      56             : 
      57             : class ServiceChainEvpn : public ServiceChainBase<
      58             :     EvpnRoute, InetVpnRoute, EvpnPrefix, Ip4Address> {
      59             : };
      60             : 
      61             : class ServiceChainEvpn6 : public ServiceChainBase<
      62             :     EvpnRoute, Inet6VpnRoute, EvpnPrefix, Ip6Address> {
      63             : };
      64             : 
      65             : typedef ConditionMatchPtr ServiceChainPtr;
      66             : 
      67             : class ServiceChainState : public ConditionMatchState {
      68             : public:
      69        8992 :     explicit ServiceChainState(ServiceChainPtr info) : info_(info) {
      70        8992 :     }
      71             :     ServiceChainPtr info() { return info_; }
      72             : 
      73             : private:
      74             :     ServiceChainPtr info_;
      75             :     DISALLOW_COPY_AND_ASSIGN(ServiceChainState);
      76             : };
      77             : 
      78             : template <typename T>
      79             : class ServiceChainRequest {
      80             : public:
      81             :     typedef typename T::PrefixT PrefixT;
      82             : 
      83             :     enum RequestType {
      84             :         MORE_SPECIFIC_ADD_CHG,
      85             :         MORE_SPECIFIC_DELETE,
      86             :         CONNECTED_ROUTE_ADD_CHG,
      87             :         CONNECTED_ROUTE_DELETE,
      88             :         EXT_CONNECT_ROUTE_ADD_CHG,
      89             :         EXT_CONNECT_ROUTE_DELETE,
      90             :         UPDATE_ALL_ROUTES,
      91             :         DELETE_ALL_ROUTES,
      92             :         STOP_CHAIN_DONE,
      93             :     };
      94             : 
      95       43551 :     ServiceChainRequest(RequestType type, BgpTable *table, BgpRoute *route,
      96             :         PrefixT aggregate_match, ServiceChainPtr info)
      97       43551 :         : type_(type),
      98       43551 :           table_(table),
      99       43551 :           rt_(route),
     100       43551 :           aggregate_match_(aggregate_match),
     101       43551 :           info_(info),
     102       43551 :           snh_resp_(NULL) {
     103       43551 :     }
     104             : 
     105             :     ServiceChainRequest(RequestType type, SandeshResponse *resp)
     106             :         : type_(type),
     107             :           table_(NULL),
     108             :           rt_(NULL),
     109             :           snh_resp_(resp) {
     110             :     }
     111             : 
     112             :     RequestType type_;
     113             :     BgpTable *table_;
     114             :     BgpRoute *rt_;
     115             :     PrefixT aggregate_match_;
     116             :     ServiceChainPtr info_;
     117             :     SandeshResponse *snh_resp_;
     118             : 
     119             : private:
     120             :     DISALLOW_COPY_AND_ASSIGN(ServiceChainRequest);
     121             : };
     122             : 
     123             : template <typename T>
     124             : class ServiceChain : public ConditionMatch {
     125             : public:
     126             :     typedef typename T::RouteT RouteT;
     127             :     typedef typename T::VpnRouteT VpnRouteT;
     128             :     typedef typename T::PrefixT PrefixT;
     129             :     typedef typename T::AddressT AddressT;
     130             :     typedef ServiceChainRequest<T> ServiceChainRequestT;
     131             :     typedef ServiceChainMgr<T> ServiceChainMgrT;
     132             : 
     133             :     // List of more specific routes resulted in Aggregate route
     134             :     typedef std::set<BgpRoute *> RouteList;
     135             : 
     136             :     // Map of Virtual Network subnet prefix to List of More Specific routes
     137             :     typedef std::map<PrefixT, RouteList> PrefixToRouteListMap;
     138             : 
     139             :     // Map of External Connecting route to Service Chain Route
     140             :     typedef std::set<BgpRoute *> ExtConnectRouteList;
     141             : 
     142             :     // List of path ids for the connected route
     143             :     typedef std::set<uint32_t> ConnectedPathIdList;
     144             : 
     145             :     ServiceChain(ServiceChainMgrT *manager, ServiceChainGroup *group,
     146             :         RoutingInstance *src, RoutingInstance *dest, RoutingInstance *connected,
     147             :         const std::vector<std::string> &subnets, AddressT addr, bool head,
     148             :         bool retain_as_path);
     149      163693 :     Address::Family GetFamily() const { return manager_->GetFamily(); }
     150       47415 :     Address::Family GetConnectedFamily() const {
     151       47415 :         return manager_->GetConnectedFamily();
     152             :     }
     153       54254 :     SCAddress::Family GetSCFamily() const { return manager_->GetSCFamily(); }
     154             : 
     155             :     // Delete is triggered from configuration, not via LifetimeManager.
     156        5397 :     void ManagedDelete() { }
     157             : 
     158             :     bool CompareServiceChainConfig(const ServiceChainConfig &config);
     159             :     void RemoveMatchState(BgpRoute *route, ServiceChainState *state);
     160             : 
     161             :     void SetConnectedRoute(BgpRoute *connected);
     162             :     bool IsConnectedRouteValid() const;
     163       45630 :     const ConnectedPathIdList &GetConnectedPathIds() {
     164       45630 :         return connected_path_ids_;
     165             :     }
     166             : 
     167      110592 :     BgpRoute *connected_route() const { return connected_route_; }
     168       19660 :     RoutingInstance *src_routing_instance() const { return src_; }
     169       16482 :     RoutingInstance *connected_routing_instance() const { return connected_; }
     170       35222 :     RoutingInstance *dest_routing_instance() const { return dest_; }
     171       54525 :     const AddressT &service_chain_addr() const { return service_chain_addr_; }
     172             :     void UpdateServiceChainRoute(PrefixT prefix, const RouteT *orig_route,
     173             :         const ConnectedPathIdList &old_path_ids, bool aggregate);
     174             :     void DeleteServiceChainRoute(PrefixT prefix, bool aggregate);
     175             : 
     176             :     bool AddMoreSpecific(PrefixT aggregate, BgpRoute *more_specific);
     177             :     bool DeleteMoreSpecific(PrefixT aggregate, BgpRoute *more_specific);
     178             : 
     179             :     BgpTable *src_table() const;
     180             :     BgpTable *connected_table() const;
     181             :     BgpTable *dest_table() const;
     182             : 
     183        7889 :     ServiceChainGroup *group() const { return group_; }
     184         208 :     void clear_group() { group_ = NULL; }
     185             : 
     186        6196 :     PrefixToRouteListMap *prefix_to_route_list_map() {
     187        6196 :         return &prefix_to_routelist_map_;
     188             :     }
     189      174855 :     const PrefixToRouteListMap *prefix_to_route_list_map() const {
     190      174855 :         return &prefix_to_routelist_map_;
     191             :     }
     192             : 
     193             :     virtual bool Match(BgpServer *server, BgpTable *table, BgpRoute *route,
     194             :         bool deleted);
     195             :     virtual std::string ToString() const;
     196             : 
     197             :     void FillServiceChainInfo(ShowServicechainInfo *info) const;
     198             : 
     199        2263 :     void set_connected_table_unregistered() {
     200        2263 :         connected_table_unregistered_ = true;
     201        2263 :     }
     202        2263 :     void set_dest_table_unregistered() {
     203        2263 :         dest_table_unregistered_ = true;
     204        2263 :     }
     205       42122 :     bool dest_table_unregistered() const {
     206       42122 :         return dest_table_unregistered_;
     207             :     }
     208       42378 :     bool connected_table_unregistered() const {
     209       42378 :         return connected_table_unregistered_;
     210             :     }
     211        6366 :     bool unregistered() const {
     212        6366 :         return connected_table_unregistered_ && dest_table_unregistered_;
     213             :     }
     214             : 
     215         288 :     const ExtConnectRouteList &ext_connecting_routes() const {
     216         288 :         return ext_connect_routes_;
     217             :     }
     218       36365 :     ExtConnectRouteList *ext_connecting_routes() {
     219       36365 :         return &ext_connect_routes_;
     220             :     }
     221             : 
     222       53541 :     bool aggregate_enable() const { return aggregate_; }
     223       79980 :     bool is_sc_head() const { return sc_head_; }
     224       18971 :     bool retain_as_path() const { return retain_as_path_; }
     225        1672 :     void set_aggregate_enable() { aggregate_ = true; }
     226        6937 :     bool group_oper_state_up() const { return group_oper_state_up_; }
     227         192 :     void set_group_oper_state_up(bool up) { group_oper_state_up_ = up; }
     228             : 
     229             : private:
     230             :     ServiceChainMgrT *manager_;
     231             :     ServiceChainGroup *group_;
     232             :     RoutingInstance *src_;
     233             :     RoutingInstance *dest_;
     234             :     RoutingInstance *connected_;
     235             :     ConnectedPathIdList connected_path_ids_;
     236             :     BgpRoute *connected_route_;
     237             :     AddressT service_chain_addr_;
     238             :     PrefixToRouteListMap prefix_to_routelist_map_;
     239             :     ExtConnectRouteList ext_connect_routes_;
     240             :     bool group_oper_state_up_;
     241             :     bool connected_table_unregistered_;
     242             :     bool dest_table_unregistered_;
     243             :     bool aggregate_;  // Whether the host route needs to be aggregated
     244             :     bool sc_head_; // Whether this SI is at the head of the chain
     245             :     bool retain_as_path_;
     246             :     LifetimeRef<ServiceChain> src_table_delete_ref_;
     247             :     LifetimeRef<ServiceChain> dest_table_delete_ref_;
     248             :     LifetimeRef<ServiceChain> connected_table_delete_ref_;
     249             : 
     250             :     // Helper function to match
     251             :     bool IsMoreSpecific(BgpRoute *route, PrefixT *aggregate_match) const;
     252             :     bool IsAggregate(BgpRoute *route) const;
     253             :     bool IsConnectedRoute(BgpRoute *route, bool is_conn_table=false) const;
     254             :     bool IsEvpnType5Route(BgpRoute *route) const;
     255             :     void GetReplicationFamilyInfo(DBTablePartition *&partition,
     256             :         BgpRoute *&route, BgpTable *&table, PrefixT prefix, bool create);
     257             :     void ProcessServiceChainPath(uint32_t path_id, BgpPath *path,
     258             :         BgpAttrPtr attr, BgpRoute *&route, DBTablePartition *&partition,
     259             :         bool aggregate, BgpTable *bgptable);
     260             :     void UpdateServiceChainRouteInternal(const RouteT *orig_route,
     261             :         const ConnectedPathIdList &old_path_ids, BgpRoute *sc_route,
     262             :         DBTablePartition *partition, BgpTable *bgptable, bool aggregate);
     263             :     void DeleteServiceChainRouteInternal(BgpRoute *service_chain_route,
     264             :                                          DBTablePartition *partition,
     265             :                                          BgpTable *bgptable, bool aggregate);
     266             : 
     267             :     DISALLOW_COPY_AND_ASSIGN(ServiceChain);
     268             : };
     269             : 
     270             : //
     271             : // This represents a service chain group within a ServiceChainMgr. All the
     272             : // individual ServiceChains that are part of the same logical service chain
     273             : // in the configuration are part of a given ServiceChainGroup.
     274             : //
     275             : // A ServiceChainGroup maintains operational state for itself based on the
     276             : // operational state of the individual ServiceChains that are part of the
     277             : // group. This is used to force fate sharing for all the ServiceChains in
     278             : // the group. If the operational status of the group is down, re-originated
     279             : // routes for all ServiceChainTs are deleted/withdrawn.
     280             : //
     281             : // A ServiceChainGroup gets created when the ServiceChainMgr processes a
     282             : // ServiceChainConfig with a non-empty service_chain_id. It gets deleted
     283             : // when there are no more ServiceChainTs or pending chains that belong to
     284             : // the ServiceChainGroup.
     285             : //
     286             : // The set of member chains is tracked using RoutingInstance pointers (as
     287             : // opposed to ServiceChainT pointers) so that the state of pending chains
     288             : // can also be tracked. Note that ServiceChainT objects are not allocated
     289             : // for pending chains.
     290             : //
     291             : // The membership of RoutingInstances in a ServiceChainGroup is updated as
     292             : // the group in the ServiceChainConfig for the RoutingInstances is updated.
     293             : //
     294             : // The operational state of the group is updated whenever a RoutingInstance
     295             : // is added or deleted to/from the ServiceChainGroup and when the connected
     296             : // route for the ServiceChainT is added/updated/deleted.
     297             : //
     298             : class ServiceChainGroup {
     299             : public:
     300             :     ServiceChainGroup(IServiceChainMgr *manager, const std::string &name);
     301             :     ~ServiceChainGroup();
     302             : 
     303             :     void AddRoutingInstance(RoutingInstance *rtinstance);
     304             :     void DeleteRoutingInstance(RoutingInstance *rtinstance);
     305             :     void UpdateOperState();
     306         624 :     std::string name() const { return name_; }
     307        1057 :     bool empty() const { return chain_set_.empty(); }
     308         216 :     bool oper_state_up() const { return oper_state_up_; }
     309             : 
     310             : private:
     311             :     typedef std::set<RoutingInstance *> ServiceChainSet;
     312             : 
     313             :     IServiceChainMgr *manager_;
     314             :     std::string name_;
     315             :     ServiceChainSet chain_set_;
     316             :     bool oper_state_up_;
     317             : };
     318             : 
     319             : template <typename T>
     320             : class ServiceChainMgr : public IServiceChainMgr {
     321             : public:
     322             :     typedef typename T::RouteT RouteT;
     323             :     typedef typename T::PrefixT PrefixT;
     324             :     typedef typename T::AddressT AddressT;
     325             :     typedef ServiceChain<T> ServiceChainT;
     326             :     typedef ServiceChainRequest<T> ServiceChainRequestT;
     327             : 
     328             :     explicit ServiceChainMgr(BgpServer *server);
     329             :     virtual ~ServiceChainMgr();
     330             : 
     331             :     void Terminate();
     332             :     void ManagedDelete();
     333             :     bool MayDelete() const;
     334             :     void RetryDelete();
     335             : 
     336             :     // Creates a new service chain between two Virtual network
     337             :     // If the two routing instance is already connected, it updates the
     338             :     // connected route address for existing service chain
     339             :     virtual bool LocateServiceChain(RoutingInstance *rtinstance,
     340             :         const ServiceChainConfig &config);
     341             : 
     342             :     // Remove the existing service chain between from routing instance
     343             :     virtual void StopServiceChain(RoutingInstance *rtinstance);
     344             :     virtual void UpdateServiceChain(RoutingInstance *rtinstance,
     345             :         bool group_oper_state_up);
     346             :     void UpdateServiceChainGroup(ServiceChainGroup *group);
     347             : 
     348        5208 :     virtual size_t PendingQueueSize() const { return pending_chains_.size(); }
     349        3525 :     virtual size_t ResolvedQueueSize() const { return chain_set_.size(); }
     350             :     virtual uint32_t GetDownServiceChainCount() const;
     351     6662964 :     virtual bool IsQueueEmpty() const { return process_queue_->IsQueueEmpty(); }
     352             :     virtual bool ServiceChainIsPending(RoutingInstance *rtinstance,
     353             :         std::string *reason = NULL) const;
     354             :     virtual bool ServiceChainIsUp(RoutingInstance *rtinstance) const;
     355             : 
     356             :     Address::Family GetFamily() const;
     357             :     Address::Family GetConnectedFamily() const;
     358             :     SCAddress::Family GetSCFamily() const;
     359             :     void Enqueue(ServiceChainRequestT *req);
     360             :     virtual bool FillServiceChainInfo(RoutingInstance *rtinstance,
     361             :                                       ShowServicechainInfo *info) const;
     362             :     virtual BgpConditionListener *GetListener();
     363             : private:
     364             :     template <typename U> friend class ServiceChainIntegrationTest;
     365             :     template <typename U> friend class ServiceChainTest;
     366             :     class DeleteActor;
     367             : 
     368             :     // All service chain related actions are performed in the context
     369             :     // of this task. This task has exclusion with db::DBTable task.
     370             :     static int service_chain_task_id_;
     371             : 
     372             :     struct PendingChainState {
     373           0 :         PendingChainState() : group(NULL) {
     374           0 :         }
     375        1517 :         PendingChainState(ServiceChainGroup *group, std::string reason)
     376        1517 :             : group(group), reason(reason) {
     377        1517 :         }
     378             :         ServiceChainGroup *group;
     379             :         std::string reason;
     380             :     };
     381             : 
     382             :     // Set of service chains created in the system
     383             :     typedef std::map<RoutingInstance *, ServiceChainPtr> ServiceChainMap;
     384             : 
     385             :     // At the time of processing, service chain request, all required info
     386             :     // may not be available (e.g. dest routing instance may not be created,
     387             :     // or marked deleted etc). Create a list of pending service chains that
     388             :     // are waiting to get created and maintain a reason string for why the
     389             :     // service chain is on the pending list.
     390             :     typedef std::map<RoutingInstance *, PendingChainState> PendingChainList;
     391             : 
     392             :     typedef boost::ptr_map<std::string, ServiceChainGroup> GroupMap;
     393             :     typedef std::set<ServiceChainGroup *> GroupSet;
     394             : 
     395             :     ServiceChainGroup *FindServiceChainGroup(RoutingInstance *rtinstance);
     396             :     ServiceChainGroup *FindServiceChainGroup(const std::string &group_name);
     397             :     ServiceChainGroup *LocateServiceChainGroup(const std::string &group_name);
     398             :     bool ProcessServiceChainGroups();
     399             : 
     400             :     bool RequestHandler(ServiceChainRequestT *req);
     401             :     void StopServiceChainDone(BgpTable *table, ConditionMatch *info);
     402             :     ServiceChainT *FindServiceChain(const std::string &instance) const;
     403             :     ServiceChainT *FindServiceChain(RoutingInstance *rtinstance) const;
     404             : 
     405        1517 :     void AddPendingServiceChain(RoutingInstance *rtinstance,
     406             :         ServiceChainGroup *group, std::string reason) {
     407        1517 :         PendingChainState state(group, reason);
     408        1517 :         pending_chains_.insert(std::make_pair(rtinstance, state));
     409        1517 :     }
     410        3294 :     void DeletePendingServiceChain(RoutingInstance *rtinstance) {
     411        3294 :         pending_chains_.erase(rtinstance);
     412        3294 :     }
     413         514 :     PendingChainState GetPendingServiceChain(RoutingInstance *rtinstance) {
     414         514 :         typename PendingChainList::const_iterator loc =
     415         514 :             pending_chains_.find(rtinstance);
     416         514 :         if (loc != pending_chains_.end()) {
     417         514 :             return loc->second;
     418             :         } else {
     419           0 :             return PendingChainState();
     420             :         }
     421             :     }
     422             : 
     423             :     void UpdateServiceChainRoutes(ServiceChainT *chain,
     424             :         const typename ServiceChainT::ConnectedPathIdList &old_path_ids);
     425             :     void DeleteServiceChainRoutes(ServiceChainT *chain);
     426             : 
     427             :     void StartResolve();
     428             :     bool ResolvePendingServiceChain();
     429             :     void RoutingInstanceCallback(std::string name, int op);
     430             :     void PeerRegistrationCallback(IPeer *peer, BgpTable *table,
     431             :         bool unregister);
     432             : 
     433        2263 :     bool aggregate_host_route() const { return aggregate_host_route_; }
     434        1424 :     virtual void set_aggregate_host_route(bool value) {
     435        1424 :         aggregate_host_route_ = value;
     436        1424 :     }
     437             : 
     438             :     virtual void DisableResolveTrigger();
     439             :     virtual void EnableResolveTrigger();
     440             :     virtual void DisableGroupTrigger();
     441             :     virtual void EnableGroupTrigger();
     442             : 
     443             :     // Work Queue to handle requests posted from Match function, called
     444             :     // in the context of db::DBTable task.
     445             :     // The actions are performed in the bgp::ServiceChain task context.
     446         128 :     virtual void DisableQueue() { process_queue_->set_disable(true); }
     447         128 :     virtual void EnableQueue() { process_queue_->set_disable(false); }
     448             : 
     449             :     // Mutex is used to serialize access from multiple bgp::ConfigHelper tasks.
     450             :     BgpServer *server_;
     451             :     std::mutex mutex_;
     452             :     BgpConditionListener *listener_;
     453             :     boost::scoped_ptr<TaskTrigger> resolve_trigger_;
     454             :     boost::scoped_ptr<WorkQueue<ServiceChainRequestT *> > process_queue_;
     455             :     ServiceChainMap chain_set_;
     456             :     PendingChainList pending_chains_;
     457             :     boost::scoped_ptr<TaskTrigger> group_trigger_;
     458             :     GroupMap group_map_;
     459             :     GroupSet group_set_;
     460             :     bool aggregate_host_route_;
     461             :     int id_;
     462             :     int registration_id_;
     463             :     boost::scoped_ptr<DeleteActor> deleter_;
     464             :     LifetimeRef<ServiceChainMgr> server_delete_ref_;
     465             : 
     466             :     DISALLOW_COPY_AND_ASSIGN(ServiceChainMgr);
     467             : };
     468             : 
     469             : typedef ServiceChainMgr<ServiceChainInet> ServiceChainMgrInet;
     470             : typedef ServiceChainMgr<ServiceChainInet6> ServiceChainMgrInet6;
     471             : typedef ServiceChainMgr<ServiceChainEvpn> ServiceChainMgrEvpn;
     472             : typedef ServiceChainMgr<ServiceChainEvpn6> ServiceChainMgrEvpn6;
     473             : 
     474             : #endif  // SRC_BGP_ROUTING_INSTANCE_SERVICE_CHAINING_H_

Generated by: LCOV version 1.14