LCOV - code coverage report
Current view: top level - vnsw/agent/oper - vm_interface_config.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 514 1134 45.3 %
Date: 2026-11-09 02:10:49 Functions: 33 48 68.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14