Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef SRC_VNSW_AGENT_SERVICES_HEALTH_CHECK_H_
6 : #define SRC_VNSW_AGENT_SERVICES_HEALTH_CHECK_H_
7 :
8 : #include <boost/scoped_ptr.hpp>
9 : #include <cmn/agent.h>
10 : #include <oper_db.h>
11 :
12 : extern SandeshTraceBufferPtr HealthCheckTraceBuf;
13 : #define HEALTH_CHECK_TRACE(obj, ...)\
14 : do {\
15 : HealthCheck##obj::TraceMsg(HealthCheckTraceBuf, __FILE__, __LINE__,\
16 : __VA_ARGS__);\
17 : } while (false)
18 :
19 : class Interface;
20 : class HealthCheckTable;
21 : class HealthCheckService;
22 : class MetaDataIp;
23 : class MetaDataIpAllocator;
24 : class InstanceTask;
25 : class InstanceTaskExecvp;
26 :
27 : ///////////////////////////////////////////////////////////////////////////////
28 : // HealthCheck module provides service to monitor status of given service
29 : // on an interface and updates the interface state accordingly to propagate
30 : // information accordingly
31 : ///////////////////////////////////////////////////////////////////////////////
32 :
33 : struct HealthCheckServiceKey : public AgentOperDBKey {
34 0 : HealthCheckServiceKey(const boost::uuids::uuid &id) :
35 0 : AgentOperDBKey(), uuid_(id) { }
36 0 : HealthCheckServiceKey(const boost::uuids::uuid &id, DBSubOperation sub_op) :
37 0 : AgentOperDBKey(sub_op), uuid_(id) { }
38 0 : virtual ~HealthCheckServiceKey() { }
39 :
40 : boost::uuids::uuid uuid_;
41 : };
42 :
43 : struct HealthCheckServiceData : public AgentOperDBData {
44 0 : HealthCheckServiceData(Agent *agent, IpAddress dest_ip,
45 : const std::string &name,
46 : const std::string &monitor_type,
47 : const std::string &stype,
48 : uint8_t ip_proto,
49 : const std::string &http_method,
50 : const std::string &url_path,
51 : uint16_t url_port,
52 : const std::string &expected_codes,
53 : uint32_t delay, uint64_t delay_usecs,
54 : uint32_t timeout, uint64_t timeout_usecs,
55 : uint32_t max_retries,
56 : bool is_all_ip,
57 : std::set<IpAddress> cfg_target_ip_list,
58 0 : IFMapNode *ifmap_node) :
59 0 : AgentOperDBData(agent, ifmap_node), dest_ip_(dest_ip), name_(name),
60 0 : monitor_type_(monitor_type), service_type_(stype), ip_proto_(ip_proto),
61 0 : http_method_(http_method), url_path_(url_path), url_port_(url_port),
62 0 : expected_codes_(expected_codes), delay_(delay),
63 0 : delay_usecs_(delay_usecs), timeout_(timeout),
64 0 : timeout_usecs_(timeout_usecs), max_retries_(max_retries),
65 0 : is_all_ip_(is_all_ip),
66 0 : new_target_ip_list_(cfg_target_ip_list) {
67 0 : }
68 0 : virtual ~HealthCheckServiceData() {}
69 :
70 : IpAddress dest_ip_;
71 : std::string name_;
72 : std::string monitor_type_;
73 : // Service type of HealthCheck segment/end-to-end/link-local
74 : std::string service_type_;
75 : uint8_t ip_proto_;
76 : std::string http_method_;
77 : std::string url_path_;
78 : uint16_t url_port_;
79 : std::string expected_codes_;
80 : uint32_t delay_;
81 : uint64_t delay_usecs_;
82 : uint32_t timeout_;
83 : uint64_t timeout_usecs_;
84 : uint32_t max_retries_;
85 : std::set<boost::uuids::uuid> intf_uuid_list_;
86 : std::set<boost::uuids::uuid> vn_uuid_list_;
87 : bool is_all_ip_;
88 : std::set<IpAddress> new_target_ip_list_;
89 : };
90 :
91 : struct HealthCheckInstanceEvent {
92 : public:
93 : enum EventType {
94 : MESSAGE_READ = 0,
95 : TASK_EXIT,
96 : SET_SERVICE,
97 : STOP_TASK,
98 : EVENT_MAXIMUM
99 : };
100 :
101 : HealthCheckInstanceEvent(HealthCheckInstanceBase *inst,
102 : HealthCheckService *service, EventType type,
103 : const std::string &message);
104 : virtual ~HealthCheckInstanceEvent();
105 :
106 : HealthCheckInstanceBase *instance_;
107 : HealthCheckService *service_;
108 : EventType type_;
109 : std::string message_;
110 : DISALLOW_COPY_AND_ASSIGN(HealthCheckInstanceEvent);
111 : };
112 :
113 : class HealthCheckInstanceBase {
114 : public:
115 :
116 : HealthCheckInstanceBase(HealthCheckService *service,
117 : MetaDataIpAllocator *allocator,
118 : VmInterface *intf,
119 : bool ignore_status_event);
120 : virtual ~HealthCheckInstanceBase();
121 :
122 : virtual bool CreateInstanceTask() = 0;
123 :
124 : // return true it instance is scheduled to destroy
125 : // when API returns false caller need to assure delete of
126 : // Health Check Instance
127 : virtual bool DestroyInstanceTask() = 0;
128 : virtual bool RunInstanceTask() = 0;
129 : virtual bool StopInstanceTask() = 0;
130 0 : virtual bool UpdateInstanceTask() { return true; }
131 :
132 : // OnRead Callback for Task
133 : void OnRead(const std::string &data);
134 : // OnExit Callback for Task
135 : void OnExit(const boost::system::error_code &ec);
136 : // Callback to enqueue set service
137 : void SetService(HealthCheckService *service);
138 : // Callback to enqueue stop task
139 : void StopTask(HealthCheckService *service);
140 :
141 : virtual void ResyncTarget(const HealthCheckService *service) const;
142 : void set_service(HealthCheckService *service);
143 : std::string to_string();
144 0 : bool active() {return active_;}
145 0 : virtual bool IsRunning() const { return true; }
146 0 : HealthCheckService *service() const { return service_.get(); }
147 0 : InterfaceRef interface() const { return intf_; }
148 0 : MetaDataIp *ip() const { return ip_.get(); }
149 0 : const std::string &last_update_time() const { return last_update_time_; }
150 0 : bool IsStatusEventIgnored() const { return ignore_status_event_; }
151 0 : void set_source_ip(const IpAddress &ip) { source_ip_ = ip; }
152 0 : IpAddress get_source_ip() const { return source_ip_; };
153 : IpAddress source_ip() const;
154 : IpAddress update_source_ip();
155 : void set_destination_ip(const IpAddress &ip);
156 : IpAddress destination_ip() const;
157 : void EnqueueHealthCheckResync(const HealthCheckService *service,
158 : const VmInterface *itf) const;
159 :
160 : protected:
161 : void EnqueueResync(const HealthCheckService *service, Interface *itf) const;
162 : friend class HealthCheckTable;
163 : // reference to health check service under
164 : // which this instance is running
165 : HealthCheckServiceRef service_;
166 : // Interface associated to this HealthCheck Instance
167 : InterfaceRef intf_;
168 : // MetaData IP Created for this HealthCheck Instance
169 : boost::scoped_ptr<MetaDataIp> ip_;
170 : // current status of HealthCheckInstance
171 : bool active_;
172 : // last update time
173 : std::string last_update_time_;
174 : // instance is delete marked
175 : bool deleted_;
176 : // true if the health check up or down status event has to be ignored
177 : bool ignore_status_event_;
178 :
179 : // source IP to be used while doing the health check
180 : IpAddress source_ip_;
181 : // destination IP for the health check
182 : IpAddress destination_ip_;
183 :
184 : private:
185 : DISALLOW_COPY_AND_ASSIGN(HealthCheckInstanceBase);
186 : };
187 :
188 : // Health check instance using the instance task infrastructure
189 : class HealthCheckInstanceTask : public HealthCheckInstanceBase {
190 : public:
191 : typedef InstanceTaskExecvp HeathCheckProcessInstance;
192 : static const std::string kHealthCheckCmd;
193 :
194 : HealthCheckInstanceTask(HealthCheckService *service,
195 : MetaDataIpAllocator *allocator, VmInterface *intf,
196 : bool ignore_status_event);
197 : virtual ~HealthCheckInstanceTask();
198 :
199 : virtual bool CreateInstanceTask();
200 : virtual bool DestroyInstanceTask();
201 : virtual bool RunInstanceTask();
202 : virtual bool StopInstanceTask();
203 : virtual bool IsRunning() const;
204 :
205 : private:
206 : friend class HealthCheckTable;
207 :
208 : void UpdateInstanceTaskCommand();
209 :
210 : // task managing external running script for status
211 : boost::scoped_ptr<HeathCheckProcessInstance> task_;
212 :
213 : DISALLOW_COPY_AND_ASSIGN(HealthCheckInstanceTask);
214 : };
215 :
216 : // Health check instance using the services infrastructure
217 : class HealthCheckInstanceService : public HealthCheckInstanceBase {
218 : public:
219 : HealthCheckInstanceService(HealthCheckService *service,
220 : MetaDataIpAllocator *allocator,
221 : VmInterface *intf, VmInterface *other_intf,
222 : bool ignore_status_event, bool multi_hop);
223 : virtual ~HealthCheckInstanceService();
224 :
225 : virtual bool CreateInstanceTask();
226 : virtual bool DestroyInstanceTask();
227 : virtual bool RunInstanceTask();
228 : virtual bool StopInstanceTask();
229 : virtual bool UpdateInstanceTask();
230 : virtual void ResyncTarget(const HealthCheckService *service) const;
231 : void EnqueueMacIpLearningHCStatus(const HealthCheckService *service) const;
232 :
233 0 : bool is_multi_hop() const { return multi_hop_; }
234 :
235 : private:
236 : friend class HealthCheckTable;
237 :
238 : // Other Interface associated to this HealthCheck Instance when
239 : // HealthCheck service type is "segment"
240 : InterfaceRef other_intf_;
241 :
242 : // BFD health check can be single hop or multi hop, when started for a
243 : // BGP flow, make it multi hop
244 : bool multi_hop_;
245 :
246 : DISALLOW_COPY_AND_ASSIGN(HealthCheckInstanceService);
247 : };
248 :
249 : class HealthCheckMacIpInstanceService : public HealthCheckInstanceService {
250 : public:
251 : HealthCheckMacIpInstanceService(HealthCheckService *service,
252 : MetaDataIpAllocator *allocator,
253 : VmInterface *intf, VmInterface *other_intf,
254 : bool ignore_status_event, bool multi_hop);
255 : virtual ~HealthCheckMacIpInstanceService();
256 :
257 : virtual void ResyncTarget(const HealthCheckService *service) const;
258 0 : virtual void set_destination_mac(const MacAddress &mac) {
259 0 : mac_ = mac;
260 0 : }
261 0 : virtual const MacAddress destination_mac() const { return mac_; }
262 :
263 : private:
264 : friend class HealthCheckTable;
265 :
266 : MacAddress mac_;
267 :
268 : DISALLOW_COPY_AND_ASSIGN(HealthCheckMacIpInstanceService);
269 : };
270 :
271 : class HealthCheckService : AgentRefCount<HealthCheckService>,
272 : public AgentOperDBEntry {
273 : public:
274 : enum HealthCheckType {
275 : PING,
276 : HTTP,
277 : BFD,
278 : SEGMENT,
279 : MAX_HEALTH_CHECK_SERVICES
280 : };
281 : typedef std::map<boost::uuids::uuid, HealthCheckInstanceBase *> InstanceList;
282 : typedef std::map<IpAddress, HealthCheckInstanceBase *> IpInstanceList;
283 :
284 : HealthCheckService(const HealthCheckTable *table,
285 : const boost::uuids::uuid &id);
286 : ~HealthCheckService();
287 :
288 : virtual bool IsLess(const DBEntry &rhs) const;
289 : virtual std::string ToString() const;
290 : virtual KeyPtr GetDBRequestKey() const;
291 : virtual void SetKey(const DBRequestKey *key);
292 0 : uint32_t GetRefCount() const {
293 0 : return AgentRefCount<HealthCheckService>::GetRefCount();
294 : }
295 :
296 : bool DBEntrySandesh(Sandesh *resp, std::string &name) const;
297 :
298 : void PostAdd();
299 : bool Copy(HealthCheckTable *table, const HealthCheckServiceData *data);
300 :
301 : HealthCheckInstanceBase *StartHealthCheckService(VmInterface *intrface,
302 : VmInterface *paired_vmi,
303 : const IpAddress &source_ip,
304 : const IpAddress &destination_ip,
305 : const MacAddress &destination_mac,
306 : bool ignore_status_event,
307 : bool multi_hop);
308 0 : HealthCheckInstanceBase *StartHealthCheckService(
309 : VmInterface *intrface, const IpAddress &source_ip,
310 : const IpAddress &destination_ip,
311 : const MacAddress destination_mac = MacAddress()) {
312 : // health check status event is ignored
313 0 : return StartHealthCheckService(intrface, NULL, source_ip,
314 : destination_ip, destination_mac,
315 0 : true, true);
316 : }
317 : void StopHealthCheckService(HealthCheckInstanceBase *instance);
318 :
319 : void UpdateInstanceServiceReference();
320 : void ResyncHealthCheckInterface(const HealthCheckService *service,
321 : const VmInterface *intf);
322 : void UpdateInterfaceInstanceServiceReference(const VmInterface *intf);
323 : void DeleteInstances();
324 :
325 0 : const boost::uuids::uuid &uuid() const { return uuid_; }
326 0 : const std::string &name() const { return name_; }
327 :
328 : uint8_t ip_proto() const { return ip_proto_; }
329 2 : uint16_t url_port() const { return url_port_; }
330 0 : uint32_t delay() const { return delay_; }
331 0 : uint64_t delay_usecs() const { return delay_usecs_; }
332 0 : uint32_t timeout() const { return timeout_; }
333 0 : uint64_t timeout_usecs() const { return timeout_usecs_; }
334 0 : uint32_t max_retries() const { return max_retries_; }
335 0 : const std::string &url_path() const { return url_path_; }
336 0 : const std::string &monitor_type() const { return monitor_type_; }
337 0 : const HealthCheckTable *table() const { return table_; }
338 : bool IsInstanceTaskBased() const;
339 : bool IsSegmentHealthCheckService() const;
340 : bool IsVnIpListHealthCheckService() const;
341 0 : HealthCheckType health_check_type() const {
342 0 : return health_check_type_;
343 : }
344 0 : const std::set<boost::uuids::uuid> &GetVnUuidList() {
345 0 : return vn_uuid_list_;
346 : }
347 0 : const std::set<IpAddress> &GetTargetIpList() {
348 0 : return target_ip_list_;
349 : }
350 0 : bool IsTargetIpPresent(IpAddress &ip) {
351 :
352 0 : if (is_hc_enable_all_ip_ ||
353 0 : target_ip_list_.find(ip) != target_ip_list_.end()) {
354 0 : return true;
355 : }
356 0 : return false;
357 : }
358 1 : IpAddress dest_ip() const { return dest_ip_;}
359 0 : bool IsHcEnableAllTargetIp() const {return is_hc_enable_all_ip_;}
360 :
361 : private:
362 : friend struct HealthCheckInstanceEvent;
363 :
364 : HealthCheckType GetHealthCheckType() const;
365 :
366 : const HealthCheckTable *table_;
367 : boost::uuids::uuid uuid_;
368 : IpAddress dest_ip_;
369 : std::string name_;
370 : // monitor type of service PING/HTTP/BFD etc
371 : std::string monitor_type_;
372 : // Service type of HealthCheck segment/end-to-end/link-local
373 : std::string service_type_;
374 : // ip_proto derived from monitor_type_
375 : uint8_t ip_proto_;
376 : std::string http_method_;
377 : std::string url_path_;
378 : // tcp/udp port numbers derived from url
379 : uint16_t url_port_;
380 : std::string expected_codes_;
381 : uint32_t delay_;
382 : uint64_t delay_usecs_;
383 : uint32_t timeout_;
384 : uint64_t timeout_usecs_;
385 : uint32_t max_retries_;
386 : // List of interfaces associated to this HealthCheck Service
387 : InstanceList intf_list_;
388 : HealthCheckType health_check_type_;
389 :
390 : std::set<boost::uuids::uuid> vn_uuid_list_;
391 : std::set<IpAddress> target_ip_list_;
392 : bool is_hc_enable_all_ip_;
393 :
394 : DISALLOW_COPY_AND_ASSIGN(HealthCheckService);
395 : };
396 :
397 : class HealthCheckTable : public AgentOperDBTable {
398 : public:
399 : enum HealthCheckServiceAction {
400 : CREATE_SERVICE,
401 : DELETE_SERVICE,
402 : RUN_SERVICE,
403 : STOP_SERVICE,
404 : UPDATE_SERVICE
405 : };
406 : typedef boost::function<bool(HealthCheckServiceAction,
407 : HealthCheckInstanceService *)>
408 : HealthCheckServiceCallback;
409 :
410 : typedef boost::function<void(const HealthCheckInstanceService *)>
411 : HealthCheckNotifyCallback;
412 :
413 : HealthCheckTable(Agent *agent, DB *db, const std::string &name);
414 : virtual ~HealthCheckTable();
415 :
416 : static DBTableBase *CreateTable(Agent *agent, DB *db,
417 : const std::string &name);
418 :
419 : virtual std::unique_ptr<DBEntry> AllocEntry(const DBRequestKey *k) const;
420 0 : virtual size_t Hash(const DBEntry *entry) const {return 0;}
421 0 : virtual size_t Hash(const DBRequestKey *key) const {return 0;}
422 :
423 : virtual DBEntry *OperDBAdd(const DBRequest *req);
424 : virtual bool OperDBOnChange(DBEntry *entry, const DBRequest *req);
425 : virtual bool OperDBResync(DBEntry *entry, const DBRequest *req);
426 : virtual bool OperDBDelete(DBEntry *entry, const DBRequest *req);
427 :
428 : virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req,
429 : const boost::uuids::uuid &u);
430 : bool ProcessConfig(IFMapNode *node, DBRequest &req,
431 : const boost::uuids::uuid &u);
432 : virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u);
433 : virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args,
434 : const std::string &context);
435 :
436 : HealthCheckService *Find(const boost::uuids::uuid &u);
437 :
438 : void InstanceEventEnqueue(HealthCheckInstanceEvent *event) const;
439 : bool InstanceEventProcess(HealthCheckInstanceEvent *event);
440 :
441 4 : void RegisterHealthCheckCallback(HealthCheckServiceCallback fn,
442 : HealthCheckService::HealthCheckType type) {
443 4 : health_check_service_cb_[type] = fn;
444 4 : }
445 0 : HealthCheckServiceCallback health_check_service_callback(
446 : HealthCheckService::HealthCheckType type) const {
447 0 : return health_check_service_cb_[type];
448 : }
449 2 : void RegisterHealthCheckNotifyCallback(HealthCheckNotifyCallback fn) {
450 2 : health_check_notify_cb_ = fn;
451 2 : }
452 0 : HealthCheckNotifyCallback health_check_notify_callback() const {
453 0 : return health_check_notify_cb_;
454 : }
455 :
456 : private:
457 :
458 : WorkQueue<HealthCheckInstanceEvent *> *inst_event_queue_;
459 : HealthCheckServiceCallback health_check_service_cb_[HealthCheckService::MAX_HEALTH_CHECK_SERVICES];
460 : HealthCheckNotifyCallback health_check_notify_cb_;
461 : DISALLOW_COPY_AND_ASSIGN(HealthCheckTable);
462 : };
463 :
464 : struct HealthCheckResyncInterfaceData : public AgentOperDBData {
465 0 : HealthCheckResyncInterfaceData(const Agent *agent, IFMapNode *node,
466 0 : const VmInterface *intf):
467 0 : AgentOperDBData(agent, node), intf_(intf) {}
468 : const VmInterface *intf_;
469 : };
470 :
471 : #endif // SRC_VNSW_AGENT_SERVICES_HEALTH_CHECK_H_
|