From 85c4b9767d4dbb46e0d08bc8b1e7444dea6fb3d3 Mon Sep 17 00:00:00 2001 From: Prince Date: Thu, 13 Sep 2018 01:50:49 +0000 Subject: [PATCH 1/4] Initial Vxlan commit --- orchagent/request_parser.h | 1 + orchagent/vxlanorch.cpp | 341 ++++++++++++++++++++++++++++++++++--- orchagent/vxlanorch.h | 137 ++++++++++++++- 3 files changed, 444 insertions(+), 35 deletions(-) diff --git a/orchagent/request_parser.h b/orchagent/request_parser.h index 1be08f39c91..57283eeec36 100644 --- a/orchagent/request_parser.h +++ b/orchagent/request_parser.h @@ -8,6 +8,7 @@ typedef enum _request_types_t REQ_T_NOT_USED, REQ_T_BOOL, REQ_T_STRING, + REQ_T_STRING_LIST, REQ_T_MAC_ADDRESS, REQ_T_PACKET_ACTION, REQ_T_IP, diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index a489c26f820..c68b3222040 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -18,17 +18,36 @@ extern sai_object_id_t gSwitchId; extern sai_object_id_t gVirtualRouterId; extern sai_tunnel_api_t *sai_tunnel_api; +extern sai_next_hop_api_t *sai_next_hop_api; extern Directory gDirectory; extern PortsOrch* gPortsOrch; static sai_object_id_t -create_tunnel_map() +create_tunnel_map(map_type maptype) { sai_attribute_t attr; std::vector tunnel_map_attrs; attr.id = SAI_TUNNEL_MAP_ATTR_TYPE; - attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID; + + switch (maptype) + { + case map_type::VNI_TO_VLAN_ID: + attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VNI_TO_VLAN_ID; + break; + case map_type::VLAN_ID_TO_VNI: + attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VLAN_ID_TO_VNI; + break; + case map_type::VRID_TO_VNI: + attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VNI; + break; + case map_type::VNI_TO_VRID: + attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VNI_TO_VIRTUAL_ROUTER_ID; + break; + default: + SWSS_LOG_NOTICE("Invalid map type %d", maptype); + return 0; + } tunnel_map_attrs.push_back(attr); sai_object_id_t tunnel_map_id; @@ -46,6 +65,113 @@ create_tunnel_map() return tunnel_map_id; } +sai_object_id_t create_encap_tunnel_map_entry( + sai_object_id_t tunnel_map_id, + sai_object_id_t router_id, + sai_uint32_t vni) +{ + sai_attribute_t attr; + sai_object_id_t tunnel_map_entry_id; + std::vector tunnel_map_entry_attrs; + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE; + attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VNI; + tunnel_map_entry_attrs.push_back(attr); + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP; + attr.value.oid = tunnel_map_id; + tunnel_map_entry_attrs.push_back(attr); + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_KEY; + attr.value.oid = router_id; + tunnel_map_entry_attrs.push_back(attr); + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_VALUE; + attr.value.u32 = vni; + tunnel_map_entry_attrs.push_back(attr); + + sai_tunnel_api->create_tunnel_map_entry(&tunnel_map_entry_id, gSwitchId, + static_cast (tunnel_map_entry_attrs.size()), + tunnel_map_entry_attrs.data()); + + return tunnel_map_entry_id; +} + +sai_object_id_t create_decap_tunnel_map_entry( + sai_object_id_t tunnel_map_id, + sai_object_id_t router_id, + sai_uint32_t vni) +{ + sai_attribute_t attr; + sai_object_id_t tunnel_map_entry_id; + std::vector tunnel_map_entry_attrs; + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE; + attr.value.s32 = SAI_TUNNEL_MAP_TYPE_VNI_TO_VIRTUAL_ROUTER_ID; + tunnel_map_entry_attrs.push_back(attr); + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP; + attr.value.oid = tunnel_map_id; + tunnel_map_entry_attrs.push_back(attr); + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY; + attr.value.u32 = vni; + tunnel_map_entry_attrs.push_back(attr); + + attr.id = SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_VALUE; + attr.value.oid = router_id; + tunnel_map_entry_attrs.push_back(attr); + + sai_tunnel_api->create_tunnel_map_entry(&tunnel_map_entry_id, gSwitchId, + static_cast (tunnel_map_entry_attrs.size()), + tunnel_map_entry_attrs.data()); + + return tunnel_map_entry_id; +} + +sai_status_t create_nexthop_tunnel( + sai_ip4_t host_ip, + sai_uint32_t vni, // optional vni + sai_mac_t mac, // inner destination mac + sai_object_id_t tunnel_id, + sai_object_id_t *next_hop_id) +{ + std::vector next_hop_attrs; + sai_attribute_t next_hop_attr; + + next_hop_attr.id = SAI_NEXT_HOP_ATTR_TYPE; + next_hop_attr.value.s32 = SAI_NEXT_HOP_TYPE_TUNNEL_ENCAP; + next_hop_attrs.push_back(next_hop_attr); + + next_hop_attr.id = SAI_NEXT_HOP_ATTR_IP; + next_hop_attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + next_hop_attr.value.ipaddr.addr.ip4 = htonl(host_ip); + next_hop_attrs.push_back(next_hop_attr); + + next_hop_attr.id = SAI_NEXT_HOP_ATTR_TUNNEL_ID; + next_hop_attr.value.oid = tunnel_id; + next_hop_attrs.push_back(next_hop_attr); + + if (vni != 0) + { + next_hop_attr.id = SAI_NEXT_HOP_ATTR_TUNNEL_VNI; + next_hop_attr.value.u32 = vni; + next_hop_attrs.push_back(next_hop_attr); + } + + if (mac != NULL) + { + next_hop_attr.id = SAI_NEXT_HOP_ATTR_TUNNEL_MAC; + memcpy(next_hop_attr.value.mac, mac, sizeof(sai_mac_t)); + next_hop_attrs.push_back(next_hop_attr); + } + + sai_status_t status = sai_next_hop_api->create_next_hop(next_hop_id, gSwitchId, + static_cast(next_hop_attrs.size()), + next_hop_attrs.data()); + return status; +} + static sai_object_id_t create_tunnel_map_entry( sai_object_id_t tunnel_map_id, @@ -88,7 +214,11 @@ create_tunnel_map_entry( // Create Tunnel static sai_object_id_t -create_tunnel(sai_object_id_t tunnel_map_id) +create_tunnel( + sai_object_id_t tunnel_encap_id, + sai_object_id_t tunnel_decap_id, + sai_ip4_t ip, + sai_object_id_t underlay_rif = 0x0) { sai_attribute_t attr; std::vector tunnel_attrs; @@ -97,17 +227,36 @@ create_tunnel(sai_object_id_t tunnel_map_id) attr.value.s32 = SAI_TUNNEL_TYPE_VXLAN; tunnel_attrs.push_back(attr); - sai_object_id_t decap_list[] = { tunnel_map_id }; + sai_object_id_t decap_list[] = { tunnel_decap_id }; attr.id = SAI_TUNNEL_ATTR_DECAP_MAPPERS; attr.value.objlist.count = 1; attr.value.objlist.list = decap_list; tunnel_attrs.push_back(attr); - sai_object_id_t encap_list[] = { tunnel_map_id }; - attr.id = SAI_TUNNEL_ATTR_ENCAP_MAPPERS; - attr.value.objlist.count = 1; - attr.value.objlist.list = encap_list; - tunnel_attrs.push_back(attr); + if (tunnel_encap_id != 0x0) + { + sai_object_id_t encap_list[] = { tunnel_encap_id }; + attr.id = SAI_TUNNEL_ATTR_ENCAP_MAPPERS; + attr.value.objlist.count = 1; + attr.value.objlist.list = encap_list; + tunnel_attrs.push_back(attr); + } + + if (underlay_rif != 0x0) + { + attr.id = SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE; + attr.value.oid = underlay_rif; + tunnel_attrs.push_back(attr); + } + + // source ip + if (ip != 0x0) + { + attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; + sai_ip_address_t ip_addr = {SAI_IP_ADDR_FAMILY_IPV4, 0x0a0a0a0a}; + attr.value.ipaddr = ip_addr; + tunnel_attrs.push_back(attr); + } sai_object_id_t tunnel_id; sai_status_t status = sai_tunnel_api->create_tunnel( @@ -186,6 +335,41 @@ create_tunnel_termination( return term_table_id; } +bool VxlanTunnel::createTunnel(map_type encap, map_type decap) +{ + try + { + ids.tunnel_decap_id = create_tunnel_map(decap); + ids.tunnel_encap_id = create_tunnel_map(encap); + ids.tunnel_id = create_tunnel(ids.tunnel_encap_id, ids.tunnel_decap_id, 0x0); + ids.tunnel_term_id = create_tunnel_termination(ids.tunnel_id, src_ip.getV4Addr(), + dst_ip.getV4Addr(), gVirtualRouterId); + active = true; + } + catch (const std::runtime_error& error) + { + SWSS_LOG_ERROR("Error creating tunnel %s: %s", tunnel_name.c_str(), error.what()); + // FIXME: add code to remove already created objects + return false; + } + + SWSS_LOG_NOTICE("Vxlan tunnel '%s' was created", tunnel_name.c_str()); + + return true; +} + +sai_object_id_t VxlanTunnel::addEncapMapperEntry(sai_object_id_t vrf, uint32_t vni) +{ + const auto encap_id = getEncapMapId(tunnel_name); + return create_encap_tunnel_map_entry(encap_id, vrf, vni); +} + +sai_object_id_t VxlanTunnel::addDecapMapperEntry(sai_object_id_t vrf, uint32_t vni) +{ + const auto decap_id = getDecapMapId(tunnel_name); + return create_decap_tunnel_map_entry(decap_id, vrf, vni); +} + bool VxlanTunnelOrch::addOperation(const Request& request) { SWSS_LOG_ENTER(); @@ -221,23 +405,10 @@ bool VxlanTunnelOrch::addOperation(const Request& request) return true; } - tunnel_ids_t ids; - try - { - ids.tunnel_map_id = create_tunnel_map(); - ids.tunnel_id = create_tunnel(ids.tunnel_map_id); - ids.tunnel_term_id = create_tunnel_termination(ids.tunnel_id, src_ip.getV4Addr(), dst_ip.getV4Addr(), gVirtualRouterId); - } - catch (const std::runtime_error& error) - { - SWSS_LOG_ERROR("Error creating tunnel %s: %s", tunnel_name.c_str(), error.what()); - // FIXME: add code to remove already created objects - return false; - } - - vxlan_tunnel_table_[tunnel_name] = ids; + std::unique_ptr tunnel_obj (new VxlanTunnel(tunnel_name, src_ip, dst_ip)); + vxlan_tunnel_table_[tunnel_name] = std::move(tunnel_obj); - SWSS_LOG_NOTICE("Vxlan tunnel '%s' was created", tunnel_name.c_str()); + SWSS_LOG_NOTICE("Vxlan tunnel '%s' saved", tunnel_name.c_str()); return true; } @@ -278,6 +449,13 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request) return false; } + auto& tunnel_obj = tunnel_orch->getVxlanTunnel(tunnel_name); + if (!tunnel_obj->isActive()) + { + //@Todo, currently only decap mapper is allowed + tunnel_obj->createTunnel(map_type::MAP_TYPE_INVALID, map_type::VNI_TO_VLAN_ID); + } + const auto full_tunnel_map_entry_name = request.getFullKey(); if (isTunnelMapExists(full_tunnel_map_entry_name)) { @@ -285,7 +463,7 @@ bool VxlanTunnelMapOrch::addOperation(const Request& request) return true; } - const auto tunnel_map_id = tunnel_orch->getTunnelMapId(tunnel_name); + const auto tunnel_map_id = tunnel_obj->getDecapMapId(tunnel_name); const auto tunnel_map_entry_name = request.getKeyString(1); try @@ -313,3 +491,114 @@ bool VxlanTunnelMapOrch::delOperation(const Request& request) return true; } + +bool VxlanVnetOrch::addOperation(const Request& request) +{ + SWSS_LOG_ENTER(); + + const auto& vnet_name = request.getKeyString(0); + SWSS_LOG_INFO("Vnet key '%s'", vnet_name.c_str()); + if(isVnetExists(vnet_name)) + { + SWSS_LOG_ERROR("Vnet peer '%s' exist", vnet_name.c_str()); + return false; + } + + auto tunnel_name = request.getAttrString("vxlan_tunnel"); + VxlanTunnelOrch* tunnel_orch = gDirectory.get(); + if (!tunnel_orch->isTunnelExists(tunnel_name)) + { + SWSS_LOG_ERROR("Vxlan tunnel '%s' doesn't exist", tunnel_name.c_str()); + return false; + } + + auto& tunnel_obj = tunnel_orch->getVxlanTunnel(tunnel_name); + if (!tunnel_obj->isActive()) + { + tunnel_obj->createTunnel(map_type::VRID_TO_VNI, map_type::VNI_TO_VRID); + } + + auto vni_id = static_cast(request.getAttrUint("vni")); + if (vni_id >= 1<<24) + { + SWSS_LOG_ERROR("Vxlan vni id is too big: %d", vni_id); + return true; + } + + //@Todo + //Get VRF Id + sai_object_id_t ing_vrf_id = 0x0; + sai_object_id_t egr_vrf_id = 0x0; + + vnet_entry_t entry = {tunnel_name, vni_id, {}}; + + try + { + /* + * Create encap and decap mapper for each VRF per VNET entry + */ + auto encap_entry = tunnel_obj->addEncapMapperEntry(ing_vrf_id, vni_id); + auto decap_entry = tunnel_obj->addDecapMapperEntry(egr_vrf_id, vni_id); + + SWSS_LOG_INFO("Vxlan tunnel encap entry '%lx' decap entry '0x%lx'", + encap_entry, decap_entry); + + } + catch(const std::runtime_error& error) + { + SWSS_LOG_ERROR("Error adding tunnel map entry. Tunnel: %s. Entry: %s. Error: %s", + tunnel_name.c_str(), vnet_name.c_str(), error.what()); + return false; + } + + vxlan_vnet_table_[vnet_name] = entry; + + SWSS_LOG_NOTICE("Vxlan tunnel map entry '%s' for tunnel '%s' was created", + vnet_name.c_str(), tunnel_name.c_str()); + + return true; +} + +bool VxlanVnetOrch::delOperation(const Request& request) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_ERROR("DEL operation is not implemented"); + + return true; +} + +bool VnetIntfOrch::addOperation(const Request& request) +{ + SWSS_LOG_ENTER(); + + auto vnet_name = request.getAttrString("vnet_name"); + VxlanVnetOrch* vnet_orch = gDirectory.get(); + if (!vnet_orch->isVnetExists(vnet_name)) + { + SWSS_LOG_ERROR("Vnet '%s' doesn't exist", vnet_name.c_str()); + return false; + } + + const auto& if_name = request.getKeyString(0); + SWSS_LOG_INFO("If name '%s'", if_name.c_str()); + + const auto& ip_addr = request.getKeyIpAddress(1); + SWSS_LOG_INFO("Ip prefix '%s'", ip_addr.to_string().c_str()); + + + SWSS_LOG_NOTICE("Vxlan interface %s created for %s", if_name.c_str(), vnet_name.c_str()); + + return true; +} + +bool VnetIntfOrch::delOperation(const Request& request) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_ERROR("DEL operation is not implemented"); + + return true; +} + + diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index 6eaac403f52..f64c1ed3466 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -1,9 +1,64 @@ #pragma once #include +#include +#include #include "request_parser.h" #include "portsorch.h" +enum class map_type +{ + MAP_TYPE_INVALID, + VNI_TO_VLAN_ID, + VLAN_ID_TO_VNI, + VRID_TO_VNI, + VNI_TO_VRID +}; + +struct tunnel_ids_t +{ + sai_object_id_t tunnel_encap_id; + sai_object_id_t tunnel_decap_id; + sai_object_id_t tunnel_id; + sai_object_id_t tunnel_term_id; +}; + +class VxlanTunnel +{ +public: + VxlanTunnel(string name, IpAddress src_ip, IpAddress dst_ip) + :tunnel_name(name), src_ip(src_ip), dst_ip(dst_ip) { } + + bool isActive() const + { + return active; + } + + bool createTunnel(map_type encap, map_type decap); + sai_object_id_t addEncapMapperEntry(sai_object_id_t vrf, uint32_t vni); + sai_object_id_t addDecapMapperEntry(sai_object_id_t vrf, uint32_t vni); + + sai_object_id_t getDecapMapId(const std::string& tunnel_name) const + { + return ids.tunnel_decap_id; + } + + sai_object_id_t getEncapMapId(const std::string& tunnel_name) const + { + return ids.tunnel_encap_id; + } + +private: + string tunnel_name; + + bool active = false; + + tunnel_ids_t ids = {0x0, 0x0, 0x0, 0x0}; + + IpAddress src_ip; + IpAddress dst_ip = 0x0; +}; + const request_description_t vxlan_tunnel_request_description = { { REQ_T_STRING }, { @@ -19,13 +74,8 @@ class VxlanTunnelRequest : public Request VxlanTunnelRequest() : Request(vxlan_tunnel_request_description, '|') { } }; -struct tunnel_ids_t -{ - sai_object_id_t tunnel_map_id; - sai_object_id_t tunnel_id; - sai_object_id_t tunnel_term_id; -}; -typedef std::map VxlanTunnelTable; +using VxlanTunnel_T = std::unique_ptr; +typedef std::map VxlanTunnelTable; class VxlanTunnelOrch : public Orch2 { @@ -37,9 +87,9 @@ class VxlanTunnelOrch : public Orch2 return vxlan_tunnel_table_.find(tunnel_name) != std::end(vxlan_tunnel_table_); } - sai_object_id_t getTunnelMapId(const std::string& tunnel_name) const + VxlanTunnel_T& getVxlanTunnel(const std::string& tunnel_name) { - return vxlan_tunnel_table_.at(tunnel_name).tunnel_map_id; + return vxlan_tunnel_table_.at(tunnel_name); } private: @@ -83,3 +133,72 @@ class VxlanTunnelMapOrch : public Orch2 VxlanTunnelMapTable vxlan_tunnel_map_table_; VxlanTunnelMapRequest request_; }; + +const request_description_t vxlan_vnet_request_description = { + { REQ_T_STRING }, + { + { "vxlan_tunnel", REQ_T_STRING }, + { "vni", REQ_T_UINT }, + { "peer_list", REQ_T_STRING_LIST }, + }, + { "vxlan_tunnel", "vni" } +}; + +class VxlanVnetRequest : public Request +{ +public: + VxlanVnetRequest() : Request(vxlan_vnet_request_description, '|') { } +}; + +struct vnet_entry_t { + string tunnel_name; + uint32_t vni; + std::set peer_list; +}; + +typedef std::map VxlanVnetTable; + +class VxlanVnetOrch : public Orch2 +{ +public: + VxlanVnetOrch(DBConnector *db, const std::string& tableName) : Orch2(db, tableName, request_) { } + + bool isVnetExists(const std::string& name) const + { + return vxlan_vnet_table_.find(name) != std::end(vxlan_vnet_table_); + } + +private: + virtual bool addOperation(const Request& request); + virtual bool delOperation(const Request& request); + + VxlanVnetTable vxlan_vnet_table_; + VxlanVnetRequest request_; +}; + +const request_description_t vnet_intf_request_description = { + { REQ_T_STRING, REQ_T_IP }, + { + { "vnet_name", REQ_T_STRING }, + }, + { "vnet_name" } +}; + +class VnetIntfRequest : public Request +{ +public: + VnetIntfRequest() : Request(vnet_intf_request_description, '|') { } +}; + +class VnetIntfOrch : public Orch2 +{ +public: + VnetIntfOrch(DBConnector *db, const std::string& tableName) : Orch2(db, tableName, request_) { } + +private: + virtual bool addOperation(const Request& request); + virtual bool delOperation(const Request& request); + + + VnetIntfRequest request_; +}; From 17d5ba7d0cbb2c96ba048be49a6e4334f393a600 Mon Sep 17 00:00:00 2001 From: Prince Date: Fri, 14 Sep 2018 18:39:40 +0000 Subject: [PATCH 2/4] VRF modifications and IntfOrch changes --- orchagent/intfsorch.cpp | 46 ++++++++++++++++++++++++------------ orchagent/intfsorch.h | 10 ++++---- orchagent/orchdaemon.cpp | 8 +++++-- orchagent/port.h | 1 + orchagent/request_parser.cpp | 23 +++++++++++++++++- orchagent/request_parser.h | 12 +++++++++- orchagent/vrforch.cpp | 33 ++++++++++++++++++++++++++ orchagent/vrforch.h | 37 +++++++++++++++++++++++++++-- orchagent/vxlanorch.cpp | 24 ++++++++++++------- orchagent/vxlanorch.h | 6 ++++- 10 files changed, 166 insertions(+), 34 deletions(-) diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index cab07f62ae0..6269d21f7da 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -27,8 +27,8 @@ extern BufferOrch *gBufferOrch; const int intfsorch_pri = 35; -IntfsOrch::IntfsOrch(DBConnector *db, string tableName) : - Orch(db, tableName, intfsorch_pri) +IntfsOrch::IntfsOrch(DBConnector *db, string tableName, VRFOrch *vrf_orch) : + Orch(db, tableName, intfsorch_pri), m_vrfOrch(vrf_orch) { SWSS_LOG_ENTER(); } @@ -114,6 +114,18 @@ void IntfsOrch::doTask(Consumer &consumer) vector keys = tokenize(kfvKey(t), ':'); string alias(keys[0]); IpPrefix ip_prefix(kfvKey(t).substr(kfvKey(t).find(':')+1)); + const vector& data = kfvFieldsValues(t); + string vrf_name = ""; + + for (auto idx : data) + { + const auto &field = fvField(idx); + const auto &value = fvValue(idx); + if (field == "vrf_name") + { + vrf_name = value; + } + } if (alias == "eth0" || alias == "docker0") { @@ -126,7 +138,7 @@ void IntfsOrch::doTask(Consumer &consumer) { if (alias == "lo") { - addIp2MeRoute(ip_prefix); + addIp2MeRoute(vrf_name, ip_prefix); it = consumer.m_toSync.erase(it); continue; } @@ -149,7 +161,7 @@ void IntfsOrch::doTask(Consumer &consumer) auto it_intfs = m_syncdIntfses.find(alias); if (it_intfs == m_syncdIntfses.end()) { - if (addRouterIntfs(port)) + if (addRouterIntfs(vrf_name, port)) { IntfsEntry intfs_entry; intfs_entry.ref_count = 0; @@ -198,7 +210,7 @@ void IntfsOrch::doTask(Consumer &consumer) } addSubnetRoute(port, ip_prefix); - addIp2MeRoute(ip_prefix); + addIp2MeRoute(vrf_name, ip_prefix); if (port.m_type == Port::VLAN && ip_prefix.isV4()) { @@ -212,7 +224,7 @@ void IntfsOrch::doTask(Consumer &consumer) { if (alias == "lo") { - removeIp2MeRoute(ip_prefix); + removeIp2MeRoute(vrf_name, ip_prefix); it = consumer.m_toSync.erase(it); continue; } @@ -230,7 +242,7 @@ void IntfsOrch::doTask(Consumer &consumer) if (m_syncdIntfses[alias].ip_addresses.count(ip_prefix)) { removeSubnetRoute(port, ip_prefix); - removeIp2MeRoute(ip_prefix); + removeIp2MeRoute(vrf_name, ip_prefix); if(port.m_type == Port::VLAN && ip_prefix.isV4()) { removeDirectedBroadcast(port, ip_prefix.getBroadcastIp()); @@ -262,7 +274,7 @@ void IntfsOrch::doTask(Consumer &consumer) } } -bool IntfsOrch::addRouterIntfs(Port &port) +bool IntfsOrch::addRouterIntfs(string& vrf_name, Port &port) { SWSS_LOG_ENTER(); @@ -274,12 +286,14 @@ bool IntfsOrch::addRouterIntfs(Port &port) return true; } + sai_object_id_t vr_id = m_vrfOrch->getVRFid(vrf_name); + /* Create router interface if the router interface doesn't exist */ sai_attribute_t attr; vector attrs; attr.id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID; - attr.value.oid = gVirtualRouterId; + attr.value.oid = vr_id; attrs.push_back(attr); attr.id = SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS; @@ -334,6 +348,8 @@ bool IntfsOrch::addRouterIntfs(Port &port) throw runtime_error("Failed to create router interface."); } + port.m_vr_id = vr_id; + gPortsOrch->setPort(port.m_alias, port); SWSS_LOG_NOTICE("Create router interface %s MTU %u", port.m_alias.c_str(), port.m_mtu); @@ -370,7 +386,7 @@ void IntfsOrch::addSubnetRoute(const Port &port, const IpPrefix &ip_prefix) { sai_route_entry_t unicast_route_entry; unicast_route_entry.switch_id = gSwitchId; - unicast_route_entry.vr_id = gVirtualRouterId; + unicast_route_entry.vr_id = port.m_vr_id; copy(unicast_route_entry.destination, ip_prefix); subnet(unicast_route_entry.destination, unicast_route_entry.destination); @@ -413,7 +429,7 @@ void IntfsOrch::removeSubnetRoute(const Port &port, const IpPrefix &ip_prefix) { sai_route_entry_t unicast_route_entry; unicast_route_entry.switch_id = gSwitchId; - unicast_route_entry.vr_id = gVirtualRouterId; + unicast_route_entry.vr_id = port.m_vr_id; copy(unicast_route_entry.destination, ip_prefix); subnet(unicast_route_entry.destination, unicast_route_entry.destination); @@ -441,11 +457,11 @@ void IntfsOrch::removeSubnetRoute(const Port &port, const IpPrefix &ip_prefix) gRouteOrch->notifyNextHopChangeObservers(ip_prefix, IpAddresses(), false); } -void IntfsOrch::addIp2MeRoute(const IpPrefix &ip_prefix) +void IntfsOrch::addIp2MeRoute(string &vrf_name, const IpPrefix &ip_prefix) { sai_route_entry_t unicast_route_entry; unicast_route_entry.switch_id = gSwitchId; - unicast_route_entry.vr_id = gVirtualRouterId; + unicast_route_entry.vr_id = m_vrfOrch->getVRFid(vrf_name);; copy(unicast_route_entry.destination, ip_prefix.getIp()); sai_attribute_t attr; @@ -481,11 +497,11 @@ void IntfsOrch::addIp2MeRoute(const IpPrefix &ip_prefix) } } -void IntfsOrch::removeIp2MeRoute(const IpPrefix &ip_prefix) +void IntfsOrch::removeIp2MeRoute(string &vrf_name, const IpPrefix &ip_prefix) { sai_route_entry_t unicast_route_entry; unicast_route_entry.switch_id = gSwitchId; - unicast_route_entry.vr_id = gVirtualRouterId; + unicast_route_entry.vr_id = m_vrfOrch->getVRFid(vrf_name); copy(unicast_route_entry.destination, ip_prefix.getIp()); sai_status_t status = sai_route_api->remove_route_entry(&unicast_route_entry); diff --git a/orchagent/intfsorch.h b/orchagent/intfsorch.h index 424cb62a7b5..8595b912555 100644 --- a/orchagent/intfsorch.h +++ b/orchagent/intfsorch.h @@ -3,6 +3,7 @@ #include "orch.h" #include "portsorch.h" +#include "vrforch.h" #include "ipaddresses.h" #include "ipprefix.h" @@ -25,7 +26,7 @@ typedef map IntfsTable; class IntfsOrch : public Orch { public: - IntfsOrch(DBConnector *db, string tableName); + IntfsOrch(DBConnector *db, string tableName, VRFOrch *vrf_orch); sai_object_id_t getRouterIntfsId(const string&); @@ -35,19 +36,20 @@ class IntfsOrch : public Orch bool setRouterIntfsMtu(Port &port); std::set getSubnetRoutes(); private: + VRFOrch *m_vrfOrch; IntfsTable m_syncdIntfses; void doTask(Consumer &consumer); int getRouterIntfsRefCount(const string&); - bool addRouterIntfs(Port &port); + bool addRouterIntfs(string &vrf_name, Port &port); bool removeRouterIntfs(Port &port); void addSubnetRoute(const Port &port, const IpPrefix &ip_prefix); void removeSubnetRoute(const Port &port, const IpPrefix &ip_prefix); - void addIp2MeRoute(const IpPrefix &ip_prefix); - void removeIp2MeRoute(const IpPrefix &ip_prefix); + void addIp2MeRoute(string &vrf_name, const IpPrefix &ip_prefix); + void removeIp2MeRoute(string &vrf_name, const IpPrefix &ip_prefix); void addDirectedBroadcast(const Port &port, const IpAddress &ip_addr); void removeDirectedBroadcast(const Port &port, const IpAddress &ip_addr); diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index ee219178a2b..2790f176e70 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -67,7 +67,10 @@ bool OrchDaemon::init() gCrmOrch = new CrmOrch(m_configDb, CFG_CRM_TABLE_NAME); gPortsOrch = new PortsOrch(m_applDb, ports_tables); gFdbOrch = new FdbOrch(m_applDb, APP_FDB_TABLE_NAME, gPortsOrch); - gIntfsOrch = new IntfsOrch(m_applDb, APP_INTF_TABLE_NAME); + VRFOrch *vrf_orch = new VRFOrch(m_applDb, APP_VRF_TABLE_NAME); + gDirectory.set(vrf_orch); + + gIntfsOrch = new IntfsOrch(m_applDb, APP_INTF_TABLE_NAME, vrf_orch); gNeighOrch = new NeighOrch(m_applDb, APP_NEIGH_TABLE_NAME, gIntfsOrch); gRouteOrch = new RouteOrch(m_applDb, APP_ROUTE_TABLE_NAME, gNeighOrch); CoppOrch *copp_orch = new CoppOrch(m_applDb, APP_COPP_TABLE_NAME); @@ -77,6 +80,8 @@ bool OrchDaemon::init() gDirectory.set(vxlan_tunnel_orch); VxlanTunnelMapOrch *vxlan_tunnel_map_orch = new VxlanTunnelMapOrch(m_configDb, CFG_VXLAN_TUNNEL_MAP_TABLE_NAME); gDirectory.set(vxlan_tunnel_map_orch); + VxlanVnetOrch *vxlan_vnet_orch = new VxlanVnetOrch(m_configDb, CFG_VNET_TABLE_NAME); + gDirectory.set(vxlan_vnet_orch); vector qos_tables = { CFG_TC_TO_QUEUE_MAP_TABLE_NAME, @@ -104,7 +109,6 @@ bool OrchDaemon::init() TableConnector appDbMirrorSession(m_applDb, APP_MIRROR_SESSION_TABLE_NAME); TableConnector confDbMirrorSession(m_configDb, CFG_MIRROR_SESSION_TABLE_NAME); MirrorOrch *mirror_orch = new MirrorOrch(appDbMirrorSession, confDbMirrorSession, gPortsOrch, gRouteOrch, gNeighOrch, gFdbOrch); - VRFOrch *vrf_orch = new VRFOrch(m_configDb, CFG_VRF_TABLE_NAME); TableConnector confDbAclTable(m_configDb, CFG_ACL_TABLE_NAME); TableConnector confDbAclRuleTable(m_configDb, CFG_ACL_RULE_TABLE_NAME); diff --git a/orchagent/port.h b/orchagent/port.h index f99aaaa0370..7f9110b6655 100644 --- a/orchagent/port.h +++ b/orchagent/port.h @@ -74,6 +74,7 @@ class Port sai_object_id_t m_bridge_port_id = 0; // TODO: port could have multiple bridge port IDs sai_vlan_id_t m_port_vlan_id = DEFAULT_PORT_VLAN_ID; // Port VLAN ID sai_object_id_t m_rif_id = 0; + sai_object_id_t m_vr_id = 0; sai_object_id_t m_hif_id = 0; sai_object_id_t m_lag_id = 0; sai_object_id_t m_lag_member_id = 0; diff --git a/orchagent/request_parser.cpp b/orchagent/request_parser.cpp index a7be4daf3c5..a0d4700e802 100644 --- a/orchagent/request_parser.cpp +++ b/orchagent/request_parser.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "sai.h" @@ -145,6 +144,9 @@ void Request::parseAttrs(const KeyOpFieldsValuesTuple& request) case REQ_T_UINT: attr_item_uint_[fvField(*i)] = parseUint(fvValue(*i)); break; + case REQ_T_SET: + attr_item_set_[fvField(*i)] = parseSet(fvValue(*i)); + break; default: throw std::logic_error(std::string("Not implemented attribute type parser for attribute:") + fvField(*i)); } @@ -207,6 +209,25 @@ IpAddress Request::parseIpAddress(const std::string& str) } } +set Request::parseSet(const std::string& str) +{ + try + { + set str_set; + string substr; + std::istringstream iss(str); + while (getline(iss, substr, ',')) + { + str_set.insert(str); + } + return str_set; + } + catch (std::invalid_argument& _) + { + throw std::invalid_argument(std::string("Invalid string set")); + } +} + uint64_t Request::parseUint(const std::string& str) { try diff --git a/orchagent/request_parser.h b/orchagent/request_parser.h index 57283eeec36..30cc9f3ab0c 100644 --- a/orchagent/request_parser.h +++ b/orchagent/request_parser.h @@ -2,18 +2,20 @@ #define __REQUEST_PARSER_H #include "ipaddress.h" +#include +#include typedef enum _request_types_t { REQ_T_NOT_USED, REQ_T_BOOL, REQ_T_STRING, - REQ_T_STRING_LIST, REQ_T_MAC_ADDRESS, REQ_T_PACKET_ACTION, REQ_T_IP, REQ_T_VLAN, REQ_T_UINT, + REQ_T_SET, } request_types_t; typedef struct _request_description @@ -113,6 +115,12 @@ class Request return attr_item_uint_.at(attr_name); } + const set& getAttrSet(const std::string& attr_name) const + { + assert(is_parsed_); + return attr_item_set_.at(attr_name); + } + protected: Request(const request_description_t& request_description, const char key_separator) : request_description_(request_description), @@ -132,6 +140,7 @@ class Request IpAddress parseIpAddress(const std::string& str); uint64_t parseUint(const std::string& str); uint16_t parseVlan(const std::string& str); + set parseSet(const std::string& str); sai_packet_action_t parsePacketAction(const std::string& str); @@ -155,6 +164,7 @@ class Request std::unordered_map attr_item_vlan_; std::unordered_map attr_item_ip_; std::unordered_map attr_item_uint_; + std::unordered_map> attr_item_set_; }; #endif // __REQUEST_PARSER_H diff --git a/orchagent/vrforch.cpp b/orchagent/vrforch.cpp index a67e6734bd7..a4944ac1e17 100644 --- a/orchagent/vrforch.cpp +++ b/orchagent/vrforch.cpp @@ -20,6 +20,7 @@ bool VRFOrch::addOperation(const Request& request) sai_attribute_t attr; vector attrs; + string vnet_name = ""; for (const auto& name: request.getAttrFieldNames()) { @@ -54,6 +55,10 @@ bool VRFOrch::addOperation(const Request& request) attr.id = SAI_VIRTUAL_ROUTER_ATTR_UNKNOWN_L3_MULTICAST_PACKET_ACTION; attr.value.s32 = request.getAttrPacketAction("l3_mc_action"); } + else if (name == "vnet_name") + { + vnet_name = request.getAttrString("vnet_name"); + } else { SWSS_LOG_ERROR("Logic error: Unknown attribute: %s", name.c_str()); @@ -80,6 +85,32 @@ bool VRFOrch::addOperation(const Request& request) vrf_table_[vrf_name] = router_id; SWSS_LOG_NOTICE("VRF '%s' was added", vrf_name.c_str()); + + /* + * FIXME - If VNET, then both ingress and egress VRF must be created + * This must be revisited in case separate request comes + */ + + if (!vnet_name.empty()) + { + struct VnetEntry ent = {vrf_name, router_id, 0x0}; + + sai_status_t status = sai_virtual_router_api->create_virtual_router(&router_id, + gSwitchId, + static_cast(attrs.size()), + attrs.data()); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create virtual router name: %s, rv: %d", vrf_name.c_str(), status); + return false; + } + + ent.egr_vrf = router_id; + vnet_table_[vnet_name] = ent; + + SWSS_LOG_NOTICE("VRF '%s' was added to Vnet '%s'", vrf_name.c_str(), vnet_name.c_str()); + + } } else { @@ -97,6 +128,8 @@ bool VRFOrch::addOperation(const Request& request) } } + // FIXME - Handle VNET case + SWSS_LOG_NOTICE("VRF '%s' was updated", vrf_name.c_str()); } diff --git a/orchagent/vrforch.h b/orchagent/vrforch.h index 49df85492ea..aa9a82a5d8c 100644 --- a/orchagent/vrforch.h +++ b/orchagent/vrforch.h @@ -3,6 +3,7 @@ #include "request_parser.h" +extern sai_object_id_t gVirtualRouterId; typedef std::unordered_map VRFTable; const request_description_t request_description = { @@ -14,6 +15,7 @@ const request_description_t request_description = { { "ttl_action", REQ_T_PACKET_ACTION }, { "ip_opt_action", REQ_T_PACKET_ACTION }, { "l3_mc_action", REQ_T_PACKET_ACTION }, + { "vnet_name", REQ_T_STRING }, }, { } // no mandatory attributes }; @@ -21,9 +23,17 @@ const request_description_t request_description = { class VRFRequest : public Request { public: - VRFRequest() : Request(request_description, '|') { } + VRFRequest() : Request(request_description, ':') { } }; +struct VnetEntry +{ + std::string vrf_name; + sai_object_id_t ing_vrf; + sai_object_id_t egr_vrf; +}; +typedef std::unordered_map VnetTable; + class VRFOrch : public Orch2 { @@ -39,13 +49,36 @@ class VRFOrch : public Orch2 sai_object_id_t getVRFid(const std::string& name) const { - return vrf_table_.at(name); + if (vrf_table_.find(name) != std::end(vrf_table_)) + { + return vrf_table_.at(name); + } + else + { + return gVirtualRouterId; + } + } + + bool isVnetexists(const std::string& name) const + { + return vnet_table_.find(name) != std::end(vnet_table_); + } + + sai_object_id_t getVRFidIngress(const std::string& name) const + { + return vnet_table_.at(name).ing_vrf; + } + + sai_object_id_t getVRFidEgress(const std::string& name) const + { + return vnet_table_.at(name).egr_vrf; } private: virtual bool addOperation(const Request& request); virtual bool delOperation(const Request& request); VRFTable vrf_table_; + VnetTable vnet_table_; VRFRequest request_; }; diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index c68b3222040..53c3fd8c6d2 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -518,6 +518,16 @@ bool VxlanVnetOrch::addOperation(const Request& request) tunnel_obj->createTunnel(map_type::VRID_TO_VNI, map_type::VNI_TO_VRID); } + VRFOrch* vrf_orch = gDirectory.get(); + if (!vrf_orch->isVnetexists(vnet_name)) + { + SWSS_LOG_INFO("VRF not created for VNET %s", vnet_name.c_str()); + return false; + } + + sai_object_id_t ing_vrf_id = vrf_orch->getVRFidIngress(vnet_name); + sai_object_id_t egr_vrf_id = vrf_orch->getVRFidEgress(vnet_name); + auto vni_id = static_cast(request.getAttrUint("vni")); if (vni_id >= 1<<24) { @@ -525,13 +535,9 @@ bool VxlanVnetOrch::addOperation(const Request& request) return true; } - //@Todo - //Get VRF Id - sai_object_id_t ing_vrf_id = 0x0; - sai_object_id_t egr_vrf_id = 0x0; - - vnet_entry_t entry = {tunnel_name, vni_id, {}}; + auto &peer_vnet = request.getAttrSet("peer_list"); + vnet_entry_t entry = {tunnel_name, vni_id, peer_vnet}; try { /* @@ -568,6 +574,10 @@ bool VxlanVnetOrch::delOperation(const Request& request) return true; } +/* + * FIXME - This must be handled by IntfMgrD + */ + bool VnetIntfOrch::addOperation(const Request& request) { SWSS_LOG_ENTER(); @@ -600,5 +610,3 @@ bool VnetIntfOrch::delOperation(const Request& request) return true; } - - diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index f64c1ed3466..3da0e8a78d5 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -5,6 +5,7 @@ #include #include "request_parser.h" #include "portsorch.h" +#include "vrforch.h" enum class map_type { @@ -139,7 +140,7 @@ const request_description_t vxlan_vnet_request_description = { { { "vxlan_tunnel", REQ_T_STRING }, { "vni", REQ_T_UINT }, - { "peer_list", REQ_T_STRING_LIST }, + { "peer_list", REQ_T_SET }, }, { "vxlan_tunnel", "vni" } }; @@ -176,6 +177,9 @@ class VxlanVnetOrch : public Orch2 VxlanVnetRequest request_; }; +/* + * FIXME - This must be handled by IntfMgrD + */ const request_description_t vnet_intf_request_description = { { REQ_T_STRING, REQ_T_IP }, { From 6a8cc6516435191a17de93e4bcbbee9b75e96b6d Mon Sep 17 00:00:00 2001 From: localadmin Date: Mon, 17 Sep 2018 00:00:38 +0000 Subject: [PATCH 3/4] Vxlan VRF to use APPDB Tunnel Map --- orchagent/orchdaemon.cpp | 4 +-- orchagent/vrforch.cpp | 35 +++++++++++++++----- orchagent/vrforch.h | 56 +++++++++++++++++++++++++++----- orchagent/vxlanorch.cpp | 69 ++++++++++++++++++++++------------------ orchagent/vxlanorch.h | 34 ++++++++++---------- 5 files changed, 131 insertions(+), 67 deletions(-) diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 2790f176e70..af83bae4a42 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -80,8 +80,8 @@ bool OrchDaemon::init() gDirectory.set(vxlan_tunnel_orch); VxlanTunnelMapOrch *vxlan_tunnel_map_orch = new VxlanTunnelMapOrch(m_configDb, CFG_VXLAN_TUNNEL_MAP_TABLE_NAME); gDirectory.set(vxlan_tunnel_map_orch); - VxlanVnetOrch *vxlan_vnet_orch = new VxlanVnetOrch(m_configDb, CFG_VNET_TABLE_NAME); - gDirectory.set(vxlan_vnet_orch); + VxlanVrfMapOrch *vxlan_vrf_orch = new VxlanVrfMapOrch(m_applDb, APP_VXLAN_VRF_TABLE_NAME); + gDirectory.set(vxlan_vrf_orch); vector qos_tables = { CFG_TC_TO_QUEUE_MAP_TABLE_NAME, diff --git a/orchagent/vrforch.cpp b/orchagent/vrforch.cpp index a4944ac1e17..0a0dccabf39 100644 --- a/orchagent/vrforch.cpp +++ b/orchagent/vrforch.cpp @@ -21,6 +21,7 @@ bool VRFOrch::addOperation(const Request& request) sai_attribute_t attr; vector attrs; string vnet_name = ""; + set peer_list = {}; for (const auto& name: request.getAttrFieldNames()) { @@ -59,6 +60,10 @@ bool VRFOrch::addOperation(const Request& request) { vnet_name = request.getAttrString("vnet_name"); } + else if (name == "peer_list") + { + peer_list = request.getAttrSet("peer_list"); + } else { SWSS_LOG_ERROR("Logic error: Unknown attribute: %s", name.c_str()); @@ -84,18 +89,15 @@ bool VRFOrch::addOperation(const Request& request) } vrf_table_[vrf_name] = router_id; - SWSS_LOG_NOTICE("VRF '%s' was added", vrf_name.c_str()); /* - * FIXME - If VNET, then both ingress and egress VRF must be created - * This must be revisited in case separate request comes + * If VNET, then both ingress and egress VRF must be created */ if (!vnet_name.empty()) { - struct VnetEntry ent = {vrf_name, router_id, 0x0}; - - sai_status_t status = sai_virtual_router_api->create_virtual_router(&router_id, + sai_object_id_t e_router_id; + sai_status_t status = sai_virtual_router_api->create_virtual_router(&e_router_id, gSwitchId, static_cast(attrs.size()), attrs.data()); @@ -105,12 +107,14 @@ bool VRFOrch::addOperation(const Request& request) return false; } - ent.egr_vrf = router_id; - vnet_table_[vnet_name] = ent; + VNetObject_T vnet_obj(new VNetObject(vrf_name, router_id, e_router_id, peer_list)); + vnet_table_[vnet_name] = std::move(vnet_obj); SWSS_LOG_NOTICE("VRF '%s' was added to Vnet '%s'", vrf_name.c_str(), vnet_name.c_str()); } + + SWSS_LOG_NOTICE("VRF '%s' was added", vrf_name.c_str()); } else { @@ -155,6 +159,21 @@ bool VRFOrch::delOperation(const Request& request) return false; } + if (isMapexists(vrf_name)) + { + auto vnet = getVnetName(vrf_name); + router_id = getVRFidEgress(vnet); + sai_status_t status = sai_virtual_router_api->remove_virtual_router(router_id); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to remove virtual router name: %s, rv:%d", vnet.c_str(), status); + return false; + } + + vnet_table_.erase(vnet); + map_table_.erase(vrf_name); + } + vrf_table_.erase(vrf_name); SWSS_LOG_NOTICE("VRF '%s' was removed", vrf_name.c_str()); diff --git a/orchagent/vrforch.h b/orchagent/vrforch.h index aa9a82a5d8c..8eadc7b99f3 100644 --- a/orchagent/vrforch.h +++ b/orchagent/vrforch.h @@ -16,6 +16,8 @@ const request_description_t request_description = { { "ip_opt_action", REQ_T_PACKET_ACTION }, { "l3_mc_action", REQ_T_PACKET_ACTION }, { "vnet_name", REQ_T_STRING }, + { "fall_through", REQ_T_BOOL }, + { "peer_list", REQ_T_SET }, }, { } // no mandatory attributes }; @@ -26,14 +28,40 @@ class VRFRequest : public Request VRFRequest() : Request(request_description, ':') { } }; -struct VnetEntry +class VNetObject { - std::string vrf_name; - sai_object_id_t ing_vrf; - sai_object_id_t egr_vrf; +public: + VNetObject(string vr_name, sai_object_id_t ivr_id, sai_object_id_t evr_id, set& list) + :vrf_name(vr_name), i_vrf_id(ivr_id),e_vrf_id(evr_id) + { + peer_list = list; + } + + sai_object_id_t getVRFidIngress() const + { + return i_vrf_id; + } + + sai_object_id_t getVRFidEgress() const + { + return e_vrf_id; + } + + string getVRFname() const + { + return vrf_name; + } + +private: + string vrf_name; + set peer_list = {}; + sai_object_id_t i_vrf_id; + sai_object_id_t e_vrf_id; }; -typedef std::unordered_map VnetTable; +using VNetObject_T = std::unique_ptr; +typedef std::unordered_map VNetTable; +typedef std::unordered_map VRFMapTable; class VRFOrch : public Orch2 { @@ -66,19 +94,31 @@ class VRFOrch : public Orch2 sai_object_id_t getVRFidIngress(const std::string& name) const { - return vnet_table_.at(name).ing_vrf; + return vnet_table_.at(name)->getVRFidIngress(); } sai_object_id_t getVRFidEgress(const std::string& name) const { - return vnet_table_.at(name).egr_vrf; + return vnet_table_.at(name)->getVRFidEgress(); + } + + bool isMapexists(const std::string& name) const + { + return map_table_.find(name) != std::end(map_table_); } + + string getVnetName(const std::string& vrf) const + { + return map_table_.at(vrf); + } + private: virtual bool addOperation(const Request& request); virtual bool delOperation(const Request& request); VRFTable vrf_table_; - VnetTable vnet_table_; + VNetTable vnet_table_; + VRFMapTable map_table_; //VRF to Vnet Map VRFRequest request_; }; diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index 53c3fd8c6d2..031459597b2 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -492,19 +492,11 @@ bool VxlanTunnelMapOrch::delOperation(const Request& request) return true; } -bool VxlanVnetOrch::addOperation(const Request& request) +bool VxlanVrfMapOrch::addOperation(const Request& request) { SWSS_LOG_ENTER(); - const auto& vnet_name = request.getKeyString(0); - SWSS_LOG_INFO("Vnet key '%s'", vnet_name.c_str()); - if(isVnetExists(vnet_name)) - { - SWSS_LOG_ERROR("Vnet peer '%s' exist", vnet_name.c_str()); - return false; - } - - auto tunnel_name = request.getAttrString("vxlan_tunnel"); + auto tunnel_name = request.getKeyString(0); VxlanTunnelOrch* tunnel_orch = gDirectory.get(); if (!tunnel_orch->isTunnelExists(tunnel_name)) { @@ -512,60 +504,75 @@ bool VxlanVnetOrch::addOperation(const Request& request) return false; } + auto vni_id = static_cast(request.getAttrUint("vni")); + if (vni_id >= 1<<24) + { + SWSS_LOG_ERROR("Vxlan vni id is too big: %d", vni_id); + return true; + } + auto& tunnel_obj = tunnel_orch->getVxlanTunnel(tunnel_name); if (!tunnel_obj->isActive()) { tunnel_obj->createTunnel(map_type::VRID_TO_VNI, map_type::VNI_TO_VRID); } + auto vrf_name = request.getAttrString("vrf"); VRFOrch* vrf_orch = gDirectory.get(); - if (!vrf_orch->isVnetexists(vnet_name)) + if (!vrf_orch->isVRFexists(vrf_name)) { - SWSS_LOG_INFO("VRF not created for VNET %s", vnet_name.c_str()); + SWSS_LOG_INFO("VRF not created for VNET %s", vrf_name.c_str()); return false; } - sai_object_id_t ing_vrf_id = vrf_orch->getVRFidIngress(vnet_name); - sai_object_id_t egr_vrf_id = vrf_orch->getVRFidEgress(vnet_name); - - auto vni_id = static_cast(request.getAttrUint("vni")); - if (vni_id >= 1<<24) + const auto full_map_entry_name = request.getFullKey(); + if (isVrfMapExists(full_map_entry_name)) { - SWSS_LOG_ERROR("Vxlan vni id is too big: %d", vni_id); + SWSS_LOG_ERROR("Vxlan VRF map '%s' is already exist", full_map_entry_name.c_str()); return true; } - auto &peer_vnet = request.getAttrSet("peer_list"); + const auto tunnel_map_entry_name = request.getKeyString(1); + sai_object_id_t ivrf, evrf; + if (!vrf_orch->isMapexists(vrf_name)) + { + ivrf = evrf = vrf_orch->getVRFid(vrf_name); + } + else + { + auto vnet_name = vrf_orch->getVnetName(vrf_name); + ivrf = vrf_orch->getVRFidEgress(vnet_name); + evrf = vrf_orch->getVRFidIngress(vnet_name); + } - vnet_entry_t entry = {tunnel_name, vni_id, peer_vnet}; + vrf_map_entry_t entry; try { /* * Create encap and decap mapper for each VRF per VNET entry */ - auto encap_entry = tunnel_obj->addEncapMapperEntry(ing_vrf_id, vni_id); - auto decap_entry = tunnel_obj->addDecapMapperEntry(egr_vrf_id, vni_id); + entry.encap_id = tunnel_obj->addEncapMapperEntry(ivrf, vni_id); + entry.decap_id = tunnel_obj->addDecapMapperEntry(evrf, vni_id); SWSS_LOG_INFO("Vxlan tunnel encap entry '%lx' decap entry '0x%lx'", - encap_entry, decap_entry); + entry.encap_id, entry.decap_id); + vxlan_vrf_table_[full_map_entry_name] = entry; } catch(const std::runtime_error& error) { SWSS_LOG_ERROR("Error adding tunnel map entry. Tunnel: %s. Entry: %s. Error: %s", - tunnel_name.c_str(), vnet_name.c_str(), error.what()); + tunnel_name.c_str(), tunnel_map_entry_name.c_str(), error.what()); return false; } - vxlan_vnet_table_[vnet_name] = entry; - - SWSS_LOG_NOTICE("Vxlan tunnel map entry '%s' for tunnel '%s' was created", - vnet_name.c_str(), tunnel_name.c_str()); + SWSS_LOG_NOTICE("Vxlan vrf map entry '%s' for tunnel '%s' was created", + tunnel_map_entry_name.c_str(), tunnel_name.c_str()); return true; } -bool VxlanVnetOrch::delOperation(const Request& request) +bool VxlanVrfMapOrch::delOperation(const Request& request) { SWSS_LOG_ENTER(); @@ -583,8 +590,8 @@ bool VnetIntfOrch::addOperation(const Request& request) SWSS_LOG_ENTER(); auto vnet_name = request.getAttrString("vnet_name"); - VxlanVnetOrch* vnet_orch = gDirectory.get(); - if (!vnet_orch->isVnetExists(vnet_name)) + VxlanVrfMapOrch* vnet_orch = gDirectory.get(); + if (!vnet_orch->isVrfMapExists(vnet_name)) { SWSS_LOG_ERROR("Vnet '%s' doesn't exist", vnet_name.c_str()); return false; diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index 3da0e8a78d5..172d35ef8c7 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -135,46 +135,44 @@ class VxlanTunnelMapOrch : public Orch2 VxlanTunnelMapRequest request_; }; -const request_description_t vxlan_vnet_request_description = { - { REQ_T_STRING }, +const request_description_t vxlan_vrf_request_description = { + { REQ_T_STRING, REQ_T_STRING }, { - { "vxlan_tunnel", REQ_T_STRING }, { "vni", REQ_T_UINT }, - { "peer_list", REQ_T_SET }, + { "vrf", REQ_T_STRING }, }, - { "vxlan_tunnel", "vni" } + { "vni", "vrf" } }; -class VxlanVnetRequest : public Request +class VxlanVrfRequest : public Request { public: - VxlanVnetRequest() : Request(vxlan_vnet_request_description, '|') { } + VxlanVrfRequest() : Request(vxlan_vrf_request_description, ':') { } }; -struct vnet_entry_t { - string tunnel_name; - uint32_t vni; - std::set peer_list; +struct vrf_map_entry_t { + sai_object_id_t encap_id; + sai_object_id_t decap_id; }; -typedef std::map VxlanVnetTable; +typedef std::map VxlanVrfTable; -class VxlanVnetOrch : public Orch2 +class VxlanVrfMapOrch : public Orch2 { public: - VxlanVnetOrch(DBConnector *db, const std::string& tableName) : Orch2(db, tableName, request_) { } + VxlanVrfMapOrch(DBConnector *db, const std::string& tableName) : Orch2(db, tableName, request_) { } - bool isVnetExists(const std::string& name) const + bool isVrfMapExists(const std::string& name) const { - return vxlan_vnet_table_.find(name) != std::end(vxlan_vnet_table_); + return vxlan_vrf_table_.find(name) != std::end(vxlan_vrf_table_); } private: virtual bool addOperation(const Request& request); virtual bool delOperation(const Request& request); - VxlanVnetTable vxlan_vnet_table_; - VxlanVnetRequest request_; + VxlanVrfTable vxlan_vrf_table_; + VxlanVrfRequest request_; }; /* From bd3bcb1298adbbbd49537598f2edf6858bbea741 Mon Sep 17 00:00:00 2001 From: Prince Date: Mon, 17 Sep 2018 00:48:43 +0000 Subject: [PATCH 4/4] Handle VNET Interface creation in IntfMgrD --- cfgmgr/intfmgr.cpp | 31 +++++++++++++++++++++++++++++++ cfgmgr/intfmgr.h | 2 +- cfgmgr/intfmgrd.cpp | 1 + orchagent/vxlanorch.cpp | 37 ------------------------------------- orchagent/vxlanorch.h | 30 ------------------------------ 5 files changed, 33 insertions(+), 68 deletions(-) diff --git a/cfgmgr/intfmgr.cpp b/cfgmgr/intfmgr.cpp index fb14df97da8..e1b008df83b 100644 --- a/cfgmgr/intfmgr.cpp +++ b/cfgmgr/intfmgr.cpp @@ -13,6 +13,7 @@ using namespace swss; #define VLAN_PREFIX "Vlan" #define LAG_PREFIX "PortChannel" +#define VNET_PREFIX "Vnet" IntfMgr::IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector &tableNames) : Orch(cfgDb, tableNames), @@ -21,6 +22,7 @@ IntfMgr::IntfMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, c m_statePortTable(stateDb, STATE_PORT_TABLE_NAME), m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME), m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME), + m_stateVrfTable(stateDb, STATE_VRF_TABLE_NAME), m_appIntfTableProducer(appDb, APP_INTF_TABLE_NAME) { } @@ -63,6 +65,14 @@ bool IntfMgr::isIntfStateOk(const string &alias) return true; } } + else if (!alias.compare(0, strlen(VNET_PREFIX), VNET_PREFIX)) + { + if (m_stateVrfTable.get(alias, temp)) + { + SWSS_LOG_DEBUG("Vnet %s is ready", alias.c_str()); + return true; + } + } else if (m_statePortTable.get(alias, temp)) { SWSS_LOG_DEBUG("Port %s is ready", alias.c_str()); @@ -89,6 +99,19 @@ void IntfMgr::doTask(Consumer &consumer) continue; } + const vector& data = kfvFieldsValues(t); + string vnet_name = ""; + + for (auto idx : data) + { + const auto &field = fvField(idx); + const auto &value = fvValue(idx); + if (field == "vnet_name") + { + vnet_name = value; + } + } + string alias(keys[0]); IpPrefix ip_prefix(keys[1]); @@ -107,6 +130,14 @@ void IntfMgr::doTask(Consumer &consumer) it++; continue; } + + if (!vnet_name.empty() && !isIntfStateOk(vnet_name)) + { + SWSS_LOG_DEBUG("VRF is not ready, skipping %s", kfvKey(t).c_str()); + it++; + continue; + } + setIntfIp(alias, "add", ip_prefix.to_string(), ip_prefix.isV4()); } else if (op == DEL_COMMAND) diff --git a/cfgmgr/intfmgr.h b/cfgmgr/intfmgr.h index 3d79d6d4779..9dc355d2b95 100644 --- a/cfgmgr/intfmgr.h +++ b/cfgmgr/intfmgr.h @@ -19,7 +19,7 @@ class IntfMgr : public Orch private: ProducerStateTable m_appIntfTableProducer; Table m_cfgIntfTable, m_cfgVlanIntfTable; - Table m_statePortTable, m_stateLagTable, m_stateVlanTable; + Table m_statePortTable, m_stateLagTable, m_stateVlanTable, m_stateVrfTable; bool setIntfIp(const string &alias, const string &opCmd, const string &ipPrefixStr, const bool ipv4 = true); void doTask(Consumer &consumer); diff --git a/cfgmgr/intfmgrd.cpp b/cfgmgr/intfmgrd.cpp index 8d7c2ef2fc3..3b16e32199a 100644 --- a/cfgmgr/intfmgrd.cpp +++ b/cfgmgr/intfmgrd.cpp @@ -42,6 +42,7 @@ int main(int argc, char **argv) { vector cfg_intf_tables = { CFG_INTF_TABLE_NAME, + CFG_VNET_INTF_TABLE_NAME, CFG_LAG_INTF_TABLE_NAME, CFG_VLAN_INTF_TABLE_NAME, }; diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index 031459597b2..651cc052541 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -580,40 +580,3 @@ bool VxlanVrfMapOrch::delOperation(const Request& request) return true; } - -/* - * FIXME - This must be handled by IntfMgrD - */ - -bool VnetIntfOrch::addOperation(const Request& request) -{ - SWSS_LOG_ENTER(); - - auto vnet_name = request.getAttrString("vnet_name"); - VxlanVrfMapOrch* vnet_orch = gDirectory.get(); - if (!vnet_orch->isVrfMapExists(vnet_name)) - { - SWSS_LOG_ERROR("Vnet '%s' doesn't exist", vnet_name.c_str()); - return false; - } - - const auto& if_name = request.getKeyString(0); - SWSS_LOG_INFO("If name '%s'", if_name.c_str()); - - const auto& ip_addr = request.getKeyIpAddress(1); - SWSS_LOG_INFO("Ip prefix '%s'", ip_addr.to_string().c_str()); - - - SWSS_LOG_NOTICE("Vxlan interface %s created for %s", if_name.c_str(), vnet_name.c_str()); - - return true; -} - -bool VnetIntfOrch::delOperation(const Request& request) -{ - SWSS_LOG_ENTER(); - - SWSS_LOG_ERROR("DEL operation is not implemented"); - - return true; -} diff --git a/orchagent/vxlanorch.h b/orchagent/vxlanorch.h index 172d35ef8c7..c5306ae9b92 100644 --- a/orchagent/vxlanorch.h +++ b/orchagent/vxlanorch.h @@ -174,33 +174,3 @@ class VxlanVrfMapOrch : public Orch2 VxlanVrfTable vxlan_vrf_table_; VxlanVrfRequest request_; }; - -/* - * FIXME - This must be handled by IntfMgrD - */ -const request_description_t vnet_intf_request_description = { - { REQ_T_STRING, REQ_T_IP }, - { - { "vnet_name", REQ_T_STRING }, - }, - { "vnet_name" } -}; - -class VnetIntfRequest : public Request -{ -public: - VnetIntfRequest() : Request(vnet_intf_request_description, '|') { } -}; - -class VnetIntfOrch : public Orch2 -{ -public: - VnetIntfOrch(DBConnector *db, const std::string& tableName) : Orch2(db, tableName, request_) { } - -private: - virtual bool addOperation(const Request& request); - virtual bool delOperation(const Request& request); - - - VnetIntfRequest request_; -};