-
Notifications
You must be signed in to change notification settings - Fork 390
/
service_chaining.h
325 lines (265 loc) · 10.8 KB
/
service_chaining.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/*
* Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
*/
#ifndef SRC_BGP_ROUTING_INSTANCE_SERVICE_CHAINING_H_
#define SRC_BGP_ROUTING_INSTANCE_SERVICE_CHAINING_H_
#include <boost/shared_ptr.hpp>
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/lifetime.h"
#include "base/queue_task.h"
#include "bgp/bgp_condition_listener.h"
#include "bgp/inet/inet_route.h"
#include "bgp/inet6/inet6_route.h"
#include "bgp/routing-instance/iservice_chain_mgr.h"
class BgpRoute;
class BgpTable;
class RoutingInstance;
class BgpTable;
class BgpServer;
class InetVpnRoute;
class Inet6VpnRoute;
class SandeshResponse;
class ServiceChainConfig;
class ShowServicechainInfo;
template <typename T> class ServiceChainMgr;
template <typename T1, typename T2, typename T3, typename T4>
struct ServiceChainBase {
typedef T1 RouteT;
typedef T2 VpnRouteT;
typedef T3 PrefixT;
typedef T4 AddressT;
};
class ServiceChainInet : public ServiceChainBase<
InetRoute, InetVpnRoute, Ip4Prefix, Ip4Address> {
};
class ServiceChainInet6 : public ServiceChainBase<
Inet6Route, Inet6VpnRoute, Inet6Prefix, Ip6Address> {
};
typedef ConditionMatchPtr ServiceChainPtr;
class ServiceChainState : public ConditionMatchState {
public:
explicit ServiceChainState(ServiceChainPtr info) : info_(info) {
}
ServiceChainPtr info() { return info_; }
private:
ServiceChainPtr info_;
DISALLOW_COPY_AND_ASSIGN(ServiceChainState);
};
template <typename T>
class ServiceChainRequest {
public:
typedef typename T::PrefixT PrefixT;
enum RequestType {
MORE_SPECIFIC_ADD_CHG,
MORE_SPECIFIC_DELETE,
CONNECTED_ROUTE_ADD_CHG,
CONNECTED_ROUTE_DELETE,
EXT_CONNECT_ROUTE_ADD_CHG,
EXT_CONNECT_ROUTE_DELETE,
UPDATE_ALL_ROUTES,
STOP_CHAIN_DONE,
};
ServiceChainRequest(RequestType type, BgpTable *table, BgpRoute *route,
PrefixT aggregate_match, ServiceChainPtr info)
: type_(type),
table_(table),
rt_(route),
aggregate_match_(aggregate_match),
info_(info),
snh_resp_(NULL) {
}
ServiceChainRequest(RequestType type, SandeshResponse *resp)
: type_(type),
table_(NULL),
rt_(NULL),
snh_resp_(resp) {
}
RequestType type_;
BgpTable *table_;
BgpRoute *rt_;
PrefixT aggregate_match_;
ServiceChainPtr info_;
SandeshResponse *snh_resp_;
private:
DISALLOW_COPY_AND_ASSIGN(ServiceChainRequest);
};
template <typename T>
class ServiceChain : public ConditionMatch {
public:
typedef typename T::RouteT RouteT;
typedef typename T::VpnRouteT VpnRouteT;
typedef typename T::PrefixT PrefixT;
typedef typename T::AddressT AddressT;
typedef ServiceChainRequest<T> ServiceChainRequestT;
typedef ServiceChainMgr<T> ServiceChainMgrT;
// List of more specific routes resulted in Aggregate route
typedef std::set<BgpRoute *> RouteList;
// Map of Virtual Network subnet prefix to List of More Specific routes
typedef std::map<PrefixT, RouteList> PrefixToRouteListMap;
// Map of External Connecting route to Service Chain Route
typedef std::set<BgpRoute *> ExtConnectRouteList;
// List of path ids for the connected route
typedef std::set<uint32_t> ConnectedPathIdList;
ServiceChain(ServiceChainMgrT *manager, RoutingInstance *src,
RoutingInstance *dest, RoutingInstance *connected,
const std::vector<std::string> &subnets, AddressT addr);
Address::Family GetFamily() const { return manager_->GetFamily(); }
// Delete is triggered from configuration, not via LifetimeManager.
void ManagedDelete() { }
bool CompareServiceChainConfig(const ServiceChainConfig &config);
void RemoveMatchState(BgpRoute *route, ServiceChainState *state);
void SetConnectedRoute(BgpRoute *connected);
bool IsConnectedRouteValid() const;
const ConnectedPathIdList &GetConnectedPathIds() {
return connected_path_ids_;
}
BgpRoute *connected_route() const { return connected_route_; }
RoutingInstance *src_routing_instance() const { return src_; }
RoutingInstance *connected_routing_instance() const { return connected_; }
RoutingInstance *dest_routing_instance() const { return dest_; }
const AddressT &service_chain_addr() const { return service_chain_addr_; }
void AddServiceChainRoute(PrefixT prefix, const RouteT *orig_route,
const ConnectedPathIdList &old_path_ids, bool aggregate);
void RemoveServiceChainRoute(PrefixT prefix, bool aggregate);
bool AddMoreSpecific(PrefixT aggregate, BgpRoute *more_specific);
bool DeleteMoreSpecific(PrefixT aggregate, BgpRoute *more_specific);
BgpTable *src_table() const;
BgpTable *connected_table() const;
BgpTable *dest_table() const;
PrefixToRouteListMap *prefix_to_route_list_map() {
return &prefix_to_routelist_map_;
}
const PrefixToRouteListMap *prefix_to_route_list_map() const {
return &prefix_to_routelist_map_;
}
virtual bool Match(BgpServer *server, BgpTable *table, BgpRoute *route,
bool deleted);
virtual std::string ToString() const;
void FillServiceChainInfo(ShowServicechainInfo *info) const;
void set_connected_table_unregistered() {
connected_table_unregistered_ = true;
}
void set_dest_table_unregistered() {
dest_table_unregistered_ = true;
}
bool dest_table_unregistered() const {
return dest_table_unregistered_;
}
bool connected_table_unregistered() const {
return connected_table_unregistered_;
}
bool unregistered() const {
return connected_table_unregistered_ && dest_table_unregistered_;
}
const ExtConnectRouteList &ext_connecting_routes() const {
return ext_connect_routes_;
}
ExtConnectRouteList *ext_connecting_routes() {
return &ext_connect_routes_;
}
bool aggregate_enable() const { return aggregate_; }
void set_aggregate_enable() { aggregate_ = true; }
private:
ServiceChainMgrT *manager_;
RoutingInstance *src_;
RoutingInstance *dest_;
RoutingInstance *connected_;
ConnectedPathIdList connected_path_ids_;
BgpRoute *connected_route_;
AddressT service_chain_addr_;
PrefixToRouteListMap prefix_to_routelist_map_;
ExtConnectRouteList ext_connect_routes_;
bool connected_table_unregistered_;
bool dest_table_unregistered_;
bool aggregate_; // Whether the host route needs to be aggregated
LifetimeRef<ServiceChain> src_table_delete_ref_;
LifetimeRef<ServiceChain> dest_table_delete_ref_;
LifetimeRef<ServiceChain> connected_table_delete_ref_;
// Helper function to match
bool IsMoreSpecific(BgpRoute *route, PrefixT *aggregate_match) const;
bool IsAggregate(BgpRoute *route) const;
bool IsConnectedRoute(BgpRoute *route) const;
DISALLOW_COPY_AND_ASSIGN(ServiceChain);
};
template <typename T>
class ServiceChainMgr : public IServiceChainMgr {
public:
typedef typename T::RouteT RouteT;
typedef typename T::PrefixT PrefixT;
typedef typename T::AddressT AddressT;
typedef ServiceChain<T> ServiceChainT;
typedef ServiceChainRequest<T> ServiceChainRequestT;
explicit ServiceChainMgr(BgpServer *server);
virtual ~ServiceChainMgr();
// Creates a new service chain between two Virtual network
// If the two routing instance is already connected, it updates the
// connected route address for existing service chain
virtual bool LocateServiceChain(RoutingInstance *rtinstance,
const ServiceChainConfig &config);
// Remove the existing service chain between from routing instance
virtual void StopServiceChain(RoutingInstance *rtinstance);
virtual size_t PendingQueueSize() const { return pending_chains_.size(); }
virtual size_t ResolvedQueueSize() const { return chain_set_.size(); }
virtual uint32_t GetDownServiceChainCount() const;
virtual bool IsQueueEmpty() const { return process_queue_->IsQueueEmpty(); }
virtual bool IsPending(RoutingInstance *rtinstance) const;
Address::Family GetFamily() const;
void Enqueue(ServiceChainRequestT *req);
virtual bool FillServiceChainInfo(RoutingInstance *rtinstance,
ShowServicechainInfo *info) const;
private:
template <typename U> friend class ServiceChainIntegrationTest;
template <typename U> friend class ServiceChainTest;
// All service chain related actions are performed in the context
// of this task. This task has exclusion with db::DBTable task.
static int service_chain_task_id_;
// Set of service chains created in the system
typedef std::map<RoutingInstance *, ServiceChainPtr> ServiceChainMap;
// At the time of processing, service chain request, all required
// routing instance may not be created. Create a list of service chain
// waiting for a routing instance to get created
typedef std::set<RoutingInstance *> PendingServiceChainList;
bool RequestHandler(ServiceChainRequestT *req);
void StopServiceChainDone(BgpTable *table, ConditionMatch *info);
ServiceChainT *FindServiceChain(const std::string &instance) const;
ServiceChainT *FindServiceChain(RoutingInstance *rtinstance) const;
void AddPendingServiceChain(RoutingInstance *rtinstance) {
pending_chains_.insert(rtinstance);
}
void DeletePendingServiceChain(RoutingInstance *rtinstance) {
pending_chains_.erase(rtinstance);
}
void StartResolve();
bool ResolvePendingServiceChain();
void RoutingInstanceCallback(std::string name, int op);
void PeerRegistrationCallback(IPeer *peer, BgpTable *table,
bool unregister);
bool aggregate_host_route() const { return aggregate_host_route_; }
virtual void set_aggregate_host_route(bool value) {
aggregate_host_route_ = value;
}
virtual void DisableResolveTrigger();
virtual void EnableResolveTrigger();
// Work Queue to handle requests posted from Match function, called
// in the context of db::DBTable task.
// The actions are performed in the bgp::ServiceChain task context.
virtual void DisableQueue() { process_queue_->set_disable(true); }
virtual void EnableQueue() { process_queue_->set_disable(false); }
int id_;
int registration_id_;
BgpServer *server_;
BgpConditionListener *listener_;
boost::scoped_ptr<TaskTrigger> resolve_trigger_;
boost::scoped_ptr<WorkQueue<ServiceChainRequestT *> > process_queue_;
bool aggregate_host_route_;
ServiceChainMap chain_set_;
PendingServiceChainList pending_chains_;
DISALLOW_COPY_AND_ASSIGN(ServiceChainMgr);
};
typedef ServiceChainMgr<ServiceChainInet> ServiceChainMgrInet;
typedef ServiceChainMgr<ServiceChainInet6> ServiceChainMgrInet6;
#endif // SRC_BGP_ROUTING_INSTANCE_SERVICE_CHAINING_H_