4 #include <boost/statechart/custom_reaction.hpp>
5 #include <boost/statechart/event.hpp>
6 #include <boost/statechart/simple_state.hpp>
7 #include <boost/statechart/state.hpp>
8 #include <boost/statechart/state_machine.hpp>
17 namespace sc = boost::statechart;
18 namespace mpl = boost::mpl;
26 static const char *
Name() {
34 static const char *
Name() {
42 static const char *
Name() {
43 return "WaitForTraffic";
50 static const char *
Name() {
60 static const char *
Name() {
68 static const char *
Name() {
69 return "Control node route in sync";
73 struct Init :
public sc::state<Init, PathPreferenceSM> {
75 sc::custom_reaction<EvStart>
78 Init(my_context ctx) : my_base(ctx) {
80 state_machine->
Log(
"INIT");
84 return transit<WaitForTraffic>();
90 sc::custom_reaction<EvTrafficSeen>,
91 sc::custom_reaction<EvSeqChange>,
92 sc::custom_reaction<EvWaitForTraffic>,
93 sc::custom_reaction<EvActiveActiveMode>,
94 sc::custom_reaction<EvControlNodeInSync>
104 state_machine->
Log(
"Wait For Traffic");
109 return transit<TrafficSeen>();
115 state_machine->
Log(
"WaitForTraffic EvSeqChange");
116 return discard_event();
120 return discard_event();
124 return transit<ActiveActiveState>();
128 return discard_event();
134 sc::custom_reaction<EvTrafficSeen>,
135 sc::custom_reaction<EvSeqChange>,
136 sc::custom_reaction<EvWaitForTraffic>,
137 sc::custom_reaction<EvActiveActiveMode>,
138 sc::custom_reaction<EvControlNodeInSync>
156 state_machine->
Log(
"Traffic seen");
161 return discard_event();
165 return transit<WaitForTraffic>();
172 state_machine->
Log(
"TrafficSeen EvSeqChange");
179 state_machine->
Log(
"Back off and retry update");
181 return discard_event();
184 return transit<WaitForTraffic>();
188 return transit<ActiveActiveState>();
193 state_machine->
Log(
"in sync with control-node");
194 return discard_event();
200 sc::custom_reaction<EvTrafficSeen>,
201 sc::custom_reaction<EvSeqChange>,
202 sc::custom_reaction<EvWaitForTraffic>,
203 sc::custom_reaction<EvActiveActiveMode>,
204 sc::custom_reaction<EvControlNodeInSync>
219 state_machine->
Log(
"Ecmp path");
224 return discard_event();
228 return transit<WaitForTraffic>();
234 state_machine->
Log(
"ActiveActiveState EvSeqChange");
235 return transit<WaitForTraffic>();
239 return discard_event();
243 return discard_event();
251 max_sequence_(0), timer_(NULL), timeout_(kMinInterval),
252 flap_count_(0), is_dependent_rt_(is_dependent_route),
253 dependent_rt_(this) {
267 for (;iter != dependent_routes_.end(); iter++) {
286 "Stale cleanup timer",
355 for (;iter != dependent_routes_.end(); iter++) {
368 bool maciplearning_prefix =
false;
391 if (
ecmp() ==
true) {
403 static_cast<const AgentPath *
>(it.operator->());
404 if (path == local_path) {
411 if (max_sequence < path->
sequence()) {
426 if ( inet_rt != NULL) {
429 GetMacIpLearningTable()->
Find(macip_entry_key);
432 maciplearning_prefix =
true;
434 Log(
"WaitForTraffic EvSeqChange skipped ");
438 if ((max_sequence >
sequence()) && (maciplearning_prefix ==
false)) {
440 }
else if (
sequence() == max_sequence &&
445 }
else if (
sequence() == max_sequence &&
455 std::string dependent_ip_str =
"";
494 family_(
Address::INET), ip_(), plen_(0), vrf_name_(), seen_(false) {
499 const std::string &vrf) :
500 family_(family), ip_(ip), plen_(plen), vrf_name_(vrf), seen_(
false) {
509 if (ip_ != rhs.
ip_) {
510 return ip_ < rhs.
ip_;
513 if (plen_ != rhs.
plen_) {
514 return plen_ < rhs.
plen_;
522 if ((family_ == rhs.
family_) && (ip_ == rhs.
ip_) &&
538 PeerPathPreferenceMap::iterator path_preference_it =
541 PeerPathPreferenceMap::iterator prev_it = path_preference_it++;
543 delete path_preference_sm;
609 vrf->GetInet4UnicastRouteTable());
612 vrf->GetInet6UnicastRouteTable());
636 PeerPathPreferenceMap::iterator path_preference_it =
640 path_preference_sm->
set_seen(
false);
641 path_preference_it++;
647 static_cast<const AgentPath *
>(it.operator->());
648 if (path->
peer() == NULL) {
655 bool new_path_added =
false;
664 std::pair<const Peer *, PathPreferenceSM *>
665 (path->
peer(), path_preference_sm));
666 new_path_added =
true;
692 if (dependent_rt ==
false && new_path_added) {
693 should_resolve =
true;
700 PeerPathPreferenceMap::iterator prev_it = path_preference_it++;
702 if (path_preference_sm->
seen() ==
false) {
703 delete path_preference_sm;
751 if (walk_ref.get() != NULL)
752 (static_cast<DBTable *>(partition))->ReleaseWalker(walk_ref);
783 for (Route::PathList::iterator it = rt->
GetPathList().begin();
786 static_cast<const AgentPath *
>(it.operator->());
787 if (path->
peer() == NULL) {
801 bool should_resolve =
false;
802 state->
Process(should_resolve);
805 if (should_resolve) {
814 work_queue_(
TaskScheduler::GetInstance()->GetTaskId(
"db::DBTable"), 0,
847 event.mac_,
event.ip_,
858 if (cpath_preference) {
860 path_preference_sm = path_preference->
GetSM(vm_intf->
peer());
861 if (path_preference_sm) {
863 path_preference_sm->process_event(ev);
876 if (cpath_preference) {
878 path_preference_sm = path_preference->
GetSM(vm_intf->
peer());
879 if (path_preference_sm) {
881 path_preference_sm->process_event(ev);
888 if (event.
ip_.is_v4()) {
891 }
else if(event.
ip_.is_v6()) {
899 if (event.
ip_.is_v4()) {
902 }
else if(event.
ip_.is_v6()) {
906 if (!cpath_preference) {
911 path_preference_sm = path_preference->
GetSM(vm_intf->
peer());
912 if (path_preference_sm) {
914 path_preference_sm->process_event(ev);
920 uint32_t interface_index,
944 vrf = vm_intf->
vrf();
953 if (!rt && !evpn_rt) {
964 evpn_path = evpn_rt->FindPath(vm_intf->
peer());
967 if (!path && !evpn_path) {
980 event.interface_index_ = interface_index;
981 event.vrf_index_ = vrf_index;
988 event.vrf_index_ = vm_intf->
vrf()->
vrf_id();
1015 uc_rt_listener->
Init();
1020 evpn_rt_listener->
Init();
1025 uc6_rt_listener->
Init();
1029 mpls_rt_listener->
Init();
1032 evpn_rt_listener->
id(),
1033 uc6_rt_listener->
id(),
1034 mpls_rt_listener->
id());
1055 bool resolve_path =
false;
1057 std::set<PathPreferenceState *>::iterator it = tmp.begin();
1058 for(; it != tmp.end(); it++) {
1059 (*it)->Process(resolve_path);
uint8_t prefix_length() const
!
static const uint32_t kMinInterval
sc::result react(const EvSeqChange &event)
void DecreaseRetryTimeout()
bool mac_ip_learning_enable() const
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
sc::result react(const EvStart &event)
const PathPreference & path_preference() const
AgentRouteTable * GetEvpnRouteTable() const
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
virtual const std::string GetAddressString() const =0
VrfEntry * FindVrfFromName(const string &name)
MacLearningPartition * Find(uint32_t index)
InetUnicastAgentRouteTable * fabric_inet4_unicast_table() const
static const uint32_t kMaxInterval
DependencyRef< PathPreferenceSM, PathPreferenceSM > dependent_rt_
Agent supports multiple route tables - Inet-unicast (IPv4/IPv6), Inet-multicast, bridge, EVPN (Type2/Type5). This base class contains common code for all types of route tables.
sc::result react(const EvControlNodeInSync &event)
uint32_t preference() const
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
boost::asio::ip::address IpAddress
MacLearningProto * mac_learning_proto() const
void Notify(DBTablePartBase *partition, DBEntryBase *e)
static const uint32_t kMaxFlapCount
DBTableBase::ListenerId uc6_rt_id_
DBTableBase::ListenerId evpn_rt_id_
std::unique_ptr< DBRequestData > data
InetUnicastAgentRouteTable * fabric_inet4_mpls_table() const
void Log(std::string state)
void VrfNotify(DBTablePartBase *partition, DBEntryBase *e)
InetUnicastAgentRouteTable * GetInet4UnicastRouteTable() const
PathPreferenceSM * GetDependentPath(const AgentPath *path) const
DBTableBase::ListenerId mpls_rt_id_
DBTableBase::ListenerId uc_rt_id_
InterfaceTable * interface_table() const
bool Enqueue(DBRequest *req)
#define PATH_PREFERENCE_TRACE(...)
InetUnicastAgentRouteTable * GetInet4MplsUnicastRouteTable() const
sc::result react(const EvWaitForTraffic &event)
InetUnicastAgentRouteTable * GetInet6UnicastRouteTable() const
bool GetRouteListenerId(const VrfEntry *vrf, const Agent::RouteTableType &table, DBTableBase::ListenerId &rt_id) const
const string & GetName() const
PathPreferenceModule(Agent *agent)
const Peer * peer() const
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
sc::result react(const EvControlNodeInSync &event)
sc::result react(const EvTrafficSeen &event)
sc::result react(const EvWaitForTraffic &event)
Base class for all Route entries in agent.
WorkQueue< PathPreferenceEventContainer > work_queue_
virtual KeyPtr GetDBRequestKey() const =0
void Unregister(ListenerId listener)
sc::result react(const EvSeqChange &event)
int GetTaskId(const std::string &name)
void set_is_dependent_rt(bool dependent_path)
void UpdateDependentRoute()
DBTableBase::ListenerId vrf_id_
PeerPathPreferenceMap path_preference_peer_map_
bool operator==(const RouteAddrList &rhs) const
AgentRoute * FindActiveEntry(const AgentRouteKey *key)
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
EvSeqChange(uint32_t sequence)
static const char * Name()
const Type GetType() const
void WalkAgain(DBTableWalkRef walk)
virtual Agent::RouteTableType GetTableType() const =0
ActiveActiveState(my_context ctx)
DBTableBase::ListenerId id() const
VrfEntry * FindVrfFromId(size_t index)
DBTableBase::ListenerId vrf_id() const
mpl::list< sc::custom_reaction< EvStart > > reactions
uint32_t local_preference() const
uint32_t interface_index_
bool IsDependentRt(void) const
sc::result react(const EvTrafficSeen &event)
sc::result react(const EvActiveActiveMode &event)
void set_dependent_ip(const IpAddress &ip)
bool static_preference() const
static TaskScheduler * GetInstance()
void Reset(LifetimeActor *actor)
PathPreferenceModule * route_preference_module() const
const std::string & vrf() const
uint32_t sequence() const
std::unique_ptr< DBRequestKey > key
EventManager * event_manager() const
static const char * Name()
void set_preference(uint32_t preference)
const Peer * peer() const
sc::result react(const EvSeqChange &event)
PathPreferenceIntfState(const VmInterface *intf)
PathPreference path_preference_
static const char * Name()
void EnqueueTrafficSeen(IpAddress ip, uint32_t plen, uint32_t interface_index, uint32_t vrf_index, const MacAddress &mac)
void set_sequence(uint32_t seq_no)
bool DequeueEvent(PathPreferenceEventContainer e)
void AddUnresolvedPath(PathPreferenceState *sm)
const uint32_t vrf_id() const
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 IsPathFlapping() const
void ClearState(DBTableBase *tbl_base, ListenerId listener)
sc::result react(const EvActiveActiveMode &event)
virtual const PrefixType & prefix_address() const
Returns the value of a stored prefix address (IPv4, IPv6 or MAC address)
boost::asio::ip::address_v4 Ip4Address
PathPreferenceSM(Agent *agent, const Peer *peer, AgentRoute *rt, bool dependent_rt, const PathPreference &pref)
VrfTable * vrf_table() const
uint32_t max_sequence() const
void IncreaseRetryTimeout()
void set_max_sequence(uint32_t seq)
uint32_t preference() const
LifetimeRef< PathPreferenceRouteListener > table_delete_ref_
std::set< PathPreferenceState * > unresolved_paths_
bool DeleteState(DBTablePartBase *partition, DBEntryBase *e)
void Walkdone(DBTable::DBTableWalkRef walk_ref, DBTableBase *partition, PathPreferenceRouteListener *state)
static uint64_t UTCTimestampUsec()
uint32_t sequence() const
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)
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
static const int kInvalidId
const VmInterface * intf_
DBEntry * Find(const DBEntry *entry)
uint64_t backoff_timer_fired_time_
static uint32_t ComputeHostIpPlen(const IpAddress &addr)
const Interface * FindInterface(size_t index) const
uint32_t ethernet_tag() const
void DeleteUnresolvedPath(PathPreferenceState *sm)
DBTable::DBTableWalkRef managed_delete_walk_ref_
PathPreferenceSM * GetSM(const Peer *)
mpl::list< sc::custom_reaction< EvTrafficSeen >, sc::custom_reaction< EvSeqChange >, sc::custom_reaction< EvWaitForTraffic >, sc::custom_reaction< EvActiveActiveMode >, sc::custom_reaction< EvControlNodeInSync > > reactions
DBTableBase::ListenerId id_
static const char * Name()
SandeshTraceBufferPtr PathPreferenceTraceBuf(SandeshTraceBufferCreate("PathPreference", 5000))
AgentRouteTable * rt_table_
virtual const NextHop * ComputeNextHop(Agent *agent) const
void Process(bool &should_resolve)
WaitForTraffic(my_context ctx)
static const char * Name()
VrfEntry * forwarding_vrf() const
static const char * Name()
const IpAddress & dependent_ip() const
boost::intrusive_ptr< DBTableWalk > DBTableWalkRef
void set_dependent_rt(PathPreferenceSM *sm)
sc::result react(const EvControlNodeInSync &event)
EvpnAgentRouteTable * fabric_evpn_table() const
InetUnicastRouteEntry * GetUcRoute(const IpAddress &addr) const
bool wait_for_traffic() const
virtual AgentPath * FindPath(const Peer *peer) const
bool is_dependent_rt() const
uint64_t last_stable_high_priority_change_at_
PathPreferenceState(Agent *agent, AgentRoute *rt_)
sc::result react(const EvTrafficSeen &event)
uint32_t sequence() const
TrafficSeen(my_context ctx)
sc::result react(const EvActiveActiveMode &event)
void set_wait_for_traffic(bool wait_for_traffic)
mpl::list< sc::custom_reaction< EvTrafficSeen >, sc::custom_reaction< EvSeqChange >, sc::custom_reaction< EvWaitForTraffic >, sc::custom_reaction< EvActiveActiveMode >, sc::custom_reaction< EvControlNodeInSync > > reactions
PathPreferenceRouteListener(Agent *agent, AgentRouteTable *table)
void set_peer(const Peer *peer)
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
static bool DeleteTimer(Timer *Timer)
const PathList & GetPathList() const
bool operator<(const RouteAddrList &rhs) const