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 2793 : FlowMgmtKey(Type type, const DBEntry *db_entry) :
30 2793 : type_(type), db_entry_(db_entry) {
31 2793 : }
32 :
33 2793 : virtual ~FlowMgmtKey() { }
34 :
35 : // Clone the key
36 : virtual FlowMgmtKey *Clone() = 0;
37 :
38 : // Convert from FlowMgmtKey to FlowEvent
39 147 : virtual void KeyToFlowRequest(FlowEvent *req) {
40 147 : req->set_db_entry(db_entry_);
41 147 : }
42 :
43 : // Is DBEntry used as key. Routes dont use DBEntry as key
44 7338 : virtual bool UseDBEntry() const { return true; }
45 :
46 : // Comparator
47 3102 : virtual bool Compare(const FlowMgmtKey *rhs) const {
48 3102 : return false;
49 : }
50 :
51 17348 : bool IsLess(const FlowMgmtKey *rhs) const {
52 17348 : if (type_ != rhs->type_)
53 3041 : return type_ < rhs->type_;
54 :
55 14307 : if (UseDBEntry()) {
56 7338 : if (db_entry_ != rhs->db_entry_)
57 4236 : return db_entry_ < rhs->db_entry_;
58 : }
59 :
60 10071 : return Compare(rhs);
61 : }
62 :
63 : FlowEvent::Event FreeDBEntryEvent() const;
64 994 : Type type() const { return type_; }
65 2150 : const DBEntry *db_entry() const { return db_entry_; }
66 119 : 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 16771 : bool operator()(const FlowMgmtKey *l, const FlowMgmtKey *r) const {
78 16771 : return l->IsLess(r);
79 : }
80 : };
81 :
82 : class AclFlowMgmtKey : public FlowMgmtKey {
83 : public:
84 74 : AclFlowMgmtKey(const AclDBEntry *acl, const AclEntryIDList *ace_id_list) :
85 74 : FlowMgmtKey(FlowMgmtKey::ACL, acl) {
86 74 : if (ace_id_list) {
87 64 : ace_id_list_ = *ace_id_list;
88 : }
89 74 : }
90 :
91 138 : virtual ~AclFlowMgmtKey() { }
92 :
93 34 : virtual FlowMgmtKey *Clone() {
94 34 : return new AclFlowMgmtKey(static_cast<const AclDBEntry *>(db_entry()),
95 34 : &ace_id_list_);
96 : }
97 :
98 83 : const AclEntryIDList *ace_id_list() const { return &ace_id_list_; }
99 :
100 23 : void set_ace_id_list(const AclEntryIDList *list) {
101 23 : ace_id_list_ = *list;
102 23 : }
103 :
104 : private:
105 : AclEntryIDList ace_id_list_;
106 : DISALLOW_COPY_AND_ASSIGN(AclFlowMgmtKey);
107 : };
108 :
109 : class VnFlowMgmtKey : public FlowMgmtKey {
110 : public:
111 229 : VnFlowMgmtKey(const VnEntry *vn) : FlowMgmtKey(FlowMgmtKey::VN, vn) { }
112 444 : virtual ~VnFlowMgmtKey() { }
113 :
114 111 : virtual FlowMgmtKey *Clone() {
115 111 : 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 311 : InterfaceFlowMgmtKey(const Interface *intf) :
125 311 : FlowMgmtKey(FlowMgmtKey::INTERFACE, intf) {
126 311 : }
127 :
128 550 : virtual ~InterfaceFlowMgmtKey() { }
129 :
130 135 : virtual FlowMgmtKey *Clone() {
131 135 : 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 606 : NhFlowMgmtKey(const NextHop *nh) : FlowMgmtKey(FlowMgmtKey::NH, nh) { }
141 932 : virtual ~NhFlowMgmtKey() { }
142 :
143 233 : virtual FlowMgmtKey *Clone() {
144 233 : 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 906 : static Type AddrToType(const IpAddress &addr) {
154 906 : if (addr.is_v4())
155 689 : return INET4;
156 :
157 217 : if (addr.is_v6())
158 217 : 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 940 : RouteFlowMgmtKey(Type type, uint32_t vrf_id) :
178 940 : FlowMgmtKey(type, NULL), vrf_id_(vrf_id) {
179 940 : }
180 :
181 376 : RouteFlowMgmtKey(Type type, const AgentRoute *rt, uint32_t vrf_id) :
182 376 : FlowMgmtKey(type, rt), vrf_id_(vrf_id) {
183 376 : }
184 :
185 1316 : virtual ~RouteFlowMgmtKey() { }
186 :
187 6969 : virtual bool UseDBEntry() const { return false; }
188 311 : 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 217 : InetRouteFlowMgmtKey(const InetUnicastRouteEntry *route) :
200 434 : RouteFlowMgmtKey(AddrToType(route->prefix_address()), route, route->vrf_id()),
201 217 : ip_(route->prefix_address()), plen_(route->prefix_length()) {
202 217 : }
203 :
204 689 : InetRouteFlowMgmtKey(uint32_t vrf_id, const IpAddress &ip, uint8_t plen) :
205 689 : RouteFlowMgmtKey(AddrToType(ip), vrf_id), ip_(ip), plen_(plen) {
206 689 : }
207 :
208 1425 : virtual ~InetRouteFlowMgmtKey() { }
209 :
210 4272 : virtual bool Compare(const FlowMgmtKey *rhs) const {
211 4272 : const InetRouteFlowMgmtKey *rhs_key =
212 : static_cast<const InetRouteFlowMgmtKey *>(rhs);
213 4272 : if (vrf_id_ != rhs_key->vrf_id_)
214 1245 : return vrf_id_ < rhs_key->vrf_id_;
215 :
216 3027 : if (ip_ != rhs_key->ip_)
217 1245 : return ip_ < rhs_key->ip_;
218 :
219 1782 : return plen_ < rhs_key->plen_;
220 : }
221 :
222 : class KeyCmp {
223 : public:
224 8172 : static std::size_t BitLength(const InetRouteFlowMgmtKey *rt) {
225 : return (((sizeof(rt->vrf_id_) + sizeof(rt->type_)) << 3) +
226 8172 : rt->plen_);
227 : }
228 :
229 16399 : static char ByteValue(const InetRouteFlowMgmtKey *rt, std::size_t idx) {
230 : const char *ch;
231 16399 : std::size_t i = idx;
232 16399 : if (i < sizeof(rt->vrf_id_)) {
233 4027 : ch = (const char *)&rt->vrf_id_;
234 4027 : return ch[sizeof(rt->vrf_id_) - i - 1];
235 : }
236 12372 : i -= sizeof(rt->vrf_id_);
237 12372 : if (i < sizeof(rt->type_)) {
238 3208 : ch = (const char *)&rt->type_;
239 3208 : return ch[sizeof(rt->type_) - i - 1];
240 : }
241 9164 : i -= sizeof(rt->type_);
242 9164 : if (rt->type_ == INET4) {
243 3587 : return rt->ip_.to_v4().to_bytes()[i];
244 5577 : } else if (rt->type_ == INET6) {
245 5577 : return rt->ip_.to_v6().to_bytes()[i];
246 : } else {
247 0 : assert(0);
248 : return 0;
249 : }
250 : }
251 : };
252 :
253 315 : FlowMgmtKey *Clone() {
254 315 : if (ip_.is_v4()) {
255 237 : return new InetRouteFlowMgmtKey(vrf_id_, ip_.to_v4(), plen_);
256 : }
257 :
258 78 : if (ip_.is_v6()) {
259 78 : 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 159 : BridgeRouteFlowMgmtKey(const BridgeRouteEntry *rt) :
294 159 : RouteFlowMgmtKey(BRIDGE, rt, rt->vrf_id()), mac_(rt->prefix_address()) {
295 159 : }
296 :
297 251 : BridgeRouteFlowMgmtKey(uint32_t vrf_id, const MacAddress &mac) :
298 251 : RouteFlowMgmtKey(BRIDGE, vrf_id), mac_(mac) {
299 251 : }
300 :
301 652 : virtual ~BridgeRouteFlowMgmtKey() { }
302 :
303 2697 : virtual bool Compare(const FlowMgmtKey *rhs) const {
304 2697 : const BridgeRouteFlowMgmtKey *rhs_key =
305 : static_cast<const BridgeRouteFlowMgmtKey *>(rhs);
306 2697 : if (vrf_id_ != rhs_key->vrf_id_)
307 646 : return vrf_id_ < rhs_key->vrf_id_;
308 :
309 2051 : 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 257 : VrfFlowMgmtKey(const VrfEntry *vrf) :
326 257 : FlowMgmtKey(FlowMgmtKey::VRF, vrf) {
327 257 : }
328 :
329 266 : virtual ~VrfFlowMgmtKey() { }
330 :
331 9 : virtual FlowMgmtKey *Clone() {
332 9 : 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__
|