Raw Ethernet: working in tests

This commit is contained in:
2023-04-11 14:21:28 +00:00
parent 49cf0dfa01
commit c4e70ca038
10 changed files with 285 additions and 290 deletions
+58 -36
View File
@@ -5,6 +5,12 @@
#include <thread>
#include <chrono>
#include <sys/mman.h>
#ifdef JFJOCH_USE_NUMA
#include <numaif.h>
#include <numa.h>
#endif
#include "IBWrappers.h"
#include "../../common/JFJochException.h"
@@ -122,11 +128,9 @@ void IBQueuePair::Init() {
ibv_qp_attr qp_attr{};
memset(&qp_attr, 0, sizeof(qp_attr));
int qp_flags = IBV_QP_STATE | IBV_QP_PORT |IBV_QP_PKEY_INDEX | IBV_QP_ACCESS_FLAGS;
int qp_flags = IBV_QP_STATE | IBV_QP_PORT;
qp_attr.qp_state = IBV_QPS_INIT;
qp_attr.port_num = 1;
qp_attr.qp_access_flags = 0;
qp_attr.pkey_index = 0;
if (ibv_modify_qp(qp, &qp_attr, qp_flags))
throw JFJochException(JFJochExceptionCategory::IBVerbs, "Failed modify IB queue pair to init.");
@@ -177,11 +181,11 @@ void IBQueuePair::PostReceiveWR(IBMemoryRegion &mr, uint32_t location, void *poi
// pointer to packet buffer size and memory key of each packet buffer
ib_sg_entry.length = size;
ib_sg_entry.lkey = mr.GetLocalKey();
ib_sg_entry.addr = (uintptr_t)(pointer);
ib_wr.num_sge = 1;
ib_wr.sg_list = &ib_sg_entry;
ib_wr.next = nullptr;
ib_sg_entry.addr = (uintptr_t)(pointer);
ib_wr.wr_id = location;
int ret;
@@ -193,7 +197,7 @@ void IBQueuePair::PostReceiveWR(IBMemoryRegion &mr, uint32_t location, void *poi
}
}
void IBQueuePair::PostInlineSendWR(void *pointer, size_t size) {
void IBQueuePair::PostSendWR(IBMemoryRegion &mr, void *pointer, size_t size) {
// Send the frame via RDMA
ibv_sge ib_sg{};
ibv_send_wr ib_wr{};
@@ -204,13 +208,14 @@ void IBQueuePair::PostInlineSendWR(void *pointer, size_t size) {
ib_sg.addr = (uintptr_t)(pointer);
ib_sg.length = size;
ib_sg.lkey = mr.GetLocalKey();
ib_wr.wr_id = UINT64_MAX;
ib_wr.sg_list = &ib_sg;
ib_wr.num_sge = 1;
ib_wr.opcode = IBV_WR_SEND;
ib_wr.send_flags = IBV_SEND_INLINE;
ib_wr.send_flags = IBV_SEND_SIGNALED;
int ret;
while ((ret = ibv_post_send(qp, &ib_wr, &ib_bad_wr))) {
@@ -221,14 +226,9 @@ void IBQueuePair::PostInlineSendWR(void *pointer, size_t size) {
}
}
void IBQueuePair::FlowSteering(uint64_t mac_addr, uint32_t ipv4) {
uint8_t dst_mac_addr[6];
for (int i = 0; i < 6; i++)
dst_mac_addr[i] = (mac_addr & (0xFF << (i*8))) >> (i * 8);
void IBQueuePair::FlowSteeringIPv4(uint32_t ipv4) {
struct raw_eth_flow_attr {
struct ibv_flow_attr attr;
struct ibv_flow_spec_eth spec_eth;
struct ibv_flow_spec_ipv4 spec_ipv4;
} __attribute__((packed)) flow_attr = {
.attr = {
@@ -236,33 +236,10 @@ void IBQueuePair::FlowSteering(uint64_t mac_addr, uint32_t ipv4) {
.type = IBV_FLOW_ATTR_NORMAL,
.size = sizeof(flow_attr),
.priority = 0,
.num_of_specs = 2,
.num_of_specs = 1,
.port = 1,
.flags = 0,
},
.spec_eth = {
.type = IBV_FLOW_SPEC_ETH,
.size = sizeof(struct ibv_flow_spec_eth),
.val = {
.dst_mac = {
dst_mac_addr[0],
dst_mac_addr[1],
dst_mac_addr[2],
dst_mac_addr[3],
dst_mac_addr[4],
dst_mac_addr[5]
},
.src_mac = {0,0,0,0,0,0},
.ether_type = 0x0800,
.vlan_tag = 0x0
},
.mask = {
.dst_mac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
.src_mac = {0,0,0,0,0,0},
.ether_type = 0xFFFF,
.vlan_tag = 0x0
}
},
.spec_ipv4 = {
.type = IBV_FLOW_SPEC_IPV4,
.size = sizeof(struct ibv_flow_spec_ipv4),
@@ -277,6 +254,7 @@ void IBQueuePair::FlowSteering(uint64_t mac_addr, uint32_t ipv4) {
}
};
flow = ibv_create_flow(qp, &flow_attr.attr);
if (flow == nullptr)
throw JFJochException(JFJochExceptionCategory::IBVerbs, "Failed to set IB flow steering");
@@ -321,4 +299,48 @@ IBMemoryRegion::~IBMemoryRegion() {
ibv_dereg_mr(buffer_mr);
}
IBRegBuffer::IBRegBuffer(IBProtectionDomain &pd, size_t in_loc_count, size_t in_loc_size, int16_t numa_node) :
loc_count(in_loc_count), loc_size(in_loc_size) {
buffer = (uint8_t *) mmap(nullptr, loc_size * loc_count, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (buffer == nullptr)
throw JFJochException(JFJochExceptionCategory::MemAllocFailed, "frame_buffer");
#ifdef JFJOCH_USE_NUMA
if (numa_node >= 0) {
unsigned long nodemask = 1L << numa_node;;
if (numa_node > sizeof(nodemask)*8) {
Unmap();
throw JFJochException(JFJochExceptionCategory::MemAllocFailed, "Mask too small for NUMA node");
}
if (mbind(buffer, loc_size * loc_count, MPOL_BIND, &nodemask, sizeof(nodemask)*8, MPOL_MF_STRICT) == -1) {
Unmap();
throw JFJochException(JFJochExceptionCategory::MemAllocFailed, "Cannot apply NUMA policy");
}
}
#endif
memset(buffer, 0, loc_size * loc_count);
mr = std::make_unique<IBMemoryRegion>(pd, buffer, loc_size * loc_count);
}
void IBRegBuffer::Unmap() {
munmap(buffer, loc_size * loc_count);
}
IBRegBuffer::~IBRegBuffer() {
mr.reset();
Unmap();
}
IBMemoryRegion *IBRegBuffer::GetMemoryRegion() {
return mr.get();
}
uint8_t *IBRegBuffer::GetLocation(uint64_t location) {
if (location < loc_count)
return buffer + loc_size * location;
else
throw JFJochException(JFJochExceptionCategory::ArrayOutOfBounds, "Location out of bounds");
}
#endif //JFJOCH_USE_IBVERBS