NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
sync_event_remote_pci_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 <unistd.h>
27 
28 #include <doca_log.h>
29 #include <doca_comch.h>
30 #include <doca_sync_event.h>
31 
32 #include <common.h>
33 
34 #include "common_common.h"
35 
36 DOCA_LOG_REGISTER(SYNC_EVENT::SAMPLE);
37 
38 /* Information exported from local sample via comch message */
39 struct export_blob {
40  char se_blob[SYNC_EVENT_CC_MAX_MSG_SIZE]; /* Data received via comch */
41  size_t se_blob_sz; /* Length of data received */
42 };
43 
44 /*
45  * DOCA device with create-doca-sync-event-from-export capability filter callback
46  *
47  * @devinfo [in]: doca_devinfo
48  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
49  */
50 static inline doca_error_t sync_event_get_create_from_export_supported(struct doca_devinfo *devinfo)
51 {
53 }
54 
55 /*
56  * Initialize sample's DOCA Sync Event
57  *
58  * @export_data [in]: data to be populated by comch message callback
59  * @se_rt_objs [in/out]: sample's runtime resources
60  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
61  */
62 static doca_error_t se_init(struct export_blob *export_data, struct sync_event_runtime_objects *se_rt_objs)
63 {
65  int timeout = SYNC_EVENT_CC_TIMEOUT_SEC;
66 
67  DOCA_LOG_INFO("Listening");
68  /* Wait for comch callback to populate the export data fields */
69  while (export_data->se_blob_sz == 0) {
70  if (timeout == 0) {
71  DOCA_LOG_ERR("Failed to retrieve set task progress: timeout");
72  return DOCA_ERROR_TIME_OUT;
73  }
74  sleep(1);
75  timeout--;
76  (void)doca_pe_progress(se_rt_objs->comch_pe);
77  }
78 
79  DOCA_LOG_INFO("Received blob from remote side");
80 
82  (const uint8_t *)export_data->se_blob,
83  export_data->se_blob_sz,
84  &se_rt_objs->se);
85  if (result != DOCA_SUCCESS) {
86  DOCA_LOG_ERR("Failed to create DOCA Sync Event from export: %s", doca_error_get_descr(result));
87  return result;
88  }
89 
90  return DOCA_SUCCESS;
91 }
92 
93 /*
94  * Communicate with remote side through DOCA Sync Event in synchronous mode
95  *
96  * @se_cfg [in]: user configuration represents command line arguments
97  * @se_rt_objs [in]: sample's runtime resources
98  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
99  */
101  struct sync_event_runtime_objects *se_rt_objs)
102 {
104  uint64_t fetched = 0;
105 
106  uint64_t se_value = 1;
107 
108  DOCA_LOG_INFO("Waiting for sync event to be signaled from remote side");
109  result = doca_sync_event_wait_eq(se_rt_objs->se, se_value, UINT64_MAX);
110  if (result != DOCA_SUCCESS) {
111  DOCA_LOG_ERR("Failed to wait for sync event: %s", doca_error_get_descr(result));
112  return result;
113  }
114 
115  se_value++;
116 
117  DOCA_LOG_INFO("Signaling sync event for remote side");
118  if (se_cfg->is_update_atomic)
119  result = doca_sync_event_update_add(se_rt_objs->se, 1, &fetched);
120  else
121  result = doca_sync_event_update_set(se_rt_objs->se, se_value);
122 
123  if (result != DOCA_SUCCESS) {
124  DOCA_LOG_ERR("Failed to signal sync event: %s", doca_error_get_descr(result));
125  return result;
126  }
127 
128  DOCA_LOG_INFO("Done");
129 
130  return DOCA_SUCCESS;
131 }
132 
133 /*
134  * Communicate with remote side through DOCA Sync Event in asynchronous mode
135  *
136  * @se_cfg [in]: user configuration represents command line arguments
137  * @se_rt_objs [in]: sample's runtime resources
138  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
139  */
141  struct sync_event_runtime_objects *se_rt_objs)
142 {
144  struct doca_sync_event_task_wait_eq *wait_eq_task;
145  struct doca_sync_event_task_notify_add *notify_add_task;
146  struct doca_sync_event_task_notify_set *notify_set_task;
147  uint64_t fetched = 0;
148  union doca_data user_data;
149 
150  user_data.u64 = 0;
151 
152  uint64_t se_value = 1;
153 
154  result =
155  doca_sync_event_task_wait_eq_alloc_init(se_rt_objs->se, se_value, UINT64_MAX, user_data, &wait_eq_task);
156  if (result != DOCA_SUCCESS)
157  return result;
158 
159  DOCA_LOG_INFO("Waiting for sync event to be signaled from remote side");
161  if (result != DOCA_SUCCESS)
162  return result;
163 
164  se_value++;
165 
166  DOCA_LOG_INFO("Signaling sync event for remote side");
167  if (se_cfg->is_update_atomic) {
169  1,
170  &fetched,
171  user_data,
172  &notify_add_task);
173  if (result != DOCA_SUCCESS)
174  return result;
175 
178 
180 
181  if (result != DOCA_SUCCESS)
182  return result;
183  } else {
185  se_value,
186  user_data,
187  &notify_set_task);
188  if (result != DOCA_SUCCESS)
189  return result;
190 
193 
195 
196  if (result != DOCA_SUCCESS)
197  return result;
198  }
199 
200  DOCA_LOG_INFO("Done");
201 
203 
204  return DOCA_SUCCESS;
205 }
206 
207 /*
208  * Callback event comch messages
209  *
210  * @event [in]: message receive event
211  * @recv_buffer [in]: array of bytes containing the message data
212  * @msg_len [in]: number of bytes in the recv_buffer
213  * @comch_connection [in]: comm channel connection over which the event occurred
214  */
215 static void comch_recv_event_cb(struct doca_comch_event_msg_recv *event,
216  uint8_t *recv_buffer,
217  uint32_t msg_len,
218  struct doca_comch_connection *comch_connection)
219 {
220  struct sync_event_runtime_objects *se_rt_objs;
221  struct export_blob *recv_data;
222  union doca_data ctx_user_data;
223  struct doca_ctx *ctx;
225 #ifdef DOCA_ARCH_DPU
226  struct doca_comch_server *server = doca_comch_server_get_server_ctx(comch_connection);
227 
228  ctx = doca_comch_server_as_ctx(server);
229 #else
230  struct doca_comch_client *client = doca_comch_client_get_client_ctx(comch_connection);
231 
232  ctx = doca_comch_client_as_ctx(client);
233 #endif
234 
235  (void)event;
236 
237  result = doca_ctx_get_user_data(ctx, &ctx_user_data);
238  if (result != DOCA_SUCCESS) {
239  DOCA_LOG_ERR("Failed to get user data from doca context: %s", doca_error_get_descr(result));
240  return;
241  }
242 
243  se_rt_objs = (struct sync_event_runtime_objects *)ctx_user_data.ptr;
244  recv_data = (struct export_blob *)se_rt_objs->user_data;
245 
246  memcpy(recv_data->se_blob, recv_buffer, msg_len);
247  recv_data->se_blob_sz = msg_len;
248 }
249 
250 /*
251  * Sample's logic
252  *
253  * @se_cfg [in]: user configuration represents command line arguments
254  * @se_rt_objs [in/out]: sample's runtime resources
255  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise
256  */
258 {
259  struct export_blob received_data = {0};
261 
264  &se_rt_objs->dev);
265  if (result != DOCA_SUCCESS) {
266  sync_event_tear_down(se_rt_objs);
267  return result;
268  }
269 
270 #ifdef DOCA_ARCH_DPU
273  se_cfg->rep_pci_addr,
274  &se_rt_objs->rep);
275  if (result != DOCA_SUCCESS) {
276  sync_event_tear_down(se_rt_objs);
277  return result;
278  }
279 #endif
280 
281  result = sync_event_config_validate(se_cfg, se_rt_objs);
282  if (result != DOCA_SUCCESS) {
283  sync_event_tear_down(se_rt_objs);
284  return result;
285  }
286 
287  /* Set sample specific cb message recv callback even for comch */
289 
290  /* Set user data to populate in callback on message recv */
291  se_rt_objs->user_data = &received_data;
292 
293  result = sync_event_cc_handshake(se_rt_objs);
294  if (result != DOCA_SUCCESS) {
295  sync_event_tear_down(se_rt_objs);
296  return result;
297  }
298 
299  result = se_init(&received_data, se_rt_objs);
300  if (result != DOCA_SUCCESS) {
301  sync_event_tear_down(se_rt_objs);
302  return result;
303  }
304 
305  if (se_cfg->is_async_mode)
306  result = sync_event_start_async(se_cfg, se_rt_objs);
307  else
308  result = doca_sync_event_start(se_rt_objs->se);
309 
310  if (result != DOCA_SUCCESS) {
311  sync_event_tear_down(se_rt_objs);
312  return result;
313  }
314 
315  if (se_cfg->is_async_mode)
316  result = se_communicate_async(se_cfg, se_rt_objs);
317  else
318  result = se_communicate_sync(se_cfg, se_rt_objs);
319 
320  sync_event_tear_down(se_rt_objs);
321 
322  return result;
323 }
int32_t result
doca_error_t open_doca_device_rep_with_pci(struct doca_dev *local, enum doca_devinfo_rep_filter filter, const char *pci_addr, struct doca_dev_rep **retval)
Definition: common.c:267
void sync_event_tear_down(struct sync_event_runtime_objects *se_rt_objs)
doca_error_t sync_event_async_task_submit(struct sync_event_runtime_objects *se_rt_objs, struct doca_task *se_task)
doca_error_t sync_event_start_async(const struct sync_event_config *se_cfg, struct sync_event_runtime_objects *se_rt_objs)
doca_error_t sync_event_cc_handshake(struct sync_event_runtime_objects *se_rt_objs)
doca_error_t sync_event_config_validate(const struct sync_event_config *se_cfg, const struct sync_event_runtime_objects *se_rt_objs)
#define SYNC_EVENT_CC_MAX_MSG_SIZE
Definition: common_common.h:37
#define SYNC_EVENT_CC_TIMEOUT_SEC
Definition: common_common.h:41
static doca_error_t open_doca_device_with_pci(const char *pcie_value, struct doca_dev **retval)
Definition: device.c:43
DOCA_STABLE struct doca_comch_server * doca_comch_server_get_server_ctx(const struct doca_comch_connection *connection)
DOCA_STABLE struct doca_ctx * doca_comch_client_as_ctx(struct doca_comch_client *comch_client)
DOCA_STABLE struct doca_comch_client * doca_comch_client_get_client_ctx(const struct doca_comch_connection *connection)
DOCA_STABLE struct doca_ctx * doca_comch_server_as_ctx(struct doca_comch_server *comch_server)
DOCA_STABLE doca_error_t doca_ctx_get_user_data(const struct doca_ctx *ctx, union doca_data *user_data)
get user data from context
@ DOCA_DEVINFO_REP_FILTER_NET
Definition: doca_dev.h:67
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_TIME_OUT
Definition: doca_error.h:47
@ 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 uint8_t doca_pe_progress(struct doca_pe *pe)
Run the progress engine.
DOCA_STABLE void doca_task_free(struct doca_task *task)
Free a task back to where it was allocated from.
DOCA_EXPERIMENTAL struct doca_task * doca_sync_event_task_notify_set_as_doca_task(struct doca_sync_event_task_notify_set *task)
Convert a DOCA Sync Event notify-set task to a DOCA Task.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_create_from_export(struct doca_dev *dev, const uint8_t *data, size_t sz, struct doca_sync_event **event)
Create a Sync Event handle from an export.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_start(struct doca_sync_event *event)
Start a Sync Event to be operate as stand-alone DOCA Core object only.
DOCA_EXPERIMENTAL struct doca_task * doca_sync_event_task_wait_eq_as_doca_task(struct doca_sync_event_task_wait_eq *task)
Convert a DOCA Sync Event wait-equal task to a DOCA Task.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_update_add(struct doca_sync_event *event, uint64_t value, uint64_t *fetched)
Atomically increase the value of a Sync Event by some value synchronously.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_task_wait_eq_alloc_init(struct doca_sync_event *event, uint64_t wait_val, uint64_t mask, union doca_data user_data, struct doca_sync_event_task_wait_eq **task)
Allocate a DOCA Sync Event wait-equal task.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_task_notify_add_alloc_init(struct doca_sync_event *event, uint64_t inc_val, uint64_t *fetched_val_ptr, union doca_data user_data, struct doca_sync_event_task_notify_add **task)
Allocate a DOCA Sync Event notify-add task.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_update_set(struct doca_sync_event *event, uint64_t value)
Set the value of a Sync Event to some value synchronously.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_cap_is_create_from_export_supported(const struct doca_devinfo *devinfo)
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_task_notify_set_alloc_init(struct doca_sync_event *event, uint64_t set_val, union doca_data user_data, struct doca_sync_event_task_notify_set **task)
Allocate a DOCA Sync Event notify-set task.
DOCA_EXPERIMENTAL doca_error_t doca_sync_event_wait_eq(struct doca_sync_event *event, uint64_t value, uint64_t mask)
Wait for the value of a Sync Event to be equal to some value synchronously in a busy wait manner.
DOCA_EXPERIMENTAL struct doca_task * doca_sync_event_task_notify_add_as_doca_task(struct doca_sync_event_task_notify_add *task)
Convert a DOCA Sync Event notify-add task to a DOCA Task.
char se_blob[SYNC_EVENT_CC_MAX_MSG_SIZE]
char rep_pci_addr[DOCA_DEVINFO_REP_PCI_ADDR_SIZE]
Definition: common_common.h:48
char dev_pci_addr[DOCA_DEVINFO_PCI_ADDR_SIZE]
Definition: common_common.h:47
struct doca_dev * dev
Definition: common_common.h:56
struct doca_pe * comch_pe
Definition: common_common.h:64
doca_comch_event_msg_recv_cb_t comch_recv_event_cb
Definition: common_common.h:70
struct doca_sync_event * se
Definition: common_common.h:58
struct doca_dev_rep * rep
Definition: common_common.h:57
static doca_error_t se_init(struct export_blob *export_data, struct sync_event_runtime_objects *se_rt_objs)
static doca_error_t sync_event_get_create_from_export_supported(struct doca_devinfo *devinfo)
static doca_error_t se_communicate_sync(const struct sync_event_config *se_cfg, struct sync_event_runtime_objects *se_rt_objs)
doca_error_t sync_event_run(const struct sync_event_config *se_cfg, struct sync_event_runtime_objects *se_rt_objs)
static void comch_recv_event_cb(struct doca_comch_event_msg_recv *event, uint8_t *recv_buffer, uint32_t msg_len, struct doca_comch_connection *comch_connection)
DOCA_LOG_REGISTER(SYNC_EVENT::SAMPLE)
static doca_error_t se_communicate_async(const struct sync_event_config *se_cfg, struct sync_event_runtime_objects *se_rt_objs)
Convenience type for representing opaque data.
Definition: doca_types.h:56
uint64_t u64
Definition: doca_types.h:58
void * ptr
Definition: doca_types.h:57
struct upf_accel_ctx * ctx