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