53static struct NotificationBufPair notification_buf_pair[MAX_NB_CORES];
56static struct SocketInternal open_sockets[MAX_NB_SOCKETS];
57static unsigned int nb_open_sockets = 0;
58static uint16_t bdf = 0;
61void set_bdf(uint16_t bdf_) { bdf = bdf_; }
63int socket([[maybe_unused]]
int domain, [[maybe_unused]]
int type,
64 [[maybe_unused]]
int protocol,
bool fallback)
noexcept {
65 if (unlikely(nb_open_sockets >= MAX_NB_SOCKETS)) {
66 std::cerr <<
"Maximum number of sockets reached" << std::endl;
70 struct SocketInternal socket_entry;
72 struct NotificationBufPair* nb_pair = ¬ification_buf_pair[sched_getcpu()];
73 socket_entry.notification_buf_pair = nb_pair;
75 struct RxEnsoPipeInternal* enso_pipe = &socket_entry.enso_pipe;
78 int socket_id =
dma_init(nb_pair, enso_pipe, bdf, bar,
79 std::string(kHugePageDefaultPrefix), fallback);
80 if (unlikely(socket_id < 0)) {
81 std::cerr <<
"Problem initializing DMA" << std::endl;
85 open_sockets[socket_id] = socket_entry;
93int bind(
int sockfd,
const struct sockaddr* addr, socklen_t addrlen)
noexcept {
95 struct SocketInternal* socket = &open_sockets[sockfd];
96 sockaddr_in* addr_in = (sockaddr_in*)addr;
102 ntohl(addr_in->sin_addr.s_addr), 0,
112uint64_t get_socket_phys_addr(
int sockfd) {
113 return open_sockets[sockfd].enso_pipe.buf_phys_addr;
119void* get_socket_virt_addr(
int sockfd) {
120 return (
void*)open_sockets[sockfd].enso_pipe.buf;
126uint64_t convert_buf_addr_to_phys(
int sockfd,
void* addr) {
127 return (uint64_t)addr + open_sockets[sockfd].enso_pipe.phys_buf_offset;
130ssize_t recv(
int sockfd,
void* buf,
size_t len,
int flags) {
135 struct SocketInternal* socket = &open_sockets[sockfd];
136 struct RxEnsoPipeInternal* enso_pipe = &socket->enso_pipe;
137 struct NotificationBufPair* notification_buf_pair =
138 socket->notification_buf_pair;
142 ssize_t bytes_received =
145 if (unlikely(bytes_received <= 0)) {
146 return bytes_received;
149 memcpy(buf, ring_buf, bytes_received);
153 return bytes_received;
156ssize_t recv_zc(
int sockfd,
void** buf,
size_t len,
int flags) {
160 struct SocketInternal* socket = &open_sockets[sockfd];
161 struct RxEnsoPipeInternal* enso_pipe = &socket->enso_pipe;
162 struct NotificationBufPair* notification_buf_pair =
163 socket->notification_buf_pair;
170ssize_t recv_select(
int ref_sockfd,
int* sockfd,
void** buf,
size_t len,
175 struct NotificationBufPair* notification_buf_pair =
176 open_sockets[ref_sockfd].notification_buf_pair;
177 return get_next_batch(notification_buf_pair, open_sockets, sockfd, buf);
180ssize_t send(
int sockfd, uint64_t phys_addr,
size_t len,
int flags) {
182 return send_to_queue(open_sockets[sockfd].notification_buf_pair, phys_addr,
186uint32_t get_completions(
int ref_sockfd) {
187 struct NotificationBufPair* notification_buf_pair =
188 open_sockets[ref_sockfd].notification_buf_pair;
192void free_enso_pipe(
int sockfd,
size_t len) {
196int enable_device_timestamp(
int ref_sockfd, uint8_t offset) {
197 if (nb_open_sockets == 0) {
204int disable_device_timestamp(
int ref_sockfd) {
205 if (nb_open_sockets == 0) {
211int enable_device_rate_limit(
int ref_sockfd, uint16_t num, uint16_t den) {
212 if (nb_open_sockets == 0) {
219int disable_device_rate_limit(
int ref_sockfd) {
220 if (nb_open_sockets == 0) {
226int enable_device_round_robin(
int ref_sockfd) {
227 if (nb_open_sockets == 0) {
233int disable_device_round_robin(
int ref_sockfd) {
234 if (nb_open_sockets == 0) {
240int shutdown(
int sockfd,
int how __attribute__((unused)))
noexcept {
250void print_sock_stats(
int sockfd) {
251 struct SocketInternal* socket = &open_sockets[sockfd];
Functions to configure the data plane.
int enable_timestamp(struct NotificationBufPair *notification_buf_pair, uint8_t offset=kDefaultRttOffset)
Enables hardware timestamping.
int enable_round_robin(struct NotificationBufPair *notification_buf_pair)
Enables packet round robin for the fallback pipes.
int disable_timestamp(struct NotificationBufPair *notification_buf_pair)
Disables hardware timestamping.
int enable_rate_limit(struct NotificationBufPair *notification_buf_pair, uint16_t num, uint16_t den)
Enables hardware rate limit.
int disable_rate_limit(struct NotificationBufPair *notification_buf_pair)
Disables hardware rate limit.
int insert_flow_entry(struct NotificationBufPair *notification_buf_pair, uint16_t dst_port, uint16_t src_port, uint32_t dst_ip, uint32_t src_ip, uint32_t protocol, uint32_t enso_pipe_id)
Inserts flow entry in the data plane flow table that will direct all packets matching the flow entry ...
int disable_round_robin(struct NotificationBufPair *notification_buf_pair)
Disables packet round robin for the fallback pipes. Using a hash of the packet's five tuple to select...
Miscellaneous helper functions.
uint16_t get_new_tails(struct NotificationBufPair *notification_buf_pair)
Gets latest tails for the pipes associated with the given notification buffer.
void print_stats(struct SocketInternal *socket_entry, bool print_global)
Prints statistics for a given socket.
uint32_t get_next_batch(struct NotificationBufPair *notification_buf_pair, struct SocketInternal *socket_entries, int *enso_pipe_id, void **buf)
Get next batch of data from the next available Enso Pipe.
uint32_t get_next_batch_from_queue(struct RxEnsoPipeInternal *enso_pipe, struct NotificationBufPair *notification_buf_pair, void **buf)
Gets the next batch of data from the given Enso Pipe.
uint32_t send_to_queue(struct NotificationBufPair *notification_buf_pair, uint64_t phys_addr, uint32_t len)
Sends data through a given queue.
uint32_t get_unreported_completions(struct NotificationBufPair *notification_buf_pair)
Returns the number of transmission requests that were completed since the last call to this function.
int dma_init(struct NotificationBufPair *notification_buf_pair, struct RxEnsoPipeInternal *enso_pipe, uint32_t bdf, int32_t bar, const std::string &huge_page_prefix, bool fallback)
Initializes an enso pipe and the notification buffer if needed.
void advance_pipe(struct RxEnsoPipeInternal *enso_pipe, size_t len)
Frees the next len bytes in the buffer associated with the socket_entry socket. If len is greater tha...
int dma_finish(struct SocketInternal *socket_entry)
Frees the notification buffer and all pipes.
uint32_t get_enso_pipe_id_from_socket(struct SocketInternal *socket_entry)
Gets the Enso Pipe ID associated with a given socket.