Line data Source code
1 : /*
2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <base/logging.h>
6 :
7 : #include <cmn/agent_cmn.h>
8 : #include <init/agent_init.h>
9 : #include <cmn/agent_factory.h>
10 : #include <init/agent_param.h>
11 :
12 : #include <cfg/cfg_init.h>
13 :
14 : #include <oper/operdb_init.h>
15 : #include <oper/vrf.h>
16 : #include <controller/controller_init.h>
17 : #include <controller/controller_vrf_export.h>
18 : #include <pkt/pkt_init.h>
19 : #include <services/services_init.h>
20 : #include <vrouter/ksync/ksync_init.h>
21 : #include <mac_learning/mac_learning_init.h>
22 : #include <uve/agent_uve.h>
23 : #include <pkt/proto_handler.h>
24 : #include <diag/diag.h>
25 : #include <vgw/cfg_vgw.h>
26 : #include <vgw/vgw.h>
27 : #include <vrouter/flow_stats/flow_stats_manager.h>
28 :
29 : #include "contrail_init_common.h"
30 :
31 6 : ContrailInitCommon::ContrailInitCommon() : AgentInit(), create_vhost_(true),
32 3 : ksync_enable_(true), services_enable_(true), packet_enable_(true),
33 3 : uve_enable_(true), vgw_enable_(true), router_id_dep_enable_(true) {
34 3 : }
35 :
36 3 : ContrailInitCommon::~ContrailInitCommon() {
37 3 : vgw_.reset();
38 3 : ksync_.reset();
39 3 : uve_.reset();
40 :
41 3 : diag_table_.reset();
42 3 : services_.reset();
43 3 : pkt_.reset();
44 3 : mac_learning_module_.reset();
45 3 : }
46 :
47 3 : void ContrailInitCommon::ProcessOptions
48 : (const std::string &config_file, const std::string &program_name) {
49 3 : AgentInit::ProcessOptions(config_file, program_name);
50 3 : }
51 :
52 3 : int ContrailInitCommon::Start(Logging &logging) {
53 3 : return AgentInit::Start(logging);
54 : }
55 :
56 : /****************************************************************************
57 : * Initialization routines
58 : ***************************************************************************/
59 3 : void ContrailInitCommon::CreateModules() {
60 3 : pkt_.reset(new PktModule(agent()));
61 3 : agent()->set_pkt(pkt_.get());
62 :
63 3 : if (services_enable_) {
64 : services_.reset
65 1 : (new ServicesModule(agent(), agent_param()->metadata_shared_secret()));
66 1 : agent()->set_services(services_.get());
67 : }
68 3 : if (vgw_enable_) {
69 0 : vgw_.reset(new VirtualGateway(agent()));
70 0 : agent()->set_vgw(vgw_.get());
71 : }
72 :
73 3 : mac_learning_module_.reset(new MacLearningModule(agent()));
74 3 : agent()->set_mac_learning_module(mac_learning_module_.get());
75 3 : }
76 :
77 3 : void ContrailInitCommon::RegisterDBClients() {
78 3 : if (agent()->uve()) {
79 3 : agent()->uve()->RegisterDBClients();
80 : }
81 :
82 3 : if (agent()->ksync()) {
83 3 : agent()->ksync()->RegisterDBClients(agent()->db());
84 : }
85 :
86 3 : if (agent()->vgw()) {
87 0 : agent()->vgw()->RegisterDBClients();
88 : }
89 :
90 3 : if (agent()->flow_stats_manager()) {
91 3 : agent()->flow_stats_manager()->RegisterDBClients();
92 : }
93 3 : }
94 :
95 3 : void ContrailInitCommon::InitModules() {
96 :
97 3 : if(agent()->params()->cat_is_dpdk_mocked()) {
98 0 : ksync_enable_= false;
99 : }
100 :
101 3 : if (agent()->pkt()) {
102 3 : agent()->pkt()->Init(ksync_enable());
103 : }
104 :
105 3 : if (agent()->services()) {
106 1 : agent()->services()->Init(ksync_enable());
107 : }
108 :
109 3 : if (agent()->uve()) {
110 3 : agent()->uve()->Init();
111 : }
112 :
113 3 : if (agent()->ksync()) {
114 3 : agent()->ksync()->Init(create_vhost_);
115 : }
116 :
117 3 : if (agent()->mac_learning_module()) {
118 3 : agent()->mac_learning_module()->Init();
119 : }
120 :
121 3 : if (agent()->flow_stats_manager()) {
122 6 : agent()->flow_stats_manager()->Init(agent()->params()->flow_stats_interval(),
123 3 : agent()->params()->flow_cache_timeout());
124 : }
125 3 : }
126 :
127 3 : void ContrailInitCommon::CreateVrf() {
128 3 : VrfTable *vrf_table = agent()->vrf_table();
129 :
130 3 : if (agent()->isXenMode()) {
131 0 : vrf_table->CreateStaticVrf(agent()->linklocal_vrf_name());
132 : }
133 :
134 : // Create VRF for VGw
135 3 : if (agent()->vgw()) {
136 0 : agent()->vgw()->CreateVrf();
137 : }
138 3 : }
139 :
140 5 : static PhysicalInterface::EncapType ComputeEncapType(const string &encap) {
141 5 : if (encap == "none") {
142 0 : return PhysicalInterface::RAW_IP;
143 : }
144 5 : return PhysicalInterface::ETHERNET;
145 : }
146 :
147 3 : void ContrailInitCommon::ProcessComputeAddress(AgentParam *param) {
148 : InetUnicastAgentRouteTable *rt_table =
149 3 : agent()->fabric_inet4_unicast_table();
150 :
151 : const AgentParam::AddressList &addr_list =
152 3 : param->compute_node_address_list();
153 3 : AgentParam::AddressList::const_iterator it = addr_list.begin();
154 3 : while (it != addr_list.end()) {
155 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE,
156 0 : boost::uuids::nil_uuid(),
157 0 : param->vhost_name());
158 0 : rt_table->AddVHostRecvRouteReq(agent()->local_peer(),
159 : agent()->fabric_vrf_name(),
160 0 : vmi_key, *it, 32,
161 : agent()->fabric_vn_name(), false,
162 : true);
163 0 : it++;
164 0 : }
165 :
166 : // If compute_node_address are specified, it will mean user wants
167 : // to run services such as metadata on an IP different than vhost.
168 : // Set compute_node_ip_ to vhost_addr if no compute_node_address are
169 : // specified. Else, pick first address to run in compute_node_address_list
170 : //
171 : // The compute_node_ip is used only in adding Flow NAT rules.
172 3 : if (param->compute_node_address_list().size()) {
173 0 : agent()->set_compute_node_ip(param->compute_node_address_list()[0]);
174 : }
175 3 : }
176 :
177 3 : void ContrailInitCommon::CreateInterfaces() {
178 3 : InterfaceTable *table = agent()->interface_table();
179 : PhysicalInterface::EncapType type;
180 :
181 3 : Interface::Transport physical_transport = Interface::TRANSPORT_ETHERNET;
182 3 : Interface::Transport vhost_transport = Interface::TRANSPORT_ETHERNET;
183 3 : if (agent_param()->vrouter_on_host_dpdk()) {
184 : //TODO : transport type for vhost interface should
185 : //be set to KNI
186 0 : vhost_transport = Interface::TRANSPORT_PMD;
187 0 : physical_transport = Interface::TRANSPORT_PMD;
188 : }
189 :
190 3 : if (agent_param()->vrouter_on_nic_mode()) {
191 0 : vhost_transport = Interface::TRANSPORT_PMD;
192 0 : physical_transport = Interface::TRANSPORT_PMD;
193 : }
194 :
195 3 : Interface *physical_intf = NULL;
196 3 : BridgeAgentRouteTable *l2_table = agent()->fabric_l2_unicast_table();
197 : InetUnicastAgentRouteTable *rt_table =
198 3 : agent()->fabric_inet4_unicast_table();
199 3 : type = ComputeEncapType(agent_param()->eth_port_encap_type());
200 6 : for (std::size_t i = 0; i != agent_param()->eth_port_list().size(); ++i) {
201 6 : PhysicalInterface::Create(table, agent_param()->eth_port_list()[i],
202 : agent()->fabric_vrf_name(),
203 : PhysicalInterface::FABRIC, type,
204 3 : agent_param()->eth_port_no_arp(),
205 3 : boost::uuids::nil_uuid(),
206 3 : agent()->is_l3mh() ?
207 0 : agent_param()->eth_port_addr_list()[i] :
208 3 : agent_param()->vhost_addr(),
209 : physical_transport);
210 3 : PhysicalInterfaceKey physical_key(agent_param()->eth_port_list()[i]);
211 3 : assert(table->FindActiveEntry(&physical_key));
212 3 : physical_intf =
213 3 : static_cast<Interface *>(table->FindActiveEntry(&physical_key));
214 :
215 : // Add L2 receive routes for physical interface MACs to both vrf 0 and 1.
216 3 : l2_table->AddBridgeReceiveRoute(agent()->local_vm_peer(),
217 : agent()->fabric_vrf_name(), 0,
218 : physical_intf->mac(), "");
219 3 : l2_table->AddBridgeReceiveRoute(agent()->local_vm_peer(),
220 : agent()->fabric_policy_vrf_name(), 0,
221 : physical_intf->mac(), "");
222 :
223 3 : if (agent()->is_l3mh()) {
224 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE,
225 0 : boost::uuids::nil_uuid(),
226 0 : agent()->params()->vhost_name());
227 : // Receive route for physical interface IP address assigned
228 0 : rt_table->AddVHostRecvRouteReq(agent()->local_peer(),
229 : agent()->fabric_vrf_name(), vmi_key,
230 0 : agent_param()->eth_port_addr_list()[i], 32,
231 : agent()->fabric_vn_name(), false, true);
232 : // Receive route for the sub-net broadcast address
233 0 : rt_table->AddVHostSubnetRecvRoute(agent()->local_peer(),
234 : agent()->fabric_vrf_name(), vmi_key,
235 0 : GetIp4SubnetBroadcastAddress(
236 0 : agent_param()->eth_port_addr_list()[i],
237 0 : agent_param()->eth_port_plen_list()[i]),
238 : 32, agent()->fabric_vn_name(), false);
239 : // Add resolve route for physical interface ip-addr to vrf 0
240 0 : rt_table->AddResolveRoute(agent()->local_peer(),
241 : agent()->fabric_vrf_name(),
242 0 : agent_param()->eth_port_addr_list()[i],
243 0 : agent_param()->eth_port_plen_list()[i],
244 : physical_key, MplsTable::kInvalidLabel,
245 : false, agent()->fabric_vn_name(),
246 0 : SecurityGroupList(), TagList());
247 0 : }
248 3 : }
249 :
250 3 : if (agent()->is_l3mh()) {
251 0 : agent()->set_router_id(agent_param()->loopback_ip());
252 : } else {
253 3 : agent()->set_router_id(agent_param()->vhost_addr());
254 3 : agent()->set_vhost_prefix(agent_param()->vhost_prefix());
255 3 : agent()->set_vhost_prefix_len(agent_param()->vhost_plen());
256 3 : agent()->set_vhost_default_gateway(agent_param()->gateway_list());
257 : }
258 3 : if (agent_param()->crypt_port() != "") {
259 2 : type = ComputeEncapType(agent_param()->crypt_port_encap_type());
260 4 : PhysicalInterface::Create(table, agent_param()->crypt_port(),
261 : agent()->fabric_vrf_name(),
262 : PhysicalInterface::FABRIC, type,
263 2 : agent_param()->crypt_port_no_arp(),
264 2 : boost::uuids::nil_uuid(),
265 : agent_param()->vhost_addr(),
266 : physical_transport);
267 2 : PhysicalInterfaceKey physical_key(agent()->crypt_interface_name());
268 : agent()->set_crypt_interface
269 2 : (static_cast<Interface *>(table->FindActiveEntry(&physical_key)));
270 2 : assert(agent()->crypt_interface());
271 2 : }
272 :
273 : //Add the interface
274 3 : table->CreateVhost();
275 : //Trigger explicit change to sync the configuration
276 3 : table->CreateVhost();
277 3 : if (agent()->tsn_enabled()) {
278 0 : InetInterfaceKey key(agent()->vhost_interface_name());
279 : agent()->set_vhost_interface
280 0 : (static_cast<Interface *>(table->FindActiveEntry(&key)));
281 0 : } else {
282 0 : VmInterfaceKey key(AgentKey::ADD_DEL_CHANGE, boost::uuids::nil_uuid(),
283 3 : agent()->vhost_interface_name());
284 : agent()->set_vhost_interface
285 3 : (static_cast<Interface *>(table->FindActiveEntry(&key)));
286 3 : }
287 3 : assert(agent()->vhost_interface());
288 :
289 : // Add vhost labelled inet route
290 : InetUnicastAgentRouteTable *inet_mpls_table =
291 : static_cast<InetUnicastAgentRouteTable *>
292 3 : (agent()->fabric_vrf()->GetInet4MplsUnicastRouteTable());
293 6 : inet_mpls_table->AddVhostMplsRoute(agent()->is_l3mh() ?
294 0 : agent()->params()->loopback_ip() :
295 3 : agent()->params()->vhost_addr(),
296 : agent()->fabric_rt_export_peer());
297 :
298 : /* Add Receive route for agent loopback incase of l3mh */
299 3 : if (agent()->is_l3mh()) {
300 : InetUnicastAgentRouteTable *rt_table =
301 0 : agent()->fabric_inet4_unicast_table();
302 :
303 : VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE,
304 0 : boost::uuids::nil_uuid(),
305 0 : agent()->params()->vhost_name());
306 0 : rt_table->AddVHostRecvRouteReq(agent()->local_peer(),
307 : agent()->fabric_vrf_name(),
308 0 : vmi_key, agent()->params()->loopback_ip(), 32,
309 : agent()->fabric_vn_name(), false,
310 : true);
311 0 : }
312 :
313 3 : agent()->InitXenLinkLocalIntf();
314 3 : if (agent_param()->isVmwareMode()) {
315 0 : PhysicalInterface::Create(agent()->interface_table(),
316 : agent_param()->vmware_physical_port(),
317 : agent()->fabric_vrf_name(),
318 : PhysicalInterface::VMWARE,
319 : PhysicalInterface::ETHERNET, false,
320 0 : boost::uuids::nil_uuid(), Ip4Address(0),
321 : physical_transport);
322 :
323 0 : PhysicalInterfaceKey vmware_pk(agent_param()->vmware_physical_port());
324 : const Interface *vmware_intf =
325 0 : static_cast<const Interface *>(table->FindActiveEntry(&vmware_pk));
326 0 : l2_table->AddBridgeReceiveRoute(agent()->local_vm_peer(),
327 : agent()->fabric_vrf_name(), 0,
328 : vmware_intf->mac(), "");
329 0 : l2_table->AddBridgeReceiveRoute(agent()->local_vm_peer(),
330 : agent()->fabric_policy_vrf_name(), 0,
331 : vmware_intf->mac(), "");
332 0 : }
333 :
334 3 : if (agent()->pkt()) {
335 3 : agent()->pkt()->CreateInterfaces();
336 : }
337 :
338 3 : if (agent()->vgw()) {
339 0 : agent()->vgw()->CreateInterfaces(vhost_transport);
340 : }
341 :
342 3 : ProcessComputeAddress(agent_param());
343 3 : }
344 :
345 3 : void ContrailInitCommon::InitDone() {
346 : //Open up mirror socket
347 3 : agent()->mirror_table()->MirrorSockInit();
348 :
349 3 : if (agent()->services()) {
350 1 : agent()->services()->ConfigInit();
351 : }
352 :
353 : // Diag module needs PktModule
354 3 : if (agent()->pkt()) {
355 3 : diag_table_.reset(new DiagTable(agent()));
356 3 : agent()->set_diag_table(diag_table_.get());
357 : }
358 :
359 3 : if (create_vhost_) {
360 : //Update mac address of vhost interface with
361 : //that of ethernet interface
362 0 : agent()->ksync()->UpdateVhostMac();
363 : }
364 :
365 3 : if (ksync_enable_) {
366 0 : agent()->ksync()->VnswInterfaceListenerInit();
367 : }
368 :
369 3 : if (agent()->pkt()) {
370 3 : agent()->pkt()->InitDone();
371 : }
372 :
373 3 : if (agent()->uve()) {
374 3 : agent()->uve()->InitDone();
375 : }
376 :
377 3 : if (agent()->ksync()) {
378 3 : agent()->ksync()->InitDone();
379 : }
380 :
381 3 : if (agent()->oper_db()) {
382 3 : agent()->oper_db()->InitDone();
383 : }
384 3 : }
385 :
386 : /****************************************************************************
387 : * Shutdown routines
388 : ***************************************************************************/
389 3 : void ContrailInitCommon::IoShutdown() {
390 3 : if (agent()->pkt())
391 3 : agent()->pkt()->IoShutdown();
392 :
393 3 : if (agent()->services())
394 1 : agent()->services()->IoShutdown();
395 3 : }
396 :
397 3 : void ContrailInitCommon::FlushFlows() {
398 3 : if (agent()->pkt())
399 3 : agent()->pkt()->FlushFlows();
400 3 : }
401 :
402 3 : void ContrailInitCommon::ServicesShutdown() {
403 3 : if (agent()->services())
404 1 : agent()->services()->Shutdown();
405 :
406 3 : if (agent()->mac_learning_module()) {
407 3 : agent()->mac_learning_module()->Shutdown();
408 : }
409 3 : }
410 :
411 3 : void ContrailInitCommon::PktShutdown() {
412 3 : if (agent()->pkt()) {
413 3 : agent()->pkt()->Shutdown();
414 : }
415 3 : }
416 :
417 3 : void ContrailInitCommon::ModulesShutdown() {
418 3 : if (agent()->diag_table()) {
419 3 : agent()->diag_table()->Shutdown();
420 : }
421 3 : }
|