Skip to content

Commit

Permalink
Use static RETA allocation (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
xguerin authored Nov 14, 2023
1 parent d6d602c commit ac2f4b8
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 139 deletions.
3 changes: 2 additions & 1 deletion include/tulips/transport/ena/Port.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class Port
void setupPoolsAndQueues(std::string_view ifn, const uint16_t buflen,
const uint16_t nqus);

void setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info);
void setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info,
const uint16_t nqus);

system::Logger& m_log;
size_t m_ntxds;
Expand Down
23 changes: 8 additions & 15 deletions include/tulips/transport/ena/RedirectionTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

#include <tulips/api/Status.h>
#include <tulips/stack/IPv4.h>
#include <tulips/system/SpinLock.h>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <vector>
#include <dpdk/rte_ethdev.h>

namespace tulips::transport::ena {
Expand All @@ -24,10 +22,11 @@ class RedirectionTable
* Allocator.
*/

static Ref allocate(const uint16_t portid, const size_t size,
const size_t hlen, const uint8_t* const hkey)
static Ref allocate(const uint16_t portid, const size_t nqus,
const size_t size, const size_t hlen,
const uint8_t* const hkey)
{
return Ref(new RedirectionTable(portid, size, hlen, hkey));
return Ref(new RedirectionTable(portid, nqus, size, hlen, hkey));
}

/*
Expand All @@ -37,14 +36,10 @@ class RedirectionTable
~RedirectionTable();

/*
* Flow registration.
* Flow matching.
*/

Status set(stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport,
const uint16_t queueid);

Status clear(stack::ipv4::Address const& laddr, const uint16_t lport,
Status match(stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport,
const uint16_t queueid);

Expand All @@ -53,8 +48,8 @@ class RedirectionTable
* Constructor.
*/

RedirectionTable(const uint16_t portid, const size_t size, const size_t hlen,
const uint8_t* const hkey);
RedirectionTable(const uint16_t portid, const size_t nqus, const size_t size,
const size_t hlen, const uint8_t* const hkey);

/*
* Attributes.
Expand All @@ -64,8 +59,6 @@ class RedirectionTable
size_t m_size;
size_t m_hlen;
const uint8_t* m_hkey;
system::SpinLock m_lock;
std::vector<size_t> m_cache;
struct rte_eth_rss_reta_entry64* m_table;
};

Expand Down
6 changes: 4 additions & 2 deletions src/transport/bond/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ Device::listen(const stack::ipv4::Protocol proto,
stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport)
{
auto index = m_listens++ % m_devices.size();
return m_devices[index]->listen(proto, laddr, lport, raddr, rport);
auto index = m_listens % m_devices.size();
auto status = m_devices[index]->listen(proto, laddr, lport, raddr, rport);
m_listens += status == Status::Ok;
return status;
}

void
Expand Down
12 changes: 6 additions & 6 deletions src/transport/ena/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,16 @@ Device::listen(UNUSED const stack::ipv4::Protocol proto,
stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport)
{
return m_reta.set(laddr, lport, raddr, rport, m_queueid);
return m_reta.match(laddr, lport, raddr, rport, m_queueid);
}

void
Device::unlisten(UNUSED const stack::ipv4::Protocol proto,
stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport)
{
m_reta.clear(laddr, lport, raddr, rport, m_queueid);
}
UNUSED stack::ipv4::Address const& laddr,
UNUSED const uint16_t lport,
UNUSED stack::ipv4::Address const& raddr,
UNUSED const uint16_t rport)
{}

Status
Device::poll(Processor& proc)
Expand Down
7 changes: 4 additions & 3 deletions src/transport/ena/Port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Port::Port(system::Logger& log, std::string_view ifn, const size_t width,
/*
* Update the RSS state.
*/
setupReceiveSideScaling(dev_info);
setupReceiveSideScaling(dev_info, nqus);
/*
* Reset the statistics of the port.
*/
Expand Down Expand Up @@ -350,7 +350,8 @@ Port::setupPoolsAndQueues(std::string_view ifn, const uint16_t buflen,
}

void
Port::setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info)
Port::setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info,
const uint16_t nqus)
{
/*
* Get the RSS configuration.
Expand All @@ -367,7 +368,7 @@ Port::setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info)
* Allocate the redirection table.
*/
auto size = dev_info.reta_size;
m_reta = RedirectionTable::allocate(m_portid, size, hlen, hkey);
m_reta = RedirectionTable::allocate(m_portid, nqus, size, hlen, hkey);
}

}
143 changes: 31 additions & 112 deletions src/transport/ena/RedirectionTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,53 @@

namespace tulips::transport::ena {

RedirectionTable::RedirectionTable(const uint16_t portid, const size_t size,
const size_t hlen, const uint8_t* const hkey)
RedirectionTable::RedirectionTable(const uint16_t portid, const size_t nqus,
const size_t size, const size_t hlen,
const uint8_t* const hkey)
: m_portid(portid)
, m_size(size)
, m_hlen(hlen)
, m_hkey(hkey)
, m_lock()
, m_cache()
, m_table(new struct rte_eth_rss_reta_entry64[size >> 6])
{
auto count = size >> 6;
auto partlen = size / (nqus - 1);
/*
* Reset the RETA to point all entries to the 0th queue.
* Reset the RETA.
*/
for (size_t i = 0; i < count; i += 1) {
m_table[i].mask = uint64_t(-1);
memset(m_table[i].reta, 0, sizeof(m_table[i].reta));
}
/*
* Partition the RETA.
*
* NOTE(xrg): we don't allocate any slot for queue 0 as its sole purpose it to
* handle L2 messages.
*/
for (size_t i = 0; i < nqus - 1; i += 1) {
for (size_t j = 0; j < partlen; j += 1) {
auto indx = i * partlen + j;
auto slot = indx >> 6;
auto eidx = indx & 0x3F;
m_table[slot].reta[eidx] = i + 1;
}
}
/*
* Allocate any remaining slots to the last queue.
*/
for (size_t i = (nqus - 1) * partlen; i < size; i += 1) {
auto slot = i >> 6;
auto eidx = i & 0x3F;
m_table[slot].reta[eidx] = nqus - 1;
}
/*
* Update the RETA.
*/
auto ret = rte_eth_dev_rss_reta_update(m_portid, m_table, m_size);
if (ret != 0) {
throw std::runtime_error("Failed to reset the RETA to the 0th queue");
throw std::runtime_error("Failed to setup the redirection table");
}
/*
* Resize the internal cache.
*/
m_cache.resize(size);
}

RedirectionTable::~RedirectionTable()
Expand All @@ -45,76 +63,11 @@ RedirectionTable::~RedirectionTable()
}

Status
RedirectionTable::set(stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport,
const uint16_t queueid)
{
using stack::utils::toeplitz;
/*
* Lock the table.
*/
auto lock = std::lock_guard(m_lock);
/*
* Hash the payload and get the table index.
*/
auto hash = toeplitz(raddr, laddr, rport, lport, m_hlen, m_hkey);
uint64_t indx = hash % m_size;
uint64_t slot = indx >> 6;
uint64_t eidx = indx & 0x3F;
/*
* Prepare the RETA for an query.
*/
memset(m_table, 0, sizeof(struct rte_eth_rss_reta_entry64[m_size >> 6]));
m_table[slot].mask = 1ULL << eidx;
/*
* Query the RETA.
*/
auto ret = rte_eth_dev_rss_reta_query(m_portid, m_table, m_size);
if (ret < 0) {
return Status::HardwareError;
}
/*
* Check the existing entry.
*/
auto preq = m_table[slot].reta[eidx];
if (preq != 0 && preq != queueid) {
return Status::ResourceBusy;
}
/*
* Check if we need to update the RETA.
*/
if (preq == 0) {
/*
* Prepare the RETA for an update.
*/
memset(m_table, 0, sizeof(struct rte_eth_rss_reta_entry64[m_size >> 6]));
m_table[slot].mask = 1ULL << eidx;
m_table[slot].reta[eidx] = queueid;
/*
* Update the RETA.
*/
auto ret = rte_eth_dev_rss_reta_update(m_portid, m_table, m_size);
if (ret != 0) {
return Status::HardwareError;
}
}
/*
* Update the cache and return.
*/
m_cache[indx] += 1;
return Status::Ok;
}

Status
RedirectionTable::clear(stack::ipv4::Address const& laddr, const uint16_t lport,
RedirectionTable::match(stack::ipv4::Address const& laddr, const uint16_t lport,
stack::ipv4::Address const& raddr, const uint16_t rport,
const uint16_t queueid)
{
using stack::utils::toeplitz;
/*
* Lock the table.
*/
auto lock = std::lock_guard(m_lock);
/*
* Hash the payload and get the table index.
*/
Expand All @@ -123,45 +76,11 @@ RedirectionTable::clear(stack::ipv4::Address const& laddr, const uint16_t lport,
uint64_t slot = indx >> 6;
uint64_t eidx = indx & 0x3F;
/*
* Prepare the RETA for a query.
*/
memset(m_table, 0, sizeof(struct rte_eth_rss_reta_entry64[m_size >> 6]));
m_table[slot].mask = 1ULL << eidx;
/*
* Query the RETA.
*/
auto ret = rte_eth_dev_rss_reta_query(m_portid, m_table, m_size);
if (ret < 0) {
return Status::HardwareError;
}
/*
* Check the existing entry.
* Check the entry.
*/
auto preq = m_table[slot].reta[eidx];
if (preq != queueid) {
return Status::InvalidArgument;
}
/*
* Update the cache.
*/
m_cache[indx] -= 1;
/*
* Check if we need to update the RETA.
*/
if (m_cache[indx] == 0) {
/*
* Prepare the RETA for an update.
*/
memset(m_table, 0, sizeof(struct rte_eth_rss_reta_entry64[m_size >> 6]));
m_table[slot].mask = 1ULL << eidx;
m_table[slot].reta[eidx] = 0;
/*
* Update the RETA.
*/
auto ret = rte_eth_dev_rss_reta_update(m_portid, m_table, m_size);
if (ret != 0) {
return Status::HardwareError;
}
return Status::ResourceBusy;
}
/*
* Done.
Expand Down

0 comments on commit ac2f4b8

Please sign in to comment.