Skip to content

Commit

Permalink
VNET/VXLAN changes (sonic-net#643)
Browse files Browse the repository at this point in the history
* Vnetvxlan changes

* VS test case for Vnet/Vxlan

* Addressed review comments, fixed a VS test case

* Modifications based on feedback for VNET Table flow, VS test restructure to adopt to new changes

* Schema updated for App DB
  • Loading branch information
prsunny authored Nov 26, 2018
1 parent b750a4b commit bffa01f
Show file tree
Hide file tree
Showing 8 changed files with 1,410 additions and 138 deletions.
29 changes: 29 additions & 0 deletions doc/swss-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,35 @@ Equivalent RedisDB entry:
12) "0"
127.0.0.1:6379>

### VXLAN\_TUNNEL\_MAP
;Stores vxlan tunnel map configuration. Defines mapping between vxlan vni and vrf

key = VXLAN_TUNNEL_MAP:tunnel_name:tunnel_map_name
; tunnel_name is a reference to created vxlan tunnel
; tunnel_map_name is an arbitrary name of the map
vni = 1*8DIGIT ; vni id, defined for tunnel map
vrf = vrf_name ; name of the vrf

### VNET\_ROUTE\_TUNNEL_TABLE
;Defines schema for VNet Route tunnel table attributes

key = VNET_ROUTE_TUNNEL_TABLE:vnet_name:prefix
; Vnet route tunnel table with prefix
; field value
endpoint = IP ; Host VM IP address
mac_address = 12HEXDIG ; Inner dest mac in encapsulated packet (Optional)
vxlanid = 1*8DIGIT ; VNI value in encapsulated packet (Optional)

;value annotations
vnet_name = 1*16VCHAR

### VNET\_ROUTE_TABLE
;Defines schema for VNet Route table attributes
key = VNET_ROUTE_TABLE:vnet_name:prefix
; Vnet route table with prefix
;field value
nexthop = IP ; Nexthop IP address (Optional)
ifname = ifname ; Interface name

## Configuration DB schema

Expand Down
3 changes: 3 additions & 0 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,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);
VxlanVrfMapOrch *vxlan_vrf_orch = new VxlanVrfMapOrch(m_applDb, APP_VXLAN_VRF_TABLE_NAME);
gDirectory.set(vxlan_vrf_orch);

vector<string> qos_tables = {
CFG_TC_TO_QUEUE_MAP_TABLE_NAME,
Expand Down Expand Up @@ -193,6 +195,7 @@ bool OrchDaemon::init()
m_orchList.push_back(vrf_orch);
m_orchList.push_back(vxlan_tunnel_orch);
m_orchList.push_back(vxlan_tunnel_map_orch);
m_orchList.push_back(vxlan_vrf_orch);

m_select = new Select();

Expand Down
77 changes: 61 additions & 16 deletions orchagent/vnetorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,25 @@
#include "portsorch.h"
#include "request_parser.h"
#include "vnetorch.h"
#include "vxlanorch.h"
#include "directory.h"
#include "swssnet.h"

extern sai_virtual_router_api_t* sai_virtual_router_api;
extern sai_route_api_t* sai_route_api;
extern sai_object_id_t gSwitchId;
extern Directory<Orch*> gDirectory;
extern PortsOrch *gPortsOrch;

/*
* VRF Modeling and VNetVrf class definitions
*/
std::vector<VR_TYPE> vr_cntxt;

VNetVrfObject::VNetVrfObject(const std::string& name, set<string>& p_list, vector<sai_attribute_t>& attrs)
: VNetObject(p_list)
VNetVrfObject::VNetVrfObject(const std::string& vnet, string& tunnel, set<string>& peer,
vector<sai_attribute_t>& attrs) : VNetObject(tunnel, peer)
{
vnet_name_ = name;
vnet_name_ = vnet;
createObj(attrs);
}

Expand Down Expand Up @@ -138,10 +141,10 @@ VNetVrfObject::~VNetVrfObject()
*/

template <class T>
std::unique_ptr<T> VNetOrch::createObject(const string& vnet_name, set<string>& plist,
std::unique_ptr<T> VNetOrch::createObject(const string& vnet_name, string& tunnel, set<string>& plist,
vector<sai_attribute_t>& attrs)
{
std::unique_ptr<T> vnet_obj(new T(vnet_name, plist, attrs));
std::unique_ptr<T> vnet_obj(new T(vnet_name, tunnel, plist, attrs));
return vnet_obj;
}

Expand All @@ -168,6 +171,8 @@ bool VNetOrch::addOperation(const Request& request)
vector<sai_attribute_t> attrs;
set<string> peer_list = {};
bool peer = false, create = false;
uint32_t vni=0;
string tunnel;

for (const auto& name: request.getAttrFieldNames())
{
Expand All @@ -183,6 +188,14 @@ bool VNetOrch::addOperation(const Request& request)
peer_list = request.getAttrSet("peer_list");
peer = true;
}
else if (name == "vni")
{
vni = static_cast<sai_uint32_t>(request.getAttrUint("vni"));
}
else if (name == "vxlan_tunnel")
{
tunnel = request.getAttrString("vxlan_tunnel");
}
else
{
SWSS_LOG_WARN("Logic error: Unknown attribute: %s", name.c_str());
Expand All @@ -199,11 +212,27 @@ bool VNetOrch::addOperation(const Request& request)
auto it = vnet_table_.find(vnet_name);
if (isVnetExecVrf())
{
VxlanTunnelOrch* vxlan_orch = gDirectory.get<VxlanTunnelOrch*>();

if (!vxlan_orch->isTunnelExists(tunnel))
{
SWSS_LOG_WARN("Vxlan tunnel '%s' doesn't exist", tunnel.c_str());
return false;
}

if (it == std::end(vnet_table_))
{
obj = createObject<VNetVrfObject>(vnet_name, peer_list, attrs);
obj = createObject<VNetVrfObject>(vnet_name, tunnel, peer_list, attrs);
create = true;
}

if (!vxlan_orch->createVxlanTunnelMap(tunnel, TUNNEL_MAP_T_VIRTUAL_ROUTER, vni,
obj->getEncapMapId(), obj->getDecapMapId()))
{
SWSS_LOG_ERROR("VNET '%s', tunnel '%s', map create failed",
vnet_name.c_str(), tunnel.c_str());
}

SWSS_LOG_INFO("VNET '%s' was added ", vnet_name.c_str());
}
else
Expand Down Expand Up @@ -291,29 +320,34 @@ VNetRouteOrch::VNetRouteOrch(DBConnector *db, vector<string> &tableNames, VNetOr
handler_map_.insert(handler_pair(APP_VNET_RT_TUNNEL_TABLE_NAME, &VNetRouteOrch::handleTunnel));
}

sai_object_id_t VNetRouteOrch::getNextHop(const string& vnet, IpAddress& ipAddr)
sai_object_id_t VNetRouteOrch::getNextHop(const string& vnet, tunnelEndpoint& endp)
{
auto it = nh_tunnels_.find(vnet);
if (it != nh_tunnels_.end())
{
if (it->second.find(ipAddr) != it->second.end())
if (it->second.find(endp.ip) != it->second.end())
{
return it->second.at(ipAddr);
return it->second.at(endp.ip);
}
}

sai_object_id_t nh_id = SAI_NULL_OBJECT_ID;
auto tun_name = vnet_orch_->getTunnelName(vnet);

/*
* @FIXEME createNextHopTunnel(vnet, ipAddr, nh_id) , throw if failed
*/
VxlanTunnelOrch* vxlan_orch = gDirectory.get<VxlanTunnelOrch*>();

nh_tunnels_[vnet].insert({ipAddr, nh_id});
nh_id = vxlan_orch->createNextHopTunnel(tun_name, endp.ip, endp.mac, endp.vni);
if (nh_id == SAI_NULL_OBJECT_ID)
{
throw std::runtime_error("NH Tunnel create failed for " + vnet + " ip " + endp.ip.to_string());
}

nh_tunnels_[vnet].insert({endp.ip, nh_id});
return nh_id;
}

template<>
bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipPrefix, IpAddress& endIp)
bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp)
{
SWSS_LOG_ENTER();

Expand Down Expand Up @@ -345,7 +379,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP

sai_ip_prefix_t pfx;
copy(pfx, ipPrefix);
sai_object_id_t nh_id = getNextHop(vnet, endIp);
sai_object_id_t nh_id = getNextHop(vnet, endp);

for (auto vr_id : vr_set)
{
Expand Down Expand Up @@ -450,13 +484,23 @@ void VNetRouteOrch::handleTunnel(const Request& request)
SWSS_LOG_ENTER();

IpAddress ip;
MacAddress mac;
uint32_t vni = 0;

for (const auto& name: request.getAttrFieldNames())
{
if (name == "endpoint")
{
ip = request.getAttrIP(name);
}
else if (name == "vni")
{
vni = static_cast<uint32_t>(request.getAttrUint(name));
}
else if (name == "mac_address")
{
mac = request.getAttrMacAddress(name);
}
else
{
SWSS_LOG_WARN("Logic error: Unknown attribute: %s", name.c_str());
Expand All @@ -469,9 +513,10 @@ void VNetRouteOrch::handleTunnel(const Request& request)

SWSS_LOG_INFO("VNET-RT '%s' add for endpoint %s", vnet_name.c_str(), ip_pfx.to_string().c_str());

tunnelEndpoint endp = { ip, mac, vni };
if (vnet_orch_->isVnetExecVrf())
{
if (!doRouteTask<VNetVrfObject>(vnet_name, ip_pfx, ip))
if (!doRouteTask<VNetVrfObject>(vnet_name, ip_pfx, endp))
{
throw std::runtime_error("Route add failed");
}
Expand Down
55 changes: 37 additions & 18 deletions orchagent/vnetorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ const request_description_t vnet_request_description = {
{ REQ_T_STRING },
{
{ "src_mac", REQ_T_MAC_ADDRESS },
{ "vnet_name", REQ_T_STRING },
{ "vxlan_tunnel", REQ_T_STRING },
{ "vni", REQ_T_UINT },
{ "peer_list", REQ_T_SET },
},
{ } // no mandatory attributes
{ "vxlan_tunnel", "vni" } // mandatory attributes
};

enum class VNET_EXEC
Expand All @@ -34,7 +35,7 @@ enum class VR_TYPE
VR_INVALID
};

using vrid_list_t = map<VR_TYPE, sai_object_id_t>;
typedef map<VR_TYPE, sai_object_id_t> vrid_list_t;
extern std::vector<VR_TYPE> vr_cntxt;

class VNetRequest : public Request
Expand All @@ -46,10 +47,7 @@ class VNetRequest : public Request
class VNetObject
{
public:
VNetObject(set<string>& p_list)
{
peer_list_ = p_list;
}
VNetObject(string& tunName, set<string>& peer) : tunnel_(tunName), peer_list_(peer) { }

virtual sai_object_id_t getEncapMapId() const = 0;

Expand All @@ -69,16 +67,22 @@ class VNetObject
return peer_list_;
}

string getTunnelName() const
{
return tunnel_;
}

virtual ~VNetObject() {};

private:
set<string> peer_list_ = {};
string tunnel_;
};

class VNetVrfObject : public VNetObject
{
public:
VNetVrfObject(const std::string& name, set<string>& p_list, vector<sai_attribute_t>& attrs);
VNetVrfObject(const string& vnet, string& tunnel, set<string>& peer, vector<sai_attribute_t>& attrs);

sai_object_id_t getVRidIngress() const;

Expand Down Expand Up @@ -112,7 +116,7 @@ class VNetVrfObject : public VNetObject
vrid_list_t vr_ids_;
};

using VNetObject_T = std::unique_ptr<VNetObject>;
typedef std::unique_ptr<VNetObject> VNetObject_T;
typedef std::unordered_map<std::string, VNetObject_T> VNetTable;

class VNetOrch : public Orch2
Expand Down Expand Up @@ -151,6 +155,11 @@ class VNetOrch : public Orch2
return vnet_table_.at(name)->getVRid();
}

string getTunnelName(const std::string& name) const
{
return vnet_table_.at(name)->getTunnelName();
}

bool isVnetExecVrf() const
{
return (vnet_exec_ == VNET_EXEC::VNET_EXEC_VRF);
Expand All @@ -166,7 +175,7 @@ class VNetOrch : public Orch2
virtual bool delOperation(const Request& request);

template <class T>
std::unique_ptr<T> createObject(const string&, set<string>&, vector<sai_attribute_t>&);
std::unique_ptr<T> createObject(const string&, string&, set<string>&, vector<sai_attribute_t>&);

VNetTable vnet_table_;
VNetRequest request_;
Expand All @@ -177,8 +186,10 @@ class VNetOrch : public Orch2
const request_description_t vnet_route_description = {
{ REQ_T_STRING, REQ_T_IP_PREFIX },
{
{ "endpoint", REQ_T_IP },
{ "ifname", REQ_T_STRING },
{ "endpoint", REQ_T_IP },
{ "ifname", REQ_T_STRING },
{ "vni", REQ_T_UINT },
{ "mac_address", REQ_T_MAC_ADDRESS },
},
{ }
};
Expand All @@ -189,15 +200,23 @@ class VNetRouteRequest : public Request
VNetRouteRequest() : Request(vnet_route_description, ':') { }
};

using NextHopMap = map<IpAddress, sai_object_id_t>;
using NextHopTunnels = map<string, NextHopMap>;
typedef map<IpAddress, sai_object_id_t> NextHopMap;
typedef map<string, NextHopMap> NextHopTunnels;

struct tunnelEndpoint
{
IpAddress ip;
MacAddress mac;
uint32_t vni;
};

class VNetRouteOrch : public Orch2
{
public:
VNetRouteOrch(DBConnector *db, vector<string> &tableNames, VNetOrch *);
using handler_pair = pair<string, void (VNetRouteOrch::*) (const Request& )>;
using handler_map = map<string, void (VNetRouteOrch::*) (const Request& )>;

typedef pair<string, void (VNetRouteOrch::*) (const Request& )> handler_pair;
typedef map<string, void (VNetRouteOrch::*) (const Request& )> handler_map;

private:
virtual bool addOperation(const Request& request);
Expand All @@ -207,12 +226,12 @@ class VNetRouteOrch : public Orch2
void handleTunnel(const Request&);

template<typename T>
bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, IpAddress& ipAddr);
bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, tunnelEndpoint& endp);

template<typename T>
bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, string& ifname);

sai_object_id_t getNextHop(const string& vnet, IpAddress& ipAddr);
sai_object_id_t getNextHop(const string& vnet, tunnelEndpoint& endp);

VNetOrch *vnet_orch_;
VNetRouteRequest request_;
Expand Down
Loading

0 comments on commit bffa01f

Please sign in to comment.