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