Line data Source code
1 : /*
2 : * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef __AGENT_PKT_FLOW_MGMT_KEY_H__
6 : #define __AGENT_PKT_FLOW_MGMT_KEY_H__
7 :
8 : #include <db/db_entry.h>
9 : #include <pkt/flow_event.h>
10 :
11 : class FlowMgmtKey {
12 : public:
13 : enum Type {
14 : INVALID,
15 : INTERFACE,
16 : ACL,
17 : ACE_ID,
18 : VN,
19 : VM,
20 : INET4,
21 : INET6,
22 : BRIDGE,
23 : NH,
24 : VRF,
25 : BGPASASERVICE,
26 : END
27 : };
28 :
29 757 : FlowMgmtKey(Type type, const DBEntry *db_entry) :
30 757 : type_(type), db_entry_(db_entry) {
31 757 : }
32 :
33 757 : virtual ~FlowMgmtKey() { }
34 :
35 : // Clone the key
36 : virtual FlowMgmtKey *Clone() = 0;
37 :
38 : // Convert from FlowMgmtKey to FlowEvent
39 20 : virtual void KeyToFlowRequest(FlowEvent *req) {
40 20 : req->set_db_entry(db_entry_);
41 20 : }
42 :
43 : // Is DBEntry used as key. Routes dont use DBEntry as key
44 1862 : virtual bool UseDBEntry() const { return true; }
45 :
46 : // Comparator
47 610 : virtual bool Compare(const FlowMgmtKey *rhs) const {
48 610 : return false;
49 : }
50 :
51 4406 : bool IsLess(const FlowMgmtKey *rhs) const {
52 4406 : if (type_ != rhs->type_)
53 417 : return type_ < rhs->type_;
54 :
55 3989 : if (UseDBEntry()) {
56 1862 : if (db_entry_ != rhs->db_entry_)
57 1252 : return db_entry_ < rhs->db_entry_;
58 : }
59 :
60 2737 : return Compare(rhs);
61 : }
62 :
63 : FlowEvent::Event FreeDBEntryEvent() const;
64 132 : Type type() const { return type_; }
65 670 : const DBEntry *db_entry() const { return db_entry_; }
66 44 : void set_db_entry(const DBEntry *db_entry) { db_entry_ = db_entry; }
67 :
68 : protected:
69 : Type type_;
70 : mutable const DBEntry *db_entry_;
71 :
72 : private:
73 : DISALLOW_COPY_AND_ASSIGN(FlowMgmtKey);
74 : };
75 :
76 : struct FlowMgmtKeyCmp {
77 4406 : bool operator()(const FlowMgmtKey *l, const FlowMgmtKey *r) const {
78 4406 : return l->IsLess(r);
79 : }
80 : };
81 :
82 : class AclFlowMgmtKey : public FlowMgmtKey {
83 : public:
84 26 : AclFlowMgmtKey(const AclDBEntry *acl, const AclEntryIDList *ace_id_list) :
85 26 : FlowMgmtKey(FlowMgmtKey::ACL, acl) {
86 26 : if (ace_id_list) {
87 22 : ace_id_list_ = *ace_id_list;
88 : }
89 26 : }
90 :
91 48 : virtual ~AclFlowMgmtKey() { }
92 :
93 8 : virtual FlowMgmtKey *Clone() {
94 8 : return new AclFlowMgmtKey(static_cast<const AclDBEntry *>(db_entry()),
95 8 : &ace_id_list_);
96 : }
97 :
98 12 : const AclEntryIDList *ace_id_list() const { return &ace_id_list_; }
99 :
100 0 : void set_ace_id_list(const AclEntryIDList *list) {
101 0 : ace_id_list_ = *list;
102 0 : }
103 :
104 : private:
105 : AclEntryIDList ace_id_list_;
106 : DISALLOW_COPY_AND_ASSIGN(AclFlowMgmtKey);
107 : };
108 :
109 : class VnFlowMgmtKey : public FlowMgmtKey {
110 : public:
111 32 : VnFlowMgmtKey(const VnEntry *vn) : FlowMgmtKey(FlowMgmtKey::VN, vn) { }
112 58 : virtual ~VnFlowMgmtKey() { }
113 :
114 14 : virtual FlowMgmtKey *Clone() {
115 14 : return new VnFlowMgmtKey(static_cast<const VnEntry *>(db_entry()));
116 : }
117 :
118 : private:
119 : DISALLOW_COPY_AND_ASSIGN(VnFlowMgmtKey);
120 : };
121 :
122 : class InterfaceFlowMgmtKey : public FlowMgmtKey {
123 : public:
124 51 : InterfaceFlowMgmtKey(const Interface *intf) :
125 51 : FlowMgmtKey(FlowMgmtKey::INTERFACE, intf) {
126 51 : }
127 :
128 84 : virtual ~InterfaceFlowMgmtKey() { }
129 :
130 21 : virtual FlowMgmtKey *Clone() {
131 21 : return new InterfaceFlowMgmtKey(static_cast<const Interface *>(db_entry()));
132 : }
133 :
134 : private:
135 : DISALLOW_COPY_AND_ASSIGN(InterfaceFlowMgmtKey);
136 : };
137 :
138 : class NhFlowMgmtKey : public FlowMgmtKey {
139 : public:
140 180 : NhFlowMgmtKey(const NextHop *nh) : FlowMgmtKey(FlowMgmtKey::NH, nh) { }
141 256 : virtual ~NhFlowMgmtKey() { }
142 :
143 64 : virtual FlowMgmtKey *Clone() {
144 64 : return new NhFlowMgmtKey(static_cast<const NextHop *>(db_entry()));
145 : }
146 :
147 : private:
148 : DISALLOW_COPY_AND_ASSIGN(NhFlowMgmtKey);
149 : };
150 :
151 : class RouteFlowMgmtKey : public FlowMgmtKey {
152 : public:
153 306 : static Type AddrToType(const IpAddress &addr) {
154 306 : if (addr.is_v4())
155 262 : return INET4;
156 :
157 44 : if (addr.is_v6())
158 44 : return INET6;
159 :
160 0 : assert(0);
161 : return INVALID;
162 : }
163 :
164 : static Type RouteToType(const AgentRoute *rt) {
165 : const InetUnicastRouteEntry *inet_rt =
166 : dynamic_cast<const InetUnicastRouteEntry *>(rt);
167 : if (inet_rt) {
168 : return AddrToType(inet_rt->prefix_address());
169 : }
170 :
171 : if (dynamic_cast<const BridgeRouteEntry *>(rt))
172 : return BRIDGE;
173 :
174 : assert(0);
175 : }
176 :
177 242 : RouteFlowMgmtKey(Type type, uint32_t vrf_id) :
178 242 : FlowMgmtKey(type, NULL), vrf_id_(vrf_id) {
179 242 : }
180 :
181 133 : RouteFlowMgmtKey(Type type, const AgentRoute *rt, uint32_t vrf_id) :
182 133 : FlowMgmtKey(type, rt), vrf_id_(vrf_id) {
183 133 : }
184 :
185 375 : virtual ~RouteFlowMgmtKey() { }
186 :
187 2127 : virtual bool UseDBEntry() const { return false; }
188 84 : uint32_t vrf_id() const { return vrf_id_; }
189 :
190 : protected:
191 : uint32_t vrf_id_;
192 :
193 : private:
194 : DISALLOW_COPY_AND_ASSIGN(RouteFlowMgmtKey);
195 : };
196 :
197 : class InetRouteFlowMgmtKey : public RouteFlowMgmtKey {
198 : public:
199 84 : InetRouteFlowMgmtKey(const InetUnicastRouteEntry *route) :
200 168 : RouteFlowMgmtKey(AddrToType(route->prefix_address()), route, route->vrf_id()),
201 84 : ip_(route->prefix_address()), plen_(route->prefix_length()) {
202 84 : }
203 :
204 222 : InetRouteFlowMgmtKey(uint32_t vrf_id, const IpAddress &ip, uint8_t plen) :
205 222 : RouteFlowMgmtKey(AddrToType(ip), vrf_id), ip_(ip), plen_(plen) {
206 222 : }
207 :
208 462 : virtual ~InetRouteFlowMgmtKey() { }
209 :
210 1596 : virtual bool Compare(const FlowMgmtKey *rhs) const {
211 1596 : const InetRouteFlowMgmtKey *rhs_key =
212 : static_cast<const InetRouteFlowMgmtKey *>(rhs);
213 1596 : if (vrf_id_ != rhs_key->vrf_id_)
214 401 : return vrf_id_ < rhs_key->vrf_id_;
215 :
216 1195 : if (ip_ != rhs_key->ip_)
217 599 : return ip_ < rhs_key->ip_;
218 :
219 596 : return plen_ < rhs_key->plen_;
220 : }
221 :
222 : class KeyCmp {
223 : public:
224 3153 : static std::size_t BitLength(const InetRouteFlowMgmtKey *rt) {
225 : return (((sizeof(rt->vrf_id_) + sizeof(rt->type_)) << 3) +
226 3153 : rt->plen_);
227 : }
228 :
229 5524 : static char ByteValue(const InetRouteFlowMgmtKey *rt, std::size_t idx) {
230 : const char *ch;
231 5524 : std::size_t i = idx;
232 5524 : if (i < sizeof(rt->vrf_id_)) {
233 1520 : ch = (const char *)&rt->vrf_id_;
234 1520 : return ch[sizeof(rt->vrf_id_) - i - 1];
235 : }
236 4004 : i -= sizeof(rt->vrf_id_);
237 4004 : if (i < sizeof(rt->type_)) {
238 1264 : ch = (const char *)&rt->type_;
239 1264 : return ch[sizeof(rt->type_) - i - 1];
240 : }
241 2740 : i -= sizeof(rt->type_);
242 2740 : if (rt->type_ == INET4) {
243 1798 : return rt->ip_.to_v4().to_bytes()[i];
244 942 : } else if (rt->type_ == INET6) {
245 942 : return rt->ip_.to_v6().to_bytes()[i];
246 : } else {
247 0 : assert(0);
248 : return 0;
249 : }
250 : }
251 : };
252 :
253 108 : FlowMgmtKey *Clone() {
254 108 : if (ip_.is_v4()) {
255 93 : return new InetRouteFlowMgmtKey(vrf_id_, ip_.to_v4(), plen_);
256 : }
257 :
258 15 : if (ip_.is_v6()) {
259 15 : return new InetRouteFlowMgmtKey(vrf_id_, ip_.to_v6(), plen_);
260 : }
261 :
262 0 : return NULL;
263 : }
264 :
265 0 : bool Match(const IpAddress &match_ip) const {
266 0 : if (ip_.is_v4()) {
267 0 : return (Address::GetIp4SubnetAddress(ip_.to_v4(), plen_) ==
268 0 : Address::GetIp4SubnetAddress(match_ip.to_v4(), plen_));
269 0 : } else if (ip_.is_v6()) {
270 0 : return (Address::GetIp6SubnetAddress(ip_.to_v6(), plen_) ==
271 0 : Address::GetIp6SubnetAddress(match_ip.to_v6(), plen_));
272 : }
273 :
274 0 : assert(0);
275 : return false;
276 : }
277 :
278 : bool NeedsReCompute(const FlowEntry *flow);
279 0 : IpAddress ip() const { return ip_; }
280 0 : uint8_t plen() const { return plen_; }
281 :
282 : private:
283 : friend class InetRouteFlowMgmtTree;
284 :
285 : IpAddress ip_;
286 : uint8_t plen_;
287 : Patricia::Node node_;
288 : DISALLOW_COPY_AND_ASSIGN(InetRouteFlowMgmtKey);
289 : };
290 :
291 : class BridgeRouteFlowMgmtKey : public RouteFlowMgmtKey {
292 : public:
293 49 : BridgeRouteFlowMgmtKey(const BridgeRouteEntry *rt) :
294 49 : RouteFlowMgmtKey(BRIDGE, rt, rt->vrf_id()), mac_(rt->prefix_address()) {
295 49 : }
296 :
297 20 : BridgeRouteFlowMgmtKey(uint32_t vrf_id, const MacAddress &mac) :
298 20 : RouteFlowMgmtKey(BRIDGE, vrf_id), mac_(mac) {
299 20 : }
300 :
301 85 : virtual ~BridgeRouteFlowMgmtKey() { }
302 :
303 531 : virtual bool Compare(const FlowMgmtKey *rhs) const {
304 531 : const BridgeRouteFlowMgmtKey *rhs_key =
305 : static_cast<const BridgeRouteFlowMgmtKey *>(rhs);
306 531 : if (vrf_id_ != rhs_key->vrf_id_)
307 156 : return vrf_id_ < rhs_key->vrf_id_;
308 :
309 375 : return mac_ < rhs_key->mac_;
310 : }
311 :
312 16 : FlowMgmtKey *Clone() {
313 16 : return new BridgeRouteFlowMgmtKey(vrf_id(), mac_);
314 : }
315 :
316 : private:
317 : friend class BridgeRouteFlowMgmtTree;
318 :
319 : MacAddress mac_;
320 : DISALLOW_COPY_AND_ASSIGN(BridgeRouteFlowMgmtKey);
321 : };
322 :
323 : class VrfFlowMgmtKey : public FlowMgmtKey {
324 : public:
325 93 : VrfFlowMgmtKey(const VrfEntry *vrf) :
326 93 : FlowMgmtKey(FlowMgmtKey::VRF, vrf) {
327 93 : }
328 :
329 97 : virtual ~VrfFlowMgmtKey() { }
330 :
331 4 : virtual FlowMgmtKey *Clone() {
332 4 : return new VrfFlowMgmtKey(static_cast<const VrfEntry *>(db_entry()));
333 : }
334 :
335 : private:
336 : DISALLOW_COPY_AND_ASSIGN(VrfFlowMgmtKey);
337 : };
338 :
339 : class BgpAsAServiceFlowMgmtKey : public FlowMgmtKey {
340 : public:
341 0 : BgpAsAServiceFlowMgmtKey(const boost::uuids::uuid &uuid,
342 : uint32_t source_port,
343 : uint8_t cn_index,
344 : HealthCheckInstanceBase *hc_instance,
345 0 : HealthCheckService *hc_service) :
346 0 : FlowMgmtKey(FlowMgmtKey::BGPASASERVICE, NULL), uuid_(uuid),
347 0 : source_port_(source_port), cn_index_(cn_index),
348 0 : bgp_health_check_instance_(hc_instance),
349 0 : bgp_health_check_service_(hc_service) { }
350 :
351 0 : virtual ~BgpAsAServiceFlowMgmtKey() { }
352 :
353 0 : virtual FlowMgmtKey *Clone() {
354 0 : return new BgpAsAServiceFlowMgmtKey(uuid_, source_port_, cn_index_,
355 : bgp_health_check_instance_,
356 0 : bgp_health_check_service_);
357 : }
358 :
359 0 : virtual bool UseDBEntry() const { return false; }
360 :
361 0 : virtual bool Compare(const FlowMgmtKey *rhs) const {
362 0 : const BgpAsAServiceFlowMgmtKey *rhs_key =
363 : static_cast<const BgpAsAServiceFlowMgmtKey *>(rhs);
364 0 : if (uuid_ != rhs_key->uuid_)
365 0 : return uuid_ < rhs_key->uuid_;
366 0 : if (cn_index_ != rhs_key->cn_index_)
367 0 : return cn_index_< rhs_key->cn_index_;
368 0 : return source_port_ < rhs_key->source_port_;
369 : }
370 :
371 0 : const boost::uuids::uuid &uuid() const { return uuid_; }
372 0 : uint32_t source_port() const { return source_port_; }
373 0 : uint8_t cn_index() const { return cn_index_; }
374 :
375 : HealthCheckInstanceBase *bgp_health_check_instance() const {
376 : return bgp_health_check_instance_;
377 : }
378 :
379 : void StartHealthCheck(Agent *agent, FlowEntry *flow,
380 : const boost::uuids::uuid &hc_uuid);
381 : void StopHealthCheck(FlowEntry *flow);
382 :
383 : private:
384 : boost::uuids::uuid uuid_;
385 : uint32_t source_port_;
386 : uint8_t cn_index_; //Control node index
387 : // By adding the health check instance here, we ensure one BFD session
388 : // per <VMI-SRC-IP, BGP-DEST-IP, VMI>
389 : mutable HealthCheckInstanceBase *bgp_health_check_instance_;
390 : mutable HealthCheckService *bgp_health_check_service_;
391 : DISALLOW_COPY_AND_ASSIGN(BgpAsAServiceFlowMgmtKey);
392 : };
393 :
394 : #endif // __AGENT_PKT_FLOW_MGMT_KEY_H__
|