Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef SRC_BGP_PEER_CLOSE_MANAGER_H_
6 : #define SRC_BGP_PEER_CLOSE_MANAGER_H_
7 :
8 : #include <list>
9 : #include <string>
10 : #include <atomic>
11 :
12 : #include "base/timer.h"
13 : #include "base/util.h"
14 : #include "base/queue_task.h"
15 : #include "db/db_table_walker.h"
16 : #include "bgp/ipeer.h"
17 :
18 : class BgpMembershipManager;
19 : class BgpNeighborResp;
20 : class BgpRoute;
21 : class BgpTable;
22 : class PeerCloseInfo;
23 :
24 : // PeerCloseManager
25 : //
26 : // Manager close process of an IPeer (And hence should support both BgpPeers
27 : // and XmppPeers)
28 : //
29 : // Among other things, RibIns and RibOuts of peers must be closed/deleted
30 : // completely before a peer can be completely closed/deleted. This class
31 : // provides this capability.
32 : //
33 : // RibIn and RibOut close are handled by invoking Unregister request with
34 : // BgpMembershipManager class.
35 : //
36 : // Once RibIns and RibOuts are processed, notification callback function is
37 : // invoked to signal the completion of close process
38 : //
39 : class PeerCloseManager {
40 : public:
41 : PeerCloseManager(IPeerClose *peer_close,
42 : boost::asio::io_context *io_service);
43 : explicit PeerCloseManager(IPeerClose *peer_close);
44 : virtual ~PeerCloseManager();
45 :
46 301700 : bool IsMembershipInUse() const {
47 301700 : return membership_state_ == MEMBERSHIP_IN_USE;
48 : }
49 99675 : bool IsMembershipInWait() const {
50 99675 : return membership_state_ == MEMBERSHIP_IN_WAIT;
51 : }
52 84 : IPeerClose *peer_close() const { return peer_close_; }
53 2304 : IPeerClose::Families *families() { return &families_; }
54 :
55 51200 : bool IsCloseInProgress() const { return state_ != NONE; }
56 14780 : bool IsInDeleteState() const { return state_ == DELETE; }
57 9016 : bool IsInGRTimerWaitState() const {
58 9016 : return state_ == GR_TIMER || state_ == LLGR_TIMER;
59 : }
60 536 : bool IsInLlgrTimerWaitState() const { return state_ == LLGR_TIMER; }
61 23712 : bool IsQueueEmpty() const { return event_queue_->IsQueueEmpty(); }
62 :
63 : void Close(bool graceful);
64 : void ProcessEORMarkerReceived(Address::Family family);
65 : void MembershipRequest();
66 : void MembershipRequestCallback();
67 : BgpNeighborResp *FillCloseInfo(BgpNeighborResp *resp) const;
68 : bool MembershipPathCallback(DBTablePartBase *root, BgpRoute *rt,
69 : BgpPath *path);
70 : void UpdateRouteStats(Address::Family family, const BgpPath *old_path,
71 : uint32_t path_flags) const;
72 :
73 : private:
74 : friend class BgpServerUnitTest;
75 : friend class PeerCloseTest;
76 : friend class PeerCloseManagerTest;
77 : friend class GracefulRestartTest;
78 :
79 : enum State {
80 : BEGIN_STATE,
81 : NONE = BEGIN_STATE,
82 : STALE,
83 : GR_TIMER,
84 : LLGR_STALE,
85 : LLGR_TIMER,
86 : SWEEP,
87 : DELETE,
88 : END_STATE = DELETE
89 : };
90 :
91 : enum MembershipState {
92 : BEGIN_MEMBERSHIP_STATE,
93 : MEMBERSHIP_NONE = BEGIN_MEMBERSHIP_STATE,
94 : MEMBERSHIP_IN_USE,
95 : MEMBERSHIP_IN_WAIT,
96 : END_MEMBERSHIP_STATE = MEMBERSHIP_IN_WAIT
97 : };
98 :
99 : enum EventType {
100 : BEGIN_EVENT,
101 : EVENT_NONE = BEGIN_EVENT,
102 : CLOSE,
103 : EOR_RECEIVED,
104 : MEMBERSHIP_REQUEST,
105 : MEMBERSHIP_REQUEST_COMPLETE_CALLBACK,
106 : TIMER_CALLBACK,
107 : END_EVENT = TIMER_CALLBACK
108 : };
109 :
110 : struct Event {
111 20844 : Event(EventType event_type, bool graceful) :
112 20844 : event_type(event_type), graceful(graceful),
113 20844 : family(Address::UNSPEC) { }
114 14723 : Event(EventType event_type, Address::Family family) :
115 14723 : event_type(event_type), graceful(true),
116 14723 : family(family) { }
117 107243 : explicit Event(EventType event_type) : event_type(event_type),
118 107243 : graceful(true),
119 107243 : family(Address::UNSPEC) { }
120 : Event() : event_type(EVENT_NONE), graceful(true),
121 : family(Address::UNSPEC) { }
122 :
123 : EventType event_type;
124 : bool graceful;
125 : Address::Family family;
126 : };
127 :
128 : struct Stats {
129 28564 : Stats():
130 28564 : init(0),
131 28564 : close(0),
132 28564 : nested(0),
133 28564 : deletes(0),
134 28564 : stale(0),
135 28564 : llgr_stale(0),
136 28564 : sweep(0),
137 28564 : gr_timer(0),
138 314203 : llgr_timer(0) {
139 28565 : }
140 :
141 : struct RouteStats {
142 285639 : RouteStats() { reset(); }
143 629310 : bool IsSet() const {
144 629310 : return staled || llgr_staled || refreshed || fresh || deleted;
145 : }
146 :
147 30720 : RouteStats& operator=(const RouteStats& other) {
148 30720 : if (this != &other) {
149 30720 : staled.store(other.staled);
150 30720 : llgr_staled.store(other.llgr_staled);
151 30720 : refreshed.store(other.refreshed);
152 30720 : fresh.store(other.fresh);
153 30720 : deleted.store(other.deleted);
154 : }
155 30720 : return *this;
156 : }
157 :
158 483879 : void reset() {
159 483879 : staled = 0;
160 483880 : llgr_staled = 0;
161 483879 : refreshed = 0;
162 483880 : fresh = 0;
163 483880 : deleted = 0;
164 483880 : }
165 :
166 : std::atomic<uint64_t> staled;
167 : std::atomic<uint64_t> llgr_staled;
168 : std::atomic<uint64_t> refreshed;
169 : std::atomic<uint64_t> fresh;
170 : std::atomic<uint64_t> deleted;
171 : };
172 :
173 19824 : void ResetRouteStats() {
174 218064 : for (size_t i = 0; i < Address::NUM_FAMILIES; i++) {
175 198240 : route_stats[i].reset();
176 : }
177 19824 : }
178 :
179 : uint64_t init;
180 : uint64_t close;
181 : uint64_t nested;
182 : uint64_t deletes;
183 : uint64_t stale;
184 : uint64_t llgr_stale;
185 : uint64_t sweep;
186 : uint64_t gr_timer;
187 : uint64_t llgr_timer;
188 : mutable RouteStats route_stats[Address::NUM_FAMILIES];
189 : };
190 :
191 9274 : State state() const { return state_; }
192 3430 : const Stats &stats() const { return stats_; }
193 : void Close(Event *event);
194 : void ProcessEORMarkerReceived(Event *event);
195 : virtual void StartRestartTimer(int time);
196 : bool RestartTimerCallback();
197 : void RestartTimerCallback(Event *event);
198 : void ProcessClosure();
199 : void CloseComplete();
200 : void TriggerSweepStateActions();
201 : std::string GetStateName(State state) const;
202 : std::string GetMembershipStateName(MembershipState state) const;
203 : void FillRouteCloseInfo(PeerCloseInfo *close_info) const;
204 : void CloseInternal();
205 : void MembershipRequest(Event *event);
206 : bool MembershipRequestCallback(Event *event);
207 : void StaleNotify();
208 : bool EventCallback(Event *event);
209 : std::string GetEventName(EventType eventType) const;
210 : void EnqueueEvent(Event *event);
211 1267 : bool close_again() const { return close_again_; }
212 : virtual bool AssertMembershipState(bool do_assert = true);
213 : virtual bool AssertMembershipReqCount(bool do_assert = true);
214 : virtual bool AssertSweepState(bool do_assert = true);
215 : virtual bool AssertMembershipManagerInUse(bool do_assert = true);
216 64206 : void set_membership_state(MembershipState state) {
217 64206 : membership_state_ = state;
218 64206 : }
219 :
220 : virtual bool CanUseMembershipManager() const;
221 : virtual void GetRegisteredRibs(std::list<BgpTable *> *tables);
222 : virtual bool IsRegistered(BgpTable *table) const;
223 : virtual void Unregister(BgpTable *table);
224 : virtual void WalkRibIn(BgpTable *table);
225 : virtual void UnregisterRibOut(BgpTable *table);
226 : virtual bool IsRibInRegistered(BgpTable *table) const;
227 : virtual void UnregisterRibIn(BgpTable *table);
228 :
229 : IPeerClose *peer_close_;
230 : Timer *gr_timer_;
231 : boost::scoped_ptr<WorkQueue<Event *> > event_queue_;
232 : State state_;
233 : bool close_again_;
234 : bool graceful_;
235 : int gr_elapsed_;
236 : int llgr_elapsed_;
237 : MembershipState membership_state_;
238 : IPeerClose::Families families_;
239 : Stats stats_;
240 : std::atomic<int> membership_req_pending_;
241 : };
242 :
243 : #endif // SRC_BGP_PEER_CLOSE_MANAGER_H_
|