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 2944 : FlowMgmtKey(Type type, const DBEntry *db_entry) :
30 2944 : type_(type), db_entry_(db_entry) {
31 2944 : }
32 :
33 2944 : virtual ~FlowMgmtKey() { }
34 :
35 : // Clone the key
36 : virtual FlowMgmtKey *Clone() = 0;
37 :
38 : // Convert from FlowMgmtKey to FlowEvent
39 144 : virtual void KeyToFlowRequest(FlowEvent *req) {
40 144 : req->set_db_entry(db_entry_);
41 144 : }
42 :
43 : // Is DBEntry used as key. Routes dont use DBEntry as key
44 7553 : virtual bool UseDBEntry() const { return true; }
45 :
46 : // Comparator
47 3138 : virtual bool Compare(const FlowMgmtKey *rhs) const {
48 3138 : return false;
49 : }
50 :
51 17626 : bool IsLess(const FlowMgmtKey *rhs) const {
52 17626 : if (type_ != rhs->type_)
53 2958 : return type_ < rhs->type_;
54 :
55 14668 : if (UseDBEntry()) {
56 7553 : if (db_entry_ != rhs->db_entry_)
57 4415 : return db_entry_ < rhs->db_entry_;
58 : }
59 :
60 10253 : return Compare(rhs);
61 : }
62 :
63 : FlowEvent::Event FreeDBEntryEvent() const;
64 970 : Type type() const { return type_; }
65 2320 : const DBEntry *db_entry() const { return db_entry_; }
66 131 : 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 17036 : bool operator()(const FlowMgmtKey *l, const FlowMgmtKey *r) const {
78 17036 : return l->IsLess(r);
79 : }
80 : };
81 :
82 : class AclFlowMgmtKey : public FlowMgmtKey {
83 : public:
84 78 : AclFlowMgmtKey(const AclDBEntry *acl, const AclEntryIDList *ace_id_list) :
85 78 : FlowMgmtKey(FlowMgmtKey::ACL, acl) {
86 78 : if (ace_id_list) {
87 68 : ace_id_list_ = *ace_id_list;
88 : }
89 78 : }
90 :
91 146 : virtual ~AclFlowMgmtKey() { }
92 :
93 36 : virtual FlowMgmtKey *Clone() {
94 36 : return new AclFlowMgmtKey(static_cast<const AclDBEntry *>(db_entry()),
95 36 : &ace_id_list_);
96 : }
97 :
98 89 : const AclEntryIDList *ace_id_list() const { return &ace_id_list_; }
99 :
100 25 : void set_ace_id_list(const AclEntryIDList *list) {
101 25 : ace_id_list_ = *list;
102 25 : }
103 :
104 : private:
105 : AclEntryIDList ace_id_list_;
106 : DISALLOW_COPY_AND_ASSIGN(AclFlowMgmtKey);
107 : };
108 :
109 : class VnFlowMgmtKey : public FlowMgmtKey {
110 : public:
111 218 : VnFlowMgmtKey(const VnEntry *vn) : FlowMgmtKey(FlowMgmtKey::VN, vn) { }
112 424 : virtual ~VnFlowMgmtKey() { }
113 :
114 106 : virtual FlowMgmtKey *Clone() {
115 106 : 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 303 : InterfaceFlowMgmtKey(const Interface *intf) :
125 303 : FlowMgmtKey(FlowMgmtKey::INTERFACE, intf) {
126 303 : }
127 :
128 534 : virtual ~InterfaceFlowMgmtKey() { }
129 :
130 131 : virtual FlowMgmtKey *Clone() {
131 131 : 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 660 : NhFlowMgmtKey(const NextHop *nh) : FlowMgmtKey(FlowMgmtKey::NH, nh) { }
141 1000 : virtual ~NhFlowMgmtKey() { }
142 :
143 250 : virtual FlowMgmtKey *Clone() {
144 250 : 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 988 : static Type AddrToType(const IpAddress &addr) {
154 988 : if (addr.is_v4())
155 784 : return INET4;
156 :
157 204 : if (addr.is_v6())
158 204 : 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 990 : RouteFlowMgmtKey(Type type, uint32_t vrf_id) :
178 990 : FlowMgmtKey(type, NULL), vrf_id_(vrf_id) {
179 990 : }
180 :
181 417 : RouteFlowMgmtKey(Type type, const AgentRoute *rt, uint32_t vrf_id) :
182 417 : FlowMgmtKey(type, rt), vrf_id_(vrf_id) {
183 417 : }
184 :
185 1407 : virtual ~RouteFlowMgmtKey() { }
186 :
187 7115 : virtual bool UseDBEntry() const { return false; }
188 317 : 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 248 : InetRouteFlowMgmtKey(const InetUnicastRouteEntry *route) :
200 496 : RouteFlowMgmtKey(AddrToType(route->prefix_address()), route, route->vrf_id()),
201 248 : ip_(route->prefix_address()), plen_(route->prefix_length()) {
202 248 : }
203 :
204 740 : InetRouteFlowMgmtKey(uint32_t vrf_id, const IpAddress &ip, uint8_t plen) :
205 740 : RouteFlowMgmtKey(AddrToType(ip), vrf_id), ip_(ip), plen_(plen) {
206 740 : }
207 :
208 1536 : virtual ~InetRouteFlowMgmtKey() { }
209 :
210 4482 : virtual bool Compare(const FlowMgmtKey *rhs) const {
211 4482 : const InetRouteFlowMgmtKey *rhs_key =
212 : static_cast<const InetRouteFlowMgmtKey *>(rhs);
213 4482 : if (vrf_id_ != rhs_key->vrf_id_)
214 1256 : return vrf_id_ < rhs_key->vrf_id_;
215 :
216 3226 : if (ip_ != rhs_key->ip_)
217 1302 : return ip_ < rhs_key->ip_;
218 :
219 1924 : return plen_ < rhs_key->plen_;
220 : }
221 :
222 : class KeyCmp {
223 : public:
224 8854 : static std::size_t BitLength(const InetRouteFlowMgmtKey *rt) {
225 : return (((sizeof(rt->vrf_id_) + sizeof(rt->type_)) << 3) +
226 8854 : rt->plen_);
227 : }
228 :
229 17051 : static char ByteValue(const InetRouteFlowMgmtKey *rt, std::size_t idx) {
230 : const char *ch;
231 17051 : std::size_t i = idx;
232 17051 : if (i < sizeof(rt->vrf_id_)) {
233 4498 : ch = (const char *)&rt->vrf_id_;
234 4498 : return ch[sizeof(rt->vrf_id_) - i - 1];
235 : }
236 12553 : i -= sizeof(rt->vrf_id_);
237 12553 : if (i < sizeof(rt->type_)) {
238 3608 : ch = (const char *)&rt->type_;
239 3608 : return ch[sizeof(rt->type_) - i - 1];
240 : }
241 8945 : i -= sizeof(rt->type_);
242 8945 : if (rt->type_ == INET4) {
243 4145 : return rt->ip_.to_v4().to_bytes()[i];
244 4800 : } else if (rt->type_ == INET6) {
245 4800 : return rt->ip_.to_v6().to_bytes()[i];
246 : } else {
247 0 : assert(0);
248 : return 0;
249 : }
250 : }
251 : };
252 :
253 346 : FlowMgmtKey *Clone() {
254 346 : if (ip_.is_v4()) {
255 274 : return new InetRouteFlowMgmtKey(vrf_id_, ip_.to_v4(), plen_);
256 : }
257 :
258 72 : if (ip_.is_v6()) {
259 72 : 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 169 : BridgeRouteFlowMgmtKey(const BridgeRouteEntry *rt) :
294 169 : RouteFlowMgmtKey(BRIDGE, rt, rt->vrf_id()), mac_(rt->prefix_address()) {
295 169 : }
296 :
297 250 : BridgeRouteFlowMgmtKey(uint32_t vrf_id, const MacAddress &mac) :
298 250 : RouteFlowMgmtKey(BRIDGE, vrf_id), mac_(mac) {
299 250 : }
300 :
301 657 : virtual ~BridgeRouteFlowMgmtKey() { }
302 :
303 2633 : virtual bool Compare(const FlowMgmtKey *rhs) const {
304 2633 : const BridgeRouteFlowMgmtKey *rhs_key =
305 : static_cast<const BridgeRouteFlowMgmtKey *>(rhs);
306 2633 : if (vrf_id_ != rhs_key->vrf_id_)
307 605 : return vrf_id_ < rhs_key->vrf_id_;
308 :
309 2028 : return mac_ < rhs_key->mac_;
310 : }
311 :
312 114 : FlowMgmtKey *Clone() {
313 114 : 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 278 : VrfFlowMgmtKey(const VrfEntry *vrf) :
326 278 : FlowMgmtKey(FlowMgmtKey::VRF, vrf) {
327 278 : }
328 :
329 290 : virtual ~VrfFlowMgmtKey() { }
330 :
331 12 : virtual FlowMgmtKey *Clone() {
332 12 : 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__
|