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