Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #ifndef vnsw_agent_route_hpp
7 : #define vnsw_agent_route_hpp
8 :
9 : #include <sys/types.h>
10 : #include <sys/socket.h>
11 : #include <net/ethernet.h>
12 :
13 : #include <base/address.h>
14 : #include <base/lifetime.h>
15 : #include <base/patricia.h>
16 : #include <base/task_annotations.h>
17 :
18 : #include <cmn/agent_cmn.h>
19 : #include <cmn/agent.h>
20 : #include <agent_types.h>
21 : #include <route/route.h>
22 : #include <route/table.h>
23 :
24 : #include <oper/interface_common.h>
25 : #include <oper/nexthop.h>
26 : #include <oper/peer.h>
27 : #include <oper/agent_types.h>
28 : #include <oper/multicast.h>
29 : #include <sandesh/sandesh_trace.h>
30 :
31 : class AgentRoute;
32 : class AgentPath;
33 : class Peer;
34 : class EcmpData;
35 :
36 : struct AgentRouteKey : public AgentKey {
37 20570 : AgentRouteKey(const Peer *peer, const std::string &vrf_name) :
38 20570 : AgentKey(), peer_(peer), vrf_name_(vrf_name) { }
39 20570 : virtual ~AgentRouteKey() { }
40 :
41 : virtual Agent::RouteTableType GetRouteTableType() = 0;
42 : virtual std::string ToString() const = 0;
43 : virtual AgentRoute *AllocRouteEntry(VrfEntry *vrf,
44 : bool is_multicast) const = 0;
45 : virtual AgentRouteKey *Clone() const = 0;
46 :
47 40176 : const std::string &vrf_name() const { return vrf_name_; }
48 67900 : const Peer *peer() const { return peer_.get(); }
49 2011 : void set_peer(const Peer *peer) {peer_ = peer;}
50 :
51 : PeerConstPtr peer_;
52 : std::string vrf_name_;
53 : DISALLOW_COPY_AND_ASSIGN(AgentRouteKey);
54 : };
55 :
56 : struct AgentRouteData : public AgentData {
57 : enum Type {
58 : ADD_DEL_CHANGE,
59 : ROUTE_PREFERENCE_CHANGE,
60 : IPAM_SUBNET,
61 : };
62 11366 : AgentRouteData(Type type, bool is_multicast, uint64_t sequence_number):
63 11366 : type_(type), is_multicast_(is_multicast),
64 11366 : sequence_number_(sequence_number) { }
65 11366 : virtual ~AgentRouteData() { }
66 :
67 : virtual std::string ToString() const = 0;
68 : virtual AgentPath *CreateAgentPath(const Peer *peer, AgentRoute *rt) const;
69 : virtual bool AddChangePathExtended(Agent *agent, AgentPath *path,
70 : const AgentRoute *rt) = 0;
71 36 : virtual bool CanDeletePath(Agent *agent, AgentPath *path,
72 : const AgentRoute *rt) const {
73 36 : return true;
74 : }
75 4589 : virtual bool UpdateRoute(AgentRoute *rt) {return false;}
76 :
77 : bool AddChangePath(Agent *agent, AgentPath *path, const AgentRoute *rt);
78 1769 : bool is_multicast() const {return is_multicast_;}
79 81 : uint64_t sequence_number() const {return sequence_number_;}
80 :
81 : Type type_;
82 : bool is_multicast_;
83 : uint64_t sequence_number_;
84 : DISALLOW_COPY_AND_ASSIGN(AgentRouteData);
85 : };
86 :
87 : struct RouteComparator {
88 : bool operator() (const AgentRoute *rt1, const AgentRoute *rt2) const;
89 : };
90 :
91 : struct NHComparator {
92 : bool operator() (const NextHop *nh1, const NextHop *nh2) const;
93 : };
94 :
95 : struct RouteTableWalkerState {
96 444 : RouteTableWalkerState(LifetimeActor *actor) : rt_delete_ref_(this, actor) {
97 444 : }
98 :
99 444 : ~RouteTableWalkerState() {
100 444 : rt_delete_ref_.Reset(NULL);
101 444 : }
102 444 : void ManagedDelete() { }
103 :
104 : LifetimeRef<RouteTableWalkerState> rt_delete_ref_;
105 : };
106 :
107 : /// @brief Agent supports multiple route tables - Inet-unicast (IPv4/IPv6),
108 : /// Inet-multicast, bridge, EVPN (Type2/Type5). This base class contains
109 : /// common code for all types of route tables.
110 : class AgentRouteTable : public RouteTable {
111 : public:
112 : static const int kPartitionCount = 1;
113 : typedef std::set<const AgentRoute *, RouteComparator> UnresolvedRouteTree;
114 : typedef std::set<const NextHop *, NHComparator> UnresolvedNHTree;
115 :
116 : AgentRouteTable(DB *db, const std::string &name);
117 : virtual ~AgentRouteTable();
118 :
119 4960 : virtual int PartitionCount() const { return kPartitionCount; }
120 : virtual std::unique_ptr<DBEntry> AllocEntry(const DBRequestKey *k) const;
121 48364 : virtual size_t Hash(const DBEntry *entry) const {return 0;}
122 22101 : virtual size_t Hash(const DBRequestKey *key) const {return 0;}
123 :
124 : virtual Agent::RouteTableType GetTableType() const = 0;
125 : virtual std::string GetTableName() const = 0;
126 :
127 831 : virtual void ProcessDelete(AgentRoute *rt) { }
128 831 : virtual void ProcessAdd(AgentRoute *rt) { }
129 : virtual void NotifyEntry(AgentRoute *entry);
130 :
131 0 : virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args,
132 : const std::string &context) {
133 0 : return AgentSandeshPtr();
134 : }
135 15548 : virtual SandeshTraceBufferPtr GetOperDBTraceBuf() const {return OperDBTraceBuf;}
136 :
137 : // Unresolved route tree accessors
138 0 : UnresolvedRouteTree::const_iterator unresolved_route_begin() const {
139 0 : return unresolved_rt_tree_.begin();
140 : }
141 0 : UnresolvedRouteTree::const_iterator unresolved_route_end() const {
142 0 : return unresolved_rt_tree_.end();
143 : }
144 10 : int unresolved_route_size() const { return unresolved_rt_tree_.size(); }
145 :
146 : // Unresolved NH tree accessors
147 : void AddUnresolvedNH(const NextHop *);
148 : void RemoveUnresolvedNH(const NextHop *);
149 : void EvaluateUnresolvedNH(void);
150 0 : UnresolvedNHTree::const_iterator unresolved_nh_begin() const {
151 0 : return unresolved_nh_tree_.begin();
152 : }
153 0 : UnresolvedNHTree::const_iterator unresolved_nh_end() const {
154 0 : return unresolved_nh_tree_.end();
155 : }
156 : void EvaluateUnresolvedRoutes(void);
157 : void AddUnresolvedRoute(const AgentRoute *rt);
158 : void RemoveUnresolvedRoute(const AgentRoute *rt);
159 :
160 93332 : Agent *agent() const { return agent_; }
161 : const std::string &vrf_name() const;
162 1548 : uint32_t vrf_id() const {return vrf_id_;}
163 : VrfEntry *vrf_entry() const;
164 : AgentRoute *FindActiveEntry(const AgentRouteKey *key);
165 : AgentRoute *FindActiveEntryNoLock(const AgentRouteKey *key);
166 : AgentRoute *FindActiveEntry(const AgentRoute *key);
167 : AgentRoute *FindActiveEntryNoLock(const AgentRoute *key);
168 :
169 : // Set VRF for the route-table
170 : void SetVrf(VrfEntry * vrf);
171 :
172 : // Helper functions to delete routes
173 : bool DelExplicitRouteWalkerCb(DBTablePartBase *part, DBEntryBase *entry);
174 :
175 : // Lifetime actor routines
176 : LifetimeActor *deleter();
177 : void ManagedDelete();
178 : virtual void RetryDelete();
179 :
180 : // Process DBRequest inline
181 : void Process(DBRequest &req);
182 :
183 : // Path comparator
184 : static bool PathSelection(const Path &path1, const Path &path2);
185 : static const std::string &GetSuffix(Agent::RouteTableType type);
186 :
187 : void AddChangeInput(DBTablePartition *part, VrfEntry *vrf, AgentRoute *rt,
188 : AgentRouteKey *key, AgentRouteData *data);
189 : AgentRoute *LocateRoute(DBTablePartition *part, VrfEntry *vrf,
190 : AgentRoute *rt, AgentRouteKey *key,
191 : AgentRouteData *data, bool *notify);
192 :
193 : private:
194 : class DeleteActor;
195 : void DeleteRouteDone(DBTable::DBTableWalkRef walk_ref, DBTableBase *base,
196 : RouteTableWalkerState *state);
197 :
198 : void Input(DBTablePartition *part, DBClient *client, DBRequest *req);
199 :
200 : Agent *agent_;
201 : uint32_t vrf_id_;
202 : VrfEntryRef vrf_entry_;
203 : boost::scoped_ptr<DeleteActor> deleter_;
204 : LifetimeRef<AgentRouteTable> vrf_delete_ref_;
205 : UnresolvedRouteTree unresolved_rt_tree_;
206 : UnresolvedNHTree unresolved_nh_tree_;
207 : // VRF is stored to identify which VRF this table belonged to
208 : // in case lifetimeactor has reset the vrf_.
209 : SandeshTraceBufferPtr OperDBTraceBuf;
210 : DISALLOW_COPY_AND_ASSIGN(AgentRouteTable);
211 : };
212 :
213 : #define OPER_TRACE_ROUTE(obj, ...)\
214 : do {\
215 : Oper##obj::TraceMsg(GetOperDBTraceBuf(), __FILE__, __LINE__, __VA_ARGS__);\
216 : } while (false)
217 :
218 : #define OPER_TRACE_ROUTE_ENTRY(obj, table, ...)\
219 : do {\
220 : Oper##obj::TraceMsg(table->GetOperDBTraceBuf(),\
221 : __FILE__, __LINE__, __VA_ARGS__);\
222 : } while (false)
223 :
224 : /// @brief Base class for all Route entries in agent
225 : class AgentRoute : public Route {
226 : public:
227 : enum Trace {
228 : ADD,
229 : DEL,
230 : ADD_PATH,
231 : DELETE_PATH,
232 : CHANGE_PATH,
233 : STALE_PATH,
234 : };
235 :
236 : typedef DependencyList<AgentRoute, AgentRoute> RouteDependencyList;
237 : typedef DependencyList<NextHop, AgentRoute> TunnelNhDependencyList;
238 :
239 27099 : AgentRoute(VrfEntry *vrf, bool is_multicast,
240 27099 : const std::string &intf_route_type = "interface") :
241 27099 : Route(), vrf_(vrf), is_multicast_(is_multicast),
242 27099 : intf_route_type_(intf_route_type), dependent_route_table_(NULL) { }
243 27099 : virtual ~AgentRoute() { }
244 :
245 : // Virtual functions from base DBEntry
246 : virtual bool IsLess(const DBEntry &rhs) const;
247 : virtual KeyPtr GetDBRequestKey() const = 0;
248 : virtual void SetKey(const DBRequestKey *key) = 0;
249 :
250 : // Virtual functions defined by AgentRoute
251 : virtual int CompareTo(const Route &rhs) const = 0;
252 : virtual Agent::RouteTableType GetTableType() const = 0;
253 : virtual bool DBEntrySandesh(Sandesh *sresp, bool stale) const = 0;
254 : virtual std::string ToString() const = 0;
255 : virtual const std::string GetAddressString() const = 0;
256 : virtual const std::string GetSourceAddressString() const = 0;
257 0 : virtual bool ReComputePathDeletion(AgentPath *path) {return false;}
258 1870 : virtual bool ReComputePathAdd(AgentPath *path) {return false;}
259 : virtual uint32_t GetActiveLabel() const;
260 : virtual AgentPath *FindPathUsingKeyData(const AgentRouteKey *key,
261 : const AgentRouteData *data) const;
262 : virtual AgentPath *FindPath(const Peer *peer) const;
263 0 : virtual bool RecomputeRoutePath(Agent *agent,
264 : DBTablePartition *part,
265 : AgentPath *path,
266 0 : AgentRouteData *data) {return false;}
267 : //Can be used for operations related to updation of route.
268 7351 : virtual void UpdateDerivedRoutes(AgentRouteTable *table,
269 : const AgentPath *path,
270 : bool active_path_changed) {
271 7351 : }
272 : //Can be used for operations resulting from deletion of route.
273 1431 : virtual void DeleteDerivedRoutes(AgentRouteTable *table) { }
274 : // Accessor functions
275 36293 : bool is_multicast() const {return is_multicast_;}
276 100433 : VrfEntry *vrf() const {return vrf_;}
277 : uint32_t vrf_id() const;
278 810 : const std::string &intf_route_type() const { return intf_route_type_; }
279 0 : void set_intf_route_type(const std::string &intf_route_type) {
280 0 : intf_route_type_ = intf_route_type;
281 0 : }
282 0 : const std::string &origin_vn_name() const {return origin_vn_name_; };
283 2598 : void set_origin_vn_name(const VnListType &dest_vn_list) {
284 2598 : for (const auto &vn_nm : dest_vn_list) {
285 2261 : if (vn_nm == "unresolved") {
286 0 : continue;
287 : }
288 : else {
289 2261 : origin_vn_name_ = vn_nm;
290 2261 : return;
291 : }
292 : };
293 337 : origin_vn_name_ = Agent::NullString();
294 : }
295 :
296 : AgentPath *FindLocalPath() const;
297 : AgentPath *FindLocalVmPortPath() const;
298 :
299 : /// @brief Finds path to an interface or a composite of interfaces and
300 : /// returns it. The priority is given to composite: if both an interface
301 : /// and a composite are present, then the composite path is returned
302 : /// @return the pointer to AgentPath if a proper path found or NULL
303 : const AgentPath *FindIntfOrCompLocalVmPortPath() const;
304 : AgentPath *GetLocalVmPortPath() const;
305 : const AgentPath *GetActivePath() const;
306 : const NextHop *GetActiveNextHop() const;
307 : const std::string &dest_vn_name() const;
308 : bool IsRPFInvalid() const;
309 :
310 : void EnqueueRouteResync() const;
311 : void ResyncTunnelNextHop();
312 : bool HasUnresolvedPath();
313 : bool Sync(void);
314 :
315 : //TODO Move dependantroutes and nh to inet4
316 : void UpdateDependantRoutes();// analogous to updategatewayroutes
317 2 : bool IsDependantRouteEmpty() { return dependant_routes_.empty(); }
318 2 : bool IsTunnelNHListEmpty() { return tunnel_nh_list_.empty(); }
319 :
320 : void FillTrace(RouteInfo &route, Trace event, const AgentPath *path) const;
321 : bool WaitForTraffic() const;
322 :
323 : bool DeleteAllBgpPath(DBTablePartBase *part, AgentRouteTable *table);
324 : void DeletePathFromPeer(DBTablePartBase *part, AgentRouteTable *table,
325 : AgentPath *path);
326 : bool SubOpResyncInput(VrfEntry *vrf, AgentRouteTable *table,
327 : AgentPath **path_ptr, AgentRouteKey *key,
328 : AgentRouteData *data);
329 : bool SubOpAddChangeInput(VrfEntry *vrf, AgentRouteTable *table,
330 : AgentPath **path_ptr, AgentRouteKey *key,
331 : AgentRouteData *data, bool route_added);
332 : void DeleteInput(DBTablePartition *part, AgentRouteTable *table,
333 : AgentRouteKey *key, AgentRouteData *data);
334 : void AddUnresolvedRouteToTable(AgentRouteTable *table);
335 : void RemoveUnresolvedRouteFromTable(AgentRouteTable *table);
336 : /// Returns the length of a stored prefix address
337 0 : virtual uint8_t prefix_length() const { return 0; }
338 : protected:
339 0 : void SetVrf(VrfEntry *vrf) { vrf_ = vrf; }
340 : void RemovePath(AgentPath *path);
341 : void InsertPath(const AgentPath *path);
342 : virtual void HandleMulticastLabel(const Agent *agent,
343 : AgentPath *path,
344 : const AgentPath *local_peer_path,
345 : const AgentPath *local_vm_peer_path,
346 : bool del, uint32_t *evpn_label);
347 : virtual bool ReComputeMulticastPaths(AgentPath *path, bool del);
348 : virtual void HandleDeviceMastershipUpdate(AgentPath *path, bool del);
349 1254 : virtual Composite::Type GetMulticastCompType() { return Composite::L2COMP; }
350 : const AgentRouteTable *GetDependentRouteTable(void) const {
351 : return dependent_route_table_;
352 : }
353 0 : virtual bool ValidateMcastSrc() const { return true; }
354 :
355 : private:
356 : friend class AgentRouteTable;
357 : //EcmpData can insert/delete path
358 : friend class EcmpData;
359 :
360 : bool ProcessPath(Agent *agent, DBTablePartition *part, AgentPath *path,
361 : AgentRouteData *data);
362 :
363 : VrfEntry *vrf_;
364 : // Unicast table can contain routes for few multicast address
365 : // (ex. subnet multicast). Flag to specify if this is multicast route
366 : bool is_multicast_;
367 : std::string intf_route_type_;
368 : std::string origin_vn_name_;
369 : AgentRouteTable *dependent_route_table_;
370 454 : DEPENDENCY_LIST(AgentRoute, AgentRoute, dependant_routes_);
371 96 : DEPENDENCY_LIST(NextHop, AgentRoute, tunnel_nh_list_);
372 : DISALLOW_COPY_AND_ASSIGN(AgentRoute);
373 : };
374 :
375 : /// @brief This class defines interfaces for manipulating the prefix
376 : /// of a route stored in an Agent VRF table
377 : template <class PrefixType>
378 : class AgentRoutePrefix {
379 : public:
380 :
381 : /// @brief Creates a new route prefix
382 27099 : AgentRoutePrefix(const PrefixType& new_prefix, uint8_t new_plen)
383 27099 : : prefix_address_(new_prefix), prefix_length_(new_plen) {}
384 :
385 : /// @brief The destructor of a route prefix
386 27099 : ~AgentRoutePrefix(){}
387 :
388 : /// @brief Returns the value of a stored prefix address
389 : /// (IPv4, IPv6 or MAC address)
390 309520 : virtual const PrefixType& prefix_address() const {return prefix_address_;}
391 :
392 : /// @brief Sets the length of a stored prefix address
393 69 : void set_prefix_length(uint8_t new_plen) {
394 69 : prefix_length_ = new_plen;
395 69 : }
396 :
397 : protected:
398 :
399 : /// @brief The prefix address
400 : PrefixType prefix_address_;
401 :
402 : /// @brief The prefix length
403 : uint8_t prefix_length_;
404 :
405 : private:
406 :
407 : /// @brief Forbid default ctor
408 : AgentRoutePrefix();
409 :
410 : DISALLOW_COPY_AND_ASSIGN(AgentRoutePrefix);
411 : };
412 :
413 : #define GETPEERNAME(peer) (peer)? peer->GetName() : ""
414 : #define AGENT_ROUTE_LOG(table, msg, route, vrf, peer_info)\
415 : do {\
416 : AgentRouteLog::TraceMsg(table->GetOperDBTraceBuf(), __FILE__, __LINE__,\
417 : msg, route, vrf, peer_info);\
418 : } while (false)
419 :
420 : #endif
|