diff --git a/src/vnsw/agent/oper/vn.cc b/src/vnsw/agent/oper/vn.cc index 77fc96c3454..67c961bc638 100644 --- a/src/vnsw/agent/oper/vn.cc +++ b/src/vnsw/agent/oper/vn.cc @@ -42,7 +42,7 @@ using boost::assign::list_of; VnTable *VnTable::vn_table_; VnIpam::VnIpam(const std::string& ip, uint32_t len, const std::string& gw, - const std::string& dns, bool dhcp, std::string &name, + const std::string& dns, bool dhcp, const std::string &name, const std::vector &dhcp_options, const std::vector &host_routes) : plen(len), installed(false), dhcp_enable(dhcp), ipam_name(name) { @@ -707,6 +707,32 @@ void VnTable::CfgForwardingFlags(IFMapNode *node, bool *l2, bool *l3, *l3 = GetLayer3ForwardingConfig(derived_forwarding_mode); } +void +VnTable::BuildVnIpamData(const std::vector &subnets, + const std::string &ipam_name, + std::vector *vn_ipam) { + for (unsigned int i = 0; i < subnets.size(); ++i) { + // if the DNS server address is not specified, set this + // to be the same as the GW address + std::string dns_server_address = subnets[i].dns_server_address; + boost::system::error_code ec; + IpAddress dns_server = + IpAddress::from_string(dns_server_address, ec); + if (ec.value() || dns_server.is_unspecified()) { + dns_server_address = subnets[i].default_gateway; + } + + vn_ipam->push_back + (VnIpam(subnets[i].subnet.ip_prefix, + subnets[i].subnet.ip_prefix_len, + subnets[i].default_gateway, + dns_server_address, + subnets[i].enable_dhcp, ipam_name, + subnets[i].dhcp_option_list.dhcp_option, + subnets[i].host_routes.route)); + } +} + VnData *VnTable::BuildData(IFMapNode *node) { VirtualNetwork *cfg = static_cast (node->GetObject()); assert(cfg); @@ -761,34 +787,25 @@ VnData *VnTable::BuildData(IFMapNode *node) { if (IFMapNode *ipam_node = FindTarget(table, adj_node, "network-ipam")) { ipam_name = ipam_node->name(); - - VirtualNetworkNetworkIpam *ipam = + VirtualNetworkNetworkIpam *vnni = static_cast (adj_node->GetObject()); - assert(ipam); - const VnSubnetsType &subnets = ipam->data(); - for (unsigned int i = 0; i < subnets.ipam_subnets.size(); ++i) { - // if the DNS server address is not specified, set this - // to be the same as the GW address - std::string dns_server_address = - subnets.ipam_subnets[i].dns_server_address; - boost::system::error_code ec; - IpAddress dns_server = - IpAddress::from_string(dns_server_address, ec); - if (ec.value() || dns_server.is_unspecified()) { - dns_server_address = - subnets.ipam_subnets[i].default_gateway; - } - - vn_ipam.push_back - (VnIpam(subnets.ipam_subnets[i].subnet.ip_prefix, - subnets.ipam_subnets[i].subnet.ip_prefix_len, - subnets.ipam_subnets[i].default_gateway, - dns_server_address, - subnets.ipam_subnets[i].enable_dhcp, ipam_name, - subnets.ipam_subnets[i].dhcp_option_list.dhcp_option, - subnets.ipam_subnets[i].host_routes.route)); + VnSubnetsType subnets; + if (vnni) + subnets = vnni->data(); + + autogen::NetworkIpam *network_ipam = + static_cast(ipam_node->GetObject()); + const std::string subnet_method = + boost::to_lower_copy(network_ipam->ipam_subnet_method()); + + if (subnet_method == "flat-subnet") { + BuildVnIpamData(network_ipam->ipam_subnets(), + ipam_name, &vn_ipam); + } else { + BuildVnIpamData(subnets.ipam_subnets, ipam_name, &vn_ipam); } + VnIpamLinkData ipam_data; ipam_data.oper_dhcp_options_.set_host_routes(subnets.host_routes.route); vn_ipam_data.insert(VnData::VnIpamDataPair(ipam_name, ipam_data)); diff --git a/src/vnsw/agent/oper/vn.h b/src/vnsw/agent/oper/vn.h index f1a160f0487..2fabfd1a6f2 100644 --- a/src/vnsw/agent/oper/vn.h +++ b/src/vnsw/agent/oper/vn.h @@ -39,7 +39,7 @@ struct VnIpam { OperDhcpOptions oper_dhcp_options; VnIpam(const std::string& ip, uint32_t len, const std::string& gw, - const std::string& dns, bool dhcp, std::string &name, + const std::string& dns, bool dhcp, const std::string &name, const std::vector &dhcp_options, const std::vector &host_routes); @@ -287,6 +287,9 @@ class VnTable : public AgentOperDBTable { void DelHostRoute(VnEntry *vn, const IpAddress &address); bool ChangeHandler(DBEntry *entry, const DBRequest *req); bool IsGatewayL2(const string &gateway) const; + void BuildVnIpamData(const std::vector &subnets, + const std::string &ipam_name, + std::vector *vn_ipam); VnData *BuildData(IFMapNode *node); IFMapNode *FindTarget(IFMapAgentTable *table, IFMapNode *node, std::string node_type); diff --git a/src/vnsw/agent/test/test_vn.cc b/src/vnsw/agent/test/test_vn.cc index 1372e393c9e..a2c278cf202 100644 --- a/src/vnsw/agent/test/test_vn.cc +++ b/src/vnsw/agent/test/test_vn.cc @@ -966,6 +966,57 @@ TEST_F(CfgTest, multicast_fabric_routes) { WAIT_FOR(1000, 1000, (VrfFind("vrf1") == false)); } +// Check that flat subnet config in an IPAM is used to update VN entries +TEST_F(CfgTest, flat_subnet_config) { + client->Reset(); + struct PortInfo input[] = { + {"vnet1", 1, "12.1.1.1", "00:00:00:01:01:11", 1, 1}, + }; + + IpamInfo ipam_info[] = { + {"11.1.1.0", 24, "11.1.1.200", true}, + }; + + char ipam_attr[] = "\n " + "default-dns-server\n " + "\n " + "flat-subnet\n " + "\n " + "\n " + "\n " + " 12.1.0.0 \n " + " 16 \n " + "\n " + " 12.1.0.1 \n " + " 12.1.0.2 \n " + "true\n " + "\n " + "\n "; + CreateVmportEnv(input, 1, 0); + client->WaitForIdle(); + + WAIT_FOR(1000, 1000, (VmPortActive(input, 0) == true)); + + AddIPAM("vn1", ipam_info, 1, ipam_attr); + client->WaitForIdle(); + + CheckVnAdd(1, 1); + VnEntry *vn = VnGet(1); + const std::vector vn_ipam = vn->GetVnIpam(); + EXPECT_TRUE(vn_ipam[0].ip_prefix.to_string() == "12.1.0.0"); + EXPECT_TRUE(vn_ipam[0].plen == 16); + EXPECT_TRUE(vn_ipam[0].default_gw.to_string() == "12.1.0.1"); + EXPECT_TRUE(vn_ipam[0].dns_server.to_string() == "12.1.0.2"); + EXPECT_TRUE(vn_ipam[0].dhcp_enable); + + client->Reset(); + DelIPAM("vn1"); + client->WaitForIdle(); + DeleteVmportEnv(input, 1, true); + client->WaitForIdle(); + WAIT_FOR(1000, 1000, (VrfFind("vrf1") == false)); +} + int main(int argc, char **argv) { GETUSERARGS();