5 #include <boost/statechart/custom_reaction.hpp>
6 #include <boost/statechart/event.hpp>
7 #include <boost/statechart/simple_state.hpp>
8 #include <boost/statechart/state.hpp>
9 #include <boost/statechart/state_machine.hpp>
18 namespace sc = boost::statechart;
19 namespace mpl = boost::mpl;
27 static const char *
Name() {
35 static const char *
Name() {
43 static const char *
Name() {
44 return "WaitForTraffic";
51 static const char *
Name() {
61 static const char *
Name() {
69 static const char *
Name() {
70 return "Control node route in sync";
74 struct Init :
public sc::state<Init, PathPreferenceSM> {
76 sc::custom_reaction<EvStart>
79 Init(my_context ctx) : my_base(ctx) {
81 state_machine->
Log(
"INIT");
85 return transit<WaitForTraffic>();
91 sc::custom_reaction<EvTrafficSeen>,
92 sc::custom_reaction<EvSeqChange>,
93 sc::custom_reaction<EvWaitForTraffic>,
94 sc::custom_reaction<EvActiveActiveMode>,
95 sc::custom_reaction<EvControlNodeInSync>
105 state_machine->
Log(
"Wait For Traffic");
110 return transit<TrafficSeen>();
116 state_machine->
Log(
"WaitForTraffic EvSeqChange");
117 return discard_event();
121 return discard_event();
125 return transit<ActiveActiveState>();
129 return discard_event();
135 sc::custom_reaction<EvTrafficSeen>,
136 sc::custom_reaction<EvSeqChange>,
137 sc::custom_reaction<EvWaitForTraffic>,
138 sc::custom_reaction<EvActiveActiveMode>,
139 sc::custom_reaction<EvControlNodeInSync>
157 state_machine->
Log(
"Traffic seen");
162 return discard_event();
166 return transit<WaitForTraffic>();
173 state_machine->
Log(
"TrafficSeen EvSeqChange");
180 state_machine->
Log(
"Back off and retry update");
182 return discard_event();
185 return transit<WaitForTraffic>();
189 return transit<ActiveActiveState>();
194 state_machine->
Log(
"in sync with control-node");
195 return discard_event();
201 sc::custom_reaction<EvTrafficSeen>,
202 sc::custom_reaction<EvSeqChange>,
203 sc::custom_reaction<EvWaitForTraffic>,
204 sc::custom_reaction<EvActiveActiveMode>,
205 sc::custom_reaction<EvControlNodeInSync>
220 state_machine->
Log(
"Ecmp path");
225 return discard_event();
229 return transit<WaitForTraffic>();
235 state_machine->
Log(
"ActiveActiveState EvSeqChange");
236 return transit<WaitForTraffic>();
240 return discard_event();
244 return discard_event();
252 max_sequence_(0), timer_(NULL), timeout_(kMinInterval),
253 flap_count_(0), is_dependent_rt_(is_dependent_route),
254 dependent_rt_(this) {
268 for (;iter != dependent_routes_.end(); iter++) {
287 "Stale cleanup timer",
356 for (;iter != dependent_routes_.end(); iter++) {
369 bool maciplearning_prefix =
false;
392 if (
ecmp() ==
true) {
404 static_cast<const AgentPath *
>(it.operator->());
405 if (path == local_path) {
412 if (max_sequence < path->
sequence()) {
427 if ( inet_rt != NULL) {
430 GetMacIpLearningTable()->
Find(macip_entry_key);
433 maciplearning_prefix =
true;
435 Log(
"WaitForTraffic EvSeqChange skipped ");
456 std::string dependent_ip_str =
"";
495 family_(
Address::INET), ip_(), plen_(0), vrf_name_(), seen_(false) {
500 const std::string &vrf) :
501 family_(family), ip_(ip), plen_(plen), vrf_name_(vrf), seen_(false) {
510 if (ip_ != rhs.
ip_) {
511 return ip_ < rhs.
ip_;
514 if (plen_ != rhs.
plen_) {
515 return plen_ < rhs.
plen_;
523 if ((family_ == rhs.
family_) && (ip_ == rhs.
ip_) &&
539 PeerPathPreferenceMap::iterator path_preference_it =
542 PeerPathPreferenceMap::iterator prev_it = path_preference_it++;
544 delete path_preference_sm;
637 PeerPathPreferenceMap::iterator path_preference_it =
641 path_preference_sm->
set_seen(
false);
642 path_preference_it++;
648 static_cast<const AgentPath *
>(it.operator->());
649 if (path->
peer() == NULL) {
656 bool new_path_added =
false;
665 std::pair<const Peer *, PathPreferenceSM *>
666 (path->
peer(), path_preference_sm));
667 new_path_added =
true;
693 if (dependent_rt ==
false && new_path_added) {
694 should_resolve =
true;
701 PeerPathPreferenceMap::iterator prev_it = path_preference_it++;
703 if (path_preference_sm->
seen() ==
false) {
704 delete path_preference_sm;
752 if (walk_ref.get() != NULL)
753 (
static_cast<DBTable *
>(partition))->ReleaseWalker(walk_ref);
784 for (Route::PathList::iterator it = rt->
GetPathList().begin();
787 static_cast<const AgentPath *
>(it.operator->());
788 if (path->
peer() == NULL) {
802 bool should_resolve =
false;
803 state->
Process(should_resolve);
806 if (should_resolve) {
815 work_queue_(
TaskScheduler::GetInstance()->GetTaskId(
"db::DBTable"), 0,
859 if (cpath_preference) {
861 path_preference_sm = path_preference->
GetSM(vm_intf->
peer());
862 if (path_preference_sm) {
864 path_preference_sm->process_event(ev);
877 if (cpath_preference) {
879 path_preference_sm = path_preference->
GetSM(vm_intf->
peer());
880 if (path_preference_sm) {
882 path_preference_sm->process_event(ev);
889 if (event.
ip_.is_v4()) {
892 }
else if(event.
ip_.is_v6()) {
900 if (event.
ip_.is_v4()) {
903 }
else if(event.
ip_.is_v6()) {
907 if (!cpath_preference) {
912 path_preference_sm = path_preference->
GetSM(vm_intf->
peer());
913 if (path_preference_sm) {
915 path_preference_sm->process_event(ev);
921 uint32_t interface_index,
945 vrf = vm_intf->
vrf();
954 if (!rt && !evpn_rt) {
968 if (!path && !evpn_path) {
981 event.interface_index_ = interface_index;
982 event.vrf_index_ = vrf_index;
989 event.vrf_index_ = vm_intf->
vrf()->
vrf_id();
1016 uc_rt_listener->
Init();
1021 evpn_rt_listener->
Init();
1026 uc6_rt_listener->
Init();
1030 mpls_rt_listener->
Init();
1033 evpn_rt_listener->
id(),
1034 uc6_rt_listener->
id(),
1035 mpls_rt_listener->
id());
1056 bool resolve_path =
false;
1058 std::set<PathPreferenceState *>::iterator it = tmp.begin();
1059 for(; it != tmp.end(); it++) {
1060 (*it)->Process(resolve_path);
boost::asio::ip::address IpAddress
boost::asio::ip::address_v4 Ip4Address
uint32_t sequence() const
const PathPreference & path_preference() const
const Peer * peer() const
virtual const NextHop * ComputeNextHop(Agent *agent) const
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge,...
AgentRoute * FindActiveEntry(const AgentRouteKey *key)
Base class for all Route entries in agent.
virtual const std::string GetAddressString() const =0
virtual KeyPtr GetDBRequestKey() const =0
virtual AgentPath * FindPath(const Peer *peer) const
virtual Agent::RouteTableType GetTableType() const =0
InterfaceTable * interface_table() const
MacLearningProto * mac_learning_proto() const
VrfTable * vrf_table() const
EventManager * event_manager() const
EvpnAgentRouteTable * fabric_evpn_table() const
InetUnicastAgentRouteTable * fabric_inet4_unicast_table() const
InetUnicastAgentRouteTable * fabric_inet4_mpls_table() const
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
void ClearState(DBTableBase *tbl_base, ListenerId listener)
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
bool Enqueue(DBRequest *req)
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
static const int kInvalidId
void Unregister(ListenerId listener)
void WalkAgain(DBTableWalkRef walk)
DBEntry * Find(const DBEntry *entry)
boost::intrusive_ptr< DBTableWalk > DBTableWalkRef
static uint32_t ComputeHostIpPlen(const IpAddress &addr)
uint8_t prefix_length() const
!
const Interface * FindInterface(size_t index) const
void Reset(LifetimeActor *actor)
MacLearningPartition * Find(uint32_t index)
PathPreferenceModule * route_preference_module() const
bool DequeueEvent(PathPreferenceEventContainer e)
void VrfNotify(DBTablePartBase *partition, DBEntryBase *e)
DBTableBase::ListenerId vrf_id_
void DeleteUnresolvedPath(PathPreferenceState *sm)
std::set< PathPreferenceState * > unresolved_paths_
PathPreferenceModule(Agent *agent)
void AddUnresolvedPath(PathPreferenceState *sm)
DBTableBase::ListenerId vrf_id() const
void EnqueueTrafficSeen(IpAddress ip, uint32_t plen, uint32_t interface_index, uint32_t vrf_index, const MacAddress &mac)
WorkQueue< PathPreferenceEventContainer > work_queue_
uint32_t sequence() const
uint64_t backoff_timer_fired_time_
bool wait_for_traffic() const
uint64_t last_stable_high_priority_change_at_
void UpdateDependentRoute()
void set_dependent_ip(const IpAddress &ip)
static const uint32_t kMaxInterval
PathPreferenceSM(Agent *agent, const Peer *peer, AgentRoute *rt, bool dependent_rt, const PathPreference &pref)
void IncreaseRetryTimeout()
void set_is_dependent_rt(bool dependent_path)
uint32_t max_sequence() const
void Log(std::string state)
PathPreference path_preference_
void set_max_sequence(uint32_t seq)
static const uint32_t kMinInterval
void set_wait_for_traffic(bool wait_for_traffic)
bool is_dependent_rt() const
DependencyRef< PathPreferenceSM, PathPreferenceSM > dependent_rt_
void DecreaseRetryTimeout()
bool IsPathFlapping() const
static const uint32_t kMaxFlapCount
void set_sequence(uint32_t seq_no)
void set_dependent_rt(PathPreferenceSM *sm)
void set_preference(uint32_t preference)
uint32_t preference() const
PathPreferenceSM * GetSM(const Peer *)
bool GetRouteListenerId(const VrfEntry *vrf, const Agent::RouteTableType &table, DBTableBase::ListenerId &rt_id) const
PathPreferenceSM * GetDependentPath(const AgentPath *path) const
PeerPathPreferenceMap path_preference_peer_map_
PathPreferenceState(Agent *agent, AgentRoute *rt_)
void Process(bool &should_resolve)
const IpAddress & dependent_ip() const
bool static_preference() const
uint32_t preference() const
uint32_t sequence() const
bool IsDependentRt(void) const
const std::string & vrf() const
const Type GetType() const
const PathList & GetPathList() const
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
int GetTaskId(const std::string &name)
static TaskScheduler * GetInstance()
static bool DeleteTimer(Timer *Timer)
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
uint32_t ethernet_tag() const
uint32_t local_preference() const
VrfEntry * forwarding_vrf() const
const Peer * peer() const
bool mac_ip_learning_enable() const
const string & GetName() const
InetUnicastAgentRouteTable * GetInet4MplsUnicastRouteTable() const
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
InetUnicastAgentRouteTable * GetInet4UnicastRouteTable() const
InetUnicastAgentRouteTable * GetInet6UnicastRouteTable() const
const uint32_t vrf_id() const
AgentRouteTable * GetEvpnRouteTable() const
VrfEntry * FindVrfFromName(const string &name)
VrfEntry * FindVrfFromId(size_t index)
SandeshTraceBufferPtr PathPreferenceTraceBuf(SandeshTraceBufferCreate("PathPreference", 5000))
#define PATH_PREFERENCE_TRACE(...)
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
sc::result react(const EvSeqChange &event)
sc::result react(const EvActiveActiveMode &event)
sc::result react(const EvWaitForTraffic &event)
sc::result react(const EvTrafficSeen &event)
mpl::list< sc::custom_reaction< EvTrafficSeen >, sc::custom_reaction< EvSeqChange >, sc::custom_reaction< EvWaitForTraffic >, sc::custom_reaction< EvActiveActiveMode >, sc::custom_reaction< EvControlNodeInSync > > reactions
sc::result react(const EvControlNodeInSync &event)
ActiveActiveState(my_context ctx)
void set_peer(const Peer *peer)
std::unique_ptr< DBRequestKey > key
std::unique_ptr< DBRequestData > data
static const char * Name()
static const char * Name()
static const char * Name()
EvSeqChange(uint32_t sequence)
static const char * Name()
static const char * Name()
static const char * Name()
sc::result react(const EvStart &event)
mpl::list< sc::custom_reaction< EvStart > > reactions
bool operator<(const RouteAddrList &rhs) const
bool operator==(const RouteAddrList &rhs) const
const VmInterface * intf_
PathPreferenceIntfState(const VmInterface *intf)
uint32_t interface_index_
bool DeleteState(DBTablePartBase *partition, DBEntryBase *e)
DBTable::DBTableWalkRef managed_delete_walk_ref_
PathPreferenceRouteListener(Agent *agent, AgentRouteTable *table)
AgentRouteTable * rt_table_
DBTableBase::ListenerId id() const
DBTableBase::ListenerId id_
LifetimeRef< PathPreferenceRouteListener > table_delete_ref_
void Notify(DBTablePartBase *partition, DBEntryBase *e)
void Walkdone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition, PathPreferenceRouteListener *state)
DBTableBase::ListenerId uc_rt_id_
DBTableBase::ListenerId evpn_rt_id_
DBTableBase::ListenerId mpls_rt_id_
DBTableBase::ListenerId uc6_rt_id_
sc::result react(const EvControlNodeInSync &event)
sc::result react(const EvSeqChange &event)
sc::result react(const EvTrafficSeen &event)
sc::result react(const EvWaitForTraffic &event)
TrafficSeen(my_context ctx)
mpl::list< sc::custom_reaction< EvTrafficSeen >, sc::custom_reaction< EvSeqChange >, sc::custom_reaction< EvWaitForTraffic >, sc::custom_reaction< EvActiveActiveMode >, sc::custom_reaction< EvControlNodeInSync > > reactions
sc::result react(const EvActiveActiveMode &event)
sc::result react(const EvTrafficSeen &event)
sc::result react(const EvSeqChange &event)
WaitForTraffic(my_context ctx)
sc::result react(const EvActiveActiveMode &event)
mpl::list< sc::custom_reaction< EvTrafficSeen >, sc::custom_reaction< EvSeqChange >, sc::custom_reaction< EvWaitForTraffic >, sc::custom_reaction< EvActiveActiveMode >, sc::custom_reaction< EvControlNodeInSync > > reactions
sc::result react(const EvWaitForTraffic &event)
sc::result react(const EvControlNodeInSync &event)
static uint64_t UTCTimestampUsec()