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 : #include "base/regex.h"
7 : #include "bgp/bgp_config.h"
8 : #include "bgp/bgp_server.h"
9 : #include "bgp/bgp_show_handler.h"
10 : #include "bgp/bgp_table.h"
11 : #include "bgp/routing-instance/routing_instance.h"
12 : #include "bgp/routing-instance/service_chaining.h"
13 : #include "bgp/routing-instance/service_chaining_types.h"
14 : #include "base/address_util.h"
15 :
16 : using contrail::regex;
17 : using contrail::regex_match;
18 : using contrail::regex_search;
19 : using std::string;
20 : using std::vector;
21 :
22 6912 : static bool FillServiceChainInfo(SCAddress::Family sc_family,
23 : const string &search_string,
24 : const regex &search_expr,
25 : ShowServicechainInfo &info,
26 : RoutingInstance *rtinstance) {
27 : SCAddress sc_addr;
28 6912 : Address::Family family = sc_addr.SCFamilyToAddressFamily(sc_family);
29 : const BgpTable *table =
30 6912 : static_cast<const BgpTable *>(rtinstance->GetTable(family));
31 6912 : if (!table)
32 0 : return false;
33 : IServiceChainMgr *service_chain_mgr =
34 6912 : rtinstance->server()->service_chain_mgr(sc_family);
35 6912 : if (!service_chain_mgr)
36 0 : return false;
37 :
38 11392 : if ((!regex_search(table->name(), search_expr)) &&
39 4480 : (search_string != "pending" ||
40 7744 : !service_chain_mgr->ServiceChainIsPending(rtinstance)) &&
41 4288 : (search_string != "down" ||
42 11392 : service_chain_mgr->ServiceChainIsUp(rtinstance)) &&
43 3648 : (search_string != "deleted" || !table->IsDeleted())) {
44 3648 : return false;
45 : }
46 3264 : const BgpInstanceConfig *rt_config = rtinstance->config();
47 3264 : if (!rt_config)
48 64 : return false;
49 :
50 : const ServiceChainConfig *sc_config =
51 3200 : rt_config->service_chain_info(sc_family);
52 3200 : if (!sc_config)
53 2864 : return false;
54 :
55 336 : info.set_family(Address::FamilyToString(family));
56 336 : info.set_src_virtual_network(rtinstance->GetVirtualNetworkName());
57 336 : info.set_dest_virtual_network(GetVNFromRoutingInstance(
58 336 : sc_config->routing_instance));
59 336 : info.set_service_instance(sc_config->service_instance);
60 336 : info.set_src_rt_instance(rtinstance->name());
61 336 : info.set_dest_rt_instance(sc_config->routing_instance);
62 336 : if (sc_config->source_routing_instance.empty()) {
63 0 : info.set_connected_rt_instance(rtinstance->name());
64 : } else {
65 336 : info.set_connected_rt_instance(sc_config->source_routing_instance);
66 : }
67 336 : info.set_service_chain_addr(sc_config->service_chain_address);
68 336 : info.set_service_chain_id(sc_config->service_chain_id);
69 :
70 336 : return service_chain_mgr->FillServiceChainInfo(rtinstance, &info);
71 : }
72 :
73 : // Specialization of BgpShowHandler<>::CallbackCommon.
74 : template <>
75 368 : bool BgpShowHandler<ShowServiceChainReq, ShowServiceChainReqIterate,
76 : ShowServiceChainResp, ShowServicechainInfo>::CallbackCommon(
77 : const BgpSandeshContext *bsc, Data *data) {
78 368 : uint32_t page_limit = bsc->page_limit() ? bsc->page_limit() : kPageLimit;
79 368 : uint32_t iter_limit = bsc->iter_limit() ? bsc->iter_limit() : kIterLimit;
80 368 : RoutingInstanceMgr *rim = bsc->bgp_server->routing_instance_mgr();
81 :
82 368 : regex search_expr(data->search_string);
83 : RoutingInstanceMgr::const_name_iterator it =
84 368 : rim->name_clower_bound(data->next_entry);
85 2096 : for (uint32_t iter_count = 0; it != rim->name_cend(); ++it, ++iter_count) {
86 1728 : RoutingInstance *rinstance = it->second;
87 1728 : ShowServicechainInfo inet_info;
88 1728 : if (FillServiceChainInfo(SCAddress::INET, data->search_string,
89 : search_expr, inet_info, rinstance)) {
90 84 : data->show_list.push_back(inet_info);
91 : }
92 1728 : ShowServicechainInfo inet6_info;
93 1728 : if (FillServiceChainInfo(SCAddress::INET6, data->search_string,
94 : search_expr, inet6_info, rinstance)) {
95 84 : data->show_list.push_back(inet6_info);
96 : }
97 1728 : ShowServicechainInfo evpn_info;
98 1728 : if (FillServiceChainInfo(SCAddress::EVPN, data->search_string,
99 : search_expr, evpn_info, rinstance)) {
100 84 : data->show_list.push_back(evpn_info);
101 : }
102 1728 : ShowServicechainInfo evpn6_info;
103 1728 : if (FillServiceChainInfo(SCAddress::EVPN6, data->search_string,
104 : search_expr, evpn6_info, rinstance)) {
105 84 : data->show_list.push_back(evpn6_info);
106 : }
107 :
108 1728 : if (data->show_list.size() >= page_limit)
109 0 : break;
110 1728 : if (iter_count >= iter_limit)
111 0 : break;
112 1728 : }
113 :
114 : // All done if we've looked at all instances.
115 368 : if (it == rim->name_cend() || ++it == rim->name_cend())
116 368 : return true;
117 :
118 : // Return true if we've reached the page limit, false if we've reached the
119 : // iteration limit.
120 0 : bool done = data->show_list.size() >= page_limit;
121 0 : SaveContextToData(it->second->name(), done, data);
122 0 : return done;
123 368 : }
124 :
125 : // Specialization of BgpShowHandler<>::FillShowList.
126 : template <>
127 336 : void BgpShowHandler<ShowServiceChainReq, ShowServiceChainReqIterate,
128 : ShowServiceChainResp, ShowServicechainInfo>::FillShowList(
129 : ShowServiceChainResp *resp,
130 : const vector<ShowServicechainInfo> &show_list) {
131 336 : resp->set_service_chain_list(show_list);
132 336 : }
133 :
134 : // Handler for ShowServiceChainReq.
135 368 : void ShowServiceChainReq::HandleRequest() const {
136 368 : RequestPipeline::PipeSpec ps(this);
137 368 : RequestPipeline::StageSpec s1;
138 368 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
139 :
140 368 : s1.taskId_ = scheduler->GetTaskId("bgp::ServiceChain");
141 : s1.cbFn_ = boost::bind(&BgpShowHandler<
142 : ShowServiceChainReq,
143 : ShowServiceChainReqIterate,
144 : ShowServiceChainResp,
145 368 : ShowServicechainInfo>::Callback, _1, _2, _3, _4, _5);
146 : s1.allocFn_ = BgpShowHandler<
147 : ShowServiceChainReq,
148 : ShowServiceChainReqIterate,
149 : ShowServiceChainResp,
150 368 : ShowServicechainInfo>::CreateData;
151 368 : s1.instances_.push_back(0);
152 368 : ps.stages_.push_back(s1);
153 368 : RequestPipeline rp(ps);
154 368 : }
155 :
156 : //
157 : // Handler for ShowServiceChainReqIterate.
158 : //
159 0 : void ShowServiceChainReqIterate::HandleRequest() const {
160 0 : RequestPipeline::PipeSpec ps(this);
161 0 : RequestPipeline::StageSpec s1;
162 0 : TaskScheduler *scheduler = TaskScheduler::GetInstance();
163 :
164 0 : s1.taskId_ = scheduler->GetTaskId("bgp::ServiceChain");
165 : s1.cbFn_ = boost::bind(&BgpShowHandler<
166 : ShowServiceChainReq,
167 : ShowServiceChainReqIterate,
168 : ShowServiceChainResp,
169 0 : ShowServicechainInfo>::CallbackIterate, _1, _2, _3, _4, _5);
170 : s1.allocFn_ = BgpShowHandler<
171 : ShowServiceChainReq,
172 : ShowServiceChainReqIterate,
173 : ShowServiceChainResp,
174 0 : ShowServicechainInfo>::CreateData;
175 0 : s1.instances_.push_back(0);
176 0 : ps.stages_.push_back(s1);
177 0 : RequestPipeline rp(ps);
178 0 : }
|