NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
urom_rdmo_core.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 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 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE
28 #endif
29 
30 #include <stdio.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <sched.h>
35 #include <unistd.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #include <malloc.h>
39 
40 #include <ucp/api/ucp.h>
41 
42 #include <doca_argp.h>
43 #include <doca_ctx.h>
44 #include <doca_urom.h>
45 
46 #include <samples/common.h>
47 
48 #include "urom_rdmo_core.h"
49 #include "utils.h"
50 #include "worker_rdmo.h"
51 
52 DOCA_LOG_REGISTER(UROM::RDMO::CORE);
53 
54 #define FLUSH_ID 0xbeef /* Flush callback id */
55 #define MAX_WORKER_ADDRESS_LEN 1024 /* Maximum address length */
56 
57 /* Remote buffer descriptor */
58 struct rbuf_desc {
59  uint64_t rkey; /* Remote key */
60  uint64_t *raddr; /* Remote address */
61 };
62 
63 /* RDMO client init result */
65  char *addr; /* Device UCP worker address */
66  uint64_t addr_len; /* Address length */
67 };
68 
69 /* RDMO RQ create result */
71  uint64_t rq_id; /* RQ id */
72 };
73 
74 /* RDMO RQ destroy result */
76  uint64_t rq_id; /* RQ id */
77 };
78 
79 /* RDMO MR register result */
81  uint64_t rkey; /* Memory remote key */
82 };
83 
84 /* RDMO MR deregister result */
86  uint64_t rkey; /* Memory remote key */
87 };
88 
89 /* RDMO task result structure */
90 struct rdmo_result {
91  doca_error_t result; /* Task result */
92  union {
93  struct client_init_result client_init; /* Client init result */
94  struct rq_create_result rq_create; /* RQ create result */
95  struct rq_destroy_result rq_destroy; /* RQ destroy result */
96  struct mr_register_result mr_reg; /* MR register result */
97  struct mr_deregister_result mr_dereg; /* MR deregister result */
98  };
99 };
100 
101 /*******************************************************************************
102  * Client functions
103  ******************************************************************************/
104 /*
105  * Client data exchange function
106  *
107  * @server_name [in]: server host name
108  * @port [in]: socket port
109  * @loc_data [in]: local data to send to the server
110  * @loc_datalen [in]: local data length
111  * @rem_data [out]: remote data to get from the server
112  * @rem_datalen [out]: remote data length
113  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
114  */
115 static doca_error_t client_exchange(const char *server_name,
116  int port,
117  void *loc_data,
118  size_t loc_datalen,
119  void **rem_data,
120  size_t *rem_datalen)
121 {
122  int n;
123  ssize_t ret;
124  void *data;
125  char *service;
126  struct addrinfo *res, *t;
127  struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM};
128  static int client_sockfd = -1;
129 
130  if (client_sockfd >= 0)
131  goto connected;
132 
133  if (asprintf(&service, "%d", port) < 0)
134  return DOCA_ERROR_IO_FAILED;
135 
136  n = getaddrinfo(server_name, service, &hints, &res);
137  if (n < 0) {
138  DOCA_LOG_ERR("getaddrinfo() returned error [%s] for %s:%d", gai_strerror(n), server_name, port);
139  free(service);
140  return DOCA_ERROR_IO_FAILED;
141  }
142 
143  for (t = res; t; t = t->ai_next) {
144  client_sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);
145  if (client_sockfd >= 0) {
146  if (!connect(client_sockfd, t->ai_addr, t->ai_addrlen))
147  break;
148  close(client_sockfd);
149  client_sockfd = -1;
150  }
151  }
152 
153  freeaddrinfo(res);
154  free(service);
155 
156  if (client_sockfd < 0) {
157  DOCA_LOG_ERR("Couldn't connect to %s:%d", server_name, port);
158  return DOCA_ERROR_BAD_STATE;
159  }
160 
161 connected:
162 
163  ret = write(client_sockfd, &loc_datalen, sizeof(loc_datalen));
164  if (ret < 0 || (size_t)ret != sizeof(loc_datalen)) {
165  DOCA_LOG_ERR("Couldn't send local datalen");
166  return DOCA_ERROR_IO_FAILED;
167  }
168 
169  ret = write(client_sockfd, loc_data, loc_datalen);
170  if (ret < 0 || (size_t)ret != loc_datalen) {
171  DOCA_LOG_ERR("Couldn't send local data");
172  return DOCA_ERROR_IO_FAILED;
173  }
174 
175  *rem_datalen = 0;
176  ret = read(client_sockfd, rem_datalen, sizeof(*rem_datalen));
177  if (ret < 0 || (size_t)ret != sizeof(*rem_datalen)) {
178  DOCA_LOG_ERR("Couldn't read/write remote datalen");
179  return DOCA_ERROR_IO_FAILED;
180  }
181 
182  if (!*rem_datalen)
183  return DOCA_SUCCESS;
184 
185  if (*rem_datalen > MAX_WORKER_ADDRESS_LEN) {
186  DOCA_LOG_ERR("Received data length greater than the limit %d", MAX_WORKER_ADDRESS_LEN);
188  }
189 
190  data = calloc(1, *rem_datalen);
191  if (data == NULL) {
192  DOCA_LOG_ERR("Failed to allocate client data buffer");
193  return DOCA_ERROR_NO_MEMORY;
194  }
195 
196  ret = read(client_sockfd, data, *rem_datalen);
197  if (ret < 0 || (size_t)ret != *rem_datalen) {
198  free(data);
199  DOCA_LOG_ERR("Couldn't read/write remote data");
200  return DOCA_ERROR_IO_FAILED;
201  }
202 
203  *rem_data = data;
204 
205  DOCA_LOG_INFO("Client received remote data, length: %lu", *rem_datalen);
206 
207  return DOCA_SUCCESS;
208 }
209 
210 /*
211  * Handle RDMO scatter operation
212  *
213  * @client_ucp_worker [in]: client UCP worker structure
214  * @client_ucp_ep [in]: client UCP endpoint structure
215  * @target [in]: remote target
216  * @data [in]: data to scatter
217  * @len [in]: data length
218  * @chunk_size [in]: chunk size to split data to chunks
219  * @rkey [in]: data remote memory key
220  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
221  */
222 static doca_error_t rdmo_scatter(ucp_worker_h client_ucp_worker,
223  ucp_ep_h client_ucp_ep,
224  uint64_t target,
225  void *data,
226  size_t len,
227  int chunk_size,
228  uint64_t rkey)
229 {
230  int i;
231  void *hdr;
232  int chunks = len / chunk_size;
233  struct urom_rdmo_hdr *rdmo_hdr;
234  ucs_status_ptr_t ucs_status_ptr;
235  struct urom_rdmo_scatter_iov *iov;
236  struct urom_rdmo_scatter_hdr *scatter_hdr;
237  ucp_request_param_t req_param = {
238  .op_attr_mask = UCP_OP_ATTR_FIELD_FLAGS,
239  .flags = UCP_AM_SEND_FLAG_REPLY,
240  };
241  int req_data_len = chunks * (sizeof(struct urom_rdmo_scatter_iov) + chunk_size);
242  size_t hdr_len = sizeof(struct urom_rdmo_hdr) + sizeof(struct urom_rdmo_scatter_hdr);
243  uint8_t req_data[req_data_len];
244 
245  memset(req_data, 0, req_data_len);
246 
247  hdr = alloca(hdr_len);
248  if (hdr == NULL)
249  return DOCA_ERROR_NO_MEMORY;
250 
251  rdmo_hdr = (struct urom_rdmo_hdr *)hdr;
252  scatter_hdr = (struct urom_rdmo_scatter_hdr *)(rdmo_hdr + 1);
253 
254  rdmo_hdr->id = 0;
255  rdmo_hdr->op_id = UROM_RDMO_OP_SCATTER;
256  rdmo_hdr->flags = 0;
257  scatter_hdr->count = chunks;
258 
259  iov = (struct urom_rdmo_scatter_iov *)req_data;
260  for (i = 0; i < chunks; i++) {
261  iov->addr = target;
262  iov->len = chunk_size;
263  iov->rkey = rkey;
264  memcpy(iov + 1, data, chunk_size);
265 
266  data += chunk_size;
267  target += chunk_size;
268  iov = (struct urom_rdmo_scatter_iov *)((uintptr_t)iov + sizeof(*iov) + chunk_size);
269  }
270 
271  ucs_status_ptr = ucp_am_send_nbx(client_ucp_ep, 0, hdr, hdr_len, req_data, req_data_len, &req_param);
272  if (UCS_PTR_IS_ERR(ucs_status_ptr))
273  return DOCA_ERROR_DRIVER;
274 
275  if (UCS_PTR_STATUS(ucs_status_ptr) == UCS_INPROGRESS) {
276  while (ucp_request_check_status(ucs_status_ptr) == UCS_INPROGRESS)
277  ucp_worker_progress(client_ucp_worker);
278 
279  if (ucp_request_check_status(ucs_status_ptr) != UCS_OK)
280  return DOCA_ERROR_DRIVER;
281  ucp_request_free(ucs_status_ptr);
282  } else {
283  if (UCS_PTR_STATUS(ucs_status_ptr) != UCS_OK)
284  return DOCA_ERROR_DRIVER;
285  }
286 
287  DOCA_LOG_INFO("RDMO Scatter complete");
288  return DOCA_SUCCESS;
289 }
290 
291 /*
292  * Handle RDMO flush operation
293  *
294  * @client_ucp_worker [in]: client UCP worker structure
295  * @client_ucp_ep [in]: client UCP endpoint structure
296  * @flushed [out]: will be set once the flush operation finished
297  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
298  */
299 static doca_error_t rdmo_flush(ucp_worker_h client_ucp_worker, ucp_ep_h client_ucp_ep, int *flushed)
300 {
301  struct urom_rdmo_hdr *hdr;
302  ucs_status_ptr_t ucs_status_ptr;
303  struct urom_rdmo_flush_hdr *flush_hdr;
304  size_t hdr_len = sizeof(*hdr) + sizeof(*flush_hdr);
305  ucp_request_param_t req_param = {
306  .op_attr_mask = UCP_OP_ATTR_FIELD_FLAGS,
307  .flags = UCP_AM_SEND_FLAG_REPLY,
308  };
309 
310  hdr = alloca(hdr_len);
311  flush_hdr = (struct urom_rdmo_flush_hdr *)(hdr + 1);
312 
313  hdr->id = 0;
314  hdr->op_id = UROM_RDMO_OP_FLUSH;
316  flush_hdr->flush_id = FLUSH_ID;
317  *flushed = 0;
318 
319  ucs_status_ptr = ucp_am_send_nbx(client_ucp_ep, 0, hdr, hdr_len, NULL, 0, &req_param);
320  if (UCS_PTR_IS_ERR(ucs_status_ptr)) {
321  DOCA_LOG_ERR("ucp_am_send_nbx() returned error [%s]",
322  ucs_status_string(ucp_request_check_status(ucs_status_ptr)));
323  return DOCA_ERROR_DRIVER;
324  }
325 
326  if (UCS_PTR_STATUS(ucs_status_ptr) == UCS_INPROGRESS) {
327  while (ucp_request_check_status(ucs_status_ptr) == UCS_INPROGRESS)
328  ucp_worker_progress(client_ucp_worker);
329 
330  if (ucp_request_check_status(ucs_status_ptr) != UCS_OK)
331  return DOCA_ERROR_DRIVER;
332 
333  ucp_request_free(ucs_status_ptr);
334  } else {
335  if (UCS_PTR_STATUS(ucs_status_ptr) != UCS_OK)
336  return DOCA_ERROR_DRIVER;
337  }
338 
339  DOCA_LOG_INFO("Sent flush request");
340 
341  while (!*flushed)
342  ucp_worker_progress(client_ucp_worker);
343 
344  DOCA_LOG_INFO("Flush complete");
345  return DOCA_SUCCESS;
346 }
347 
348 /*
349  * Handle RDMO append operation
350  *
351  * @client_ucp_worker [in]: client UCP worker structure
352  * @client_ucp_ep [in]: client UCP endpoint structure
353  * @ptr_addr [in]: remote buffer address
354  * @data [in]: data to set
355  * @len [in]: data length
356  * @rkey [in]: memory remote key
357  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
358  */
359 static doca_error_t rdmo_append(ucp_worker_h client_ucp_worker,
360  ucp_ep_h client_ucp_ep,
361  uint64_t *ptr_addr,
362  void *data,
363  size_t len,
364  uint64_t rkey)
365 {
366  void *hdr;
367  struct urom_rdmo_hdr *rdmo_hdr;
368  ucs_status_ptr_t ucs_status_ptr;
369  struct urom_rdmo_append_hdr *append_hdr;
370  size_t hdr_len = sizeof(struct urom_rdmo_hdr) + sizeof(struct urom_rdmo_append_hdr);
371  ucp_request_param_t req_param = {
372  .op_attr_mask = UCP_OP_ATTR_FIELD_FLAGS,
373  .flags = UCP_AM_SEND_FLAG_REPLY,
374  };
375 
376  hdr = alloca(hdr_len);
377  rdmo_hdr = (struct urom_rdmo_hdr *)hdr;
378  append_hdr = (struct urom_rdmo_append_hdr *)(rdmo_hdr + 1);
379 
380  rdmo_hdr->id = 0;
381  rdmo_hdr->op_id = UROM_RDMO_OP_APPEND;
382  rdmo_hdr->flags = 0;
383  append_hdr->ptr_addr = (uint64_t)ptr_addr;
384  append_hdr->ptr_rkey = rkey;
385  append_hdr->data_rkey = rkey;
386 
387  ucs_status_ptr = ucp_am_send_nbx(client_ucp_ep, 0, hdr, hdr_len, data, len, &req_param);
388  if (UCS_PTR_IS_ERR(ucs_status_ptr)) {
389  DOCA_LOG_ERR("ucp_am_send_nbx() returned error [%s]",
390  ucs_status_string(ucp_request_check_status(ucs_status_ptr)));
391  return DOCA_ERROR_DRIVER;
392  }
393 
394  if (UCS_PTR_STATUS(ucs_status_ptr) == UCS_INPROGRESS) {
395  while (ucp_request_check_status(ucs_status_ptr) == UCS_INPROGRESS)
396  ucp_worker_progress(client_ucp_worker);
397 
398  if (ucp_request_check_status(ucs_status_ptr) != UCS_OK)
399  return DOCA_ERROR_DRIVER;
400 
401  ucp_request_free(ucs_status_ptr);
402  } else {
403  if (UCS_PTR_STATUS(ucs_status_ptr) != UCS_OK)
404  return DOCA_ERROR_DRIVER;
405  }
406  DOCA_LOG_INFO("RDMO Append complete");
407  return DOCA_SUCCESS;
408 }
409 
410 /*
411  * RDMO recv callback
412  *
413  * @arg [in]: program argument
414  * @header [in]: active message header
415  * @header_length [in]: header length
416  * @data [in]: received data
417  * @length [in]: data length
418  * @param [in]: data receive parameters
419  * @return: UCS_OK on success and UCS_ERR otherwise
420  */
421 static ucs_status_t rdmo_am_cb(void *arg,
422  const void *header,
423  size_t header_length,
424  void *data,
425  size_t length,
426  const ucp_am_recv_param_t *param)
427 {
428  (void)header_length;
429  (void)data;
430  (void)length;
431  (void)param;
432 
433  int *flushed = (int *)arg;
434  struct urom_rdmo_rsp_hdr *rsp_hdr;
435  struct urom_rdmo_flush_rsp_hdr *flush_hdr;
436 
437  rsp_hdr = (struct urom_rdmo_rsp_hdr *)header;
438  flush_hdr = (struct urom_rdmo_flush_rsp_hdr *)(rsp_hdr + 1);
439  *flushed = 1;
440 
441  DOCA_LOG_INFO("Received AM Reply, ID: %#lx", flush_hdr->flush_id);
442  return UCS_OK;
443 }
444 
445 /*
446  * Client wireup function
447  *
448  * @server_name [in]: server host name
449  * @port [in]: socket port
450  * @client_ucp_ep [out]: set client UCP endpoint
451  * @ucp_worker [out]: set client UCP worker
452  * @flushed [out]: client argument will be set once flush op is done
453  * @ucp_context_p [out]: set UCP context
454  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
455  */
456 static doca_error_t rdmo_wireup_client(char *server_name,
457  int port,
458  ucp_ep_h *client_ucp_ep,
459  ucp_worker_h *ucp_worker,
460  int *flushed,
461  ucp_context_h *ucp_context_p)
462 {
464  ucp_params_t ucp_params;
465  ucs_status_t ucs_status;
466  ucp_config_t *ucp_config;
467  ucp_context_h ucp_context;
468  ucs_status_ptr_t close_req;
469  ucp_worker_h client_ucp_worker;
470  ucp_am_handler_param_t am_param;
471  ucp_ep_params_t ep_params = {0};
472  ucp_worker_params_t worker_params;
473  size_t client_worker_addr_len, client_peer_dev_addr_len;
474  ucp_address_t *client_worker_addr = NULL, *client_peer_dev_addr = NULL;
475  ucp_request_param_t close_params = {/* Indicate that flags parameter is specified */
476  .op_attr_mask = UCP_OP_ATTR_FIELD_FLAGS,
477  /* UCP EP closure flags */
478  .flags = UCP_OP_ATTR_FIELD_FLAGS};
479 
480  ucs_status = ucp_config_read(NULL, NULL, &ucp_config);
481  if (ucs_status != UCS_OK) {
482  DOCA_LOG_ERR("Failed to get UCP config structure");
483  return DOCA_ERROR_DRIVER;
484  }
485 
486  ucp_params.field_mask = UCP_PARAM_FIELD_FEATURES;
487  ucp_params.features = UCP_FEATURE_AM | UCP_FEATURE_RMA | UCP_FEATURE_AMO64 | UCP_FEATURE_EXPORTED_MEMH;
488 
489  ucs_status = ucp_init(&ucp_params, ucp_config, &ucp_context);
490  ucp_config_release(ucp_config);
491  if (ucs_status != UCS_OK) {
492  DOCA_LOG_ERR("Failed to init UCP");
493  return DOCA_ERROR_DRIVER;
494  }
495 
496  worker_params.field_mask = UCP_WORKER_PARAM_FIELD_THREAD_MODE;
497  worker_params.thread_mode = UCS_THREAD_MODE_SINGLE;
498 
499  /* Client worker (initiates RDMOs) */
500  ucs_status = ucp_worker_create(ucp_context, &worker_params, &client_ucp_worker);
501  if (ucs_status != UCS_OK) {
502  DOCA_LOG_ERR("Failed to create UCP worker address");
504  goto ucp_context_free;
505  }
506 
507  ucs_status = ucp_worker_get_address(client_ucp_worker, &client_worker_addr, &client_worker_addr_len);
508  if (ucs_status != UCS_OK) {
509  DOCA_LOG_ERR("Failed to get UCP worker address");
511  goto ucp_worker_destroy;
512  }
513 
514  DOCA_LOG_INFO("Created client UCP Worker");
515 
516  /* Exchange worker addresses, give: local worker addr and get: server urom rdmo worker addr */
517  result = client_exchange(server_name,
518  port,
519  client_worker_addr,
520  client_worker_addr_len,
521  (void **)&client_peer_dev_addr,
522  &client_peer_dev_addr_len);
523  if (result != DOCA_SUCCESS) {
524  DOCA_LOG_ERR("Failed to exchange data with server");
525  goto worker_addr_destroy;
526  }
527 
528  DOCA_LOG_INFO("Received dev addr (len: %lu)", client_peer_dev_addr_len);
529 
530  /* Create initiator EP */
531  ep_params.field_mask = UCP_EP_PARAM_FIELD_REMOTE_ADDRESS;
532  ep_params.address = client_peer_dev_addr;
533 
534  ucs_status = ucp_ep_create(client_ucp_worker, &ep_params, client_ucp_ep);
535  if (ucs_status != UCS_OK) {
536  DOCA_LOG_ERR("Failed to create UCP endpoint");
538  goto dev_addr_free;
539  }
540 
541  am_param.field_mask = UCP_AM_HANDLER_PARAM_FIELD_ID | UCP_AM_HANDLER_PARAM_FIELD_CB |
542  UCP_AM_HANDLER_PARAM_FIELD_ARG;
543  am_param.id = 0;
544  am_param.cb = rdmo_am_cb;
545  am_param.arg = flushed;
546 
547  ucs_status = ucp_worker_set_am_recv_handler(client_ucp_worker, &am_param);
548  if (ucs_status != UCS_OK) {
549  DOCA_LOG_ERR("Failed to set AM recv handler");
551  goto ep_destroy;
552  }
553 
554  DOCA_LOG_INFO("Created initiator EP: %p", *client_ucp_ep);
555 
556  ucp_worker_release_address(client_ucp_worker, client_worker_addr);
557  free(client_peer_dev_addr);
558 
559  *ucp_worker = client_ucp_worker;
560  *ucp_context_p = ucp_context;
561 
562  return DOCA_SUCCESS;
563 
564 ep_destroy:
565  close_req = ucp_ep_close_nbx(*client_ucp_ep, &close_params);
566  if (UCS_PTR_IS_PTR(close_req)) {
567  /* Wait completion of UCP EP close operation */
568  do {
569  /* Progress UCP worker */
570  ucp_worker_progress(client_ucp_worker);
571  } while (ucp_request_check_status(close_req) == UCS_INPROGRESS);
572 
573  /* Free UCP request */
574  ucp_request_free(close_req);
575  }
576 
577 dev_addr_free:
578  free(client_peer_dev_addr);
579 
580 worker_addr_destroy:
581  ucp_worker_release_address(client_ucp_worker, client_worker_addr);
582 
583 ucp_worker_destroy:
584  ucp_worker_destroy(client_ucp_worker);
585 
586 ucp_context_free:
587  ucp_cleanup(ucp_context);
588 
589  return result;
590 }
591 
592 /*
593  * Client UCP objects destroy function
594  *
595  * @client_ucp_ep [in]: client UCP endpoint
596  * @ucp_worker [in]: client UCP worker
597  * @ucp_context [in]: UCP context
598  */
599 static void rdmo_ucp_client_destroy(ucp_ep_h client_ucp_ep, ucp_worker_h ucp_worker, ucp_context_h ucp_context)
600 {
601  ucs_status_ptr_t close_req;
602  ucp_request_param_t close_params = {/* Indicate that flags parameter is specified */
603  .op_attr_mask = UCP_OP_ATTR_FIELD_FLAGS,
604  /* UCP EP closure flags */
605  .flags = UCP_OP_ATTR_FIELD_FLAGS};
606 
607  close_req = ucp_ep_close_nbx(client_ucp_ep, &close_params);
608  if (UCS_PTR_IS_PTR(close_req)) {
609  /* Wait completion of UCP EP close operation */
610  do {
611  /* Progress UCP worker */
612  ucp_worker_progress(ucp_worker);
613  } while (ucp_request_check_status(close_req) == UCS_INPROGRESS);
614 
615  /* Free UCP request */
616  ucp_request_free(close_req);
617  }
618 
619  ucp_worker_destroy(ucp_worker);
620  ucp_cleanup(ucp_context);
621 }
622 
623 /*******************************************************************************
624  * Server functions
625  ******************************************************************************/
626 
627 /*
628  * RDMO MR register callback
629  *
630  * @result [in]: task result
631  * @cookie [in]: program cookie
632  * @rkey [out]: memory region rkey
633  */
634 static void mr_register_finished(doca_error_t result, union doca_data cookie, uint64_t rkey)
635 {
636  struct rdmo_result *res = (struct rdmo_result *)cookie.ptr;
637 
638  if (res == NULL)
639  return;
640 
641  res->result = result;
642  if (result != DOCA_SUCCESS)
643  return;
644 
645  res->mr_reg.rkey = rkey;
646 }
647 
648 /*
649  * Server data exchange function
650  *
651  * @port [in]: socket port
652  * @loc_data [in]: local data to send to the client
653  * @loc_datalen [in]: local data length
654  * @rem_data [out]: remote data to get from the client
655  * @rem_datalen [out]: remote data length
656  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
657  */
658 static doca_error_t server_exchange(int port, void *loc_data, size_t loc_datalen, void **rem_data, size_t *rem_datalen)
659 {
660  int n;
661  ssize_t ret;
662  void *data;
663  char *service;
664  struct addrinfo *res, *t;
665  struct addrinfo hints = {.ai_flags = AI_PASSIVE, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM};
666  static int server_sockfd = -1, server_connfd = -1;
667 
668  if (server_connfd >= 0)
669  goto connected;
670 
671  if (asprintf(&service, "%d", port) < 0)
672  return DOCA_ERROR_IO_FAILED;
673 
674  n = getaddrinfo(NULL, service, &hints, &res);
675  if (n < 0) {
676  DOCA_LOG_ERR("%s for port %d", gai_strerror(n), port);
677  free(service);
678  return DOCA_ERROR_IO_FAILED;
679  }
680 
681  for (t = res; t; t = t->ai_next) {
682  server_sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);
683  if (server_sockfd >= 0) {
684  n = 1;
685  if (setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n) != 0) {
686  close(server_sockfd);
687  server_sockfd = -1;
688  break;
689  }
690 
691  if (!bind(server_sockfd, t->ai_addr, t->ai_addrlen))
692  break;
693  close(server_sockfd);
694  server_sockfd = -1;
695  }
696  }
697 
698  freeaddrinfo(res);
699  free(service);
700 
701  if (server_sockfd < 0) {
702  DOCA_LOG_ERR("Couldn't listen to port %d", port);
703  return DOCA_ERROR_IO_FAILED;
704  }
705 
706  listen(server_sockfd, 1);
707  server_connfd = accept(server_sockfd, NULL, NULL);
708  if (server_connfd < 0) {
709  DOCA_LOG_ERR("accept() failed");
710  return DOCA_ERROR_IO_FAILED;
711  }
712 
713 connected:
714  ret = write(server_connfd, &loc_datalen, sizeof(loc_datalen));
715  if (ret < 0 || (size_t)ret != sizeof(loc_datalen)) {
716  DOCA_LOG_ERR("Couldn't write local datalen");
717  return DOCA_ERROR_IO_FAILED;
718  }
719 
720  ret = write(server_connfd, loc_data, loc_datalen);
721  if (ret < 0 || (size_t)ret != loc_datalen) {
722  DOCA_LOG_ERR("Couldn't write local data");
723  return DOCA_ERROR_IO_FAILED;
724  }
725 
726  *rem_datalen = 0;
727  ret = read(server_connfd, rem_datalen, sizeof(*rem_datalen));
728  if (ret < 0 || (size_t)ret != sizeof(*rem_datalen)) {
729  DOCA_LOG_ERR("%ld/%lu: Couldn't read remote data", ret, sizeof(*rem_datalen));
730  return DOCA_ERROR_IO_FAILED;
731  }
732 
733  if (!*rem_datalen)
734  return DOCA_SUCCESS;
735 
736  if (*rem_datalen > MAX_WORKER_ADDRESS_LEN) {
737  DOCA_LOG_ERR("Received data length greater than the limit %d", MAX_WORKER_ADDRESS_LEN);
739  }
740 
741  data = malloc(*rem_datalen);
742  if (data == NULL) {
743  DOCA_LOG_ERR("Failed to create server exchanged data buffer");
744  return DOCA_ERROR_NO_MEMORY;
745  }
746 
747  ret = read(server_connfd, data, *rem_datalen);
748  if (ret < 0 || (size_t)ret != *rem_datalen) {
749  free(data);
750  DOCA_LOG_ERR("%ld/%lu: Couldn't read remote data", ret, *rem_datalen);
751  return DOCA_ERROR_IO_FAILED;
752  }
753 
754  *rem_data = data;
755 
756  DOCA_LOG_INFO("Server received remote data, length: %lu", *rem_datalen);
757 
758  return DOCA_SUCCESS;
759 }
760 
761 /*
762  * Offloading MR register task
763  *
764  * @server_ucp_worker [in]: server UCP worker
765  * @worker [in]: DOCA UROM worker context
766  * @pe [in]: DOCA progress engine
767  * @ucp_context [in]: server UCP context
768  * @buf [in]: server memory region to register
769  * @len [in]: memory length
770  * @memh [out]: buffer memory handle
771  * @rkey [out]: buffer remote key
772  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
773  */
774 static doca_error_t rdmo_mr_reg(ucp_worker_h server_ucp_worker,
775  struct doca_urom_worker *worker,
776  struct doca_pe *pe,
777  ucp_context_h ucp_context,
778  void *buf,
779  size_t len,
780  ucp_mem_h *memh,
781  uint64_t *rkey)
782 {
783  int ret;
784  ucp_mem_h mh;
785  void *packed_memh;
786  void *packed_rkey;
788  size_t packed_memh_len;
789  size_t packed_rkey_len;
790  struct rdmo_result res = {0};
791  ucs_status_t ucs_status;
792  union doca_data cookie = {0};
793  ucp_mem_map_params_t mmap_params;
794  ucp_memh_pack_params_t pack_params;
795 
796  cookie.ptr = &res;
797 
798  /* Memory map */
799  mmap_params.field_mask = UCP_MEM_MAP_PARAM_FIELD_ADDRESS | UCP_MEM_MAP_PARAM_FIELD_LENGTH;
800  mmap_params.address = buf;
801  mmap_params.length = len;
802 
803  ucs_status = ucp_mem_map(ucp_context, &mmap_params, &mh);
804  if (ucs_status != UCS_OK) {
805  DOCA_LOG_ERR("ucp_mem_map() returned an error [%s]", ucs_status_string(ucs_status));
806  return DOCA_ERROR_DRIVER;
807  }
808 
809  /* Memory rkey pack */
810  ucs_status = ucp_rkey_pack(ucp_context, mh, &packed_rkey, &packed_rkey_len);
811  if (ucs_status != UCS_OK) {
812  DOCA_LOG_ERR("ucp_rkey_pack() returned an error [%s]", ucs_status_string(ucs_status));
814  goto memh_destroy;
815  }
816 
817  /* Memory memh pack */
818  pack_params.field_mask = UCP_MEMH_PACK_PARAM_FIELD_FLAGS;
819  pack_params.flags = UCP_MEMH_PACK_FLAG_EXPORT;
820 
821  ucs_status = ucp_memh_pack(mh, &pack_params, &packed_memh, &packed_memh_len);
822  if (ucs_status == UCS_OK) {
823  DOCA_LOG_INFO("ucp_memh_pack() packed length: %lu", packed_memh_len);
824  } else if (ucs_status == UCS_ERR_UNSUPPORTED) {
825  DOCA_LOG_WARN("ucp_memh_pack() export is not supported");
826  packed_memh = NULL;
827  packed_memh_len = 0;
828  } else {
829  DOCA_LOG_ERR("ucp_memh_pack() returned error [%s]", ucs_status_string(ucs_status));
831  goto packed_rkey_free;
832  }
833 
834  res.result = DOCA_SUCCESS;
836  cookie,
837  (uint64_t)buf,
838  len,
839  packed_rkey,
840  packed_rkey_len,
841  packed_memh,
842  packed_memh_len,
844 
845  if (result != DOCA_SUCCESS) {
846  DOCA_LOG_ERR("Failed to register server MR");
847  goto packed_mh_free;
848  }
849 
850  do {
851  ret = doca_pe_progress(pe);
852  ucp_worker_progress(server_ucp_worker);
853  } while (ret == 0 && res.result == DOCA_SUCCESS);
854 
855  if (res.result != DOCA_SUCCESS) {
856  result = res.result;
857  goto packed_mh_free;
858  }
859 
860  *memh = mh;
861  *rkey = res.mr_reg.rkey;
862 
863  ucp_rkey_buffer_release(packed_rkey);
864  ucp_memh_buffer_release(packed_memh, NULL);
865 
866  DOCA_LOG_INFO("Allocated rkey: %lu", *rkey);
867  return DOCA_SUCCESS;
868 
869 packed_mh_free:
870  ucp_memh_buffer_release(packed_memh, NULL);
871 
872 packed_rkey_free:
873  ucp_rkey_buffer_release(packed_rkey);
874 
875 memh_destroy:
876  if (ucp_mem_unmap(ucp_context, mh) != UCS_OK)
877  DOCA_LOG_ERR("Failed to unmap memory handle");
878  return result;
879 }
880 
881 /*
882  * RDMO client init callback
883  *
884  * @result [in]: task result
885  * @cookie [in]: program cookie
886  * @addr [in]: device UCP worker address
887  * @addr_len [in]: address length
888  */
889 static void client_init_finished(doca_error_t result, union doca_data cookie, void *addr, uint64_t addr_len)
890 {
891  struct rdmo_result *res = (struct rdmo_result *)cookie.ptr;
892 
893  if (res == NULL)
894  return;
895 
896  res->result = result;
897  if (result != DOCA_SUCCESS)
898  return;
899 
900  res->client_init.addr = malloc(addr_len);
901  if (res->client_init.addr == NULL) {
903  return;
904  }
905  memcpy(res->client_init.addr, addr, addr_len);
906  res->client_init.addr_len = addr_len;
907 }
908 
909 /*
910  * RDMO RQ create callback
911  *
912  * @result [in]: task result
913  * @cookie [in]: program cookie
914  * @rq_id [in]: RQ id
915  */
916 static void rq_create_finished(doca_error_t result, union doca_data cookie, uint64_t rq_id)
917 {
918  struct rdmo_result *res = (struct rdmo_result *)cookie.ptr;
919 
920  if (res == NULL)
921  return;
922 
923  res->result = result;
924  if (result != DOCA_SUCCESS)
925  return;
926 
927  res->rq_create.rq_id = rq_id;
928 }
929 
930 /*
931  * RDMO RQ destroy callback
932  *
933  * @result [in]: task result
934  * @cookie [in]: program cookie
935  * @rq_id [in]: RQ id
936  */
937 static void rq_destroy_finished(doca_error_t result, union doca_data cookie, uint64_t rq_id)
938 {
939  struct rdmo_result *res = (struct rdmo_result *)cookie.ptr;
940 
941  if (res == NULL)
942  return;
943 
944  res->result = result;
945  if (result != DOCA_SUCCESS)
946  return;
947 
948  res->rq_destroy.rq_id = rq_id;
949 }
950 
951 /*
952  * RDMO MR deregister callback
953  *
954  * @result [in]: task result
955  * @cookie [in]: program cookie
956  * @rkey [in]: MR rkey
957  */
958 static void mr_deregister_finished(doca_error_t result, union doca_data cookie, uint64_t rkey)
959 {
960  struct rdmo_result *res = (struct rdmo_result *)cookie.ptr;
961 
962  if (res == NULL)
963  return;
964 
965  res->result = result;
966  if (result != DOCA_SUCCESS)
967  return;
968 
969  res->mr_dereg.rkey = rkey;
970 }
971 
972 /*
973  * Offloading MR deregister task
974  *
975  * @worker [in]: UROM worker context
976  * @pe [in]: DOCA progress engine
977  * @rkey [in]: MR rkey to deregister
978  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
979  */
980 static doca_error_t rdmo_deregister_mr(struct doca_urom_worker *worker, struct doca_pe *pe, uint64_t rkey)
981 {
982  int ret;
984  union doca_data cookie;
985  struct rdmo_result res = {0};
986 
987  cookie.ptr = &res;
988 
990  if (result != DOCA_SUCCESS)
991  return result;
992 
993  do {
994  ret = doca_pe_progress(pe);
995  } while (ret == 0 && res.result == DOCA_SUCCESS);
996 
997  if (res.result != DOCA_SUCCESS) {
998  DOCA_LOG_ERR("Failed to exchange client address");
999  return res.result;
1000  }
1001 
1002  if (rkey != res.mr_dereg.rkey) {
1003  DOCA_LOG_ERR("MR deregister notification received wrong rkey");
1004  return DOCA_ERROR_INVALID_VALUE;
1005  }
1006  DOCA_LOG_INFO("Deallocated rkey: %lu", rkey);
1007  return DOCA_SUCCESS;
1008 }
1009 
1010 /*
1011  * Offloading RQ destroy task
1012  *
1013  * @worker [in]: UROM worker context
1014  * @pe [in]: DOCA progress engine
1015  * @rq_id [in]: RQ id to destroy
1016  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1017  */
1018 static doca_error_t rdmo_destroy_rq(struct doca_urom_worker *worker, struct doca_pe *pe, uint64_t rq_id)
1019 {
1020  int ret;
1022  union doca_data cookie;
1023  struct rdmo_result res = {0};
1024 
1025  cookie.ptr = &res;
1026 
1028  if (result != DOCA_SUCCESS)
1029  return result;
1030 
1031  do {
1032  ret = doca_pe_progress(pe);
1033  } while (ret == 0 && res.result == DOCA_SUCCESS);
1034 
1035  if (res.result != DOCA_SUCCESS) {
1036  DOCA_LOG_ERR("Failed to exchange client address");
1037  return res.result;
1038  }
1039 
1040  if (rq_id != res.rq_destroy.rq_id) {
1041  DOCA_LOG_ERR("RQ destroy notification received wrong id");
1042  return DOCA_ERROR_INVALID_VALUE;
1043  }
1044  DOCA_LOG_INFO("Destroyed RQ for ID: %lu", rq_id);
1045  return DOCA_SUCCESS;
1046 }
1047 
1048 /*
1049  * Server wireup function
1050  *
1051  * @worker [in]: UROM worker context
1052  * @pe [in]: DOCA progress engine
1053  * @port [in]: socket port
1054  * @ucp_context [out]: set server UCP context
1055  * @server_ucp_worker [out]: set server UCP worker
1056  * @rq_id [out]: set client receive queue
1057  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1058  */
1059 static doca_error_t rdmo_wireup_server(struct doca_urom_worker *worker,
1060  struct doca_pe *pe,
1061  int port,
1062  ucp_context_h *ucp_context,
1063  ucp_worker_h *server_ucp_worker,
1064  uint64_t *rq_id)
1065 {
1066  int ret;
1068  uint64_t server_rq_id;
1069  struct rdmo_result res = {0};
1070  ucs_status_t ucs_status;
1071  ucp_config_t *ucp_config;
1072  ucp_params_t ucp_params;
1073  union doca_data cookie = {0};
1074  size_t server_worker_addr_len;
1075  ucp_address_t *server_worker_addr;
1076  size_t server_peer_host_addr_len;
1077  ucp_worker_params_t worker_params;
1078  ucp_address_t *server_peer_host_addr;
1079 
1080  cookie.ptr = &res;
1081 
1082  ucs_status = ucp_config_read(NULL, NULL, &ucp_config);
1083  if (ucs_status != UCS_OK) {
1084  DOCA_LOG_ERR("Failed to read UCP configuration");
1085  return DOCA_ERROR_DRIVER;
1086  }
1087 
1088  /* Create UCP worker for the server */
1089  ucp_params.field_mask = UCP_PARAM_FIELD_FEATURES;
1090  ucp_params.features = UCP_FEATURE_AM | UCP_FEATURE_RMA | UCP_FEATURE_AMO64 | UCP_FEATURE_EXPORTED_MEMH;
1091 
1092  ucs_status = ucp_init(&ucp_params, ucp_config, ucp_context);
1093  ucp_config_release(ucp_config);
1094  if (ucs_status != UCS_OK) {
1095  DOCA_LOG_ERR("Failed to init UCP layer");
1096  return DOCA_ERROR_DRIVER;
1097  }
1098 
1099  worker_params.field_mask = UCP_WORKER_PARAM_FIELD_THREAD_MODE;
1100  worker_params.thread_mode = UCS_THREAD_MODE_SINGLE;
1101 
1102  /* Server worker (receives RDMOs) */
1103  ucs_status = ucp_worker_create(*ucp_context, &worker_params, server_ucp_worker);
1104  if (ucs_status != UCS_OK) {
1105  DOCA_LOG_ERR("Failed to create server worker");
1107  goto ucp_context_free;
1108  }
1109 
1110  ucs_status = ucp_worker_get_address(*server_ucp_worker, &server_worker_addr, &server_worker_addr_len);
1111  if (ucs_status != UCS_OK) {
1112  DOCA_LOG_ERR("Failed to create server worker");
1114  goto worker_destroy;
1115  }
1116 
1117  DOCA_LOG_INFO("Created server UCP Worker");
1118 
1119  res.result = DOCA_SUCCESS;
1120  /* RDMO Client init */
1122  cookie,
1123  0,
1124  server_worker_addr,
1125  server_worker_addr_len,
1127 
1128  if (result != DOCA_SUCCESS) {
1129  DOCA_LOG_ERR("Failed to create client init");
1130  goto worker_addr_destroy;
1131  }
1132 
1133  do {
1134  ret = doca_pe_progress(pe);
1135  ucp_worker_progress(*server_ucp_worker);
1136  } while (ret == 0 && res.result == DOCA_SUCCESS);
1137 
1138  if (res.result != DOCA_SUCCESS) {
1139  DOCA_LOG_ERR("Client init task finished with error");
1140  result = res.result;
1141  goto worker_addr_destroy;
1142  }
1143 
1144  DOCA_LOG_INFO("Initialized RDMO client (host addr len: %lu, dev addr len: %lu)",
1145  server_worker_addr_len,
1146  res.client_init.addr_len);
1147 
1148  /* Exchange worker addresses, give: server urom rdmo worker addr get: client worker addr */
1149  result = server_exchange(port,
1150  res.client_init.addr,
1151  res.client_init.addr_len,
1152  (void **)&server_peer_host_addr,
1153  &server_peer_host_addr_len);
1154  free(res.client_init.addr);
1155  if (result != DOCA_SUCCESS) {
1156  DOCA_LOG_ERR("Failed to exchange client address");
1157  goto worker_addr_destroy;
1158  }
1159 
1160  DOCA_LOG_INFO("Received host addr (len: %lu)", server_peer_host_addr_len);
1161 
1162  res.result = DOCA_SUCCESS;
1163  /* Create RDMO receive queue */
1164  urom_rdmo_task_rq_create(worker, cookie, server_peer_host_addr, server_peer_host_addr_len, rq_create_finished);
1165 
1166  do {
1167  ret = doca_pe_progress(pe);
1168  } while (ret == 0 && res.result == DOCA_SUCCESS);
1169 
1170  if (res.result != DOCA_SUCCESS) {
1171  DOCA_LOG_ERR("Failed to exchange client address");
1172  free(server_peer_host_addr);
1173  goto worker_addr_destroy;
1174  }
1175 
1176  server_rq_id = res.rq_create.rq_id;
1177  DOCA_LOG_INFO("Created RQ: %#lx", server_rq_id);
1178  ucp_worker_release_address(*server_ucp_worker, server_worker_addr);
1179  free(server_peer_host_addr);
1180  *rq_id = server_rq_id;
1181  return DOCA_SUCCESS;
1182 
1183 worker_addr_destroy:
1184  ucp_worker_release_address(*server_ucp_worker, server_worker_addr);
1185 
1186 worker_destroy:
1187  ucp_worker_destroy(*server_ucp_worker);
1188 
1189 ucp_context_free:
1190  ucp_cleanup(*ucp_context);
1191 
1192  return result;
1193 }
1194 
1195 /*
1196  * Init server UROM objects
1197  *
1198  * @device_name [in]: UROM device name
1199  * @pe [out]: set DOCA progress engine
1200  * @service [out]: set DOCA UROM service engine
1201  * @worker [out]: set DOCA UROM worker engine
1202  * @dev [out]: set DOCA device
1203  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1204  */
1205 static doca_error_t rdmo_server_urom_init(char *device_name,
1206  struct doca_pe **pe,
1207  struct doca_urom_service **service,
1208  struct doca_urom_worker **worker,
1209  struct doca_dev **dev)
1210 {
1211  size_t i, plugins_count = 0;
1212  char *plugin_name = "worker_rdmo";
1213  const struct doca_urom_service_plugin_info *plugins, *rdmo_info = NULL;
1214  doca_error_t result, tmp_result;
1215  enum doca_ctx_states state;
1216 
1217  /* UROM service create and connect */
1218  result = open_doca_device_with_ibdev_name((uint8_t *)device_name, strlen(device_name), NULL, dev);
1219  if (result != DOCA_SUCCESS)
1220  return result;
1221 
1223  if (result != DOCA_SUCCESS)
1224  goto close_dev;
1225 
1226  result = start_urom_service(*pe, *dev, 2, service);
1227  if (result != DOCA_SUCCESS)
1228  goto pe_cleanup;
1229 
1230  result = doca_urom_service_get_plugins_list(*service, &plugins, &plugins_count);
1231  if (result != DOCA_SUCCESS || plugins_count == 0)
1232  goto service_stop;
1233 
1234  for (i = 0; i < plugins_count; i++) {
1235  if (strcmp(plugin_name, plugins[i].plugin_name) == 0) {
1236  rdmo_info = &plugins[i];
1237  break;
1238  }
1239  }
1240 
1241  if (rdmo_info == NULL) {
1242  DOCA_LOG_ERR("Failed to match RDMO plugin");
1244  goto service_stop;
1245  }
1246 
1247  result = urom_rdmo_init(rdmo_info->id, rdmo_info->version);
1248  if (result != DOCA_SUCCESS)
1249  goto service_stop;
1250 
1251  /* Create and start worker context */
1252  result =
1253  start_urom_worker(*pe, *service, DOCA_UROM_WORKER_ID_ANY, NULL, 16, NULL, NULL, 0, rdmo_info->id, worker);
1254  if (result != DOCA_SUCCESS)
1255  goto service_stop;
1256 
1257  /* Loop till worker state changes to running */
1258  do {
1259  doca_pe_progress(*pe);
1261  } while (state == DOCA_CTX_STATE_STARTING && result == DOCA_SUCCESS);
1262 
1263  if (state != DOCA_CTX_STATE_RUNNING || result != DOCA_SUCCESS)
1264  goto worker_cleanup;
1265 
1266  return DOCA_SUCCESS;
1267 
1268 worker_cleanup:
1269  tmp_result = doca_urom_worker_destroy(*worker);
1270  if (tmp_result != DOCA_SUCCESS) {
1271  DOCA_LOG_ERR("Failed to destroy UROM worker");
1272  DOCA_ERROR_PROPAGATE(result, tmp_result);
1273  }
1274 
1275 service_stop:
1276  tmp_result = doca_ctx_stop(doca_urom_service_as_ctx(*service));
1277  if (tmp_result != DOCA_SUCCESS) {
1278  DOCA_LOG_ERR("Failed to stop UROM service");
1279  DOCA_ERROR_PROPAGATE(result, tmp_result);
1280  }
1281  tmp_result = doca_urom_service_destroy(*service);
1282  if (tmp_result != DOCA_SUCCESS) {
1283  DOCA_LOG_ERR("Failed to destroy UROM service");
1284  DOCA_ERROR_PROPAGATE(result, tmp_result);
1285  }
1286 
1287 pe_cleanup:
1288  tmp_result = doca_pe_destroy(*pe);
1289  if (tmp_result != DOCA_SUCCESS) {
1290  DOCA_LOG_ERR("Failed to destroy PE");
1291  DOCA_ERROR_PROPAGATE(result, tmp_result);
1292  }
1293 
1294 close_dev:
1295  tmp_result = doca_dev_close(*dev);
1296  if (tmp_result != DOCA_SUCCESS) {
1297  DOCA_LOG_ERR("Failed to close device");
1298  DOCA_ERROR_PROPAGATE(result, tmp_result);
1299  }
1300  return result;
1301 }
1302 
1303 /*
1304  * Destroy server UROM objects
1305  *
1306  * @pe [in]: DOCA progress engine
1307  * @service [in]: DOCA UROM service engine
1308  * @worker [in]: DOCA UROM worker engine
1309  * @dev [in]: DOCA UROM device
1310  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1311  */
1313  struct doca_urom_service *service,
1314  struct doca_urom_worker *worker,
1315  struct doca_dev *dev)
1316 {
1317  int ret = 0;
1318  enum doca_ctx_states state;
1319  doca_error_t tmp_result, result = DOCA_SUCCESS;
1320 
1321  tmp_result = doca_ctx_stop(doca_urom_worker_as_ctx(worker));
1322  if (tmp_result != DOCA_SUCCESS && tmp_result != DOCA_ERROR_IN_PROGRESS) {
1323  DOCA_LOG_ERR("Failed to request stop UROM worker");
1324  DOCA_ERROR_PROPAGATE(result, tmp_result);
1325  }
1326 
1327  do {
1328  ret += doca_pe_progress(pe);
1329  tmp_result = doca_ctx_get_state(doca_urom_worker_as_ctx(worker), &state);
1330  } while (state != DOCA_CTX_STATE_IDLE);
1331 
1332  if (ret == 0 || tmp_result != DOCA_SUCCESS)
1333  DOCA_ERROR_PROPAGATE(result, tmp_result);
1334 
1335  tmp_result = doca_urom_worker_destroy(worker);
1336  if (tmp_result != DOCA_SUCCESS) {
1337  DOCA_LOG_ERR("Failed to destroy UROM worker");
1338  DOCA_ERROR_PROPAGATE(result, tmp_result);
1339  }
1340 
1341  tmp_result = doca_ctx_stop(doca_urom_service_as_ctx(service));
1342  if (tmp_result != DOCA_SUCCESS) {
1343  DOCA_LOG_ERR("Failed to stop UROM service");
1344  DOCA_ERROR_PROPAGATE(result, tmp_result);
1345  }
1346  tmp_result = doca_urom_service_destroy(service);
1347  if (tmp_result != DOCA_SUCCESS) {
1348  DOCA_LOG_ERR("Failed to destroy UROM service");
1349  DOCA_ERROR_PROPAGATE(result, tmp_result);
1350  }
1351 
1352  tmp_result = doca_pe_destroy(pe);
1353  if (tmp_result != DOCA_SUCCESS) {
1354  DOCA_LOG_ERR("Failed to destroy PE");
1355  DOCA_ERROR_PROPAGATE(result, tmp_result);
1356  }
1357 
1358  tmp_result = doca_dev_close(dev);
1359  if (tmp_result != DOCA_SUCCESS) {
1360  DOCA_LOG_ERR("Failed to close device");
1361  DOCA_ERROR_PROPAGATE(result, tmp_result);
1362  }
1363 
1364  return result;
1365 }
1366 
1367 /*******************************************************************************
1368  * Common server and client functions
1369  ******************************************************************************/
1370 
1371 /*
1372  * Client-Server barrier
1373  *
1374  * @server_name [in]: server hostname
1375  * @port [in]: socket port
1376  * @mode [in]: client or server mode
1377  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1378  */
1379 static doca_error_t cs_barrier(const char *server_name, int port, enum rdmo_mode mode)
1380 {
1381  size_t len;
1382 
1383  if (mode == RDMO_MODE_SERVER)
1384  return server_exchange(port, NULL, 0, NULL, &len);
1385  else
1386  return client_exchange(server_name, port, NULL, 0, NULL, &len);
1387 }
1388 
1389 /*
1390  * ARGP Callback - Handle mode parameter
1391  *
1392  * @param [in]: Input parameter
1393  * @config [in/out]: Program configuration context
1394  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1395  */
1396 static doca_error_t mode_callback(void *param, void *config)
1397 {
1398  struct rdmo_cfg *rdmo_cfg = (struct rdmo_cfg *)config;
1399  char *mode = (char *)param;
1400 
1402  return DOCA_ERROR_BAD_STATE;
1403 
1404  if (strcmp("client", mode) == 0)
1406  else if (strcmp("server", mode) == 0)
1408  else {
1409  DOCA_LOG_ERR("Invalid mode type [%s]", mode);
1410  return DOCA_ERROR_INVALID_VALUE;
1411  }
1412 
1413  return DOCA_SUCCESS;
1414 }
1415 
1416 /*
1417  * ARGP Callback - Handle server name parameter
1418  *
1419  * @param [in]: Input parameter
1420  * @config [in/out]: Program configuration context
1421  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
1422  */
1423 static doca_error_t server_address_callback(void *param, void *config)
1424 {
1425  struct rdmo_cfg *rdmo_cfg = (struct rdmo_cfg *)config;
1426  char *server_name = (char *)param;
1427  int len;
1428 
1429  len = strnlen(server_name, HOST_NAME_MAX);
1430  if (len == HOST_NAME_MAX) {
1431  DOCA_LOG_ERR("Entered server name exceeding the maximum size of %d", HOST_NAME_MAX - 1);
1432  return DOCA_ERROR_INVALID_VALUE;
1433  }
1434  strlcpy(rdmo_cfg->server_name, server_name, HOST_NAME_MAX);
1435 
1436  return DOCA_SUCCESS;
1437 }
1438 
1439 /*******************************************************************************
1440  * External server and client functions
1441  ******************************************************************************/
1442 doca_error_t rdmo_server(char *device_name)
1443 {
1444  ucp_mem_h memh;
1445  size_t bytes_sent = 8;
1446  int port = 18515;
1447  uint64_t rq_id = 0, expected_ptr;
1448  bool succeeded = true;
1449  void *queue_buf = NULL;
1450  ucp_context_h ucp_context;
1451  struct rbuf_desc rbuf_desc;
1452  char *byte, data_val = 0x33;
1453  size_t queue_len = 128 * 1024;
1454  ucp_worker_h server_ucp_worker;
1455  doca_error_t result, tmp_result;
1456  size_t i, *queue_ptr, send_len = 8;
1457  uint64_t rbuf_desc_len, rkey = 0;
1458  /* DOCA UROM objects */
1459  struct doca_pe *pe;
1460  struct doca_dev *dev;
1461  struct doca_urom_service *service;
1462  struct doca_urom_worker *worker;
1463 
1464  if (device_name == NULL)
1465  return DOCA_ERROR_INVALID_VALUE;
1466 
1467  /* Create UROM objects */
1468  result = rdmo_server_urom_init(device_name, &pe, &service, &worker, &dev);
1469  if (result != DOCA_SUCCESS) {
1470  DOCA_LOG_ERR("Failed to initialize UROM objects");
1471  return result;
1472  }
1473 
1474  /* Server wireup */
1475  result = rdmo_wireup_server(worker, pe, port, &ucp_context, &server_ucp_worker, &rq_id);
1476  if (result != DOCA_SUCCESS) {
1477  DOCA_LOG_ERR("Failed to execute server wireup");
1478  goto destroy_urom;
1479  }
1480 
1481  /* buffer setup */
1482  queue_buf = calloc(1, queue_len);
1483  if (queue_buf == NULL) {
1485  goto ucp_destroy;
1486  }
1487 
1488  queue_ptr = queue_buf;
1489  *queue_ptr = (uint64_t)(queue_ptr + 1);
1490 
1491  result = rdmo_mr_reg(server_ucp_worker, worker, pe, ucp_context, queue_buf, queue_len, &memh, &rkey);
1492  if (result != DOCA_SUCCESS)
1493  goto queue_free;
1494 
1495  /* Exchange rkey */
1496  rbuf_desc.rkey = rkey;
1497  rbuf_desc.raddr = queue_ptr;
1498 
1499  DOCA_LOG_INFO("Sent rkey %lu and queue pointer %p", rkey, queue_ptr);
1500 
1501  result = server_exchange(port, &rbuf_desc, sizeof(rbuf_desc), NULL, &rbuf_desc_len);
1502  if (result != DOCA_SUCCESS) {
1503  DOCA_LOG_ERR("Failed to exchange server data");
1504  goto memh_unmap;
1505  }
1506 
1507  /* Worker progress append and flush */
1508  expected_ptr = (uintptr_t)queue_buf + sizeof(queue_ptr) + bytes_sent;
1509  while (*queue_ptr != expected_ptr) {
1510  ucp_worker_progress(server_ucp_worker);
1511  sched_yield();
1512  }
1513 
1514  succeeded = true;
1515  byte = (char *)&queue_ptr[1];
1516  for (i = 0; i < bytes_sent; i++) {
1517  if (byte[i] != data_val) {
1518  succeeded = false;
1519  DOCA_LOG_ERR("Append bad data[%ld]: %#x, expected: %#x", i, byte[i], data_val);
1520  }
1521  }
1522 
1523  if (!succeeded) {
1524  DOCA_LOG_ERR("Append operation failed");
1526  goto memh_unmap;
1527  } else
1528  DOCA_LOG_INFO("Append operation was finished successfully");
1529 
1530  /* One additional progress for flush operation */
1531  ucp_worker_progress(server_ucp_worker);
1532 
1533  memset(queue_ptr, 0, queue_len);
1534 
1535  /* Client-Server barrier */
1537 
1538  /* Worker progress scatter and flush */
1539  byte = (char *)queue_ptr;
1540  while (byte[send_len - 1] != data_val) {
1541  ucp_worker_progress(server_ucp_worker);
1542  sched_yield();
1543  }
1544 
1545  succeeded = true;
1546  for (i = 0; i < send_len; i++) {
1547  if (byte[i] != data_val) {
1548  succeeded = false;
1549  DOCA_LOG_ERR("Scatter Bad data[%ld]: %#x, expected: %#x", i, byte[i], data_val);
1550  }
1551  }
1552 
1553  if (!succeeded) {
1554  DOCA_LOG_ERR("Scatter operation failed");
1556  goto memh_unmap;
1557  } else
1558  DOCA_LOG_INFO("Scatter operation was finished successfully");
1559 
1560  result = DOCA_SUCCESS;
1561 
1562 memh_unmap:
1563  ucp_mem_unmap(ucp_context, memh);
1564  rdmo_deregister_mr(worker, pe, rkey);
1565 queue_free:
1566  free(queue_buf);
1567 ucp_destroy:
1568  tmp_result = rdmo_destroy_rq(worker, pe, rq_id);
1569  if (tmp_result != DOCA_SUCCESS) {
1570  DOCA_LOG_ERR("Failed to destroy RQ");
1571  DOCA_ERROR_PROPAGATE(result, tmp_result);
1572  }
1573  ucp_worker_destroy(server_ucp_worker);
1574  ucp_cleanup(ucp_context);
1575 destroy_urom:
1576  tmp_result = rdmo_server_urom_destroy(pe, service, worker, dev);
1577  if (tmp_result != DOCA_SUCCESS) {
1578  DOCA_LOG_ERR("Failed to destroy UROM objects");
1579  DOCA_ERROR_PROPAGATE(result, tmp_result);
1580  }
1581  return result;
1582 }
1583 
1584 doca_error_t rdmo_client(char *server_name)
1585 {
1586  size_t send_len;
1588  char data_val = 0x33;
1589  void *send_buf = NULL;
1590  ucp_ep_h client_ucp_ep;
1591  ucp_worker_h ucp_worker;
1592  ucp_context_h ucp_context;
1593  size_t queue_len = 128 * 1024;
1594  struct rbuf_desc *rbuf_desc = NULL;
1595  int flushed = 0, port = 18515;
1596  uint64_t rkey, rbuf_desc_len, *queue_ptr;
1597  int scatter_chunk_size = 8, scatter_chunks = 16;
1598 
1599  /* Client wireup */
1600  result = rdmo_wireup_client(server_name, port, &client_ucp_ep, &ucp_worker, &flushed, &ucp_context);
1601  if (result != DOCA_SUCCESS) {
1602  DOCA_LOG_ERR("rdmo_wireup_client() returned error");
1603  return result;
1604  }
1605 
1606  /* Create send buffer */
1607  send_buf = calloc(1, queue_len);
1608  if (send_buf == NULL) {
1609  DOCA_LOG_ERR("Failed to allocate send buffer memory");
1611  goto ucp_destroy;
1612  }
1613 
1614  memset(send_buf, data_val, queue_len);
1615  DOCA_LOG_INFO("Send buffer contains [%c] char", data_val);
1616 
1617  /* Exchange rkey */
1618  result = client_exchange(server_name, port, NULL, 0, (void **)&rbuf_desc, &rbuf_desc_len);
1619  if (result != DOCA_SUCCESS || rbuf_desc == NULL) {
1620  DOCA_LOG_ERR("Failed to exchange client data");
1621  goto free_buf;
1622  }
1623 
1624  rkey = rbuf_desc->rkey;
1625  queue_ptr = rbuf_desc->raddr;
1626  free(rbuf_desc);
1627  DOCA_LOG_INFO("Received rkey %lu and queue pointer %p", rkey, queue_ptr);
1628 
1629  /* Set send buffer length */
1630  send_len = 8;
1631 
1632  /* RDMO append operation */
1633  result = rdmo_append(ucp_worker, client_ucp_ep, queue_ptr, send_buf, send_len, rkey);
1634  if (result != DOCA_SUCCESS) {
1635  DOCA_LOG_ERR("Failed to start append RDMO op");
1636  goto free_buf;
1637  }
1638 
1639  /* RDMO flush operation */
1640  result = rdmo_flush(ucp_worker, client_ucp_ep, &flushed);
1641  if (result != DOCA_SUCCESS) {
1642  DOCA_LOG_ERR("Failed to start flush RDMO op");
1643  goto free_buf;
1644  }
1645 
1646  /* Client-Server barrier */
1647  result = cs_barrier(server_name, port, RDMO_MODE_CLIENT);
1648  if (result != DOCA_SUCCESS) {
1649  DOCA_LOG_ERR("Failed to execute barrier between client and server");
1650  goto free_buf;
1651  }
1652 
1653  /* RDMO scatter operation */
1654  send_len = scatter_chunk_size * scatter_chunks;
1655 
1656  result = rdmo_scatter(ucp_worker,
1657  client_ucp_ep,
1658  (uint64_t)queue_ptr,
1659  send_buf,
1660  send_len,
1661  scatter_chunk_size,
1662  rkey);
1663  if (result != DOCA_SUCCESS) {
1664  DOCA_LOG_ERR("Failed to start scatter RDMO op");
1665  goto free_buf;
1666  }
1667 
1668  /* RDMO flush operation */
1669  result = rdmo_flush(ucp_worker, client_ucp_ep, &flushed);
1670  if (result != DOCA_SUCCESS) {
1671  DOCA_LOG_ERR("Failed to start flush RDMO op");
1672  goto free_buf;
1673  }
1674 
1675  return DOCA_SUCCESS;
1676 
1677 free_buf:
1678  free(send_buf);
1679 
1680 ucp_destroy:
1681  rdmo_ucp_client_destroy(client_ucp_ep, ucp_worker, ucp_context);
1682 
1683  return result;
1684 }
1685 
1687 {
1689  struct doca_argp_param *server_name, *mode;
1690 
1692  if (result != DOCA_SUCCESS) {
1693  DOCA_LOG_ERR("Failed to register UROM common param: %s", doca_error_get_descr(result));
1694  return result;
1695  }
1696 
1697  /* Create and register server name param */
1698  result = doca_argp_param_create(&server_name);
1699  if (result != DOCA_SUCCESS) {
1700  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1701  return result;
1702  }
1703 
1704  doca_argp_param_set_short_name(server_name, "s");
1705  doca_argp_param_set_long_name(server_name, "server-name");
1706  doca_argp_param_set_arguments(server_name, "<server name>");
1707  doca_argp_param_set_description(server_name, "server name.");
1710  result = doca_argp_register_param(server_name);
1711  if (result != DOCA_SUCCESS) {
1712  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1713  return result;
1714  }
1715 
1716  /* Create and register server name param */
1717  result = doca_argp_param_create(&mode);
1718  if (result != DOCA_SUCCESS) {
1719  DOCA_LOG_ERR("Failed to create ARGP param: %s", doca_error_get_descr(result));
1720  return result;
1721  }
1722 
1723  doca_argp_param_set_short_name(mode, "m");
1724  doca_argp_param_set_long_name(mode, "mode");
1725  doca_argp_param_set_arguments(mode, "{server, client}");
1726  doca_argp_param_set_description(mode, "Set mode type {server, client}");
1731  if (result != DOCA_SUCCESS) {
1732  DOCA_LOG_ERR("Failed to register program param: %s", doca_error_get_descr(result));
1733  return result;
1734  }
1735 
1736  return DOCA_SUCCESS;
1737 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
doca_error_t open_doca_device_with_ibdev_name(const uint8_t *value, size_t val_size, tasks_check func, struct doca_dev **retval)
Definition: common.c:84
uintptr_t addr
uint64_t len
uint64_t cookie
if(bitoffset % 64+bitlength > 64) result|
static struct doca_pe * pe
DOCA_EXPERIMENTAL void doca_argp_param_set_description(struct doca_argp_param *param, const char *description)
Set the description of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_long_name(struct doca_argp_param *param, const char *name)
Set the long name of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_arguments(struct doca_argp_param *param, const char *arguments)
Set the description of the expected arguments of the program param, used during program usage.
DOCA_EXPERIMENTAL void doca_argp_param_set_callback(struct doca_argp_param *param, doca_argp_param_cb_t callback)
Set the callback function of the program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_mandatory(struct doca_argp_param *param)
Mark the program param as mandatory.
DOCA_EXPERIMENTAL doca_error_t doca_argp_param_create(struct doca_argp_param **param)
Create new program param.
DOCA_EXPERIMENTAL void doca_argp_param_set_type(struct doca_argp_param *param, enum doca_argp_type type)
Set the type of the param arguments.
DOCA_EXPERIMENTAL void doca_argp_param_set_short_name(struct doca_argp_param *param, const char *name)
Set the short name of the program param.
DOCA_EXPERIMENTAL doca_error_t doca_argp_register_param(struct doca_argp_param *input_param)
Register a program flag.
@ DOCA_ARGP_TYPE_STRING
Definition: doca_argp.h:56
DOCA_STABLE doca_error_t doca_ctx_get_state(const struct doca_ctx *ctx, enum doca_ctx_states *state)
Get context state.
DOCA_STABLE doca_error_t doca_ctx_stop(struct doca_ctx *ctx)
Stops the context allowing reconfiguration.
doca_ctx_states
This enum defines the states of a context.
Definition: doca_ctx.h:83
@ DOCA_CTX_STATE_STARTING
Definition: doca_ctx.h:93
@ DOCA_CTX_STATE_IDLE
Definition: doca_ctx.h:88
@ DOCA_CTX_STATE_RUNNING
Definition: doca_ctx.h:98
DOCA_STABLE doca_error_t doca_dev_close(struct doca_dev *dev)
Destroy allocated local device instance.
#define DOCA_ERROR_PROPAGATE(r, t)
Save the first encountered doca_error_t.
Definition: doca_error.h:83
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_ERROR_BAD_STATE
Definition: doca_error.h:56
@ DOCA_ERROR_IO_FAILED
Definition: doca_error.h:55
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_ERROR_NO_MEMORY
Definition: doca_error.h:45
@ DOCA_ERROR_IN_PROGRESS
Definition: doca_error.h:64
@ DOCA_ERROR_DRIVER
Definition: doca_error.h:59
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
Definition: doca_log.h:466
#define DOCA_LOG_WARN(format,...)
Generates a WARNING application log message.
Definition: doca_log.h:476
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
Definition: doca_log.h:486
DOCA_STABLE doca_error_t doca_pe_destroy(struct doca_pe *pe)
Destroy doca progress engine.
DOCA_STABLE uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_STABLE doca_error_t doca_pe_create(struct doca_pe **pe)
Creates DOCA progress engine.
DOCA_EXPERIMENTAL doca_error_t doca_urom_service_get_plugins_list(struct doca_urom_service *service_ctx, const struct doca_urom_service_plugin_info **plugins, size_t *plugins_count)
This method gets the list of supported plugins on service's DPU side.
DOCA_EXPERIMENTAL struct doca_ctx * doca_urom_service_as_ctx(struct doca_urom_service *service_ctx)
Convert service_ctx instance into a generalized context for use with DOCA core objects.
DOCA_EXPERIMENTAL doca_error_t doca_urom_service_destroy(struct doca_urom_service *service_ctx)
This method destroys a UROM Service context.
DOCA_EXPERIMENTAL doca_error_t doca_urom_worker_destroy(struct doca_urom_worker *worker_ctx)
This method destroys a UROM Worker context.
#define DOCA_UROM_WORKER_ID_ANY
DOCA UROM WORKER ID any give the library the responsibility to generate a worker id.
Definition: doca_urom.h:556
DOCA_EXPERIMENTAL struct doca_ctx * doca_urom_worker_as_ctx(struct doca_urom_worker *worker_ctx)
doca_error_t urom_rdmo_task_mr_deregister(struct doca_urom_worker *worker_ctx, union doca_data cookie, uint64_t rkey_id, urom_rdmo_mr_deregister_finished cb)
Definition: worker_rdmo.c:552
doca_error_t urom_rdmo_init(uint64_t plugin_id, uint64_t version)
Definition: worker_rdmo.c:603
doca_error_t urom_rdmo_task_rq_destroy(struct doca_urom_worker *worker_ctx, union doca_data cookie, uint64_t rq_id, urom_rdmo_rq_destroy_finished cb)
Definition: worker_rdmo.c:406
doca_error_t urom_rdmo_task_client_init(struct doca_urom_worker *worker_ctx, union doca_data cookie, uint64_t id, void *addr, uint64_t addr_len, urom_rdmo_client_init_finished cb)
Definition: worker_rdmo.c:264
doca_error_t urom_rdmo_task_mr_register(struct doca_urom_worker *worker_ctx, union doca_data cookie, uint64_t va, uint64_t len, void *rkey, uint64_t rkey_len, void *memh, uint64_t memh_len, urom_rdmo_mr_register_finished cb)
Definition: worker_rdmo.c:474
doca_error_t urom_rdmo_task_rq_create(struct doca_urom_worker *worker_ctx, union doca_data cookie, void *addr, uint64_t addr_len, urom_rdmo_rq_create_finished cb)
Definition: worker_rdmo.c:336
__UINTPTR_TYPE__ uintptr_t
Definition: stdint.h:298
char plugin_name[DOCA_UROM_PLUGIN_NAME_MAX_LEN]
uint64_t rkey
uint64_t * raddr
enum rdmo_mode mode
char server_name[HOST_NAME_MAX]
struct mr_deregister_result mr_dereg
struct rq_destroy_result rq_destroy
struct mr_register_result mr_reg
struct client_init_result client_init
struct rq_create_result rq_create
doca_error_t result
uint32_t flags
Definition: urom_rdmo.h:163
uint64_t id
Definition: urom_rdmo.h:161
uint32_t op_id
Definition: urom_rdmo.h:162
Convenience type for representing opaque data.
Definition: doca_types.h:56
doca_error_t start_urom_service(struct doca_pe *pe, struct doca_dev *dev, uint64_t nb_workers, struct doca_urom_service **service)
Definition: urom_common.c:95
doca_error_t register_urom_common_params(void)
Definition: urom_common.c:69
doca_error_t start_urom_worker(struct doca_pe *pe, struct doca_urom_service *service, uint64_t worker_id, uint32_t *gid, uint64_t nb_tasks, doca_cpu_set_t *cpuset, char **env, size_t env_count, uint64_t plugins, struct doca_urom_worker **worker)
Definition: urom_common.c:148
@ UROM_RDMO_OP_APPEND
Definition: urom_rdmo.h:155
@ UROM_RDMO_OP_SCATTER
Definition: urom_rdmo.h:156
@ UROM_RDMO_OP_FLUSH
Definition: urom_rdmo.h:154
@ UROM_RDMO_REQ_FLAG_FENCE
Definition: urom_rdmo.h:149
doca_error_t register_urom_rdmo_params(void)
static doca_error_t server_address_callback(void *param, void *config)
static void rq_create_finished(doca_error_t result, union doca_data cookie, uint64_t rq_id)
static ucs_status_t rdmo_am_cb(void *arg, const void *header, size_t header_length, void *data, size_t length, const ucp_am_recv_param_t *param)
static doca_error_t rdmo_server_urom_init(char *device_name, struct doca_pe **pe, struct doca_urom_service **service, struct doca_urom_worker **worker, struct doca_dev **dev)
static doca_error_t rdmo_deregister_mr(struct doca_urom_worker *worker, struct doca_pe *pe, uint64_t rkey)
static doca_error_t rdmo_destroy_rq(struct doca_urom_worker *worker, struct doca_pe *pe, uint64_t rq_id)
#define MAX_WORKER_ADDRESS_LEN
static void client_init_finished(doca_error_t result, union doca_data cookie, void *addr, uint64_t addr_len)
static doca_error_t rdmo_scatter(ucp_worker_h client_ucp_worker, ucp_ep_h client_ucp_ep, uint64_t target, void *data, size_t len, int chunk_size, uint64_t rkey)
static doca_error_t rdmo_wireup_client(char *server_name, int port, ucp_ep_h *client_ucp_ep, ucp_worker_h *ucp_worker, int *flushed, ucp_context_h *ucp_context_p)
#define FLUSH_ID
static void rq_destroy_finished(doca_error_t result, union doca_data cookie, uint64_t rq_id)
static doca_error_t rdmo_append(ucp_worker_h client_ucp_worker, ucp_ep_h client_ucp_ep, uint64_t *ptr_addr, void *data, size_t len, uint64_t rkey)
static doca_error_t client_exchange(const char *server_name, int port, void *loc_data, size_t loc_datalen, void **rem_data, size_t *rem_datalen)
doca_error_t rdmo_client(char *server_name)
static void mr_register_finished(doca_error_t result, union doca_data cookie, uint64_t rkey)
static doca_error_t mode_callback(void *param, void *config)
static doca_error_t rdmo_wireup_server(struct doca_urom_worker *worker, struct doca_pe *pe, int port, ucp_context_h *ucp_context, ucp_worker_h *server_ucp_worker, uint64_t *rq_id)
static doca_error_t rdmo_flush(ucp_worker_h client_ucp_worker, ucp_ep_h client_ucp_ep, int *flushed)
DOCA_LOG_REGISTER(UROM::RDMO::CORE)
static doca_error_t rdmo_mr_reg(ucp_worker_h server_ucp_worker, struct doca_urom_worker *worker, struct doca_pe *pe, ucp_context_h ucp_context, void *buf, size_t len, ucp_mem_h *memh, uint64_t *rkey)
doca_error_t rdmo_server(char *device_name)
static doca_error_t server_exchange(int port, void *loc_data, size_t loc_datalen, void **rem_data, size_t *rem_datalen)
static doca_error_t rdmo_server_urom_destroy(struct doca_pe *pe, struct doca_urom_service *service, struct doca_urom_worker *worker, struct doca_dev *dev)
static doca_error_t cs_barrier(const char *server_name, int port, enum rdmo_mode mode)
static void mr_deregister_finished(doca_error_t result, union doca_data cookie, uint64_t rkey)
static void rdmo_ucp_client_destroy(ucp_ep_h client_ucp_ep, ucp_worker_h ucp_worker, ucp_context_h ucp_context)
rdmo_mode
@ RDMO_MODE_UNKNOWN
@ RDMO_MODE_CLIENT
@ RDMO_MODE_SERVER
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: utils.c:123