NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
rdma_read_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 DOCA_LOG_REGISTER(RDMA_READ_RESPONDER::SAMPLE);
35 
36 /*
37  * Write the connection details and the mmap details for the requester to read,
38  * and read the connection details of the requester
39  * In DC transport mode it is only needed to read the remote connection details
40  *
41  * @cfg [in]: Configuration parameters
42  * @resources [in/out]: RDMA resources
43  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
44  */
46 {
48 
49  /* Write the RDMA connection details */
50  result = write_file(cfg->local_connection_desc_path,
53  if (result != DOCA_SUCCESS) {
54  DOCA_LOG_ERR("Failed to write the RDMA connection details: %s", doca_error_get_descr(result));
55  return result;
56  }
57 
58  /* Write the RDMA connection details */
59  result = write_file(cfg->remote_resource_desc_path,
60  (char *)resources->mmap_descriptor,
62  if (result != DOCA_SUCCESS) {
63  DOCA_LOG_ERR("Failed to write the RDMA mmap details: %s", doca_error_get_descr(result));
64  return result;
65  }
66 
67  DOCA_LOG_INFO("You can now copy %s and %s to the requester",
68  cfg->local_connection_desc_path,
69  cfg->remote_resource_desc_path);
70 
71  if (cfg->transport_type == DOCA_RDMA_TRANSPORT_TYPE_DC) {
72  return result;
73  }
74 
75  DOCA_LOG_INFO("Please copy %s from the requester and then press enter", cfg->remote_connection_desc_path);
76 
77  /* Wait for enter */
79 
80  /* Read the remote RDMA connection details */
81  result = read_file(cfg->remote_connection_desc_path,
84  if (result != DOCA_SUCCESS)
85  DOCA_LOG_ERR("Failed to read the remote RDMA connection details: %s", doca_error_get_descr(result));
86 
87  return result;
88 }
89 
90 /*
91  * Export and receive connection details, and connect to the remote RDMA
92  *
93  * @resources [in]: RDMA resources
94  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
95  */
97 {
98  size_t read_string_len = strlen(resources->cfg->read_string) + 1;
99  struct rdma_config *cfg = resources->cfg;
101 
102  if (cfg->use_rdma_cm == true)
103  return rdma_cm_connect(resources);
104 
105  /* Export RDMA connection details */
109  &(resources->connections[0]));
110  if (result != DOCA_SUCCESS) {
111  DOCA_LOG_ERR("Failed to export RDMA: %s", doca_error_get_descr(result));
112  return result;
113  }
114 
115  /* Copy the read string to the mmap memory range */
116  strncpy(resources->mmap_memrange, resources->cfg->read_string, read_string_len);
117 
118  /* Export RDMA mmap */
121  (const void **)&(resources->mmap_descriptor),
123  if (result != DOCA_SUCCESS) {
124  DOCA_LOG_ERR("Failed to export DOCA mmap for RDMA: %s", doca_error_get_descr(result));
125  return result;
126  }
127 
128  /* write and read connection details from the requester */
130  if (result != DOCA_SUCCESS) {
131  DOCA_LOG_ERR("Failed to write and read connection details from the requester: %s",
133  return result;
134  }
135 
136  if (cfg->transport_type == DOCA_RDMA_TRANSPORT_TYPE_DC) {
137  return result;
138  }
139  /* Connect RDMA */
143  resources->connections[0]);
144  if (result != DOCA_SUCCESS)
145  DOCA_LOG_ERR("Failed to connect the responder's RDMA to the requester's RDMA: %s",
147 
148  return result;
149 }
150 
151 /*
152  * RDMA read responder state change callback
153  * This function represents the state machine for this RDMA program
154  *
155  * @user_data [in]: doca_data from the context
156  * @ctx [in]: DOCA context
157  * @prev_state [in]: Previous DOCA context state
158  * @next_state [in]: Next DOCA context state
159  */
160 static void rdma_read_responder_state_change_callback(const union doca_data user_data,
161  struct doca_ctx *ctx,
162  enum doca_ctx_states prev_state,
163  enum doca_ctx_states next_state)
164 {
165  struct rdma_resources *resources = (struct rdma_resources *)user_data.ptr;
166  struct rdma_config *cfg = resources->cfg;
168  (void)prev_state;
169 
170  switch (next_state) {
172  DOCA_LOG_INFO("RDMA context entered starting state");
173  break;
175  DOCA_LOG_INFO("RDMA context is running");
176 
178  if (result != DOCA_SUCCESS) {
179  DOCA_LOG_ERR("rdma_read_responder_export_and_connect() failed: %s",
181  break;
182  } else
183  DOCA_LOG_INFO("RDMA context finished initialization");
184 
185  if (cfg->use_rdma_cm == true)
186  break;
187 
188  /* Wait for enter which means that the requester has finished reading */
189  DOCA_LOG_INFO("Wait till the requester has finished reading and press enter");
190  wait_for_enter();
191 
192  /* Stop context */
194  break;
203  DOCA_LOG_INFO("RDMA context entered into stopping state. Any inflight tasks will be flushed");
204  break;
205  case DOCA_CTX_STATE_IDLE:
206  DOCA_LOG_INFO("RDMA context has been stopped");
207 
208  /* We can stop progressing the PE */
209  resources->run_pe_progress = false;
210  break;
211  default:
212  break;
213  }
214 
215  /* If something failed - update that an error was encountered and stop the ctx */
216  if (result != DOCA_SUCCESS) {
218  (void)doca_ctx_stop(ctx);
219  }
220 }
221 
222 /*
223  * Responder wait for requester to finish
224  *
225  * @resources [in]: RDMA resources
226  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
227  */
229 {
231 
232  DOCA_LOG_INFO("Wait till the requester has finished reading and press enter");
233  wait_for_enter();
234 
235  if (resources->cfg->use_rdma_cm == true) {
237  if (result != DOCA_SUCCESS) {
238  DOCA_LOG_ERR("Failed to disconnect RDMA connection: %s", doca_error_get_descr(result));
239  return result;
240  }
241  }
242 
244  return DOCA_SUCCESS;
245 }
246 
247 /*
248  * Responder side of the RDMA read
249  *
250  * @cfg [in]: Configuration parameters
251  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
252  */
254 {
255  struct rdma_resources resources = {0};
256  union doca_data ctx_user_data = {0};
257  const uint32_t mmap_permissions = DOCA_ACCESS_FLAG_LOCAL_READ_WRITE | DOCA_ACCESS_FLAG_RDMA_READ;
258  const uint32_t rdma_permissions = DOCA_ACCESS_FLAG_RDMA_READ;
259  doca_error_t result, tmp_result;
260  struct timespec ts = {
261  .tv_sec = 0,
262  .tv_nsec = SLEEP_IN_NANOS,
263  };
264 
265  /* Allocating resources */
266  result = allocate_rdma_resources(cfg, mmap_permissions, rdma_permissions, NULL, &resources);
267  if (result != DOCA_SUCCESS) {
268  DOCA_LOG_ERR("Failed to allocate RDMA Resources: %s", doca_error_get_descr(result));
269  return result;
270  }
271 
273  if (result != DOCA_SUCCESS) {
274  DOCA_LOG_ERR("Unable to set state change callback for RDMA context: %s", doca_error_get_descr(result));
275  goto destroy_resources;
276  }
277 
278  /* Include the program's resources in user data of context to be used in callbacks */
279  ctx_user_data.ptr = &(resources);
281  if (result != DOCA_SUCCESS) {
282  DOCA_LOG_ERR("Failed to set context user data: %s", doca_error_get_descr(result));
283  goto destroy_resources;
284  }
285 
286  if (cfg->use_rdma_cm == true) {
287  resources.is_requester = false;
290  /* Copy the read string to the mmap memory range */
291  memset(resources.mmap_memrange, 0, strlen(resources.cfg->read_string) + 1);
293 
295  /* need_send_mmap_info */ true,
296  /* need_recv_mmap_info */ false);
297  if (result != DOCA_SUCCESS) {
298  DOCA_LOG_ERR("Failed to config RDMA CM callbacks and negotiation functions: %s",
300  goto destroy_resources;
301  }
302  }
303 
304  /* Start RDMA context */
306  if (result != DOCA_SUCCESS) {
307  DOCA_LOG_ERR("Failed to start RDMA context: %s", doca_error_get_descr(result));
308  goto destroy_resources;
309  }
310 
311  /*
312  * Run the progress engine which will run the state machine defined in
313  * rdma_read_responder_state_change_callback() When the context moves to idle, the context change callback call
314  * will signal to stop running the progress engine.
315  */
316  while (resources.run_pe_progress) {
317  if (doca_pe_progress(resources.pe) == 0)
318  nanosleep(&ts, &ts);
319  }
320 
321  /* Assign the result we update in the callbacks */
323 
324 destroy_resources:
325  if (resources.buf_inventory != NULL) {
327  if (tmp_result != DOCA_SUCCESS) {
328  DOCA_LOG_ERR("Failed to stop DOCA buffer inventory: %s", doca_error_get_descr(tmp_result));
329  DOCA_ERROR_PROPAGATE(result, tmp_result);
330  }
332  if (tmp_result != DOCA_SUCCESS) {
333  DOCA_LOG_ERR("Failed to destroy DOCA buffer inventory: %s", doca_error_get_descr(tmp_result));
334  DOCA_ERROR_PROPAGATE(result, tmp_result);
335  }
336  }
337  tmp_result = destroy_rdma_resources(&resources, cfg);
338  if (tmp_result != DOCA_SUCCESS) {
339  DOCA_LOG_ERR("Failed to destroy DOCA RDMA resources: %s", doca_error_get_descr(tmp_result));
340  DOCA_ERROR_PROPAGATE(result, tmp_result);
341  }
342  return result;
343 }
#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_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_READ
Definition: doca_types.h:84
const struct ip_frag_config * cfg
Definition: ip_frag_dp.c:0
static void rdma_read_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_read_responder(struct rdma_config *cfg)
DOCA_LOG_REGISTER(RDMA_READ_RESPONDER::SAMPLE)
static doca_error_t rdma_read_responder_export_and_connect(struct rdma_resources *resources)
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)
bool use_rdma_cm
Definition: rdma_common.h:71
char read_string[MAX_ARG_SIZE]
Definition: rdma_common.h:81
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