Skip to content

Commit 548bb22

Browse files
committed
[coro_rdma][feat] add rdmapp and coro_rdma example
1 parent c4fc58e commit 548bb22

File tree

17 files changed

+2313
-2
lines changed

17 files changed

+2313
-2
lines changed

.github/workflows/code-coverage.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ jobs:
2121
chmod +x ./llvm.sh
2222
sudo ./llvm.sh 17
2323
24+
- name: Install RDMA tools
25+
run: |
26+
sudo apt-get install libibverbs1 ibverbs-utils librdmacm1 libibumad3 ibverbs-providers rdma-core perftest iproute2
27+
28+
- name: Setup SoftRoCE
29+
run: |
30+
export IF_NAME=$(ip -o -4 route show to default | awk '{print $5}')
31+
sudo modprobe -v rdma_rxe
32+
sudo rdma link add rxe0 type rxe netdev $IF_NAME
33+
2434
- name: Configure
2535
run: |
2636
cmake -B ${{github.workspace}}/build \

cmake/Find/Findibverbs.cmake

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
find_path(IBVERBS_INCLUDE_DIRS
2+
NAMES infiniband/verbs.h
3+
HINTS
4+
${IBVERBS_INCLUDE_DIR}
5+
${IBVERBS_ROOT_DIR}
6+
${IBVERBS_ROOT_DIR}/include)
7+
8+
find_library(IBVERBS_LIBRARIES
9+
NAMES ibverbs
10+
HINTS
11+
${IBVERBS_LIB_DIR}
12+
${IBVERBS_ROOT_DIR}
13+
${IBVERBS_ROOT_DIR}/lib)
14+
15+
include(FindPackageHandleStandardArgs)
16+
find_package_handle_standard_args(ibverbs DEFAULT_MSG IBVERBS_INCLUDE_DIRS IBVERBS_LIBRARIES)
17+
mark_as_advanced(IBVERBS_INCLUDE_DIR IBVERBS_LIBRARIES)

coverage_gen.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ export LLVM_PROFILE_FILE="test_ylt-%m.profraw"
1818
cd output/tests
1919
./coro_io_test
2020
./coro_rpc_test
21+
./coro_rdma_test
2122
./easylog_test
2223
./struct_pack_test
2324
./struct_pack_test_with_optimize
2425
./metric_test
2526
./struct_pb_test
2627
./reflection_test
2728
llvm-profdata merge -sparse test_ylt-*.profraw -o test_ylt.profdata
28-
llvm-cov show -object ./coro_io_test -object ./coro_rpc_test -object ./easylog_test -object ./struct_pack_test -object ./struct_pack_test_with_optimize -object ./metric_test -object ./struct_pb_test -object ./reflection_test -instr-profile=test_ylt.profdata -format=html -output-dir=../../.coverage_llvm_cov -ignore-filename-regex="thirdparty|standalone|src|template_switch" -show-instantiations=false
29-
llvm-cov report -object ./coro_io_test -object ./coro_rpc_test -object ./easylog_test -object ./struct_pack_test -object ./struct_pack_test_with_optimize -object ./metric_test -object ./struct_pb_test -object ./reflection_test -instr-profile=test_ylt.profdata -ignore-filename-regex="thirdparty|standalone|src|template_switch" -show-region-summary=false
29+
llvm-cov show -object ./coro_io_test -object ./coro_rpc_test -object ./coro_rdma_test -object ./easylog_test -object ./struct_pack_test -object ./struct_pack_test_with_optimize -object ./metric_test -object ./struct_pb_test -object ./reflection_test -instr-profile=test_ylt.profdata -format=html -output-dir=../../.coverage_llvm_cov -ignore-filename-regex="thirdparty|standalone|src|template_switch" -show-instantiations=false
30+
llvm-cov report -object ./coro_io_test -object ./coro_rpc_test -object ./coro_rdma_test -object ./easylog_test -object ./struct_pack_test -object ./struct_pack_test_with_optimize -object ./metric_test -object ./struct_pb_test -object ./reflection_test -instr-profile=test_ylt.profdata -ignore-filename-regex="thirdparty|standalone|src|template_switch" -show-region-summary=false
3031
echo 'For more Detail, see:/build/.coverage_llvm_cov/index.html'
3132

3233
# OR, we can use gcc && lcov

include/ylt/standalone/rdmapp/cq.h

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#pragma once
2+
3+
#include <infiniband/verbs.h>
4+
5+
#include <array>
6+
#include <memory>
7+
#include <vector>
8+
9+
#include "device.h"
10+
#include "error.h"
11+
#include "fcntl.h"
12+
13+
namespace rdmapp {
14+
15+
class qp;
16+
class cq;
17+
typedef cq *cq_ptr;
18+
19+
class comp_channel {
20+
struct ibv_comp_channel *comp_channel_;
21+
22+
public:
23+
comp_channel(device_ptr device) {
24+
comp_channel_ = ::ibv_create_comp_channel(device->ctx());
25+
check_ptr(comp_channel_, "failed to create comp channel");
26+
}
27+
28+
void set_non_blocking() {
29+
int flags = ::fcntl(comp_channel_->fd, F_GETFL);
30+
if (flags < 0) {
31+
check_errno(errno, "failed to get flags");
32+
}
33+
int ret = ::fcntl(comp_channel_->fd, F_SETFL, flags | O_NONBLOCK);
34+
if (ret < 0) {
35+
check_errno(errno, "failed to set flags");
36+
}
37+
}
38+
39+
cq_ptr get_event() {
40+
struct ibv_cq *cq;
41+
void *ev_ctx;
42+
check_rc(::ibv_get_cq_event(comp_channel_, &cq, &ev_ctx),
43+
"failed to get event");
44+
auto cq_obj_ptr = reinterpret_cast<cq_ptr>(ev_ctx);
45+
return cq_obj_ptr;
46+
}
47+
48+
int fd() const { return comp_channel_->fd; }
49+
50+
~comp_channel() {
51+
if (comp_channel_ == nullptr) [[unlikely]] {
52+
return;
53+
}
54+
if (auto rc = ::ibv_destroy_comp_channel(comp_channel_); rc != 0) {
55+
}
56+
else {
57+
}
58+
}
59+
60+
struct ibv_comp_channel *channel() const { return comp_channel_; }
61+
};
62+
63+
typedef comp_channel *comp_channel_ptr;
64+
65+
/**
66+
* @brief This class is an abstraction of a Completion Queue.
67+
*
68+
*/
69+
class cq {
70+
device_ptr device_;
71+
struct ibv_cq *cq_;
72+
friend class qp;
73+
74+
public:
75+
cq(cq const &) = delete;
76+
cq &operator=(cq const &) = delete;
77+
78+
/**
79+
* @brief Construct a new cq object.
80+
*
81+
* @param device The device to use.
82+
* @param num_cqe The number of completion entries to allocate.
83+
* @param channel If not null, assign this cq to the completion channel
84+
*/
85+
cq(device_ptr device, size_t nr_cqe = 128, comp_channel_ptr channel = nullptr)
86+
: device_(device) {
87+
cq_ = ::ibv_create_cq(device->ctx_, nr_cqe, this,
88+
channel ? channel->channel() : nullptr, 0);
89+
check_ptr(cq_, "failed to create cq");
90+
}
91+
92+
void request_notify() {
93+
check_rc(::ibv_req_notify_cq(cq_, 0), "failed to request notify");
94+
}
95+
96+
void ack_event(unsigned int nr_events = 1) {
97+
::ibv_ack_cq_events(cq_, nr_events);
98+
}
99+
100+
/**
101+
* @brief Poll the completion queue.
102+
*
103+
* @param wc If any, this will be filled with a completion entry.
104+
* @return true If there is a completion entry.
105+
* @return false If there is no completion entry.
106+
* @exception std::runtime_exception Error occured while polling the
107+
* completion queue.
108+
*/
109+
bool poll(struct ibv_wc &wc) {
110+
if (auto rc = ::ibv_poll_cq(cq_, 1, &wc); rc < 0) [[unlikely]] {
111+
check_rc(-rc, "failed to poll cq");
112+
}
113+
else if (rc == 0) {
114+
return false;
115+
}
116+
else {
117+
return true;
118+
}
119+
return false;
120+
}
121+
122+
/**
123+
* @brief Poll the completion queue.
124+
*
125+
* @param wc_vec If any, this will be filled with completion entries up to the
126+
* size of the vector.
127+
* @return size_t The number of completion entries. 0 means no completion
128+
* entry.
129+
* @exception std::runtime_exception Error occured while polling the
130+
* completion queue.
131+
*/
132+
size_t poll(std::vector<struct ibv_wc> &wc_vec) {
133+
return poll(&wc_vec[0], wc_vec.size());
134+
}
135+
136+
template <class It>
137+
size_t poll(It wc, int count) {
138+
int rc = ::ibv_poll_cq(cq_, count, wc);
139+
if (rc < 0) {
140+
throw_with("failed to poll cq: %s (rc=%d)", strerror(rc), rc);
141+
}
142+
return rc;
143+
}
144+
145+
template <int N>
146+
size_t poll(std::array<struct ibv_wc, N> &wc_array) {
147+
return poll(&wc_array[0], N);
148+
}
149+
150+
~cq() {
151+
if (cq_ == nullptr) [[unlikely]] {
152+
return;
153+
}
154+
155+
if (auto rc = ::ibv_destroy_cq(cq_); rc != 0) [[unlikely]] {
156+
}
157+
else {
158+
}
159+
}
160+
};
161+
162+
} // namespace rdmapp
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
3+
#include <algorithm>
4+
#include <cstdint>
5+
#include <endian.h>
6+
#include <netinet/in.h>
7+
#include <type_traits>
8+
9+
#include <infiniband/verbs.h>
10+
11+
namespace rdmapp {
12+
namespace detail {
13+
14+
static inline uint16_t ntoh(uint16_t const &value) { return ::be16toh(value); }
15+
16+
static inline uint32_t ntoh(uint32_t const &value) { return ::be32toh(value); }
17+
18+
static inline uint64_t ntoh(uint64_t const &value) { return ::be64toh(value); }
19+
20+
static inline uint16_t hton(uint16_t const &value) { return ::htobe16(value); }
21+
22+
static inline uint32_t hton(uint32_t const &value) { return ::htobe32(value); }
23+
24+
static inline uint64_t hton(uint64_t const &value) { return ::htobe64(value); }
25+
26+
template <class T, class It>
27+
typename std::enable_if<std::is_integral<T>::value>::type
28+
serialize(T const &value, It &it) {
29+
T nvalue = hton(value);
30+
std::copy_n(reinterpret_cast<uint8_t *>(&nvalue), sizeof(T), it);
31+
}
32+
33+
template <class T, class It>
34+
typename std::enable_if<std::is_same<T, union ibv_gid>::value>::type
35+
serialize(T const &value, It &it) {
36+
std::copy_n(reinterpret_cast<uint8_t const *>(&value), sizeof(T), it);
37+
}
38+
39+
template <class T, class It>
40+
typename std::enable_if<std::is_integral<T>::value>::type
41+
deserialize(It &it, T &value) {
42+
std::copy_n(it, sizeof(T), reinterpret_cast<uint8_t *>(&value));
43+
it += sizeof(T);
44+
value = ntoh(value);
45+
}
46+
47+
template <class T, class It>
48+
typename std::enable_if<std::is_same<T, void *>::value>::type
49+
deserialize(It &it, T &value) {
50+
std::copy_n(it, sizeof(T), reinterpret_cast<uint8_t *>(&value));
51+
it += sizeof(T);
52+
value = reinterpret_cast<void *>(ntoh(reinterpret_cast<uint64_t>(value)));
53+
}
54+
55+
template <class T, class It>
56+
typename std::enable_if<std::is_same<T, union ibv_gid>::value>::type
57+
deserialize(It &it, T &value) {
58+
std::copy_n(it, sizeof(T), reinterpret_cast<uint8_t *>(&value));
59+
it += sizeof(T);
60+
}
61+
62+
} // namespace detail
63+
} // namespace rdmapp

0 commit comments

Comments
 (0)