NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
rdma_write_responder_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2023 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 <doca_error.h>
27 #include <doca_log.h>
28 #include <doca_buf_inventory.h>
29 #include <doca_buf.h>
30 #include <doca_ctx.h>
31 
32 #include "rdma_common.h"
33 
34 #define MAX_BUFF_SIZE (256) /* Maximum DOCA buffer size */
35 
36 DOCA_LOG_REGISTER(RDMA_WRITE_RESPONDER::SAMPLE);
37 
38 /*
39  * Write the connection details and the mmap details for the requester to read,
40  * and read the connection details of the requester
41  * In DC transport mode it is only needed to read the remote connection details
42  *
43  * @cfg [in]: Configuration parameters
44  * @resources [in/out]: RDMA resources
45  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
46  */
48 {
50 
51  /* Write the RDMA connection details */
52  result = write_file(cfg->local_connection_desc_path,
55  if (result != DOCA_SUCCESS) {
56  DOCA_LOG_ERR("Failed to write the RDMA connection details: %s", doca_error_get_descr(result));
57  return result;
58  }
59 
60  /* Write the mmap connection details */
61  result = write_file(cfg->remote_resource_desc_path,
62  (char *)resources->mmap_descriptor,
64  if (result != DOCA_SUCCESS) {
65  DOCA_LOG_ERR("Failed to write the RDMA mmap details: %s", doca_error_get_descr(result));
66  return result;
67  }
68 
69  DOCA_LOG_INFO("You can now copy %s and %s to the requester",
70  cfg->local_connection_desc_path,
71  cfg->remote_resource_desc_path);
72 
73  if (cfg->transport_type == DOCA_RDMA_TRANSPORT_TYPE_DC) {
74  return result;
75  }
76  DOCA_LOG_INFO("Please copy %s from the requester and then press enter", cfg->remote_connection_desc_path);
77 
78  /* Wait for enter */
80 
81  /* Read the remote RDMA connection details */
82  result = read_file(cfg->remote_connection_desc_path,
85  if (result != DOCA_SUCCESS)
86  DOCA_LOG_ERR("Failed to read the remote RDMA connection details: %s", doca_error_get_descr(result));
87 
88  return result;
89 }
90 
91 /*
92  * Export and receive connection details, and connect to the remote RDMA
93  *
94  * @resources [in]: RDMA resources
95  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
96  */
98 {
100 
101  if (resources->cfg->use_rdma_cm == true)
102  return rdma_cm_connect(resources);
103 
104  /* Export RDMA connection details */
108  &(resources->connections[0]));
109  if (result != DOCA_SUCCESS) {
110  DOCA_LOG_ERR("Failed to export RDMA: %s", doca_error_get_descr(result));
111  return result;
112  }
113 
114  /* Export RDMA mmap */
117  (const void **)&(resources->mmap_descriptor),
119  if (result != DOCA_SUCCESS) {
120  DOCA_LOG_ERR("Failed to export DOCA mmap for RDMA: %s", doca_error_get_descr(result));
121  return result;
122  }
123 
124  /* write and read connection details from the requester */
126  if (result != DOCA_SUCCESS)
127  DOCA_LOG_ERR("Failed to write and read connection details from the requester: %s",
129 
131  return result;
132  }
133  /* Connect RDMA */
137  resources->connections[0]);
138  if (result != DOCA_SUCCESS)
139  DOCA_LOG_ERR("Failed to connect the responder's RDMA to the requester's RDMA: %s",
141 
142  return result;
143 }
144 
145 /*
146  * Responder wait for requester to finish
147  *
148  * @resources [in]: RDMA resources
149  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
150  */
152 {
154  char buffer[MAX_BUFF_SIZE];
155 
156  /* Wait for enter which means that the requester has finished writing */
157  DOCA_LOG_INFO("Wait till the requester has finished writing and press enter");
158  wait_for_enter();
159 
160  /* Initialize buffer to zeros */
161  memset(buffer, 0, MAX_BUFF_SIZE);
162 
163  /* Read the data that was written on the mmap */
164  strncpy(buffer, resources->mmap_memrange, MAX_BUFF_SIZE - 1);
165 
166  /* Check if the buffer is null terminated and of legal size */
167  if (strnlen(buffer, MAX_BUFF_SIZE) == MAX_BUFF_SIZE) {
168  DOCA_LOG_ERR("The message that was written by the requester exceeds buffer size %d", MAX_BUFF_SIZE);
170  goto length_check_error;
171  }
172 
173  DOCA_LOG_INFO("Requester has written: \"%s\"", buffer);
174 
175 length_check_error:
176  if (resources->cfg->use_rdma_cm == true) {
178  if (result != DOCA_SUCCESS) {
179  DOCA_LOG_ERR("Failed to disconnect RDMA connection: %s", doca_error_get_descr(result));
180  }
181  }
182 
184 
185  return result;
186 }
187 
188 /*
189  * RDMA write responder state change callback
190  * This function represents the state machine for this RDMA program
191  *
192  * @user_data [in]: doca_data from the context
193  * @ctx [in]: DOCA context
194  * @prev_state [in]: Previous DOCA context state
195  * @next_state [in]: Next DOCA context state
196  */
197 static void rdma_write_responder_state_change_callback(const union doca_data user_data,
198  struct doca_ctx *ctx,
199  enum doca_ctx_states prev_state,
200  enum doca_ctx_states next_state)
201 {
202  struct rdma_resources *resources = (struct rdma_resources *)user_data.ptr;
203  struct rdma_config *cfg = resources->cfg;
205  (void)prev_state;
206  (void)ctx;
207 
208  switch (next_state) {
210  DOCA_LOG_INFO("RDMA context entered starting state");
211  break;
213  DOCA_LOG_INFO("RDMA context is running");
214 
216  if (result != DOCA_SUCCESS) {
217  DOCA_LOG_ERR("rdma_write_responder_export_and_connect() failed: %s",
219  break;
220  } else
221  DOCA_LOG_INFO("RDMA context finished initialization");
222 
223  if (cfg->use_rdma_cm == true)
224  break;
225 
227  break;
236  DOCA_LOG_INFO("RDMA context entered into stopping state. Any inflight tasks will be flushed");
237  break;
238  case DOCA_CTX_STATE_IDLE:
239  DOCA_LOG_INFO("RDMA context has been stopped");
240 
241  /* We can stop progressing the PE */
242  resources->run_pe_progress = false;
243  break;
244  default:
245  break;
246  }
247 
248  /* If something failed - update that an error was encountered and stop the ctx */
249  if (result != DOCA_SUCCESS) {
251  (void)doca_ctx_stop(ctx);
252  }
253 }
254 
255 /*
256  * Responder side of the RDMA write
257  *
258  * @cfg [in]: Configuration parameters
259  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
260  */
262 {
263  struct rdma_resources resources = {0};
264  union doca_data ctx_user_data = {0};
265  const uint32_t mmap_permissions = DOCA_ACCESS_FLAG_LOCAL_READ_WRITE | DOCA_ACCESS_FLAG_RDMA_WRITE;
266  const uint32_t rdma_permissions = DOCA_ACCESS_FLAG_RDMA_WRITE;
267  doca_error_t result, tmp_result;
268  struct timespec ts = {
269  .tv_sec = 0,
270  .tv_nsec = SLEEP_IN_NANOS,
271  };
272 
273  /* Allocating resources */
274  result = allocate_rdma_resources(cfg, mmap_permissions, rdma_permissions, NULL, &resources);
275  if (result != DOCA_SUCCESS) {
276  DOCA_LOG_ERR("Failed to allocate RDMA Resources: %s", doca_error_get_descr(result));
277  return result;
278  }
279 
281  if (result != DOCA_SUCCESS) {
282  DOCA_LOG_ERR("Unable to set state change callback for RDMA context: %s", doca_error_get_descr(result));
283  goto destroy_resources;
284  }
285 
286  /* Include the program's resources in user data of context to be used in callbacks */
287  ctx_user_data.ptr = &(resources);
289  if (result != DOCA_SUCCESS) {
290  DOCA_LOG_ERR("Failed to set context user data: %s", doca_error_get_descr(result));
291  goto destroy_resources;
292  }
293 
294  if (cfg->use_rdma_cm == true) {
295  resources.is_requester = false;
299  /* need_send_mmap_info */ true,
300  /* need_recv_mmap_info */ false);
301  if (result != DOCA_SUCCESS) {
302  DOCA_LOG_ERR("Failed to config RDMA CM callbacks and negotiation functions: %s",
304  goto destroy_resources;
305  }
306  }
307 
308  /* Start RDMA context */
310  if (result != DOCA_SUCCESS) {
311  DOCA_LOG_ERR("Failed to start RDMA context: %s", doca_error_get_descr(result));
312  goto destroy_resources;
313  }
314 
315  /*
316  * Run the progress engine which will run the state machine defined in
317  * rdma_write_responder_state_change_callback() When the requester finishes writing, the user will signal to
318  * stop running the progress engine.
319  */
320  while (resources.run_pe_progress) {
321  if (doca_pe_progress(resources.pe) == 0)
322  nanosleep(&ts, &ts);
323  }
324 
325  /* Assign the result we update in the callbacks */
327 
328 destroy_resources:
329  if (resources.buf_inventory != NULL) {
331  if (tmp_result != DOCA_SUCCESS) {
332  DOCA_LOG_ERR("Failed to stop DOCA buffer inventory: %s", doca_error_get_descr(tmp_result));
333  DOCA_ERROR_PROPAGATE(result, tmp_result);
334  }
336  if (tmp_result != DOCA_SUCCESS) {
337  DOCA_LOG_ERR("Failed to destroy DOCA buffer inventory: %s", doca_error_get_descr(tmp_result));
338  DOCA_ERROR_PROPAGATE(result, tmp_result);
339  }
340  }
341  tmp_result = destroy_rdma_resources(&resources, cfg);
342  if (tmp_result != DOCA_SUCCESS) {
343  DOCA_LOG_ERR("Failed to destroy DOCA RDMA resources: %s", doca_error_get_descr(tmp_result));
344  DOCA_ERROR_PROPAGATE(result, tmp_result);
345  }
346  return result;
347 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
#define SLEEP_IN_NANOS
Definition: comch_utils.c:40
doca_error_t destroy_rdma_resources(struct rdma_resources *resources)
Definition: rdma_common.c:470
void wait_for_enter(void)
Definition: rdma_common.c:1771
doca_error_t write_file(const char *file_path, const char *string, size_t string_len)
Definition: rdma_common.c:1087
doca_error_t rdma_cm_connect(struct rdma_resources *resources)
Definition: rdma_common.c:1172
doca_error_t allocate_rdma_resources(struct rdma_config *cfg, const uint32_t mmap_permissions, const uint32_t rdma_permissions, task_check func, struct rdma_resources *resources)
Definition: rdma_common.c:758
doca_error_t config_rdma_cm_callback_and_negotiation_task(struct rdma_resources *resources, bool need_send_task, bool need_recv_task)
Definition: rdma_common.c:1720
doca_error_t rdma_cm_disconnect(struct rdma_resources *resources)
Definition: rdma_common.c:1244
struct rdma_resources resources
DOCA_STABLE doca_error_t doca_buf_inventory_destroy(struct doca_buf_inventory *inventory)
Destroy buffer inventory structure.
DOCA_STABLE doca_error_t doca_buf_inventory_stop(struct doca_buf_inventory *inventory)
Stop element retrieval from inventory.
DOCA_STABLE doca_error_t doca_ctx_start(struct doca_ctx *ctx)
Finalizes all configurations, and starts the DOCA CTX.
DOCA_STABLE doca_error_t doca_ctx_set_state_changed_cb(struct doca_ctx *ctx, doca_ctx_state_changed_callback_t cb)
Set state changed callback.
DOCA_STABLE doca_error_t doca_ctx_set_user_data(struct doca_ctx *ctx, union doca_data user_data)
set user data to context
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_STOPPING
Definition: doca_ctx.h:106
@ DOCA_CTX_STATE_IDLE
Definition: doca_ctx.h:88
@ DOCA_CTX_STATE_RUNNING
Definition: doca_ctx.h:98
#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_SUCCESS
Definition: doca_error.h:38
#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_export_rdma(struct doca_mmap *mmap, const struct doca_dev *dev, const void **export_desc, size_t *export_desc_len)
Compose memory map representation for later import with doca_mmap_create_from_export() for one of the...
DOCA_STABLE uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_EXPERIMENTAL doca_error_t doca_rdma_export(struct doca_rdma *rdma, const void **local_rdma_conn_details, size_t *local_rdma_conn_details_size, struct doca_rdma_connection **rdma_connection)
Export doca_rdma connection details object The doca_rdma_conn_details are used in doca_rdma_connect()...
DOCA_EXPERIMENTAL doca_error_t doca_rdma_connect(struct doca_rdma *rdma, const void *remote_rdma_conn_details, size_t remote_rdma_conn_details_size, struct doca_rdma_connection *rdma_connection)
Connect to remote doca_rdma peer. Can only be called when the ctx is in DOCA_CTX_STATE_STARTING state...
@ DOCA_RDMA_TRANSPORT_TYPE_DC
Definition: doca_rdma.h:47
@ DOCA_ACCESS_FLAG_LOCAL_READ_WRITE
Definition: doca_types.h:83
@ DOCA_ACCESS_FLAG_RDMA_WRITE
Definition: doca_types.h:85
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
#define MAX_BUFF_SIZE
static doca_error_t rdma_write_responder_export_and_connect(struct rdma_resources *resources)
DOCA_LOG_REGISTER(RDMA_WRITE_RESPONDER::SAMPLE)
static void rdma_write_responder_state_change_callback(const union doca_data user_data, struct doca_ctx *ctx, enum doca_ctx_states prev_state, enum doca_ctx_states next_state)
doca_error_t rdma_write_responder(struct rdma_config *cfg)
static doca_error_t responder_wait_for_requester_finish(struct rdma_resources *resources)
static doca_error_t write_read_connection(struct rdma_config *cfg, struct rdma_resources *resources)
enum doca_rdma_transport_type transport_type
Definition: rdma_common.h:90
bool use_rdma_cm
Definition: rdma_common.h:71
size_t remote_rdma_conn_descriptor_size
Definition: rdma_common.h:127
doca_error_t first_encountered_error
Definition: rdma_common.h:132
bool require_remote_mmap
Definition: rdma_common.h:152
struct doca_ctx * rdma_ctx
Definition: rdma_common.h:85
const void * mmap_descriptor
Definition: rdma_common.h:118
prepare_and_submit_task_fn task_fn
Definition: rdma_common.h:150
const void * rdma_conn_descriptor
Definition: rdma_common.h:124
void * remote_rdma_conn_descriptor
Definition: rdma_common.h:126
struct doca_rdma_connection * connections[MAX_NUM_CONNECTIONS]
Definition: rdma_common.h:138
struct rdma_config * cfg
Definition: rdma_common.h:80
struct doca_rdma * rdma
Definition: rdma_common.h:83
size_t mmap_descriptor_size
Definition: rdma_common.h:119
struct doca_pe * pe
Definition: rdma_common.h:86
struct doca_mmap * mmap
Definition: rdma_common.h:112
bool run_pe_progress
Definition: rdma_common.h:133
struct doca_dev * doca_device
Definition: rdma_common.h:81
struct doca_buf_inventory * buf_inventory
Definition: rdma_common.h:117
size_t rdma_conn_descriptor_size
Definition: rdma_common.h:125
char * mmap_memrange
Definition: rdma_common.h:116
Convenience type for representing opaque data.
Definition: doca_types.h:56
void * ptr
Definition: doca_types.h:57
struct upf_accel_ctx * ctx
doca_error_t read_file(char const *path, char **out_bytes, size_t *out_bytes_len)
Definition: utils.c:56