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