Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 : #include <bgp_schema_types.h>
5 : #include <base/address_util.h>
6 :
7 : #include <cmn/agent_cmn.h>
8 : #include <cfg/cfg_init.h>
9 : #include <oper/bridge_domain.h>
10 : #include <oper/config_manager.h>
11 : #include <oper/interface_common.h>
12 : #include <oper/mirror_table.h>
13 : #include <oper/sg.h>
14 : #include <oper/tag.h>
15 : #include <oper/bgp_as_service.h>
16 : #include <init/agent_param.h>
17 : #include "ifmap/ifmap_link.h"
18 :
19 : #include <port_ipc/port_ipc_handler.h>
20 : #include <port_ipc/port_subscribe_table.h>
21 :
22 : #define LOGICAL_ROUTER_NAME "logical-router"
23 : #define VIRTUAL_PORT_GROUP_CONFIG_NAME "virtual-port-group"
24 :
25 : #define VMI_NETWORK_ROUTER_INTERFACE "network:router_interface"
26 :
27 : using namespace std;
28 : using namespace boost::uuids;
29 : using namespace autogen;
30 :
31 0 : static void AddFabricFloatingIp(Agent *agent, VmInterfaceConfigData *data,
32 : IpAddress src_ip) {
33 0 : if (agent->fabric_vn_uuid() == nil_uuid()) {
34 0 : return;
35 : }
36 :
37 0 : VmInterface::FloatingIp::PortMap src_port_map;
38 0 : VmInterface::FloatingIp::PortMap dst_port_map;
39 : data->floating_ip_list_.list_.insert
40 0 : (VmInterface::FloatingIp(agent->router_id(),
41 : agent->fabric_policy_vrf_name(),
42 : agent->fabric_vn_uuid(), src_ip,
43 : VmInterface::FloatingIp::DIRECTION_EGRESS,
44 : false, src_port_map, dst_port_map, true));
45 0 : }
46 :
47 : // Build one VN and VRF for a floating-ip. Can reach here from 2 paths,
48 : // 1. floating-ip <-> floating-ip-pool <-> virtual-network <-> routing-instance
49 : // 2. floating-ip <-> instance-ip <-> virtual-network <-> routing-instance
50 0 : static bool BuildFloatingIpVnVrf(Agent *agent, VmInterfaceConfigData *data,
51 : IFMapNode *node, IFMapNode *vn_node) {
52 0 : ConfigManager *cfg_manager= agent->config_manager();
53 0 : if (cfg_manager->SkipNode(vn_node, agent->cfg()->cfg_vn_table())) {
54 0 : return false;
55 : }
56 :
57 0 : VirtualNetwork *cfg = static_cast<VirtualNetwork *>(vn_node->GetObject());
58 0 : assert(cfg);
59 0 : autogen::IdPermsType id_perms = cfg->id_perms();
60 : boost::uuids::uuid vn_uuid;
61 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, vn_uuid);
62 :
63 : IFMapAgentTable *vn_table = static_cast<IFMapAgentTable *>
64 0 : (vn_node->table());
65 0 : DBGraph *vn_graph = vn_table->GetGraph();
66 : // Iterate thru links for virtual-network looking for routing-instance
67 0 : for (DBGraphVertex::adjacency_iterator vn_iter = vn_node->begin(vn_graph);
68 0 : vn_iter != vn_node->end(vn_graph); ++vn_iter) {
69 :
70 0 : IFMapNode *vrf_node = static_cast<IFMapNode *>(vn_iter.operator->());
71 0 : if (cfg_manager->SkipNode(vrf_node, agent->cfg()->cfg_vrf_table())) {
72 0 : continue;
73 : }
74 : // We are interested only in default-vrf
75 : RoutingInstance *ri = static_cast<RoutingInstance *>
76 0 : (vrf_node->GetObject());
77 0 : if(!(ri->is_default())) {
78 0 : continue;
79 : }
80 0 : FloatingIp *fip = static_cast<FloatingIp *>(node->GetObject());
81 0 : assert(fip != NULL);
82 :
83 0 : boost::system::error_code ec;
84 0 : IpAddress addr = IpAddress::from_string(fip->address(), ec);
85 0 : if (ec.value() != 0) {
86 0 : LOG(ERROR, "Error decoding Floating IP address " << fip->address());
87 0 : OPER_TRACE_ENTRY(Trace, agent->interface_table(),
88 : "Error decoding Floating IP address " +
89 : fip->address());
90 : } else {
91 : IpAddress fixed_ip_addr =
92 0 : IpAddress::from_string(fip->fixed_ip_address(), ec);
93 0 : if (ec.value() != 0) {
94 0 : fixed_ip_addr = IpAddress();
95 : }
96 0 : if (!fixed_ip_addr.is_unspecified()) {
97 0 : if ((addr.is_v4() && !fixed_ip_addr.is_v4()) ||
98 0 : (addr.is_v6() && !fixed_ip_addr.is_v6())) {
99 0 : string msg = "Invalid fixed-ip " + fip->fixed_ip_address() +
100 0 : " for FloatingIP " + fip->address();
101 0 : LOG(ERROR, msg);
102 0 : OPER_TRACE_ENTRY(Trace, agent->interface_table(), msg);
103 :
104 0 : return true;
105 0 : }
106 : }
107 :
108 0 : if (ri->fabric_snat()) {
109 0 : AddFabricFloatingIp(agent, data, fixed_ip_addr);
110 : }
111 :
112 0 : VmInterface::FloatingIp::Direction dir =
113 : VmInterface::FloatingIp::DIRECTION_BOTH;
114 : // Get direction
115 0 : if (boost::iequals(fip->traffic_direction(), "ingress"))
116 0 : dir = VmInterface::FloatingIp::DIRECTION_INGRESS;
117 0 : else if (boost::iequals(fip->traffic_direction(), "egress"))
118 0 : dir = VmInterface::FloatingIp::DIRECTION_EGRESS;
119 :
120 : // Make port-map
121 0 : VmInterface::FloatingIp::PortMap src_port_map;
122 0 : VmInterface::FloatingIp::PortMap dst_port_map;
123 0 : for (PortMappings::const_iterator it = fip->port_mappings().begin();
124 0 : it != fip->port_mappings().end(); it++) {
125 0 : uint16_t protocol = Agent::ProtocolStringToInt(it->protocol);
126 : VmInterface::FloatingIp::PortMapKey dst(protocol,
127 0 : it->src_port);
128 0 : dst_port_map.insert(std::make_pair(dst, it->dst_port));
129 : VmInterface::FloatingIp::PortMapKey src(protocol,
130 0 : it->dst_port);
131 0 : src_port_map.insert(std::make_pair(src, it->src_port));
132 0 : }
133 : data->floating_ip_list_.list_.insert
134 0 : (VmInterface::FloatingIp (addr, vrf_node->name(), vn_uuid,
135 : fixed_ip_addr, dir,
136 0 : fip->port_mappings_enable(),
137 : src_port_map,
138 : dst_port_map, false));
139 0 : if (addr.is_v4()) {
140 0 : data->floating_ip_list_.v4_count_++;
141 : } else {
142 0 : data->floating_ip_list_.v6_count_++;
143 : }
144 0 : }
145 0 : return true;
146 : }
147 0 : return false;
148 0 : }
149 :
150 : // Build one Floating IP entry for a virtual-machine-interface
151 0 : static void BuildFloatingIpList(Agent *agent, VmInterfaceConfigData *data,
152 : IFMapNode *node) {
153 0 : ConfigManager *cfg_manager= agent->config_manager();
154 0 : if (cfg_manager->SkipNode(node)) {
155 0 : return;
156 : }
157 :
158 : // Find VRF for the floating-ip. Following paths leads to VRF
159 : // 1. virtual-machine-port <-> floating-ip <-> floating-ip-pool
160 : // <-> virtual-network <-> routing-instance
161 : // 2. virtual-machine-port <-> floating-ip <-> instance-ip
162 : // <-> virtual-network <-> routing-instance
163 0 : IFMapAgentTable *fip_table = static_cast<IFMapAgentTable *>(node->table());
164 0 : DBGraph *fip_graph = fip_table->GetGraph();
165 :
166 : // Iterate thru links for floating-ip looking for floating-ip-pool or
167 : // instance-ip node
168 0 : for (DBGraphVertex::adjacency_iterator fip_iter = node->begin(fip_graph);
169 0 : fip_iter != node->end(fip_graph); ++fip_iter) {
170 0 : IFMapNode *node1 = static_cast<IFMapNode *>(fip_iter.operator->());
171 0 : if (cfg_manager->SkipNode(node1)) {
172 0 : continue;
173 : }
174 : IFMapAgentTable *table1 =
175 0 : static_cast<IFMapAgentTable *> (node1->table());
176 :
177 : // We are interested in floating-ip-pool or instance-ip neighbours
178 0 : if (table1 == agent->cfg()->cfg_floatingip_pool_table() ||
179 0 : table1 == agent->cfg()->cfg_instanceip_table()) {
180 : // Iterate thru links for floating-ip-pool/instance-ip looking for
181 : // virtual-network and routing-instance
182 0 : DBGraph *pool_graph = table1->GetGraph();
183 0 : for (DBGraphVertex::adjacency_iterator node1_iter =
184 0 : node1->begin(pool_graph);
185 0 : node1_iter != node1->end(pool_graph); ++node1_iter) {
186 :
187 : IFMapNode *vn_node =
188 0 : static_cast<IFMapNode *>(node1_iter.operator->());
189 0 : if (BuildFloatingIpVnVrf(agent, data, node, vn_node) == true)
190 0 : break;
191 : }
192 0 : break;
193 : }
194 : }
195 0 : return;
196 : }
197 :
198 : // Build one Alias IP entry for a virtual-machine-interface
199 0 : static void BuildAliasIpList(InterfaceTable *intf_table,
200 : VmInterfaceConfigData *data,
201 : IFMapNode *node) {
202 0 : Agent *agent = intf_table->agent();
203 0 : ConfigManager *cfg_manager= agent->config_manager();
204 0 : if (cfg_manager->SkipNode(node)) {
205 0 : return;
206 : }
207 :
208 : // Find VRF for the alias-ip. Following path in graphs leads to VRF
209 : // virtual-machine-port <-> alias-ip <-> alias-ip-pool
210 : // <-> virtual-network <-> routing-instance
211 0 : IFMapAgentTable *aip_table = static_cast<IFMapAgentTable *>(node->table());
212 0 : DBGraph *aip_graph = aip_table->GetGraph();
213 :
214 : // Iterate thru links for alias-ip looking for alias-ip-pool node
215 0 : for (DBGraphVertex::adjacency_iterator aip_iter = node->begin(aip_graph);
216 0 : aip_iter != node->end(aip_graph); ++aip_iter) {
217 0 : IFMapNode *pool_node = static_cast<IFMapNode *>(aip_iter.operator->());
218 0 : if (cfg_manager->SkipNode
219 0 : (pool_node, agent->cfg()->cfg_aliasip_pool_table())) {
220 0 : continue;
221 : }
222 :
223 : // Iterate thru links for alias-ip-pool looking for virtual-network
224 : IFMapAgentTable *pool_table =
225 0 : static_cast<IFMapAgentTable *> (pool_node->table());
226 0 : DBGraph *pool_graph = pool_table->GetGraph();
227 0 : for (DBGraphVertex::adjacency_iterator pool_iter =
228 0 : pool_node->begin(pool_graph);
229 0 : pool_iter != pool_node->end(pool_graph); ++pool_iter) {
230 :
231 : IFMapNode *vn_node =
232 0 : static_cast<IFMapNode *>(pool_iter.operator->());
233 0 : if (cfg_manager->SkipNode
234 0 : (vn_node, agent->cfg()->cfg_vn_table())) {
235 0 : continue;
236 : }
237 :
238 : VirtualNetwork *cfg = static_cast <VirtualNetwork *>
239 0 : (vn_node->GetObject());
240 0 : assert(cfg);
241 0 : autogen::IdPermsType id_perms = cfg->id_perms();
242 : boost::uuids::uuid vn_uuid;
243 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
244 : vn_uuid);
245 :
246 : IFMapAgentTable *vn_table =
247 0 : static_cast<IFMapAgentTable *> (vn_node->table());
248 0 : DBGraph *vn_graph = vn_table->GetGraph();
249 : // Iterate thru links for virtual-network looking for
250 : // routing-instance
251 0 : for (DBGraphVertex::adjacency_iterator vn_iter =
252 0 : vn_node->begin(vn_graph);
253 0 : vn_iter != vn_node->end(vn_graph); ++vn_iter) {
254 :
255 : IFMapNode *vrf_node =
256 0 : static_cast<IFMapNode *>(vn_iter.operator->());
257 0 : if (cfg_manager->SkipNode
258 0 : (vrf_node, agent->cfg()->cfg_vrf_table())){
259 0 : continue;
260 : }
261 : // Checking whether it is default vrf of not
262 : RoutingInstance *ri =
263 0 : static_cast<RoutingInstance *>(vrf_node->GetObject());
264 0 : if(!(ri->is_default())) {
265 0 : continue;
266 : }
267 0 : AliasIp *aip = static_cast<AliasIp *>(node->GetObject());
268 0 : assert(aip != NULL);
269 :
270 0 : boost::system::error_code ec;
271 0 : IpAddress addr = IpAddress::from_string(aip->address(), ec);
272 0 : if (ec.value() != 0) {
273 0 : OPER_TRACE_ENTRY(Trace, intf_table,
274 : "Error decoding Alias IP address " +
275 : aip->address());
276 : } else {
277 : data->alias_ip_list_.list_.insert
278 0 : (VmInterface::AliasIp(addr, vrf_node->name(), vn_uuid));
279 0 : if (addr.is_v4()) {
280 0 : data->alias_ip_list_.v4_count_++;
281 : } else {
282 0 : data->alias_ip_list_.v6_count_++;
283 : }
284 : }
285 0 : break;
286 : }
287 0 : break;
288 0 : }
289 0 : break;
290 : }
291 0 : return;
292 : }
293 :
294 : // Build list of static-routes on virtual-machine-interface
295 0 : static void BuildStaticRouteList(VmInterfaceConfigData *data, IFMapNode *node) {
296 : InterfaceRouteTable *entry =
297 0 : static_cast<InterfaceRouteTable*>(node->GetObject());
298 0 : assert(entry);
299 :
300 0 : for (std::vector<RouteType>::const_iterator it = entry->routes().begin();
301 0 : it != entry->routes().end(); it++) {
302 : int plen;
303 0 : boost::system::error_code ec;
304 0 : IpAddress ip;
305 0 : bool add = false;
306 :
307 0 : Ip4Address ip4;
308 0 : ec = Ip4PrefixParse(it->prefix, &ip4, &plen);
309 0 : if (ec.value() == 0) {
310 0 : ip = ip4;
311 0 : add = true;
312 : } else {
313 0 : Ip6Address ip6;
314 0 : ec = Inet6PrefixParse(it->prefix, &ip6, &plen);
315 0 : if (ec.value() == 0) {
316 0 : ip = ip6;
317 0 : add = true;
318 : } else {
319 0 : LOG(DEBUG, "Error decoding v4/v6 Static Route address " <<
320 : it->prefix);
321 : }
322 : }
323 :
324 0 : IpAddress gw = IpAddress::from_string(it->next_hop, ec);
325 0 : if (ec) {
326 0 : gw = IpAddress::from_string("0.0.0.0", ec);
327 : }
328 :
329 0 : if (add) {
330 : data->static_route_list_.list_.insert
331 0 : (VmInterface::StaticRoute
332 0 : (ip, plen, AddressList(1, gw.to_v4()),
333 0 : it->community_attributes.community_attribute));
334 : }
335 : }
336 0 : }
337 :
338 0 : static void BuildResolveRoute(VmInterfaceConfigData *data, IFMapNode *node) {
339 : Subnet *entry =
340 0 : static_cast<Subnet *>(node->GetObject());
341 0 : assert(entry);
342 0 : Ip4Address ip;
343 0 : boost::system::error_code ec;
344 0 : ip = Ip4Address::from_string(entry->ip_prefix().ip_prefix, ec);
345 0 : if (ec.value() == 0) {
346 0 : data->subnet_ = ip;
347 0 : data->subnet_plen_ = entry->ip_prefix().ip_prefix_len;
348 : }
349 0 : }
350 :
351 : // Check if VMI is a sub-interface. Sub-interface will have
352 : // sub_interface_vlan_tag property set to non-zero
353 66 : static bool IsVlanSubInterface(VirtualMachineInterface *cfg) {
354 66 : if (cfg->IsPropertySet(VirtualMachineInterface::PROPERTIES) == false)
355 66 : return false;
356 :
357 0 : if (cfg->properties().sub_interface_vlan_tag == 0)
358 0 : return false;
359 :
360 0 : return true;
361 : }
362 :
363 : // Get VLAN if linked to physical interface and router
364 4 : static void BuildInterfaceConfigurationData(Agent *agent,
365 : IFMapNode *node,
366 : uint16_t *rx_vlan_id,
367 : uint16_t *tx_vlan_id,
368 : IFMapNode **li_node,
369 : IFMapNode **phy_interface,
370 : IFMapNode **phy_device) {
371 4 : if (*li_node == NULL) {
372 4 : *li_node = node;
373 : }
374 :
375 4 : if (*phy_interface == NULL) {
376 4 : *phy_interface = agent->config_manager()->
377 4 : FindAdjacentIFMapNode(node, "physical-interface");
378 : // Update li_node if phy_interface is set
379 4 : if (*phy_interface) {
380 4 : *li_node = node;
381 : }
382 : }
383 4 : if (!(*phy_interface)) {
384 0 : *rx_vlan_id = VmInterface::kInvalidVlanId;
385 0 : *tx_vlan_id = VmInterface::kInvalidVlanId;
386 0 : return;
387 : }
388 :
389 4 : if (*phy_device == NULL) {
390 4 : *phy_device =
391 : agent->config_manager()->
392 4 : FindAdjacentIFMapNode(*phy_interface, "physical-router");
393 : }
394 4 : if (!(*phy_device)) {
395 0 : *rx_vlan_id = VmInterface::kInvalidVlanId;
396 0 : *tx_vlan_id = VmInterface::kInvalidVlanId;
397 0 : return;
398 : }
399 :
400 : autogen::LogicalInterface *port =
401 4 : static_cast <autogen::LogicalInterface *>(node->GetObject());
402 4 : if (port->IsPropertySet(autogen::LogicalInterface::VLAN_TAG)) {
403 4 : *rx_vlan_id = port->vlan_tag();
404 4 : *tx_vlan_id = port->vlan_tag();
405 : }
406 : }
407 :
408 0 : static void BuildInterfaceConfigurationDataFromVpg(Agent *agent,
409 : IFMapNode *node,
410 : IFMapNode **vpg_node,
411 : IFMapNode **phy_interface,
412 : IFMapNode **phy_device) {
413 0 : if (*vpg_node == NULL) {
414 0 : *vpg_node = node;
415 : }
416 :
417 : IFMapNode *vpg_pi_node = agent->config_manager()->
418 0 : FindAdjacentIFMapNode(node, "virtual-port-group-physical-interface");
419 0 : if (vpg_pi_node == NULL) {
420 0 : return;
421 : }
422 :
423 0 : if (*phy_interface == NULL) {
424 0 : *phy_interface = agent->config_manager()->
425 0 : FindAdjacentIFMapNode(vpg_pi_node, "physical-interface");
426 : // Update vpg_node if phy_interface is present
427 0 : if (*phy_interface) {
428 0 : *vpg_node = node;
429 : }
430 : }
431 0 : if (*phy_interface == NULL) {
432 0 : return;
433 : }
434 :
435 0 : if (*phy_device == NULL) {
436 0 : *phy_device =
437 : agent->config_manager()->
438 0 : FindAdjacentIFMapNode(*phy_interface, "physical-router");
439 : }
440 0 : if (*phy_device == NULL) {
441 0 : return;
442 : }
443 : }
444 :
445 70 : static void BuildAllowedAddressPairRouteList(VirtualMachineInterface *cfg,
446 : VmInterfaceConfigData *data) {
447 70 : for (std::vector<AllowedAddressPair>::const_iterator it =
448 70 : cfg->allowed_address_pairs().begin();
449 70 : it != cfg->allowed_address_pairs().end(); ++it) {
450 0 : boost::system::error_code ec;
451 0 : int plen = it->ip.ip_prefix_len;
452 0 : IpAddress ip = Ip4Address::from_string(it->ip.ip_prefix, ec);
453 0 : if (ec.value() != 0) {
454 0 : ip = Ip6Address::from_string(it->ip.ip_prefix, ec);
455 : }
456 0 : if (ec.value() != 0) {
457 0 : continue;
458 : }
459 :
460 0 : MacAddress mac = MacAddress::FromString(it->mac, &ec);
461 0 : if (ec.value() != 0) {
462 0 : mac.Zero();
463 : }
464 :
465 0 : if (ip.is_unspecified() && mac == MacAddress::kZeroMac) {
466 0 : continue;
467 : }
468 :
469 0 : bool ecmp = false;
470 0 : if (it->address_mode == "active-active") {
471 0 : ecmp = true;
472 : }
473 :
474 0 : VmInterface::AllowedAddressPair entry(ip, plen, ecmp, mac);
475 0 : data->allowed_address_pair_list_.list_.insert(entry);
476 0 : }
477 70 : }
478 :
479 : // Build VM Interface VRF or one Service Vlan entry for VM Interface
480 58 : static void BuildVrfAndServiceVlanInfo(Agent *agent,
481 : VmInterfaceConfigData *data,
482 : IFMapNode *node) {
483 :
484 58 : ConfigManager *cfg_manager= agent->config_manager();
485 : VirtualMachineInterfaceRoutingInstance *entry =
486 58 : static_cast<VirtualMachineInterfaceRoutingInstance*>(node->GetObject());
487 58 : assert(entry);
488 :
489 : // Ignore node if direction is not yet set. An update will come later
490 58 : const PolicyBasedForwardingRuleType &rule = entry->data();
491 58 : if (rule.direction == "" && !agent->isMockMode()) {
492 0 : return;
493 : }
494 :
495 : // Find VRF by looking for link
496 : // virtual-machine-interface-routing-instance <-> routing-instance
497 58 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
498 58 : DBGraph *graph = table->GetGraph();
499 :
500 : // Iterate thru links looking for routing-instance node
501 58 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
502 78 : iter != node->end(graph); ++iter) {
503 :
504 74 : IFMapNode *vrf_node = static_cast<IFMapNode *>(iter.operator->());
505 74 : if (cfg_manager->SkipNode(vrf_node, agent->cfg()->cfg_vrf_table())) {
506 20 : continue;
507 : }
508 :
509 108 : if (rule.vlan_tag == 0 && rule.protocol == "" &&
510 54 : rule.service_chain_address == "") {
511 54 : data->vrf_name_ = vrf_node->name();
512 : const autogen::RoutingInstance *ri =
513 54 : static_cast<autogen::RoutingInstance *>(vrf_node->GetObject());
514 54 : if (ri->fabric_snat()) {
515 0 : AddFabricFloatingIp(agent, data, Ip4Address(0));
516 : }
517 : } else {
518 0 : if (!rule.service_chain_address.size() &&
519 0 : !rule.ipv6_service_chain_address.size()) {
520 0 : LOG(DEBUG, "Service VLAN IP address not specified for "
521 : << node->name());
522 0 : break;
523 : }
524 0 : boost::system::error_code ec;
525 0 : Ip4Address addr;
526 0 : bool ip_set = true, ip6_set = true;
527 0 : if (rule.service_chain_address.size()) {
528 0 : addr = Ip4Address::from_string(rule.service_chain_address, ec);
529 0 : if (ec.value() != 0) {
530 0 : ip_set = false;
531 0 : LOG(DEBUG, "Error decoding Service VLAN IP address " <<
532 : rule.service_chain_address);
533 : }
534 : }
535 0 : Ip6Address addr6;
536 0 : if (rule.ipv6_service_chain_address.size()) {
537 0 : addr6 = Ip6Address::from_string(rule.ipv6_service_chain_address,
538 0 : ec);
539 0 : if (ec.value() != 0) {
540 0 : ip6_set = false;
541 0 : LOG(DEBUG, "Error decoding Service VLAN IP address " <<
542 : rule.ipv6_service_chain_address);
543 : }
544 : }
545 0 : if (!ip_set && !ip6_set) {
546 0 : break;
547 : }
548 :
549 0 : if (rule.vlan_tag > 4093) {
550 0 : LOG(DEBUG, "Invalid VLAN Tag " << rule.vlan_tag);
551 0 : break;
552 : }
553 :
554 0 : LOG(DEBUG, "Add Service VLAN entry <" << rule.vlan_tag << " : " <<
555 : rule.service_chain_address << " : " << vrf_node->name());
556 :
557 0 : MacAddress smac(agent->vrrp_mac());
558 0 : MacAddress dmac = MacAddress::FromString(Agent::BcastMac());
559 0 : if (rule.src_mac != Agent::NullString()) {
560 0 : smac = MacAddress::FromString(rule.src_mac);
561 : }
562 0 : if (rule.src_mac != Agent::NullString()) {
563 0 : dmac = MacAddress::FromString(rule.dst_mac);
564 : }
565 : data->service_vlan_list_.list_.insert
566 0 : (VmInterface::ServiceVlan(rule.vlan_tag, vrf_node->name(), addr,
567 : addr6, smac, dmac));
568 : }
569 54 : break;
570 : }
571 :
572 58 : return;
573 : }
574 :
575 : // Build proxy-arp flag on VMI
576 : // In future, we expect a proxy-arp flag on VMI. In the meanwhile, we want
577 : // to enable proxy-arp on following,
578 : // 1. Left and right interface of transparent service-chain
579 : // 2. Left and right interface of in-network service-chain
580 : // 3. Left interface of in-network-nat service-chain
581 : //
582 : // The common attribute for all these interface are,
583 : // - They have vrf-assign rules
584 : // - They have service-interface-type attribute
585 : //
586 : // Note: Right interface of in-network-nat will not have vrf-assign
587 70 : static void BuildProxyArpFlags(Agent *agent, VmInterfaceConfigData *data,
588 : VirtualMachineInterface *cfg) {
589 70 : if (cfg->vrf_assign_table().size() == 0)
590 70 : return;
591 :
592 : // Proxy-mode valid only on left or right interface os SI
593 0 : if (cfg->properties().service_interface_type != "left" &&
594 0 : cfg->properties().service_interface_type != "right") {
595 0 : return;
596 : }
597 :
598 0 : data->proxy_arp_mode_ = VmInterface::PROXY_ARP_UNRESTRICTED;
599 : }
600 :
601 9 : static bool ValidateFatFlowCfg(const boost::uuids::uuid &u, const ProtocolType *pt)
602 : {
603 9 : if (pt->source_prefix.ip_prefix.length() > 0) {
604 0 : if (pt->source_prefix.ip_prefix_len < 8) {
605 0 : LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u
606 : << " Protocol:" << pt->protocol << " Port:" << pt->port
607 : << " Plen:" << pt->source_prefix.ip_prefix_len
608 : << " src mask cannot be < 8\n");
609 0 : return false;
610 : }
611 0 : if (pt->source_aggregate_prefix_length < pt->source_prefix.ip_prefix_len) {
612 0 : LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u
613 : << " Protocol:" << pt->protocol << " Port:" << pt->port
614 : << " src aggr plen is less than src mask\n");
615 0 : return false;
616 : }
617 : }
618 9 : if (pt->destination_prefix.ip_prefix.length() > 0) {
619 0 : if (pt->destination_prefix.ip_prefix_len < 8) {
620 0 : LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u
621 : << " Protocol:" << pt->protocol << " Port:" << pt->port
622 : << " Plen:" << pt->destination_prefix.ip_prefix_len
623 : << " dst mask cannot be < 8\n");
624 0 : return false;
625 : }
626 0 : if (pt->destination_aggregate_prefix_length <
627 0 : pt->destination_prefix.ip_prefix_len) {
628 0 : LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u
629 : << " Protocol:" << pt->protocol << " Port:" << pt->port
630 : << " dst aggr plen is less than dst mask\n");
631 0 : return false;
632 : }
633 : }
634 9 : if ((pt->source_prefix.ip_prefix.length() > 0) &&
635 0 : (pt->destination_prefix.ip_prefix.length() > 0)) {
636 0 : IpAddress ip_src = IpAddress::from_string(pt->source_prefix.ip_prefix);
637 0 : IpAddress ip_dst = IpAddress::from_string(pt->destination_prefix.ip_prefix);
638 0 : if ((ip_src.is_v4() && ip_dst.is_v6()) ||
639 0 : (ip_src.is_v6() && ip_dst.is_v4())) {
640 0 : LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u << " Protocol:" << pt->protocol
641 : << " Port:" << pt->port << " src and dst addr family mismatch\n");
642 0 : return false;
643 : }
644 : }
645 9 : return true;
646 : }
647 :
648 70 : static void BuildFatFlowTable(Agent *agent, const boost::uuids::uuid &u,
649 : VmInterfaceConfigData *data, IFMapNode *node) {
650 : VirtualMachineInterface *cfg = static_cast <VirtualMachineInterface *>
651 70 : (node->GetObject());
652 :
653 70 : for (FatFlowProtocols::const_iterator it = cfg->fat_flow_protocols().begin();
654 79 : it != cfg->fat_flow_protocols().end(); it++) {
655 9 : if (!ValidateFatFlowCfg(u, &(*it))) {
656 0 : continue;
657 : }
658 : VmInterface::FatFlowEntry e = VmInterface::FatFlowEntry::MakeFatFlowEntry(
659 9 : it->protocol, it->port,
660 9 : it->ignore_address,
661 9 : it->source_prefix.ip_prefix,
662 9 : it->source_prefix.ip_prefix_len,
663 9 : it->source_aggregate_prefix_length,
664 9 : it->destination_prefix.ip_prefix,
665 9 : it->destination_prefix.ip_prefix_len,
666 18 : it->destination_aggregate_prefix_length);
667 9 : data->fat_flow_list_.Insert(&e);
668 9 : }
669 70 : }
670 :
671 10 : static void BuildInstanceIp(Agent *agent, VmInterfaceConfigData *data,
672 : IFMapNode *node) {
673 10 : InstanceIp *ip = static_cast<InstanceIp *>(node->GetObject());
674 10 : boost::system::error_code err;
675 10 : IpAddress addr = IpAddress::from_string(ip->address(), err);
676 10 : bool is_primary = false;
677 :
678 10 : if (err.value() != 0) {
679 0 : return;
680 : }
681 :
682 20 : if (ip->secondary() != true && ip->service_instance_ip() != true &&
683 10 : ip->service_health_check_ip() != true) {
684 10 : is_primary = true;
685 10 : if (addr.is_v4()) {
686 10 : if (addr == Ip4Address(0)) {
687 0 : return;
688 : }
689 :
690 10 : if (data->addr_ == Ip4Address(0) ||
691 10 : data->addr_ > addr.to_v4()) {
692 10 : data->addr_ = addr.to_v4();
693 10 : if (ip->mode() == "active-active") {
694 4 : data->ecmp_ = true;
695 : } else {
696 6 : data->ecmp_ = false;
697 : }
698 : }
699 0 : } else if (addr.is_v6()) {
700 0 : if (addr == Ip6Address()) {
701 0 : return;
702 : }
703 0 : if (data->ip6_addr_ == Ip6Address() ||
704 0 : data->ip6_addr_ > addr.to_v6()) {
705 0 : data->ip6_addr_ = addr.to_v6();
706 : }
707 0 : if (ip->mode() == "active-active") {
708 0 : data->ecmp6_ = true;
709 : } else {
710 0 : data->ecmp6_ = false;
711 : }
712 : }
713 : }
714 :
715 10 : if (ip->service_instance_ip()) {
716 0 : if (addr.is_v4()) {
717 0 : data->service_ip_ = addr.to_v4();
718 0 : data->service_ip_ecmp_ = false;
719 0 : if (ip->mode() == "active-active") {
720 0 : data->service_ip_ecmp_ = true;
721 : }
722 0 : } else if (addr.is_v6()) {
723 0 : data->service_ip6_ = addr.to_v6();
724 0 : data->service_ip_ecmp6_ = false;
725 0 : if (ip->mode() == "active-active") {
726 0 : data->service_ip_ecmp6_ = true;
727 : }
728 : }
729 : }
730 :
731 10 : bool ecmp = false;
732 10 : if (ip->mode() == "active-active") {
733 4 : ecmp = true;
734 : }
735 :
736 10 : IpAddress tracking_ip = Ip4Address(0);
737 10 : if (ip->secondary() || ip->service_instance_ip()) {
738 0 : tracking_ip = IpAddress::from_string(
739 0 : ip->secondary_ip_tracking_ip().ip_prefix, err);
740 0 : if (err.value() != 0) {
741 0 : tracking_ip = Ip4Address(0);
742 : }
743 :
744 0 : if (tracking_ip == addr) {
745 0 : tracking_ip = Ip4Address(0);
746 : }
747 : }
748 :
749 10 : if (ip->service_health_check_ip()) {
750 : // if instance ip is service health check ip along with adding
751 : // it to instance ip list to allow route export and save it
752 : // under service_health_check_ip_ to allow usage for health
753 : // check service
754 0 : if (addr.is_v4()) {
755 : // TODO: currently only v4 health check is supported
756 0 : data->service_health_check_ip_ = addr;
757 : }
758 : }
759 :
760 10 : if (addr.is_v4()) {
761 10 : data->instance_ipv4_list_.list_.insert(
762 10 : VmInterface::InstanceIp(addr, Address::kMaxV4PrefixLen, ecmp,
763 10 : is_primary, ip->service_instance_ip(),
764 10 : ip->service_health_check_ip(),
765 10 : ip->local_ip(), tracking_ip));
766 : } else {
767 0 : data->instance_ipv6_list_.list_.insert(
768 0 : VmInterface::InstanceIp(addr, Address::kMaxV6PrefixLen, ecmp,
769 0 : is_primary, ip->service_instance_ip(),
770 0 : ip->service_health_check_ip(),
771 0 : ip->local_ip(), tracking_ip));
772 : }
773 : }
774 :
775 0 : static void BuildTagList(VmInterface::TagEntryList *tag_list, IFMapNode *node) {
776 :
777 0 : Tag *tag_cfg = static_cast<Tag *>(node->GetObject());
778 0 : assert(tag_cfg);
779 :
780 0 : uuid tag_uuid = nil_uuid();
781 0 : autogen::IdPermsType id_perms = tag_cfg->id_perms();
782 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
783 : tag_uuid);
784 0 : uint64_t tag_type = TagEntry::GetTypeVal(tag_cfg->type_name(),
785 : tag_cfg->id());
786 0 : tag_list->list_.insert(VmInterface::TagEntry(tag_type, tag_uuid));
787 0 : }
788 :
789 3 : static void BuildSgList(VmInterfaceConfigData *data, IFMapNode *node) {
790 : SecurityGroup *sg_cfg = static_cast<SecurityGroup *>
791 3 : (node->GetObject());
792 3 : assert(sg_cfg);
793 3 : autogen::IdPermsType id_perms = sg_cfg->id_perms();
794 3 : uint32_t sg_id = sg_cfg->id();
795 3 : if (sg_id != SgTable::kInvalidSgId) {
796 3 : uuid sg_uuid = nil_uuid();
797 3 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
798 : sg_uuid);
799 : data->sg_list_.list_.insert
800 3 : (VmInterface::SecurityGroupEntry(sg_uuid));
801 : }
802 3 : }
803 :
804 0 : static bool BuildBridgeDomainVrfTable(Agent *agent, IFMapNode *vn_node) {
805 :
806 0 : ConfigManager *cfg_manager= agent->config_manager();
807 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
808 0 : DBGraph *graph = table->GetGraph();
809 :
810 : // Iterate thru links for virtual-network looking for routing-instance
811 0 : for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
812 0 : iter != vn_node->end(graph); ++iter) {
813 :
814 0 : IFMapNode *vrf_node = static_cast<IFMapNode *>(iter.operator->());
815 0 : if (cfg_manager->SkipNode(vrf_node, agent->cfg()->cfg_vrf_table())) {
816 0 : continue;
817 : }
818 :
819 : // We are interested only in default-vrf
820 : RoutingInstance *ri = static_cast<RoutingInstance *>
821 0 : (vrf_node->GetObject());
822 0 : if(ri->is_default()) {
823 0 : return true;
824 : }
825 : }
826 :
827 0 : return false;
828 : }
829 :
830 0 : static bool BuildBridgeDomainVnTable(Agent *agent,
831 : IFMapNode *bridge_domain_node) {
832 :
833 0 : ConfigManager *cfg_manager= agent->config_manager();
834 : IFMapAgentTable *table =
835 0 : static_cast<IFMapAgentTable *>(bridge_domain_node->table());
836 0 : DBGraph *graph = table->GetGraph();
837 :
838 : // Iterate thru links for virtual-network fron bridge domain
839 0 : for (DBGraphVertex::adjacency_iterator iter =
840 0 : bridge_domain_node->begin(graph);
841 0 : iter != bridge_domain_node->end(graph); ++iter) {
842 :
843 0 : IFMapNode *vn_node = static_cast<IFMapNode *>(iter.operator->());
844 0 : if (cfg_manager->SkipNode(vn_node, agent->cfg()->cfg_vn_table())) {
845 0 : continue;
846 : }
847 :
848 0 : if (BuildBridgeDomainVrfTable(agent, vn_node) == true) {
849 0 : return true;
850 : }
851 : }
852 0 : return false;
853 : }
854 :
855 0 : static void UpdateVmiSiMode(Agent *agent, VmInterfaceConfigData *data,
856 : IFMapNode *node) {
857 :
858 0 : ServiceInstance *entry = static_cast<ServiceInstance*>(node->GetObject());
859 0 : assert(entry);
860 :
861 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
862 0 : DBGraph *graph = table->GetGraph();
863 :
864 0 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
865 0 : iter != node->end(graph); ++iter) {
866 :
867 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
868 0 : if (agent->config_manager()->SkipNode(adj_node)) {
869 0 : continue;
870 : }
871 0 : if (adj_node->table() != agent->cfg()->cfg_service_template_table()) {
872 0 : continue;
873 : }
874 0 : ServiceTemplate *entry = static_cast<ServiceTemplate*>(adj_node->GetObject());
875 0 : if (entry == NULL)
876 0 : return;
877 :
878 0 : ServiceTemplateType svc_template_props = entry->properties();
879 0 : string service_mode = svc_template_props.service_mode;
880 :
881 0 : if (service_mode == "in-network") {
882 0 : data->service_mode_ = VmInterface::ROUTED_MODE;
883 0 : } else if (service_mode == "transparent") {
884 0 : data->service_mode_ = VmInterface::BRIDGE_MODE;
885 0 : } else if (service_mode == "in-network-nat") {
886 0 : data->service_mode_ = VmInterface::ROUTED_NAT_MODE;
887 : } else {
888 0 : data->service_mode_ = VmInterface::SERVICE_MODE_ERROR;
889 : }
890 0 : }
891 : }
892 :
893 0 : static void BuildVmiSiMode(Agent *agent, VmInterfaceConfigData *data,
894 : IFMapNode *node) {
895 :
896 0 : PortTuple *entry = static_cast<PortTuple*>(node->GetObject());
897 0 : assert(entry);
898 :
899 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
900 0 : DBGraph *graph = table->GetGraph();
901 :
902 0 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
903 0 : iter != node->end(graph); ++iter) {
904 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
905 0 : if (adj_node->table() != agent->cfg()->cfg_service_instance_table()) {
906 0 : continue;
907 : }
908 0 : UpdateVmiSiMode(agent, data, adj_node);
909 : }
910 0 : }
911 :
912 0 : static bool BuildLogicalRouterData(Agent *agent,
913 : VmInterfaceConfigData *data,
914 : IFMapNode *node) {
915 : VirtualMachineInterface *vmi =
916 : static_cast<autogen::VirtualMachineInterface *>
917 0 : (node->GetObject());
918 0 : if (!vmi->IsPropertySet(VirtualMachineInterface::DEVICE_OWNER)) {
919 0 : return false;
920 : }
921 0 : if (vmi->device_owner() != VMI_NETWORK_ROUTER_INTERFACE) {
922 0 : return false;
923 : }
924 0 : return true;
925 : }
926 :
927 0 : static void BuildSiOtherVmi(Agent *agent, VmInterfaceConfigData *data,
928 : IFMapNode *node, const string &s_intf_type) {
929 0 : PortTuple *entry = static_cast<PortTuple*>(node->GetObject());
930 0 : assert(entry);
931 :
932 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
933 0 : DBGraph *graph = table->GetGraph();
934 :
935 0 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
936 0 : iter != node->end(graph); ++iter) {
937 :
938 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
939 0 : if (agent->config_manager()->SkipNode(adj_node)) {
940 0 : continue;
941 : }
942 0 : if (adj_node->table() != agent->cfg()->cfg_vm_interface_table()) {
943 0 : continue;
944 : }
945 : VirtualMachineInterface *cfg = static_cast <VirtualMachineInterface *>
946 0 : (adj_node->GetObject());
947 0 : if (!cfg->IsPropertySet(VirtualMachineInterface::PROPERTIES)) {
948 0 : continue;
949 : }
950 :
951 0 : string interface_to_find = "right";
952 0 : if (s_intf_type == "right") {
953 0 : interface_to_find = "left";
954 : }
955 0 : const string &cfg_intf_type = cfg->properties().service_interface_type;
956 0 : if (cfg_intf_type != interface_to_find) {
957 0 : continue;
958 : }
959 :
960 0 : data->is_left_si_ = (interface_to_find == "right") ? true : false;
961 0 : data->si_other_end_vmi_ = nil_uuid();
962 0 : autogen::IdPermsType id_perms = cfg->id_perms();
963 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
964 0 : data->si_other_end_vmi_);
965 : /* No further iterations required for setting data->si_other_end_vmi */
966 0 : break;
967 0 : }
968 0 : }
969 :
970 : // Build VM Interface bridge domain link
971 0 : static void BuildBridgeDomainTable(Agent *agent,
972 : VmInterfaceConfigData *data,
973 : IFMapNode *node) {
974 :
975 0 : ConfigManager *cfg_manager= agent->config_manager();
976 : VirtualMachineInterfaceBridgeDomain *entry =
977 0 : static_cast<VirtualMachineInterfaceBridgeDomain*>(node->GetObject());
978 0 : assert(entry);
979 :
980 0 : const BridgeDomainMembershipType &vlan = entry->data();
981 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
982 0 : DBGraph *graph = table->GetGraph();
983 :
984 0 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
985 0 : iter != node->end(graph); ++iter) {
986 :
987 : IFMapNode *bridge_domain_node =
988 0 : static_cast<IFMapNode *>(iter.operator->());
989 0 : if (cfg_manager->SkipNode
990 0 : (bridge_domain_node, agent->cfg()->cfg_bridge_domain_table())) {
991 0 : continue;
992 : }
993 :
994 : //Verify that bridge domain has link to VN and VRF
995 : //then insert in config node list
996 0 : if (BuildBridgeDomainVnTable(agent, bridge_domain_node) == false) {
997 0 : continue;
998 : }
999 : autogen::BridgeDomain *bd_cfg = static_cast<autogen::BridgeDomain *>
1000 0 : (bridge_domain_node->GetObject());
1001 0 : if (bd_cfg->isid() == 0) {
1002 0 : continue;
1003 : }
1004 0 : autogen::IdPermsType id_perms = bd_cfg->id_perms();
1005 0 : uuid bd_uuid = nil_uuid();
1006 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1007 : bd_uuid);
1008 0 : data->bridge_domain_list_.list_.insert(
1009 0 : VmInterface::BridgeDomain(bd_uuid, vlan.vlan_tag));
1010 :
1011 0 : if (bd_cfg->mac_learning_enabled()) {
1012 0 : data->learning_enabled_ = true;
1013 : }
1014 0 : break;
1015 0 : }
1016 0 : return;
1017 : }
1018 :
1019 70 : static void CompareVnVm(const uuid &vmi_uuid, VmInterfaceConfigData *data,
1020 : const PortSubscribeEntry *entry) {
1021 : /* VN uuid is mandatory for port adds from REST API only for port type of
1022 : * PortSubscribeEntry::VMPORT. Hence VN match check should be done only for
1023 : * port type of PortSubscribeEntry::VMPORT
1024 : */
1025 108 : if (entry && entry->type() == PortSubscribeEntry::VMPORT &&
1026 38 : (entry->MatchVn(data->vn_uuid_) == false)) {
1027 19 : IFMAP_ERROR(InterfaceConfiguration,
1028 : "Virtual-network UUID mismatch for interface:",
1029 : UuidToString(vmi_uuid),
1030 : "configuration VN uuid",
1031 : UuidToString(data->vn_uuid_),
1032 : "compute VN uuid",
1033 : UuidToString(entry->vn_uuid()));
1034 : }
1035 :
1036 70 : if (entry && (entry->MatchVm(data->vm_uuid_) == false)) {
1037 0 : IFMAP_ERROR(InterfaceConfiguration,
1038 : "Virtual-machine UUID mismatch for interface:",
1039 : UuidToString(vmi_uuid),
1040 : "configuration VM UUID is",
1041 : UuidToString(data->vm_uuid_),
1042 : "compute VM uuid is",
1043 : UuidToString(entry->vm_uuid()));
1044 : }
1045 70 : }
1046 :
1047 62 : static void BuildVn(VmInterfaceConfigData *data,
1048 : IFMapNode *node,
1049 : const boost::uuids::uuid &u,
1050 : VmInterface::TagEntryList *tag_list) {
1051 62 : const Agent *agent = data->agent();
1052 : VirtualNetwork *vn =
1053 62 : static_cast<VirtualNetwork *>(node->GetObject());
1054 62 : assert(vn);
1055 62 : autogen::IdPermsType id_perms = vn->id_perms();
1056 62 : CfgUuidSet(id_perms.uuid.uuid_mslong,
1057 62 : id_perms.uuid.uuid_lslong, data->vn_uuid_);
1058 :
1059 62 : if (node->name() == agent->fabric_vn_name()) {
1060 0 : data->proxy_arp_mode_ = VmInterface::PROXY_ARP_UNRESTRICTED;
1061 : }
1062 :
1063 : /* Copy fat-flow configured at VN level */
1064 62 : for (FatFlowProtocols::const_iterator it = vn->fat_flow_protocols().begin();
1065 62 : it != vn->fat_flow_protocols().end(); it++) {
1066 0 : if (!ValidateFatFlowCfg(u, &(*it))) {
1067 0 : continue;
1068 : }
1069 :
1070 : VmInterface::FatFlowEntry e = VmInterface::FatFlowEntry::MakeFatFlowEntry(
1071 0 : it->protocol, it->port,
1072 0 : it->ignore_address,
1073 0 : it->source_prefix.ip_prefix,
1074 0 : it->source_prefix.ip_prefix_len,
1075 0 : it->source_aggregate_prefix_length,
1076 0 : it->destination_prefix.ip_prefix,
1077 0 : it->destination_prefix.ip_prefix_len,
1078 0 : it->destination_aggregate_prefix_length);
1079 0 : data->fat_flow_list_.Insert(&e);
1080 0 : }
1081 62 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1082 62 : for (DBGraphVertex::adjacency_iterator iter =
1083 62 : node->begin(table->GetGraph());
1084 300 : iter != node->end(table->GetGraph()); ++iter) {
1085 :
1086 238 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
1087 238 : if (agent->config_manager()->CanUseNode(adj_node,
1088 : agent->cfg()->cfg_vn_table())) {
1089 0 : if (adj_node->name() == agent->fabric_vn_name()) {
1090 0 : data->proxy_arp_mode_ = VmInterface::PROXY_ARP_UNRESTRICTED;
1091 : }
1092 : }
1093 :
1094 238 : if (agent->config_manager()->SkipNode(adj_node,
1095 : agent->cfg()->cfg_tag_table())) {
1096 238 : continue;
1097 : }
1098 0 : BuildTagList(tag_list, adj_node);
1099 : }
1100 :
1101 62 : data->mac_ip_learning_enable_ = vn->mac_ip_learning_enable();
1102 62 : }
1103 :
1104 70 : static void FillHbsInfo(VmInterfaceConfigData *data,
1105 : IFMapNode *vn_node) {
1106 : //Reset the hbs interface
1107 70 : data->hbs_intf_type_ = VmInterface::HBS_INTF_INVALID;
1108 :
1109 70 : if (vn_node == NULL) {
1110 8 : return;
1111 : }
1112 :
1113 62 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
1114 62 : DBGraph *graph = table->GetGraph();
1115 :
1116 : //Get the HBS information from project
1117 62 : for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
1118 300 : iter != vn_node->end(graph); ++iter) {
1119 238 : if (iter->IsDeleted()) {
1120 0 : continue;
1121 : }
1122 238 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
1123 : //Check if HBS service is enabled for this project
1124 238 : if (strcmp(adj_node->table()->Typename(),
1125 238 : "host-based-service-virtual-network") == 0) {
1126 : autogen::HostBasedServiceVirtualNetwork *hbsvn =
1127 0 : static_cast<HostBasedServiceVirtualNetwork *>(adj_node->GetObject());
1128 0 : ServiceVirtualNetworkType type = hbsvn->data();
1129 0 : if (strcmp(type.virtual_network_type.c_str(),
1130 0 : "right") == 0) {
1131 0 : data->hbs_intf_type_ = VmInterface::HBS_INTF_RIGHT;
1132 0 : } else if (strcmp(type.virtual_network_type.c_str(),
1133 0 : "left") == 0) {
1134 0 : data->hbs_intf_type_ = VmInterface::HBS_INTF_LEFT;
1135 0 : } else if (strcmp(type.virtual_network_type.c_str(),
1136 0 : "management") == 0) {
1137 0 : data->hbs_intf_type_ = VmInterface::HBS_INTF_MGMT;
1138 : }
1139 0 : }
1140 : }
1141 : }
1142 :
1143 0 : static void BuildProject(VmInterfaceConfigData *data,
1144 : IFMapNode *node,
1145 : const boost::uuids::uuid &u,
1146 : VmInterface::TagEntryList *tag_list) {
1147 0 : const Agent *agent = data->agent();
1148 0 : Project *pr = static_cast<Project *>(node->GetObject());
1149 0 : assert(pr);
1150 :
1151 : //We parse thru edge table while getting tag attached to project
1152 : //This is done because project to tag has 2 links
1153 : //1> With metadata project-scoped-tag this is used to create tag
1154 : // specific to project
1155 : //2> Another with metadata project-tag which signifies that tag
1156 : // is attached to project
1157 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1158 0 : for (DBGraphVertex::edge_iterator iter =
1159 0 : node->edge_list_begin(table->GetGraph());
1160 0 : iter != node->edge_list_end(table->GetGraph()); ++iter) {
1161 :
1162 0 : IFMapLink *link = static_cast<IFMapLink *>(iter.operator->());
1163 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.target());
1164 0 : if (link->metadata() != "project-tag") {
1165 0 : continue;
1166 : }
1167 :
1168 0 : if (agent->config_manager()->SkipNode(adj_node,
1169 : agent->cfg()->cfg_tag_table())) {
1170 0 : continue;
1171 : }
1172 0 : BuildTagList(tag_list, adj_node);
1173 : }
1174 0 : }
1175 :
1176 0 : static void BuildQosConfig(VmInterfaceConfigData *data, IFMapNode *node) {
1177 : autogen::QosConfig *qc =
1178 0 : static_cast<autogen::QosConfig *>(node->GetObject());
1179 0 : assert(qc);
1180 0 : autogen::IdPermsType id_perms = qc->id_perms();
1181 0 : CfgUuidSet(id_perms.uuid.uuid_mslong,
1182 0 : id_perms.uuid.uuid_lslong, data->qos_config_uuid_);
1183 0 : }
1184 :
1185 70 : static void BuildVm(VmInterfaceConfigData *data,
1186 : IFMapNode *node,
1187 : const boost::uuids::uuid &u,
1188 : VmInterface::TagEntryList *tag_list) {
1189 70 : const Agent *agent = data->agent();
1190 70 : VirtualMachine *vm = static_cast<VirtualMachine *>(node->GetObject());
1191 70 : assert(vm);
1192 :
1193 70 : autogen::IdPermsType id_perms = vm->id_perms();
1194 70 : CfgUuidSet(id_perms.uuid.uuid_mslong,
1195 70 : id_perms.uuid.uuid_lslong, data->vm_uuid_);
1196 :
1197 :
1198 70 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1199 70 : for (DBGraphVertex::adjacency_iterator iter =
1200 70 : node->begin(table->GetGraph());
1201 146 : iter != node->end(table->GetGraph()); ++iter) {
1202 :
1203 76 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
1204 76 : if (agent->config_manager()->SkipNode(adj_node,
1205 : agent->cfg()->cfg_tag_table())) {
1206 76 : continue;
1207 : }
1208 0 : BuildTagList(tag_list, adj_node);
1209 : }
1210 70 : }
1211 :
1212 : // Get DHCP configuration
1213 70 : static void ReadDhcpOptions(VirtualMachineInterface *cfg,
1214 : VmInterfaceConfigData &data) {
1215 70 : data.oper_dhcp_options_.set_options(cfg->dhcp_option_list());
1216 70 : data.oper_dhcp_options_.set_host_routes(cfg->host_routes());
1217 70 : }
1218 :
1219 : // Get interface mirror configuration.
1220 70 : static void ReadAnalyzerNameAndCreate(Agent *agent,
1221 : VirtualMachineInterface *cfg,
1222 : VmInterfaceConfigData &data) {
1223 70 : if (!cfg) {
1224 70 : return;
1225 : }
1226 70 : MirrorActionType mirror_to = cfg->properties().interface_mirror.mirror_to;
1227 70 : if (mirror_to.analyzer_name.empty())
1228 70 : return;
1229 : // Check for nic assisted mirroring support.
1230 0 : if (!mirror_to.nic_assisted_mirroring) {
1231 0 : boost::system::error_code ec;
1232 : IpAddress dip = IpAddress::from_string(mirror_to.analyzer_ip_address,
1233 0 : ec);
1234 0 : if (ec.value() != 0) {
1235 0 : return;
1236 : }
1237 : uint16_t dport;
1238 0 : if (mirror_to.udp_port) {
1239 0 : dport = mirror_to.udp_port;
1240 : } else {
1241 0 : dport = ContrailPorts::AnalyzerUdpPort();
1242 : }
1243 : MirrorEntryData::MirrorEntryFlags mirror_flag =
1244 0 : MirrorTable::DecodeMirrorFlag(mirror_to.nh_mode,
1245 0 : mirror_to.juniper_header);
1246 : // not using the vrf coming in; by setting this to empty, -1 will be
1247 : // configured so that current VRF will be used (for leaked routes).
1248 0 : if (mirror_flag == MirrorEntryData::DynamicNH_With_JuniperHdr) {
1249 0 : agent->mirror_table()->AddMirrorEntry
1250 0 : (mirror_to.analyzer_name, std::string(),
1251 0 : agent->GetMirrorSourceIp(dip),
1252 0 : agent->mirror_port(), dip, dport);
1253 0 : } else if (mirror_flag ==
1254 : MirrorEntryData::DynamicNH_Without_JuniperHdr) {
1255 0 : agent->mirror_table()->AddMirrorEntry(mirror_to.analyzer_name,
1256 0 : mirror_to.routing_instance, agent->GetMirrorSourceIp(dip),
1257 0 : agent->mirror_port(), dip, dport, 0, mirror_flag,
1258 0 : MacAddress::FromString(mirror_to.analyzer_mac_address));
1259 0 : } else if (mirror_flag ==
1260 : MirrorEntryData::StaticNH_Without_JuniperHdr) {
1261 : IpAddress vtep_dip = IpAddress::from_string
1262 0 : (mirror_to.static_nh_header.vtep_dst_ip_address, ec);
1263 0 : if (ec.value() != 0) {
1264 0 : return;
1265 : }
1266 0 : agent->mirror_table()->AddMirrorEntry(mirror_to.analyzer_name,
1267 0 : mirror_to.routing_instance, agent->GetMirrorSourceIp(dip),
1268 0 : agent->mirror_port(), vtep_dip, dport,
1269 0 : mirror_to.static_nh_header.vni, mirror_flag,
1270 : MacAddress::FromString
1271 0 : (mirror_to.static_nh_header.vtep_dst_mac_address));
1272 : }
1273 : else {
1274 0 : LOG(ERROR, "Mirror nh mode not supported");
1275 : }
1276 : } else {
1277 0 : agent->mirror_table()->AddMirrorEntry(
1278 : mirror_to.analyzer_name,
1279 0 : mirror_to.nic_assisted_mirroring_vlan);
1280 : }
1281 0 : data.analyzer_name_ = mirror_to.analyzer_name;
1282 : string traffic_direction =
1283 0 : cfg->properties().interface_mirror.traffic_direction;
1284 0 : if (traffic_direction.compare("egress") == 0) {
1285 0 : data.mirror_direction_ = Interface::MIRROR_TX;
1286 0 : } else if (traffic_direction.compare("ingress") == 0) {
1287 0 : data.mirror_direction_ = Interface::MIRROR_RX;
1288 : } else {
1289 0 : data.mirror_direction_ = Interface::MIRROR_RX_TX;
1290 : }
1291 70 : }
1292 :
1293 70 : static void BuildVrfAssignRule(VirtualMachineInterface *cfg,
1294 : VmInterfaceConfigData *data) {
1295 70 : uint32_t id = 1;
1296 70 : for (std::vector<VrfAssignRuleType>::const_iterator iter =
1297 140 : cfg->vrf_assign_table().begin(); iter != cfg->vrf_assign_table().end();
1298 0 : ++iter) {
1299 0 : VmInterface::VrfAssignRule entry(id++, iter->match_condition,
1300 0 : iter->routing_instance,
1301 0 : iter->ignore_acl);
1302 0 : data->vrf_assign_rule_list_.list_.insert(entry);
1303 0 : }
1304 70 : }
1305 :
1306 10 : static IFMapNode *FindTarget(IFMapAgentTable *table, IFMapNode *node,
1307 : const std::string &node_type) {
1308 10 : for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
1309 10 : it != node->end(table->GetGraph()); ++it) {
1310 10 : IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
1311 10 : if (adj_node->table()->Typename() == node_type)
1312 10 : return adj_node;
1313 : }
1314 0 : return NULL;
1315 : }
1316 :
1317 10 : static void ReadDhcpEnable(Agent *agent, VmInterfaceConfigData *data,
1318 : IFMapNode *node) {
1319 10 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1320 10 : for (DBGraphVertex::adjacency_iterator it = node->begin(table->GetGraph());
1321 63 : it != node->end(table->GetGraph()); ++it) {
1322 53 : IFMapNode *adj_node = static_cast<IFMapNode *>(it.operator->());
1323 53 : IFMapNode *ipam_node = NULL;
1324 63 : if (adj_node->table() == agent->cfg()->cfg_vn_network_ipam_table() &&
1325 63 : (ipam_node = FindTarget(table, adj_node, "network-ipam"))) {
1326 : VirtualNetworkNetworkIpam *ipam =
1327 10 : static_cast<VirtualNetworkNetworkIpam *>(adj_node->GetObject());
1328 10 : assert(ipam);
1329 10 : const VnSubnetsType &subnets = ipam->data();
1330 10 : boost::system::error_code ec;
1331 20 : for (unsigned int i = 0; i < subnets.ipam_subnets.size(); ++i) {
1332 10 : if (IsIp4SubnetMember(data->addr_,
1333 0 : Ip4Address::from_string(
1334 10 : subnets.ipam_subnets[i].subnet.ip_prefix, ec),
1335 20 : subnets.ipam_subnets[i].subnet.ip_prefix_len) && data->addr_ != Ip4Address(0)) {
1336 10 : data->dhcp_enable_ = subnets.ipam_subnets[i].enable_dhcp;
1337 : }
1338 0 : else if (IsIp6SubnetMember(data->ip6_addr_,
1339 0 : (Ip6Address::from_string(
1340 0 : subnets.ipam_subnets[i].subnet.ip_prefix, ec)),
1341 0 : subnets.ipam_subnets[i].subnet.ip_prefix_len)) {
1342 0 : data->dhcp_enable_v6_ = subnets.ipam_subnets[i].enable_dhcp;
1343 : }
1344 :
1345 : }
1346 : }
1347 : }
1348 10 : }
1349 :
1350 :
1351 :
1352 : // Builds parent for VMI (not to be confused with parent ifmap-node)
1353 : // Possible values are,
1354 : // - logical-interface or virtual-port-group : Incase of baremetals
1355 : // logical-interface would be examined before virtual-port-group
1356 : // - virtual-machine-interface : We support virtual-machine-interface
1357 : // sub-interfaces. In this case, another virtual-machine-interface itself
1358 : // can be a parent
1359 70 : static PhysicalRouter *BuildParentInfo(Agent *agent,
1360 : VirtualMachineInterface *cfg,
1361 : IFMapNode *node,
1362 : IFMapNode *logical_node,
1363 : IFMapNode *vpg_node,
1364 : VmInterfaceConfigData *data,
1365 : IFMapNode *parent_vmi_node,
1366 : IFMapNode **phy_interface,
1367 : IFMapNode **phy_device) {
1368 70 : if (logical_node) {
1369 4 : if (*phy_interface) {
1370 4 : data->physical_interface_ = (*phy_interface)->name();
1371 : }
1372 : agent->interface_table()->
1373 4 : LogicalInterfaceIFNodeToUuid(logical_node, data->logical_interface_);
1374 4 : if ((*phy_device) == NULL) {
1375 0 : return NULL;
1376 : }
1377 4 : return static_cast<PhysicalRouter *>((*phy_device)->GetObject());
1378 : }
1379 :
1380 66 : if (vpg_node) {
1381 0 : if (*phy_interface) {
1382 0 : data->physical_interface_ = (*phy_interface)->name();
1383 : }
1384 0 : if (IsVlanSubInterface(cfg) == true) {
1385 0 : data->rx_vlan_id_ = cfg->properties().sub_interface_vlan_tag;
1386 0 : data->tx_vlan_id_ = cfg->properties().sub_interface_vlan_tag;
1387 : }
1388 0 : if ((*phy_device) == NULL) {
1389 0 : return NULL;
1390 : }
1391 0 : return static_cast<PhysicalRouter *>((*phy_device)->GetObject());
1392 : }
1393 :
1394 : // Check if this is VLAN sub-interface VMI
1395 66 : if (IsVlanSubInterface(cfg) == false) {
1396 66 : return NULL;
1397 : }
1398 :
1399 0 : if (!parent_vmi_node)
1400 0 : return NULL;
1401 :
1402 : // process Parent VMI for sub-interface
1403 : VirtualMachineInterface *parent_cfg =
1404 0 : static_cast <VirtualMachineInterface *> (parent_vmi_node->GetObject());
1405 0 : assert(parent_cfg);
1406 0 : if (IsVlanSubInterface(parent_cfg)) {
1407 0 : return NULL;
1408 : }
1409 0 : autogen::IdPermsType id_perms = parent_cfg->id_perms();
1410 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1411 0 : data->parent_vmi_);
1412 0 : data->rx_vlan_id_ = cfg->properties().sub_interface_vlan_tag;
1413 0 : data->tx_vlan_id_ = cfg->properties().sub_interface_vlan_tag;
1414 0 : return NULL;
1415 0 : }
1416 :
1417 70 : static void BuildEcmpHashingIncludeFields(VirtualMachineInterface *cfg,
1418 : IFMapNode *vn_node,
1419 : VmInterfaceConfigData *data) {
1420 70 : data->ecmp_load_balance_.set_use_global_vrouter(false);
1421 70 : if (cfg->IsPropertySet
1422 70 : (VirtualMachineInterface::ECMP_HASHING_INCLUDE_FIELDS) &&
1423 0 : (cfg->ecmp_hashing_include_fields().hashing_configured)) {
1424 0 : data->ecmp_load_balance_.UpdateFields(cfg->
1425 0 : ecmp_hashing_include_fields());
1426 : } else {
1427 : //Extract from VN
1428 70 : if (!vn_node) {
1429 8 : data->ecmp_load_balance_.reset();
1430 8 : data->ecmp_load_balance_.set_use_global_vrouter(true);
1431 8 : return;
1432 : }
1433 : VirtualNetwork *vn_cfg =
1434 62 : static_cast <VirtualNetwork *> (vn_node->GetObject());
1435 62 : if ((vn_cfg->IsPropertySet
1436 62 : (VirtualNetwork::ECMP_HASHING_INCLUDE_FIELDS) == false) ||
1437 0 : (vn_cfg->ecmp_hashing_include_fields().hashing_configured == false)) {
1438 62 : data->ecmp_load_balance_.set_use_global_vrouter(true);
1439 62 : data->ecmp_load_balance_.reset();
1440 62 : return;
1441 : }
1442 0 : data->ecmp_load_balance_.UpdateFields(vn_cfg->
1443 0 : ecmp_hashing_include_fields());
1444 : }
1445 :
1446 : }
1447 :
1448 : // Get IGMP configuration
1449 70 : static void ReadIgmpConfig(Agent *agent, const IFMapNode *vn_node,
1450 : const VirtualMachineInterface *cfg,
1451 : VmInterfaceConfigData *data) {
1452 :
1453 70 : const VirtualNetwork *vn = NULL;
1454 70 : bool igmp_enabled = false;
1455 :
1456 70 : if (vn_node) {
1457 62 : vn = static_cast<const VirtualNetwork *>(vn_node->GetObject());
1458 : }
1459 :
1460 70 : if (cfg) igmp_enabled = cfg->igmp_enable();
1461 :
1462 70 : if (vn && !igmp_enabled) igmp_enabled = vn->igmp_enable();
1463 :
1464 70 : if (!igmp_enabled) {
1465 : igmp_enabled =
1466 70 : agent->oper_db()->global_system_config()->cfg_igmp_enable();
1467 : }
1468 :
1469 70 : data->cfg_igmp_enable_ = cfg->igmp_enable();
1470 70 : data->igmp_enabled_ = igmp_enabled;
1471 :
1472 70 : return;
1473 : }
1474 :
1475 : // max_flows is read from vmi properties preferentially , else vn properties
1476 70 : static void ReadMaxFlowsConfig(const IFMapNode *vn_node,
1477 : const VirtualMachineInterface *cfg,
1478 : VmInterfaceConfigData *data) {
1479 :
1480 70 : const VirtualNetwork *vn = NULL;
1481 70 : if (vn_node) {
1482 62 : vn = static_cast<const VirtualNetwork *>(vn_node->GetObject());
1483 : }
1484 :
1485 70 : if (cfg->IsPropertySet(VirtualMachineInterface::PROPERTIES)) {
1486 0 : data->max_flows_ = cfg->properties().max_flows;
1487 : }
1488 70 : if (vn && (data->max_flows_ == 0)) {
1489 62 : autogen::VirtualNetworkType properties = vn->properties();
1490 62 : data->max_flows_ = properties.max_flows;
1491 :
1492 62 : }
1493 70 : }
1494 :
1495 70 : static void BuildAttributes(Agent *agent, IFMapNode *node,
1496 : VirtualMachineInterface *cfg,
1497 : VmInterfaceConfigData *data) {
1498 : //Extract the local preference
1499 70 : if (cfg->IsPropertySet(VirtualMachineInterface::PROPERTIES)) {
1500 0 : data->local_preference_ = cfg->properties().local_preference;
1501 : }
1502 :
1503 70 : ReadAnalyzerNameAndCreate(agent, cfg, *data);
1504 :
1505 : // Fill DHCP option data
1506 70 : ReadDhcpOptions(cfg, *data);
1507 :
1508 : //Fill config data items
1509 70 : data->cfg_name_ = node->name();
1510 70 : data->admin_state_ = cfg->id_perms().enable;
1511 :
1512 70 : BuildVrfAssignRule(cfg, data);
1513 70 : BuildAllowedAddressPairRouteList(cfg, data);
1514 :
1515 70 : if (cfg->mac_addresses().size()) {
1516 0 : data->vm_mac_ = cfg->mac_addresses().at(0);
1517 : }
1518 70 : data->disable_policy_ = cfg->disable_policy();
1519 70 : BuildProxyArpFlags(agent, data, cfg);
1520 70 : }
1521 :
1522 70 : static void UpdateAttributes(Agent *agent, VmInterfaceConfigData *data) {
1523 : // Compute fabric_port_ and need_linklocal_ip_ flags
1524 70 : data->fabric_port_ = false;
1525 70 : data->need_linklocal_ip_ = true;
1526 140 : if (data->vrf_name_ == agent->fabric_vrf_name() ||
1527 70 : data->vrf_name_ == agent->linklocal_vrf_name()) {
1528 0 : data->fabric_port_ = true;
1529 0 : data->need_linklocal_ip_ = false;
1530 : }
1531 :
1532 70 : if (agent->isXenMode()) {
1533 0 : data->need_linklocal_ip_ = false;
1534 : }
1535 70 : }
1536 :
1537 70 : static void ComputeTypeInfo(Agent *agent, VmInterfaceConfigData *data,
1538 : const PortSubscribeEntry *entry,
1539 : PhysicalRouter *prouter,
1540 : IFMapNode *node, IFMapNode *logical_node,
1541 : IFMapNode *logical_router) {
1542 70 : if (entry != NULL) {
1543 : // Have got InstancePortAdd message. Treat it as VM_ON_TAP by default
1544 : // TODO: Need to identify more cases here
1545 38 : data->device_type_ = VmInterface::VM_ON_TAP;
1546 38 : data->vmi_type_ = VmInterface::INSTANCE;
1547 38 : return;
1548 : }
1549 :
1550 : VirtualMachineInterface *cfg = static_cast <VirtualMachineInterface *>
1551 32 : (node->GetObject());
1552 32 : const std::vector<KeyValuePair> &bindings = cfg->bindings();
1553 32 : bool vnic_type_direct = false;
1554 32 : bool vif_type_hw_veb = false;
1555 32 : for (std::vector<KeyValuePair>::const_iterator it = bindings.begin();
1556 32 : it != bindings.end(); ++it) {
1557 0 : KeyValuePair kvp = *it;
1558 0 : if ((kvp.key == "vnic_type") && (kvp.value == "direct")) {
1559 0 : vnic_type_direct = true;
1560 0 : } else if ((kvp.key == "vif_type") && (kvp.value == "hw_veb")) {
1561 0 : vif_type_hw_veb = true;
1562 : }
1563 0 : }
1564 :
1565 32 : if (vnic_type_direct && vif_type_hw_veb) {
1566 0 : data->device_type_ = VmInterface::VM_SRIOV;
1567 0 : data->vmi_type_ = VmInterface::SRIOV;
1568 0 : return;
1569 : }
1570 :
1571 32 : data->device_type_ = VmInterface::DEVICE_TYPE_INVALID;
1572 32 : data->vmi_type_ = VmInterface::VMI_TYPE_INVALID;
1573 : // Does it have physical-interface
1574 32 : if (data->physical_interface_.empty() == false) {
1575 : // no physical-router connected. Should be transient case
1576 4 : if (prouter == NULL) {
1577 : // HACK : TSN/ToR agent only supports barements. So, set as
1578 : // baremetal anyway
1579 0 : if (agent->tsn_enabled() || agent->tor_agent_enabled()) {
1580 0 : data->device_type_ = VmInterface::TOR;
1581 0 : data->vmi_type_ = VmInterface::BAREMETAL;
1582 : }
1583 0 : return;
1584 : }
1585 :
1586 : // VMI is either Baremetal or Gateway interface
1587 4 : if (prouter->display_name() == agent->agent_name()) {
1588 : // VMI connected to local vrouter. Treat it as GATEWAY / Remote VM.
1589 0 : if (agent->server_gateway_mode() ||
1590 0 : agent->pbb_gateway_mode()) {
1591 0 : data->device_type_ = VmInterface::REMOTE_VM_VLAN_ON_VMI;
1592 0 : data->vmi_type_ = VmInterface::REMOTE_VM;
1593 : } else {
1594 0 : data->device_type_ = VmInterface::LOCAL_DEVICE;
1595 0 : data->vmi_type_ = VmInterface::GATEWAY;
1596 : }
1597 0 : if (logical_node) {
1598 : autogen::LogicalInterface *port =
1599 : static_cast <autogen::LogicalInterface *>
1600 0 : (logical_node->GetObject());
1601 0 : data->rx_vlan_id_ = port->vlan_tag();
1602 0 : data->tx_vlan_id_ = port->vlan_tag();
1603 : }
1604 0 : return;
1605 : } else {
1606 : // prouter does not match. Treat as baremetal
1607 4 : data->device_type_ = VmInterface::TOR;
1608 4 : data->vmi_type_ = VmInterface::BAREMETAL;
1609 4 : return;
1610 : }
1611 : return;
1612 : }
1613 :
1614 : // Physical router not specified. Check if this is VMI sub-interface
1615 28 : if (data->parent_vmi_.is_nil() == false) {
1616 0 : data->device_type_ = VmInterface::VM_VLAN_ON_VMI;
1617 0 : data->vmi_type_ = VmInterface::INSTANCE;
1618 0 : return;
1619 : }
1620 :
1621 : // Logical Router attached node
1622 28 : if (logical_router) {
1623 : /*
1624 : * since logical-router type "snat-routing" is handled
1625 : * via service-instances, vmi update should happen only
1626 : * for logical-router type "vxlan-routing".
1627 : */
1628 : autogen::LogicalRouter *lr_obj =
1629 : static_cast <autogen::LogicalRouter *>
1630 0 : (logical_router->GetObject());
1631 0 : if (lr_obj->type() == "vxlan-routing") {
1632 0 : data->device_type_ = VmInterface::VMI_ON_LR;
1633 0 : data->vmi_type_ = VmInterface::ROUTER;
1634 : }
1635 0 : return;
1636 : }
1637 :
1638 28 : return;
1639 : }
1640 :
1641 280 : void CopyTagList(VmInterfaceConfigData *data,
1642 : VmInterface::TagEntryList &tag_list, bool *label_added) {
1643 280 : bool dont_copy_label = *label_added;
1644 :
1645 280 : VmInterface::TagEntrySet::iterator tag_it;
1646 280 : for (tag_it = tag_list.list_.begin(); tag_it != tag_list.list_.end();
1647 0 : tag_it++) {
1648 0 : if (tag_it->type_ == TagTable::LABEL) {
1649 0 : *label_added = true;
1650 0 : if (dont_copy_label) {
1651 0 : continue;
1652 : }
1653 : }
1654 0 : data->tag_list_.list_.insert(*tag_it);
1655 : }
1656 280 : }
1657 :
1658 70 : void CopyTag(VmInterfaceConfigData *data ,
1659 : VmInterface::TagEntryList &vmi_list,
1660 : VmInterface::TagEntryList &vm_list,
1661 : VmInterface::TagEntryList &vn_list,
1662 : VmInterface::TagEntryList &project_list) {
1663 70 : bool label_added = false;
1664 : //Order of below should be maintained
1665 : //This is becasue any tag present at VMI takes
1666 : //precedence over VM, VN and project and since
1667 : //tag type is key (except for label) duplicate
1668 : //insertion doesnt happen
1669 70 : CopyTagList(data, vmi_list, &label_added);
1670 70 : CopyTagList(data, vm_list, &label_added);
1671 70 : CopyTagList(data, vn_list, &label_added);
1672 70 : CopyTagList(data, project_list, &label_added);
1673 70 : }
1674 :
1675 70 : bool InterfaceTable::VmiProcessConfig(IFMapNode *node, DBRequest &req,
1676 : const boost::uuids::uuid &u) {
1677 : // Get interface UUID
1678 : VirtualMachineInterface *cfg = static_cast <VirtualMachineInterface *>
1679 70 : (node->GetObject());
1680 :
1681 70 : boost::uuids::uuid vmi_uuid = u;
1682 70 : assert(cfg);
1683 : // Handle object delete
1684 70 : if (node->IsDeleted()) {
1685 0 : return false;
1686 : }
1687 :
1688 70 : assert(!u.is_nil());
1689 : // Update interface configuration
1690 70 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1691 70 : VmInterfaceConfigData *data = new VmInterfaceConfigData(agent(), NULL);
1692 70 : data->SetIFMapNode(node);
1693 :
1694 70 : BuildAttributes(agent_, node, cfg, data);
1695 :
1696 : // Graph walk to get interface configuration
1697 70 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
1698 70 : IFMapNode *vn_node = NULL;
1699 70 : IFMapNode *li_node = NULL;
1700 70 : IFMapNode *vpg_node = NULL;
1701 70 : IFMapNode *lr_node = NULL;
1702 70 : IFMapNode *phy_interface = NULL;
1703 70 : IFMapNode *phy_device = NULL;
1704 70 : IFMapNode *parent_vmi_node = NULL;
1705 70 : uint16_t rx_vlan_id = VmInterface::kInvalidVlanId;
1706 70 : uint16_t tx_vlan_id = VmInterface::kInvalidVlanId;
1707 70 : VmInterface::TagEntryList vmi_list;
1708 70 : VmInterface::TagEntryList vm_list;
1709 70 : VmInterface::TagEntryList vn_list;
1710 70 : VmInterface::TagEntryList project_list;
1711 70 : string service_intf_type = "";
1712 :
1713 70 : if (cfg->IsPropertySet(VirtualMachineInterface::PROPERTIES)) {
1714 0 : service_intf_type = cfg->properties().service_interface_type;
1715 0 : data->service_intf_type_ = cfg->properties().service_interface_type;
1716 : /* Overwrite service_intf_type if it is not left or right interface */
1717 0 : if (service_intf_type != "left" && service_intf_type != "right") {
1718 0 : service_intf_type = "";
1719 : }
1720 : }
1721 :
1722 70 : data->vmi_cfg_uuid_ = vmi_uuid;
1723 70 : std::list<IFMapNode *> bgp_as_a_service_node_list;
1724 70 : std::list<IFMapNode *> bgp_router_node_list;
1725 70 : for (DBGraphVertex::adjacency_iterator iter =
1726 70 : node->begin(table->GetGraph());
1727 277 : iter != node->end(table->GetGraph()); ++iter) {
1728 :
1729 207 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
1730 : /* SkipNode() will be true, if node is registed with dependency_manager.
1731 : * Eventhough bgp-router is registered with dependency_manager,
1732 : * bgp_routers associated to a vmi is passed to bgp-as-a-sercice
1733 : * process_config() for validation. */
1734 207 : if (agent_->config_manager()->SkipNode(adj_node)) {
1735 0 : if (strcmp(adj_node->table()->Typename(),
1736 0 : BGP_ROUTER_CONFIG_NAME) != 0) {
1737 0 : continue;
1738 : }
1739 : }
1740 :
1741 207 : if (adj_node->table() == agent_->cfg()->cfg_sg_table()) {
1742 3 : BuildSgList(data, adj_node);
1743 : }
1744 :
1745 207 : if (adj_node->table() == agent_->cfg()->cfg_tag_table()) {
1746 0 : BuildTagList(&vmi_list, adj_node);
1747 : }
1748 :
1749 207 : if (adj_node->table() == agent()->cfg()->cfg_slo_table()) {
1750 0 : uuid slo_uuid = nil_uuid();
1751 : autogen::SecurityLoggingObject *slo =
1752 : static_cast<autogen::SecurityLoggingObject *>(adj_node->
1753 0 : GetObject());
1754 0 : autogen::IdPermsType id_perms = slo->id_perms();
1755 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
1756 : slo_uuid);
1757 0 : data->slo_list_.push_back(slo_uuid);
1758 0 : }
1759 :
1760 207 : if (adj_node->table() == agent_->cfg()->cfg_vn_table()) {
1761 62 : vn_node = adj_node;
1762 62 : BuildVn(data, adj_node, u, &vn_list);
1763 : }
1764 :
1765 207 : if (adj_node->table() == agent_->cfg()->cfg_qos_table()) {
1766 0 : BuildQosConfig(data, adj_node);
1767 : }
1768 :
1769 207 : if (adj_node->table() == agent_->cfg()->cfg_vm_table()) {
1770 70 : BuildVm(data, adj_node, u, &vm_list);
1771 : }
1772 :
1773 207 : if (adj_node->table() == agent_->cfg()->cfg_project_table()) {
1774 0 : BuildProject(data, adj_node, u, &project_list);
1775 : }
1776 :
1777 207 : if (adj_node->table() == agent_->cfg()->cfg_instanceip_table()) {
1778 10 : BuildInstanceIp(agent_, data, adj_node);
1779 : }
1780 :
1781 207 : if (adj_node->table() == agent_->cfg()->cfg_floatingip_table()) {
1782 0 : BuildFloatingIpList(agent_, data, adj_node);
1783 : }
1784 :
1785 207 : if (adj_node->table() == agent_->cfg()->cfg_aliasip_table()) {
1786 0 : BuildAliasIpList(this, data, adj_node);
1787 : }
1788 :
1789 207 : if (adj_node->table() == agent_->cfg()->cfg_vm_port_vrf_table()) {
1790 58 : BuildVrfAndServiceVlanInfo(agent_, data, adj_node);
1791 : }
1792 :
1793 207 : if (adj_node->table() == agent_->cfg()->cfg_route_table()) {
1794 0 : BuildStaticRouteList(data, adj_node);
1795 : }
1796 :
1797 207 : if (adj_node->table() == agent_->cfg()->cfg_subnet_table()) {
1798 0 : BuildResolveRoute(data, adj_node);
1799 : }
1800 :
1801 207 : if (adj_node->table() == agent_->cfg()->cfg_logical_port_table()) {
1802 4 : BuildInterfaceConfigurationData(agent(), adj_node,
1803 : &rx_vlan_id, &tx_vlan_id,
1804 : &li_node, &phy_interface,
1805 : &phy_device);
1806 : }
1807 :
1808 207 : if (adj_node->table() == agent_->cfg()->cfg_vm_interface_table()) {
1809 0 : parent_vmi_node = adj_node;
1810 : }
1811 :
1812 207 : if (strcmp(adj_node->table()->Typename(), BGP_AS_SERVICE_CONFIG_NAME) == 0) {
1813 0 : bgp_as_a_service_node_list.push_back(adj_node);
1814 : }
1815 :
1816 207 : if (strcmp(adj_node->table()->Typename(), BGP_ROUTER_CONFIG_NAME) == 0) {
1817 0 : bgp_router_node_list.push_back(adj_node);
1818 : }
1819 :
1820 207 : if (adj_node->table() == agent_->cfg()->cfg_vm_port_bridge_domain_table()) {
1821 0 : BuildBridgeDomainTable(agent_, data, adj_node);
1822 : }
1823 :
1824 207 : if (adj_node->table() == agent_->cfg()->cfg_port_tuple_table()) {
1825 0 : if (!service_intf_type.empty()) {
1826 0 : BuildSiOtherVmi(agent_, data, adj_node, service_intf_type);
1827 : }
1828 0 : BuildVmiSiMode(agent_, data, adj_node);
1829 : }
1830 :
1831 207 : if (strcmp(adj_node->table()->Typename(), LOGICAL_ROUTER_NAME) == 0) {
1832 0 : if (BuildLogicalRouterData(agent_, data, node)) {
1833 0 : lr_node = adj_node;
1834 : }
1835 : }
1836 :
1837 207 : if (strcmp(adj_node->table()->Typename(),
1838 207 : VIRTUAL_PORT_GROUP_CONFIG_NAME) == 0) {
1839 0 : BuildInterfaceConfigurationDataFromVpg(agent(), adj_node,
1840 : &vpg_node,
1841 : &phy_interface,
1842 : &phy_device);
1843 : }
1844 : }
1845 :
1846 : //Fill HBS data
1847 70 : FillHbsInfo(data, vn_node);
1848 :
1849 : // Fill IGMP data
1850 70 : ReadIgmpConfig(agent(), vn_node, cfg, data);
1851 :
1852 : // Read flow control parameter on vmi
1853 70 : ReadMaxFlowsConfig(vn_node, cfg, data);
1854 :
1855 70 : if (parent_vmi_node && data->vm_uuid_ == nil_uuid()) {
1856 : IFMapAgentTable *vmi_table = static_cast<IFMapAgentTable *>
1857 0 : (parent_vmi_node->table());
1858 0 : DBGraph *vmi_graph = vmi_table->GetGraph();
1859 : //iterate through links for paremt VMI for VM
1860 0 : for (DBGraphVertex::adjacency_iterator vmi_iter = parent_vmi_node->begin(vmi_graph);
1861 0 : vmi_iter != parent_vmi_node->end(vmi_graph); ++vmi_iter) {
1862 :
1863 0 : IFMapNode *vm_node = static_cast<IFMapNode *>(vmi_iter.operator->());
1864 0 : if (agent_->config_manager()->SkipNode(vm_node, agent_->cfg()->cfg_vm_table())) {
1865 0 : continue;
1866 : }
1867 0 : BuildVm(data, vm_node, u, &vm_list);
1868 0 : break;
1869 : }
1870 : }
1871 :
1872 :
1873 70 : agent_->oper_db()->bgp_as_a_service()->ProcessConfig
1874 70 : (data->vrf_name_, bgp_router_node_list, bgp_as_a_service_node_list, u);
1875 70 : UpdateAttributes(agent_, data);
1876 70 : BuildFatFlowTable(agent_, u, data, node);
1877 :
1878 : // Get DHCP enable flag from subnet
1879 70 : if ((vn_node && data->addr_.to_ulong()) || (vn_node && !(data->ip6_addr_.is_unspecified()))) {
1880 10 : ReadDhcpEnable(agent_, data, vn_node);
1881 : }
1882 :
1883 :
1884 70 : PhysicalRouter *prouter = NULL;
1885 : // Build parent for the virtual-machine-interface
1886 70 : prouter = BuildParentInfo(agent_, cfg, node, li_node, vpg_node,
1887 : data, parent_vmi_node, &phy_interface,
1888 : &phy_device);
1889 70 : BuildEcmpHashingIncludeFields(cfg, vn_node, data);
1890 :
1891 : // Compare and log any mismatch in vm/vn between config and port-subscribe
1892 70 : PortSubscribeEntryPtr subscribe_entry;
1893 70 : PortIpcHandler *pih = agent_->port_ipc_handler();
1894 70 : if (pih) {
1895 : subscribe_entry =
1896 70 : pih->port_subscribe_table()->Get(u, data->vm_uuid_, data->vn_uuid_);
1897 70 : CompareVnVm(u, data, subscribe_entry.get());
1898 70 : pih->port_subscribe_table()->HandleVmiIfnodeAdd(u, data);
1899 : }
1900 :
1901 : // Compute device-type and vmi-type for the interface
1902 70 : ComputeTypeInfo(agent_, data, subscribe_entry.get(), prouter, node,
1903 : li_node, lr_node);
1904 :
1905 70 : if (cfg->display_name() == agent_->vhost_interface_name()) {
1906 0 : data->CopyVhostData(agent());
1907 0 : agent_->set_vhost_disable_policy(cfg->disable_policy());
1908 0 : vmi_uuid = nil_uuid();
1909 : }
1910 :
1911 70 : InterfaceKey *key = NULL;
1912 70 : if (cfg->display_name() == agent_->vhost_interface_name()) {
1913 0 : key = new VmInterfaceKey(AgentKey::RESYNC, vmi_uuid, cfg->display_name());
1914 70 : } else if (data->device_type_ == VmInterface::VM_ON_TAP ||
1915 32 : data->device_type_ == VmInterface::DEVICE_TYPE_INVALID) {
1916 66 : key = new VmInterfaceKey(AgentKey::RESYNC, u, "");
1917 : } else {
1918 4 : key = new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, vmi_uuid,
1919 4 : cfg->display_name());
1920 : }
1921 :
1922 70 : if (data->device_type_ != VmInterface::DEVICE_TYPE_INVALID) {
1923 42 : AddVmiToVmiType(u, data->device_type_);
1924 : }
1925 :
1926 70 : CopyTag(data, vmi_list, vm_list, vn_list, project_list);
1927 :
1928 70 : if (data->device_type_ == VmInterface::REMOTE_VM_VLAN_ON_VMI &&
1929 0 : (rx_vlan_id == VmInterface::kInvalidVlanId ||
1930 0 : tx_vlan_id == VmInterface::kInvalidVlanId)) {
1931 0 : req.key.reset(key);
1932 0 : req.data.reset(data);
1933 0 : return false;
1934 : }
1935 :
1936 70 : if (data->vm_mac_ == MacAddress::ZeroMac().ToString()) {
1937 0 : req.key.reset(key);
1938 0 : req.data.reset(data);
1939 0 : return false;
1940 : }
1941 :
1942 70 : req.key.reset(key);
1943 70 : req.data.reset(data);
1944 :
1945 70 : boost::uuids::uuid dev = nil_uuid();
1946 70 : if (prouter) {
1947 4 : autogen::IdPermsType id_perms = prouter->id_perms();
1948 4 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, dev);
1949 4 : }
1950 70 : UpdatePhysicalDeviceVnEntry(u, dev, data->vn_uuid_, vn_node);
1951 70 : vmi_ifnode_to_req_++;
1952 :
1953 70 : return true;
1954 70 : }
1955 :
1956 12 : static bool DeleteVmi(InterfaceTable *table, const uuid &u, DBRequest *req) {
1957 12 : int type = table->GetVmiToVmiType(u);
1958 12 : if (type <= (int)VmInterface::VMI_TYPE_INVALID)
1959 10 : return false;
1960 :
1961 2 : table->DelVmiToVmiType(u);
1962 : // Process delete based on VmiType
1963 2 : if (type == VmInterface::INSTANCE) {
1964 : // INSTANCE type are not added by config. We only do RESYNC
1965 0 : req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1966 0 : req->key.reset(new VmInterfaceKey(AgentKey::RESYNC, u, ""));
1967 0 : req->data.reset(new VmInterfaceConfigData(NULL, NULL));
1968 0 : table->Enqueue(req);
1969 0 : return false;
1970 : } else {
1971 2 : VmInterface::Delete(table, u, VmInterface::CONFIG);
1972 2 : return false;
1973 : }
1974 : }
1975 :
1976 186 : bool InterfaceTable::VmiIFNodeToReq(IFMapNode *node, DBRequest &req,
1977 : const boost::uuids::uuid &u) {
1978 : // Handle object delete
1979 186 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
1980 12 : agent_->oper_db()->bgp_as_a_service()->DeleteVmInterface(u);
1981 12 : DelPhysicalDeviceVnEntry(u);
1982 12 : PortIpcHandler *pih = agent_->port_ipc_handler();
1983 12 : if (pih) {
1984 12 : pih->port_subscribe_table()->HandleVmiIfnodeDelete(u);
1985 : }
1986 12 : return DeleteVmi(this, u, &req);
1987 : }
1988 :
1989 174 : IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager();
1990 174 : IFMapNodeState *state = dep->IFMapNodeGet(node);
1991 174 : IFMapDependencyManager::IFMapNodePtr vm_node_ref;
1992 174 : if (!state) {
1993 0 : vm_node_ref = dep->SetState(node);
1994 0 : state = dep->IFMapNodeGet(node);
1995 : }
1996 :
1997 174 : if (state->uuid().is_nil())
1998 0 : state->set_uuid(u);
1999 :
2000 174 : agent()->config_manager()->AddVmiNode(node);
2001 174 : return false;
2002 174 : }
2003 :
2004 186 : bool InterfaceTable::VmiIFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) {
2005 :
2006 : VirtualMachineInterface *cfg = static_cast <VirtualMachineInterface *>
2007 186 : (node->GetObject());
2008 186 : autogen::IdPermsType id_perms = cfg->id_perms();
2009 186 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
2010 186 : return true;
2011 186 : }
|