NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
http_txbuf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023-2024 NVIDIA CORPORATION AND AFFILIATES. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification, are permitted
5  * provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright notice, this list of
7  * conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright notice, this list of
9  * conditions and the following disclaimer in the documentation and/or other materials
10  * provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
12  * to endorse or promote products derived from this software without specific prior written
13  * permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21  * STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  *
24  */
25 
26 #include <arpa/inet.h>
27 #include <rte_ethdev.h>
28 #include <doca_flow.h>
29 #include <doca_mmap.h>
30 #include <doca_gpunetio.h>
31 #include <doca_buf_array.h>
32 
33 #include "common.h"
34 #include "packets.h"
36 
37 DOCA_LOG_REGISTER(GPU_PACKET_PROCESSING_TXBUF);
38 
39 const char *payload_page_index = "HTTP/1.1 200 OK\r\n"
40  "Date: Sun, 30 Apr 2023 20:30:40 GMT\r\n"
41  "Content-Type: text/html; charset=UTF-8\r\n"
42  "Content-Length: 158\r\n"
43  "Last-Modified: Sun, 30 Apr 2023 22:38:34 GMT\r\n"
44  "Server: GPUNetIO\r\n"
45  "Accept-Ranges: bytes\r\n"
46  "Connection: keep-alive\r\n"
47  "Keep-Alive: timeout=5\r\n"
48  "\r\n"
49  "<html>\r\n"
50  " <head>\r\n"
51  " <title>GPUNetIO index page</title>\r\n"
52  " </head>\r\n"
53  " <body>\r\n"
54  " <p>Hello World, the GPUNetIO server Index page!</p>\r\n"
55  " </body>\r\n"
56  "</html>\r\n"
57  "\r\n";
58 
59 const char *payload_page_contacts = "HTTP/1.1 200 OK\r\n"
60  "Date: Sun, 30 Apr 2023 20:30:40 GMT\r\n"
61  "Content-Type: text/html; charset=UTF-8\r\n"
62  "Content-Length: 175\r\n"
63  "Last-Modified: Sun, 30 Apr 2023 22:38:34 GMT\r\n"
64  "Server: GPUNetIO\r\n"
65  "Accept-Ranges: bytes\r\n"
66  "Connection: keep-alive\r\n"
67  "Keep-Alive: timeout=5\r\n"
68  "\r\n"
69  "<html>\r\n"
70  " <head>\r\n"
71  " <title>GPUNetIO Contact page</title>\r\n"
72  " </head>\r\n"
73  " <body>\r\n"
74  " <p>For any GPUNetIO question please contact support@nvidia.com</p>\r\n"
75  " </body>\r\n"
76  "</html>\r\n"
77  "\r\n";
78 
79 const char *payload_page_not_found = "HTTP/1.1 404 Not Found\r\n"
80  "Date: Sun, 30 Apr 2023 20:30:40 GMT\r\n"
81  "Content-Type: text/html; charset=UTF-8\r\n"
82  "Content-Length: 152\r\n"
83  "Last-Modified: Sun, 30 Apr 2023 22:38:34 GMT\r\n"
84  "Server: GPUNetIO\r\n"
85  "Connection: close\r\n"
86  "\r\n"
87  "<html>\r\n"
88  " <head>\r\n"
89  " <title>GPUNetIO 404 page</title>\r\n"
90  " </head>\r\n"
91  " <body>\r\n"
92  " <p>Hello! Page you requested doesn't exist!</p>\r\n"
93  " </body>\r\n"
94  "</html>\r\n"
95  "\r\n";
96 
98  struct doca_gpu *gpu_dev,
99  struct doca_dev *ddev,
100  uint32_t num_packets,
101  uint32_t max_pkt_sz)
102 {
103  doca_error_t status;
104 
105  if (buf == NULL || gpu_dev == NULL || ddev == NULL || num_packets == 0 || max_pkt_sz == 0) {
106  DOCA_LOG_ERR("Invalid input arguments");
108  }
109 
110  buf->gpu_dev = gpu_dev;
111  buf->ddev = ddev;
112  buf->num_packets = num_packets;
113  buf->max_pkt_sz = max_pkt_sz;
114 
115  status = doca_mmap_create(&(buf->mmap));
116  if (status != DOCA_SUCCESS) {
117  DOCA_LOG_ERR("Unable to create doca_buf: failed to create mmap");
118  return status;
119  }
120 
121  status = doca_mmap_add_dev(buf->mmap, buf->ddev);
122  if (status != DOCA_SUCCESS) {
123  DOCA_LOG_ERR("Unable to add dev to buf: doca mmap internal error");
124  return status;
125  }
126 
127  status = doca_gpu_mem_alloc(buf->gpu_dev,
128  buf->num_packets * buf->max_pkt_sz,
129  4096,
131  (void **)&(buf->gpu_pkt_addr),
132  NULL);
133  if ((status != DOCA_SUCCESS) || (buf->gpu_pkt_addr == NULL)) {
134  DOCA_LOG_ERR("Unable to alloc txbuf: failed to allocate gpu memory");
135  return status;
136  }
137 
138  /* Map GPU memory buffer used to send packets with DMABuf */
139  status = doca_gpu_dmabuf_fd(buf->gpu_dev,
140  buf->gpu_pkt_addr,
141  buf->num_packets * buf->max_pkt_sz,
142  &(buf->dmabuf_fd));
143  if (status != DOCA_SUCCESS) {
144  DOCA_LOG_INFO("Mapping send queue buffer (0x%p size %dB) with legacy nvidia-peermem mode",
145  buf->gpu_pkt_addr,
146  buf->num_packets * buf->max_pkt_sz);
147 
148  /* If failed, use nvidia-peermem legacy method */
149  status = doca_mmap_set_memrange(buf->mmap, buf->gpu_pkt_addr, (buf->num_packets * buf->max_pkt_sz));
150  if (status != DOCA_SUCCESS) {
151  DOCA_LOG_ERR("Unable to start buf: doca mmap internal error");
152  return status;
153  }
154  } else {
155  DOCA_LOG_INFO("Mapping send queue buffer (0x%p size %dB dmabuf fd %d) with dmabuf mode",
156  buf->gpu_pkt_addr,
157  (buf->num_packets * buf->max_pkt_sz),
158  buf->dmabuf_fd);
159 
160  status = doca_mmap_set_dmabuf_memrange(buf->mmap,
161  buf->dmabuf_fd,
162  buf->gpu_pkt_addr,
163  0,
164  (buf->num_packets * buf->max_pkt_sz));
165  if (status != DOCA_SUCCESS) {
166  DOCA_LOG_ERR("Failed to set dmabuf memrange for mmap %s", doca_error_get_descr(status));
167  return status;
168  }
169  }
170 
171  status = doca_mmap_set_permissions(buf->mmap,
173  if (status != DOCA_SUCCESS) {
174  DOCA_LOG_ERR("Unable to start buf: doca mmap internal error");
175  return status;
176  }
177 
178  status = doca_mmap_start(buf->mmap);
179  if (status != DOCA_SUCCESS) {
180  DOCA_LOG_ERR("Unable to start buf: doca mmap internal error");
181  return status;
182  }
183 
184  status = doca_buf_arr_create(buf->num_packets, &buf->buf_arr);
185  if (status != DOCA_SUCCESS) {
186  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
187  return status;
188  }
189 
190  status = doca_buf_arr_set_target_gpu(buf->buf_arr, buf->gpu_dev);
191  if (status != DOCA_SUCCESS) {
192  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
193  return status;
194  }
195 
196  status = doca_buf_arr_set_params(buf->buf_arr, buf->mmap, buf->max_pkt_sz, 0);
197  if (status != DOCA_SUCCESS) {
198  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
199  return status;
200  }
201 
202  status = doca_buf_arr_start(buf->buf_arr);
203  if (status != DOCA_SUCCESS) {
204  DOCA_LOG_ERR("Unable to start buf: doca buf_arr internal error");
205  return status;
206  }
207 
208  status = doca_buf_arr_get_gpu_handle(buf->buf_arr, &(buf->buf_arr_gpu));
209  if (status != DOCA_SUCCESS) {
210  DOCA_LOG_ERR("Unable to get buff_arr GPU handle: %s", doca_error_get_descr(status));
211  return status;
212  }
213 
214  return DOCA_SUCCESS;
215 }
216 
217 doca_error_t prepare_tx_buf(struct tx_buf *buf, enum http_page_get page_type)
218 {
219  uint8_t *cpu_pkt_addr;
220  uint8_t *pkt;
221  struct eth_ip_tcp_hdr *hdr;
222  const char *payload;
223  cudaError_t res_cuda;
224 
225  if (page_type == HTTP_GET_INDEX)
226  payload = payload_page_index;
227  else if (page_type == HTTP_GET_CONTACTS)
228  payload = payload_page_contacts;
229  else
230  payload = payload_page_not_found;
231 
232  buf->pkt_nbytes = strlen(payload);
233 
234  cpu_pkt_addr = (uint8_t *)calloc(buf->num_packets * buf->max_pkt_sz, sizeof(uint8_t));
235  if (cpu_pkt_addr == NULL) {
236  DOCA_LOG_ERR("Error in txbuf preparation, failed to allocate memory");
237  return DOCA_ERROR_NO_MEMORY;
238  }
239 
240  for (uint32_t idx = 0; idx < buf->num_packets; idx++) {
241  pkt = cpu_pkt_addr + (idx * buf->max_pkt_sz);
242  hdr = (struct eth_ip_tcp_hdr *)pkt;
243 
244  hdr->l2_hdr.ether_type = rte_cpu_to_be_16(DOCA_FLOW_ETHER_TYPE_IPV4);
245 
246  hdr->l3_hdr.version_ihl = 0x45;
247  hdr->l3_hdr.type_of_service = 0x0;
248  hdr->l3_hdr.total_length =
249  BYTE_SWAP16(sizeof(struct ipv4_hdr) + sizeof(struct tcp_hdr) + buf->pkt_nbytes);
250  hdr->l3_hdr.packet_id = 0;
251  hdr->l3_hdr.fragment_offset = 0;
252  hdr->l3_hdr.time_to_live = 60;
253  hdr->l3_hdr.next_proto_id = 6;
254  hdr->l3_hdr.hdr_checksum = 0;
255  hdr->l3_hdr.src_addr = 0;
256  hdr->l3_hdr.dst_addr = 0;
257 
258  hdr->l4_hdr.src_port = 0;
259  hdr->l4_hdr.dst_port = 0;
260  hdr->l4_hdr.sent_seq = 0;
261  hdr->l4_hdr.recv_ack = 0;
262  /* Assuming no TCP flags needed */
263  hdr->l4_hdr.dt_off = 0x50; // 5 << 4;
264  /* Assuming no TCP flags needed */
265  hdr->l4_hdr.tcp_flags = TCP_FLAG_PSH | TCP_FLAG_ACK; //| TCP_FLAG_FIN;
266  hdr->l4_hdr.rx_win = BYTE_SWAP16(6000);
267  hdr->l4_hdr.cksum = 0;
268  hdr->l4_hdr.tcp_urp = 0;
269 
270  /* Assuming no TCP flags needed */
271  pkt = pkt + sizeof(struct eth_ip_tcp_hdr);
272 
273  memcpy(pkt, payload, buf->pkt_nbytes);
274  }
275 
276  /* Copy the whole list of packets into GPU memory buffer */
277  res_cuda = cudaMemcpy(buf->gpu_pkt_addr, cpu_pkt_addr, buf->num_packets * buf->max_pkt_sz, cudaMemcpyDefault);
278  free(cpu_pkt_addr);
279  if (res_cuda != cudaSuccess) {
280  DOCA_LOG_ERR("Function CUDA Memcpy cqe_addr failed with %s", cudaGetErrorString(res_cuda));
281  return DOCA_ERROR_DRIVER;
282  }
283 
284  return DOCA_SUCCESS;
285 }
286 
288 {
289  doca_error_t status;
290 
291  if (buf == NULL) {
292  DOCA_LOG_ERR("Invalid input arguments");
294  }
295 
296  status = doca_mmap_stop(buf->mmap);
297  if (status != DOCA_SUCCESS) {
298  DOCA_LOG_ERR("Unable to stop buf: unable to stop mmap");
299  return status;
300  }
301 
302  status = doca_mmap_rm_dev(buf->mmap, buf->ddev);
303  if (status != DOCA_SUCCESS) {
304  DOCA_LOG_ERR("Unable to remove dev from buf: doca mmap internal error");
305  return status;
306  }
307 
308  status = doca_mmap_destroy(buf->mmap);
309  if (status != DOCA_SUCCESS) {
310  DOCA_LOG_ERR("Unable to destroy doca_buf: failed to destroy mmap");
311  return status;
312  }
313 
314  status = doca_gpu_mem_free(buf->gpu_dev, buf->gpu_pkt_addr);
315  if (status != DOCA_SUCCESS) {
316  DOCA_LOG_ERR("Unable to stop buf: failed to free gpu memory");
317  return status;
318  }
319 
320  status = doca_buf_arr_stop(buf->buf_arr);
321  if (status != DOCA_SUCCESS) {
322  DOCA_LOG_ERR("Unable to stop buf: failed to destroy doca_buf_arr");
323  return status;
324  }
325 
326  status = doca_buf_arr_destroy(buf->buf_arr);
327  if (status != DOCA_SUCCESS) {
328  DOCA_LOG_ERR("Unable to stop buf: failed to destroy doca_buf_arr");
329  return status;
330  }
331 
332  return status;
333 }
#define NULL
Definition: __stddef_null.h:26
#define BYTE_SWAP16(v)
Definition: defines.h:78
http_page_get
Definition: defines.h:90
@ HTTP_GET_INDEX
Definition: defines.h:91
@ HTTP_GET_CONTACTS
Definition: defines.h:92
static struct doca_gpu * gpu_dev
static struct doca_dev * ddev
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_destroy(struct doca_buf_arr *buf_arr)
Destroys a doca buf array instance.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_set_params(struct doca_buf_arr *buf_arr, struct doca_mmap *mmap, size_t elem_size, uint64_t start_offset)
Sets the buf array params.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_stop(struct doca_buf_arr *buf_arr)
Stops a started doca buf array.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_set_target_gpu(struct doca_buf_arr *buf_arr, struct doca_gpu *gpu_handler)
Configures the buf array to be created on the gpu device.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_get_gpu_handle(const struct doca_buf_arr *buf_arr, struct doca_gpu_buf_arr **gpu_buf_arr)
Retrieves the handle in the gpu memory space of a doca_buf_arr.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_create(size_t num_elem, struct doca_buf_arr **buf_arr)
Allocates a doca_buf_arr.
DOCA_EXPERIMENTAL doca_error_t doca_buf_arr_start(struct doca_buf_arr *buf_arr)
This method enables the allocation of doca_bufs.
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
Definition: doca_error.h:44
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
DOCA_STABLE doca_error_t doca_mmap_set_memrange(struct doca_mmap *mmap, void *addr, size_t len)
Set the memory range of DOCA memory map.
DOCA_STABLE doca_error_t doca_mmap_rm_dev(struct doca_mmap *mmap, struct doca_dev *dev)
Deregister given device from DOCA memory map.
DOCA_STABLE doca_error_t doca_mmap_destroy(struct doca_mmap *mmap)
Destroy DOCA Memory Map structure.
DOCA_STABLE doca_error_t doca_mmap_create(struct doca_mmap **mmap)
Allocates zero size memory map object with default/unset attributes.
DOCA_STABLE doca_error_t doca_mmap_set_permissions(struct doca_mmap *mmap, uint32_t access_mask)
Set access flags of the registered memory.
DOCA_STABLE doca_error_t doca_mmap_start(struct doca_mmap *mmap)
Start DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_stop(struct doca_mmap *mmap)
Stop DOCA Memory Map.
DOCA_STABLE doca_error_t doca_mmap_add_dev(struct doca_mmap *mmap, struct doca_dev *dev)
Register DOCA memory map on a given device.
DOCA_STABLE doca_error_t doca_mmap_set_dmabuf_memrange(struct doca_mmap *mmap, int dmabuf_fd, void *addr, size_t dmabuf_offset, size_t len)
Set the memory range of DOCA memory map using dmabuf.
@ DOCA_GPU_MEM_TYPE_GPU
Definition: doca_types.h:131
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
@ DOCA_ACCESS_FLAG_PCI_RELAXED_ORDERING
Definition: doca_types.h:95
doca_error_t create_tx_buf(struct tx_buf *buf, struct doca_gpu *gpu_dev, struct doca_dev *ddev, uint32_t num_packets, uint32_t max_pkt_sz)
Definition: http_txbuf.c:97
const char * payload_page_index
Definition: http_txbuf.c:39
const char * payload_page_contacts
Definition: http_txbuf.c:59
doca_error_t destroy_tx_buf(struct tx_buf *buf)
Definition: http_txbuf.c:287
DOCA_LOG_REGISTER(GPU_PACKET_PROCESSING_TXBUF)
const char * payload_page_not_found
Definition: http_txbuf.c:79
doca_error_t prepare_tx_buf(struct tx_buf *buf, enum http_page_get page_type)
Definition: http_txbuf.c:217
@ TCP_FLAG_PSH
Definition: packets.h:48
@ TCP_FLAG_ACK
Definition: packets.h:50
struct ether_hdr l2_hdr
Definition: packets.h:92
uint16_t ether_type
Definition: packets.h:63
Definition: common.h:120
struct doca_mmap * mmap
Definition: common.h:127
struct doca_buf_arr * buf_arr
Definition: common.h:128
uint32_t pkt_nbytes
Definition: common.h:125
struct doca_gpu_buf_arr * buf_arr_gpu
Definition: common.h:129
uint8_t * gpu_pkt_addr
Definition: common.h:126
uint32_t max_pkt_sz
Definition: common.h:124
int dmabuf_fd
Definition: common.h:130
struct doca_dev * ddev
Definition: common.h:122
uint32_t num_packets
Definition: common.h:123
struct doca_gpu * gpu_dev
Definition: common.h:121