LCOV - code coverage report
Current view: top level - vnsw/agent/oper - path_preference.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 38 42 90.5 %
Date: 2026-06-08 02:02:55 Functions: 19 23 82.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #ifndef __ROUTE_PREFERENCE_H__
       5             : #define __ROUTE_PREFERENCE_H__
       6             : 
       7             : #include <boost/statechart/custom_reaction.hpp>
       8             : #include <boost/statechart/event.hpp>
       9             : #include <boost/statechart/simple_state.hpp>
      10             : #include <boost/statechart/state.hpp>
      11             : #include <boost/statechart/state_machine.hpp>
      12             : 
      13             : namespace sc = boost::statechart;
      14             : struct Init;
      15             : struct WaitForTraffic;
      16             : struct TrafficSeen;
      17             : struct ActiveActiveState;
      18             : class PathPreferenceModule;
      19             : 
      20             : #define PATH_PREFERENCE_TRACE(...)                                   \
      21             : do {                                                                      \
      22             :    PathPreferenceTrace::TraceMsg(PathPreferenceTraceBuf, __FILE__, __LINE__,\
      23             :                             ##__VA_ARGS__);                               \
      24             : } while (false) \
      25             : 
      26             : //Per Path state machine to determine preference of a path based on
      27             : //traffic(GARP or flow from VM)
      28             : class PathPreferenceSM:
      29             :     public sc::state_machine<PathPreferenceSM, Init> {
      30             :     typedef DependencyList<PathPreferenceSM, PathPreferenceSM> PathDependencyList;
      31             : public:
      32             :     static const uint32_t kMinInterval = 4 * 1000;
      33             :     static const uint32_t kMaxInterval = 32 * 1000;
      34             :     static const uint32_t kMaxFlapCount = 5;
      35             :     PathPreferenceSM(Agent *agent, const Peer *peer,
      36             :                      AgentRoute *rt, bool dependent_rt,
      37             :                      const PathPreference &pref);
      38             :     ~PathPreferenceSM();
      39         170 :     uint32_t sequence() const {return path_preference_.sequence();}
      40          54 :     uint32_t preference() const {return path_preference_.preference();}
      41          52 :     bool wait_for_traffic() const {return path_preference_.wait_for_traffic();}
      42         118 :     bool ecmp() const {return path_preference_.ecmp();}
      43          52 :     uint32_t timeout() const { return timeout_;}
      44             : 
      45             :     uint64_t last_stable_high_priority_change_at() const {
      46             :         return last_stable_high_priority_change_at_;
      47             :     }
      48             :     uint32_t flap_count() const { return flap_count_;}
      49             : 
      50          63 :     bool is_dependent_rt() const { return is_dependent_rt_;}
      51          13 :     void set_sequence(uint32_t seq_no) {
      52          13 :         path_preference_.set_sequence(seq_no);
      53          13 :     }
      54             : 
      55          13 :     void set_preference(uint32_t preference) {
      56          13 :         path_preference_.set_preference(preference);
      57          13 :     }
      58             : 
      59          13 :     void set_wait_for_traffic(bool wait_for_traffic) {
      60          13 :         path_preference_.set_wait_for_traffic(wait_for_traffic);
      61          13 :     }
      62             : 
      63             :     void set_ecmp(bool ecmp) {
      64             :         path_preference_.set_ecmp(ecmp);
      65             :     }
      66             : 
      67         220 :     void set_seen(bool seen) {
      68         220 :         seen_ = seen;
      69         220 :     }
      70             : 
      71          13 :     void set_max_sequence(uint32_t seq) {
      72          13 :         max_sequence_ = seq;
      73          13 :     }
      74             : 
      75             :     void set_timeout(uint32_t timeout) {
      76             :         timeout_ = timeout;
      77             :     }
      78             : 
      79             :     void set_last_stable_high_priority_change_at(uint64_t timestamp) {
      80             :         last_stable_high_priority_change_at_ = timestamp;
      81             :     }
      82             : 
      83         129 :     void set_dependent_rt(PathPreferenceSM *sm) {
      84         129 :         dependent_rt_.reset(sm);
      85         129 :     }
      86             : 
      87         129 :     void set_is_dependent_rt(bool dependent_path) {
      88         129 :         is_dependent_rt_ = dependent_path;
      89         129 :     }
      90             : 
      91         129 :     void set_dependent_ip(const IpAddress &ip) {
      92         129 :         path_preference_.set_dependent_ip(ip);
      93         129 :     }
      94             : 
      95           0 :     IpAddress dependent_ip() {
      96           0 :         return path_preference_.dependent_ip();
      97             :     }
      98             : 
      99             :     bool IsFlap() const;
     100         130 :     bool seen() { return seen_; }
     101          11 :     uint32_t max_sequence() const { return max_sequence_;}
     102             :     void Process();
     103             :     void Delete();
     104             :     void Log(std::string state);
     105             :     void EnqueuePathChange();
     106             :     bool Retry();
     107             :     void StartRetryTimer();
     108             :     void CancelRetryTimer();
     109             :     bool RetryTimerRunning();
     110             :     void IncreaseRetryTimeout();
     111             :     void DecreaseRetryTimeout();
     112             :     bool IsPathFlapping() const;
     113             :     bool IsPathStable() const;
     114             :     void UpdateFlapTime();
     115             :     void UpdateDependentRoute();
     116             : private:
     117             :     Agent *agent_;
     118             :     const Peer *peer_;
     119             :     AgentRoute *rt_;
     120             :     PathPreference path_preference_;
     121             :     uint32_t max_sequence_;
     122             :     bool seen_;
     123             :     Timer *timer_;
     124             :     uint32_t timeout_;
     125             :     uint64_t last_stable_high_priority_change_at_;
     126             :     uint64_t backoff_timer_fired_time_;
     127             :     uint32_t flap_count_;
     128             :     bool is_dependent_rt_;
     129             :     DependencyRef<PathPreferenceSM, PathPreferenceSM> dependent_rt_;
     130           0 :     DEPENDENCY_LIST(PathPreferenceSM, PathPreferenceSM, dependent_routes_);
     131             : };
     132             : 
     133             : //Per Route state machine containing a map for all
     134             : //local path state machine data
     135             : class PathPreferenceState: public DBState {
     136             : public:
     137             :     typedef std::map<const Peer *, PathPreferenceSM *> PeerPathPreferenceMap;
     138             :     PathPreferenceState(Agent *agent, AgentRoute *rt_);
     139             :     ~PathPreferenceState();
     140             :     void Process(bool &should_resolve);
     141             :     PathPreferenceSM *GetSM(const Peer *);
     142             :     PathPreferenceSM* GetDependentPath(const AgentPath *path) const;
     143             : private:
     144             :     bool GetRouteListenerId(const VrfEntry *vrf,
     145             :                             const Agent::RouteTableType &table,
     146             :                             DBTableBase::ListenerId &rt_id) const;
     147             :     Agent *agent_;
     148             :     AgentRoute *rt_;
     149             :     PeerPathPreferenceMap path_preference_peer_map_;
     150             : };
     151             : 
     152             : //Per VM interface state, containing floating IP
     153             : //and static route a interface contains
     154             : struct PathPreferenceIntfState : public DBState {
     155             :     PathPreferenceIntfState(const VmInterface *intf);
     156             :     struct RouteAddrList {
     157             :         RouteAddrList();
     158             :         RouteAddrList(const Address::Family &family, const IpAddress &ip,
     159             :                       uint32_t plen, const std::string &vrf);
     160             :         bool operator<(const RouteAddrList &rhs) const;
     161             :         bool operator==(const RouteAddrList &rhs) const;
     162             : 
     163             :         Address::Family family_;
     164             :         IpAddress ip_;
     165             :         uint32_t plen_;
     166             :         std::string vrf_name_;
     167             :         mutable bool seen_;
     168             :     };
     169             :     uint32_t DependentRouteListSize() const { return dependent_rt_.size(); }
     170             : private:
     171             :     const VmInterface *intf_;
     172             :     RouteAddrList instance_ip_;
     173             :     std::set<RouteAddrList> dependent_rt_;
     174             : };
     175             : 
     176             : struct PathPreferenceVrfState: public DBState {
     177           8 :     PathPreferenceVrfState(DBTableBase::ListenerId uc_rt_id,
     178             :                            DBTableBase::ListenerId evpn_rt_id,
     179             :                            DBTableBase::ListenerId uc6_rt_id,
     180           8 :                            DBTableBase::ListenerId mpls_rt_id):
     181           8 :         uc_rt_id_(uc_rt_id), evpn_rt_id_(evpn_rt_id),
     182           8 :         uc6_rt_id_(uc6_rt_id),mpls_rt_id_(mpls_rt_id) {}
     183             :     DBTableBase::ListenerId uc_rt_id_;
     184             :     DBTableBase::ListenerId evpn_rt_id_;
     185             :     DBTableBase::ListenerId uc6_rt_id_;
     186             :     DBTableBase::ListenerId mpls_rt_id_;
     187             : };
     188             : 
     189             : struct PathPreferenceRouteListener : public DBState {
     190             :     PathPreferenceRouteListener(Agent *agent, AgentRouteTable *table);
     191             :     virtual void Delete();
     192             : 
     193             :     void Notify(DBTablePartBase *partition, DBEntryBase *e);
     194             :     void Init();
     195             :     bool DeleteState(DBTablePartBase *partition, DBEntryBase *e);
     196             :     void Walkdone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition,
     197             :                   PathPreferenceRouteListener *state);
     198          32 :     DBTableBase::ListenerId id() const { return id_;}
     199             :     void ManagedDelete();
     200          32 :     void set_deleted() {deleted_ = true;}
     201             :     bool deleted() const {return deleted_;}
     202             : private:
     203             :     Agent *agent_;
     204             :     AgentRouteTable *rt_table_;
     205             :     DBTableBase::ListenerId id_;
     206             :     LifetimeRef<PathPreferenceRouteListener> table_delete_ref_;
     207             :     bool deleted_;
     208             :     DBTable::DBTableWalkRef managed_delete_walk_ref_;
     209             : };
     210             : 
     211             : class PathPreferenceModule {
     212             : public:
     213             :     struct PathPreferenceEventContainer {
     214             :         IpAddress ip_;
     215             :         uint32_t plen_;
     216             :         MacAddress mac_;
     217             :         uint32_t interface_index_;
     218             :         uint32_t vrf_index_;
     219             :         uint32_t vxlan_id_;
     220             :         boost::intrusive_ptr<const sc::event_base> event;
     221             :     };
     222             : 
     223             :     PathPreferenceModule(Agent *agent);
     224             :     void Init();
     225             :     void Shutdown();
     226             :     void VrfNotify(DBTablePartBase *partition, DBEntryBase *e);
     227             :     void EnqueueTrafficSeen(IpAddress ip, uint32_t plen,
     228             :                             uint32_t interface_index, uint32_t vrf_index,
     229             :                             const MacAddress &mac);
     230             :     bool DequeueEvent(PathPreferenceEventContainer e);
     231             :     Agent *agent() { return agent_;}
     232           0 :     DBTableBase::ListenerId vrf_id() const { return vrf_id_;}
     233             :     DBTableBase::ListenerId intf_id() const { return intf_id_;}
     234             :     void AddUnresolvedPath(PathPreferenceState *sm);
     235             :     void DeleteUnresolvedPath(PathPreferenceState *sm);
     236             :     void Resolve();
     237             : private:
     238             :     Agent *agent_;
     239             :     DBTableBase::ListenerId vrf_id_;
     240             :     DBTableBase::ListenerId intf_id_;
     241             :     WorkQueue<PathPreferenceEventContainer> work_queue_;
     242             :     std::set<PathPreferenceState *> unresolved_paths_;
     243             : };
     244             : #endif

Generated by: LCOV version 1.14