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