Skip to content

Commit

Permalink
Fix Toeplitz hash computation when using the default RSS key
Browse files Browse the repository at this point in the history
  • Loading branch information
xguerin committed Nov 28, 2023
1 parent f1852a4 commit 6e98f8c
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 21 deletions.
2 changes: 1 addition & 1 deletion include/tulips/stack/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ cap(const uint32_t length)
uint32_t toeplitz(stack::ipv4::Address const& saddr,
stack::ipv4::Address const& daddr, const uint16_t sport,
const uint16_t dport, const size_t key_len,
const uint8_t* const key);
const uint8_t* const key, const uint32_t init);

}
8 changes: 5 additions & 3 deletions include/tulips/transport/ena/RedirectionTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ class RedirectionTable

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

/*
Expand All @@ -49,7 +49,8 @@ class RedirectionTable
*/

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

/*
* Attributes.
Expand All @@ -59,6 +60,7 @@ class RedirectionTable
size_t m_size;
size_t m_hlen;
const uint8_t* m_hkey;
bool m_default;
struct rte_eth_rss_reta_entry64* m_table;
};

Expand Down
4 changes: 2 additions & 2 deletions src/stack/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ headerLength(const uint8_t* const packet, const uint32_t plen, uint32_t& len)
uint32_t
toeplitz(stack::ipv4::Address const& saddr, stack::ipv4::Address const& daddr,
const uint16_t sport, const uint16_t dport, const size_t len,
const uint8_t* const key)
const uint8_t* const key, const uint32_t init)
{
uint32_t ret = 0;
uint32_t ret = init;
uint8_t tuple[12];
/*
* Copy the key in a local buffer.
Expand Down
16 changes: 7 additions & 9 deletions src/transport/ena/Port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,12 @@ void
Port::setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info,
const uint16_t nqus)
{
auto hlen = dev_info.hash_key_size;
auto hkey = new uint8_t[hlen];
auto dflt = false;
/*
* Get the RSS configuration.
*/
auto hlen = dev_info.hash_key_size;
auto hkey = new uint8_t[hlen];
struct rte_eth_rss_conf rss_conf = { .rss_key = hkey };
auto ret = rte_eth_dev_rss_hash_conf_get(m_portid, &rss_conf);
if (ret != 0) {
Expand All @@ -384,20 +385,17 @@ Port::setupReceiveSideScaling(struct rte_eth_dev_info const& dev_info,
*/
hlen = ENA_LEGACY_HASH_KEY_LEN;
hkey = new uint8_t[hlen];
dflt = true;
/*
* Copy the legacy key by flipping it:
*
* https://github.com/amzn/amzn-drivers/issues/267#issuecomment-1566119986
* Copy the legacy key.
*/
for (size_t i = 0; i < ENA_LEGACY_HASH_KEY_LEN; i += 1) {
hkey[i] = ENA_LEGACY_HASH_KEY[ENA_LEGACY_HASH_KEY_LEN - i];
}
memcpy(hkey, ENA_LEGACY_HASH_KEY, hlen);
}
/*
* Allocate the redirection table.
*/
auto size = dev_info.reta_size;
m_reta = RedirectionTable::allocate(m_portid, nqus, size, hlen, hkey);
m_reta = RedirectionTable::allocate(m_portid, nqus, size, hlen, hkey, dflt);
}

}
1 change: 0 additions & 1 deletion src/transport/ena/RawProcessor.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <tulips/stack/Ethernet.h>
#include <tulips/system/SpinLock.h>
#include <tulips/transport/ena/RawProcessor.h>
#include <iostream>
#include <mutex>
#include <netinet/in.h>

Expand Down
41 changes: 39 additions & 2 deletions src/transport/ena/RedirectionTable.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
#include <tulips/stack/Utils.h>
#include <tulips/system/SpinLock.h>
#include <tulips/transport/ena/RedirectionTable.h>
#include <cstdint>
#include <iostream>
#include <mutex>
#include <endian.h>

namespace tulips::transport::ena {

RedirectionTable::RedirectionTable(const uint16_t portid, const size_t nqus,
const size_t size, const size_t hlen,
const uint8_t* const hkey)
const uint8_t* const hkey, const bool dflt)
: m_portid(portid)
, m_size(size)
, m_hlen(hlen)
, m_hkey(hkey)
, m_default(dflt)
, m_table(new struct rte_eth_rss_reta_entry64[size >> 6])
{
auto count = size >> 6;
Expand Down Expand Up @@ -46,6 +50,10 @@ RedirectionTable::RedirectionTable(const uint16_t portid, const size_t nqus,
* Reserve the first slot to redirect L2 flows to queue 0.
*/
m_table[0].reta[0] = 0;
stack::utils::hexdump((const uint8_t*)m_table[0].reta,
sizeof(m_table[0].reta), std::cout);
stack::utils::hexdump((const uint8_t*)m_table[0].reta,
sizeof(m_table[0].reta), std::cout);
/*
* Update the RETA.
*/
Expand All @@ -69,10 +77,36 @@ RedirectionTable::match(stack::ipv4::Address const& laddr, const uint16_t lport,
const uint16_t queueid)
{
using stack::utils::toeplitz;
stack::ipv4::Address rx_ip = laddr, tx_ip = raddr;
uint16_t rx_port = lport, tx_port = rport;
uint32_t init = 0;
/*
* Re-order IPs and ports if necessary: https://tinyurl.com/mryamc52
*/
if (m_default) {
if (be32toh(*rx_ip.data()) < be32toh(*tx_ip.data())) {
rx_ip = raddr;
tx_ip = laddr;
}
if (rx_port < tx_port) {
rx_port = rport;
tx_port = lport;
}
init = uint32_t(-1);
}
/*
* Hash the payload and get the table index.
*/
auto hash = toeplitz(raddr, laddr, rport, lport, m_hlen, m_hkey);
auto hash = toeplitz(tx_ip, rx_ip, tx_port, rx_port, m_hlen, m_hkey, init);
/*
* Default keys only use the lower 16 bits: https://tinyurl.com/47vkdanv
*/
if (m_default) {
hash = ((hash & 0xFFFF) | (hash << 16)) & 0xFFFFFFFF;
}
/*
* Compute the indexes and the slot.
*/
uint64_t indx = hash % m_size;
uint64_t slot = indx >> 6;
uint64_t eidx = indx & 0x3F;
Expand All @@ -83,6 +117,9 @@ RedirectionTable::match(stack::ipv4::Address const& laddr, const uint16_t lport,
if (preq != queueid) {
return Status::ResourceBusy;
}
std::cout << raddr.toString() << ":" << rport << " -> " << laddr.toString()
<< ":" << lport << " = " << std::hex << hash << std::dec
<< std::endl;
/*
* Done.
*/
Expand Down
31 changes: 28 additions & 3 deletions tests/stack/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ using namespace tulips;

static constexpr size_t KEY_LEN = 40;

static uint8_t KEY[KEY_LEN] = {
static uint8_t DYNAMIC_KEY[KEY_LEN] = {
0x00, 0x8b, 0xe0, 0x5e, 0xd4, 0xa5, 0x54, 0xf8, 0x3c, 0xf8,
0x08, 0x75, 0x07, 0x2c, 0x4e, 0x8b, 0x6f, 0x1d, 0xbf, 0x10,
0x3b, 0x04, 0x3b, 0x41, 0xb3, 0xa4, 0xa4, 0xae, 0x56, 0xc9,
0xa4, 0xec, 0x13, 0x76, 0xa0, 0xaf, 0x04, 0x10, 0x81, 0x66,
};

TEST(Stack, RssHashing)
static const uint8_t STATIC_KEY[KEY_LEN] = {
0xbe, 0xac, 0x01, 0xfa, 0x6a, 0x42, 0xb7, 0x3b, 0x80, 0x30,
0xf2, 0x0c, 0x77, 0xcb, 0x2d, 0xa3, 0xae, 0x7b, 0x30, 0xb4,
0xd0, 0xca, 0x2b, 0xcb, 0x43, 0xa3, 0x8f, 0xb0, 0x41, 0x67,
0x25, 0x3d, 0x25, 0x5b, 0x0e, 0xc2, 0x6d, 0x5a, 0x56, 0xda,
};

TEST(Stack, RssHashingDynamic)
{
using stack::utils::toeplitz;
/*
* Define the tuple entries.
*/
Expand All @@ -25,6 +33,23 @@ TEST(Stack, RssHashing)
/*
* Compute the hash.
*/
auto h = stack::utils::toeplitz(saddr, daddr, sport, dport, KEY_LEN, KEY);
auto h = toeplitz(saddr, daddr, sport, dport, KEY_LEN, DYNAMIC_KEY, 0);
ASSERT_EQ(0xd90a078c, h);
}

TEST(Stack, RssHashingStatic)
{
using stack::utils::toeplitz;
/*
* Define the tuple entries.
*/
auto saddr = stack::ipv4::Address(10, 1, 0, 1);
auto daddr = stack::ipv4::Address(10, 1, 0, 2);
auto sport = uint16_t(8888);
auto dport = uint16_t(9999);
/*
* Compute the hash.
*/
auto h = toeplitz(saddr, daddr, sport, dport, KEY_LEN, STATIC_KEY, -1);
ASSERT_EQ(0x108ad839, h);
}

0 comments on commit 6e98f8c

Please sign in to comment.