NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_mark_set_sample.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2022 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 <string.h>
27 #include <unistd.h>
28 
29 #include <doca_log.h>
30 #include <doca_flow.h>
31 #include <doca_bitfield.h>
32 
33 #include "flow_common.h"
34 #include <rte_byteorder.h>
35 #include <rte_ethdev.h>
36 #include <rte_mempool.h>
37 #include <rte_mbuf.h>
38 #include <rte_net.h>
39 #include "flow_mark_set.h"
40 
41 DOCA_LOG_REGISTER(FLOW_MARK_SET);
42 
43 #define MAX_PKTS 16
44 #define WAIT_SECS 15
45 
46 static doca_error_t create_match_pipe(struct doca_flow_port *port,
47  struct doca_flow_pipe **pipe,
48  struct doca_flow_pipe *fwd_pipe,
49  struct mark_set_config *app_cfg)
50 {
51  struct doca_flow_match match;
52  struct doca_flow_actions actions, *actions_arr[NB_ACTIONS_ARR];
53  struct doca_flow_fwd fwd;
54  struct doca_flow_pipe_cfg *pipe_cfg;
56 
57  memset(&match, 0, sizeof(match));
58  memset(&actions, 0, sizeof(actions));
59  memset(&fwd, 0, sizeof(fwd));
60 
61  match.parser_meta.outer_l3_type = DOCA_HTOBE32(0xffffffff);
63  match.outer.ip4.src_ip = BE_IPV4_ADDR(255, 255, 255, 255);
64  if (app_cfg->action_changeable)
65  actions.meta.mark = UINT32_MAX;
66  else
67  actions.meta.mark = DOCA_HTOBE32(app_cfg->mark_value);
68 
69  actions_arr[0] = &actions;
70 
71  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
72  if (result != DOCA_SUCCESS) {
73  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
74  return result;
75  }
76 
77  result = set_flow_pipe_cfg(pipe_cfg, "MATCH_PIPE", DOCA_FLOW_PIPE_BASIC, true);
78  if (result != DOCA_SUCCESS) {
79  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
80  goto destroy_pipe_cfg;
81  }
82  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
83  if (result != DOCA_SUCCESS) {
84  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
85  goto destroy_pipe_cfg;
86  }
87 
88  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTIONS_ARR);
89  if (result != DOCA_SUCCESS) {
90  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
91  goto destroy_pipe_cfg;
92  }
93 
94  /* forwarding traffic to other port */
96  fwd.next_pipe = fwd_pipe;
97 
98  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
100  doca_flow_pipe_cfg_destroy(pipe_cfg);
101  return result;
102 }
103 
104 static doca_error_t add_match_pipe_entry(struct doca_flow_pipe *pipe,
105  struct entries_status *status,
106  struct mark_set_config *app_cfg)
107 {
108  struct doca_flow_match match;
109  struct doca_flow_actions actions;
110  struct doca_flow_pipe_entry *entry;
112 
113  memset(&match, 0, sizeof(match));
114  memset(&actions, 0, sizeof(actions));
115 
118  match.outer.ip4.src_ip = BE_IPV4_ADDR(1, 2, 3, 4);
119  if (app_cfg->action_changeable) {
120  actions.meta.mark = DOCA_HTOBE32(app_cfg->mark_value);
121  }
122  actions.action_idx = 0;
123 
124  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
125  if (result != DOCA_SUCCESS)
126  return result;
127 
128  return DOCA_SUCCESS;
129 }
130 
131 static doca_error_t create_rss_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
132 {
133  struct doca_flow_match match;
134  struct doca_flow_monitor monitor;
135  struct doca_flow_fwd fwd;
136  struct doca_flow_pipe_cfg *pipe_cfg;
137  uint16_t rss_queues[1];
139  struct doca_flow_actions actions, *actions_arr[NB_ACTIONS_ARR];
140 
141  memset(&match, 0, sizeof(match));
142  memset(&fwd, 0, sizeof(fwd));
143  memset(&monitor, 0, sizeof(monitor));
144  memset(&actions, 0, sizeof(actions));
145 
146  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
147  if (result != DOCA_SUCCESS) {
148  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
149  return result;
150  }
151 
152  result = set_flow_pipe_cfg(pipe_cfg, "RSS_PIPE", DOCA_FLOW_PIPE_BASIC, false);
153  if (result != DOCA_SUCCESS) {
154  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
155  goto destroy_pipe_cfg;
156  }
157  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
158  if (result != DOCA_SUCCESS) {
159  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
160  goto destroy_pipe_cfg;
161  }
162  actions_arr[0] = &actions;
163  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTIONS_ARR);
164  if (result != DOCA_SUCCESS) {
165  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
166  goto destroy_pipe_cfg;
167  }
169  if (result != DOCA_SUCCESS) {
170  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg monitor: %s", doca_error_get_descr(result));
171  goto destroy_pipe_cfg;
172  }
173 
174  /* RSS queue - send matched traffic to queue 0 */
175  rss_queues[0] = 0;
180  fwd.rss.nr_queues = 1;
181 
182  result = doca_flow_pipe_create(pipe_cfg, &fwd, NULL, pipe);
184  doca_flow_pipe_cfg_destroy(pipe_cfg);
185  return result;
186 }
187 
188 static doca_error_t add_rss_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
189 {
190  struct doca_flow_pipe_entry *entry;
191  struct doca_flow_actions actions;
192  struct doca_flow_match match;
194 
195  memset(&match, 0, sizeof(match));
196  memset(&actions, 0, sizeof(actions));
197 
198  actions.action_idx = 0;
199 
200  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
201  if (result != DOCA_SUCCESS)
202  return result;
203 
204  return DOCA_SUCCESS;
205 }
206 
207 static void handle_rx_tx_pkts(uint32_t port_id, uint16_t nb_queues)
208 {
209  int rc;
210  uint32_t queue_id;
211  uint32_t secs = WAIT_SECS;
212  uint32_t nb_rx;
213  uint32_t i;
214  uint32_t sw_packet_type;
215  uint32_t nb_tx;
216  uint32_t retry;
217  struct rte_mbuf *mbufs[MAX_PKTS];
218 
219  rc = rte_flow_dynf_metadata_register();
220  if (unlikely(rc)) {
221  DOCA_LOG_ERR("Enable metadata failed");
222  return;
223  }
224 
225  while (secs--) {
226  sleep(1);
227  for (queue_id = 0; queue_id < nb_queues; queue_id++) {
228  nb_rx = rte_eth_rx_burst(port_id, queue_id, mbufs, MAX_PKTS);
229  for (i = 0; i < nb_rx; i++) {
230  sw_packet_type = rte_net_get_ptype(mbufs[i], NULL, RTE_PTYPE_ALL_MASK);
231  if (mbufs[i]->ol_flags & RTE_MBUF_F_RX_FDIR_ID) {
232  DOCA_LOG_INFO("packet mark value: 0x%x", mbufs[i]->hash.fdir.hi);
233  mbufs[i]->ol_flags |= RTE_MBUF_DYNFLAG_TX_METADATA;
234  } else {
235  DOCA_LOG_INFO("Pkt received: 0x%x\n", sw_packet_type);
236  }
237 
238  retry = 0;
239  do {
240  nb_tx = rte_eth_tx_burst(port_id, queue_id, &mbufs[i], 1);
241  if (nb_tx == 1)
242  break;
243  else
244  rte_delay_us(50000);
245  } while (++retry < 5);
246  rte_pktmbuf_free(mbufs[i]);
247  }
248  }
249  }
250 }
251 
253 {
254  int nb_ports = 2;
255  struct flow_resources resource = {0};
256  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
257  struct doca_flow_port *ports[nb_ports];
258  struct doca_dev *dev_arr[nb_ports];
259  int num_of_entries = 2;
260  uint32_t actions_mem_size[nb_ports];
262  int port_id;
263  struct entries_status status;
264  struct doca_flow_pipe *rss_pipe;
265  struct doca_flow_pipe *match_pipe;
266 
267  resource.nr_counters = 16;
268  result = init_doca_flow(nb_queues, "vnf,hws", &resource, nr_shared_resources);
269  if (result != DOCA_SUCCESS) {
270  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
271  return result;
272  }
273 
274  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
275  ARRAY_INIT(actions_mem_size, ACTIONS_MEM_SIZE(nb_queues, num_of_entries));
277  if (result != DOCA_SUCCESS) {
278  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
280  return result;
281  }
282 
283  for (port_id = 0; port_id < nb_ports; port_id++) {
284  memset(&status, 0, sizeof(status));
285 
286  result = create_rss_pipe(ports[port_id], &rss_pipe);
287  if (result != DOCA_SUCCESS) {
288  DOCA_LOG_ERR("Failed to create rss pipe: %s", doca_error_get_descr(result));
291  return result;
292  }
293 
294  result = add_rss_pipe_entry(rss_pipe, &status);
295  if (result != DOCA_SUCCESS) {
296  DOCA_LOG_ERR("Failed to add entry: %s", doca_error_get_descr(result));
299  return result;
300  }
301 
302  result = create_match_pipe(ports[port_id], &match_pipe, rss_pipe, app_cfg);
303  if (result != DOCA_SUCCESS) {
304  DOCA_LOG_ERR("Failed to create classifier pipe: %s", doca_error_get_descr(result));
307  return result;
308  }
309 
310  result = add_match_pipe_entry(match_pipe, &status, app_cfg);
311  if (result != DOCA_SUCCESS) {
312  DOCA_LOG_ERR("Failed to add entry to classifier pipe: %s", doca_error_get_descr(result));
315  return result;
316  }
317 
318  result = doca_flow_entries_process(ports[port_id], 0, DEFAULT_TIMEOUT_US, num_of_entries);
319  if (result != DOCA_SUCCESS) {
320  DOCA_LOG_ERR("Failed to process entries: %s", doca_error_get_descr(result));
323  return result;
324  }
325 
326  if (status.nb_processed != num_of_entries || status.failure) {
327  DOCA_LOG_ERR("Failed to process entries: %d, %d, %d",
328  status.nb_processed,
329  num_of_entries,
330  status.failure);
333  return DOCA_ERROR_BAD_STATE;
334  }
335  }
336 
337  DOCA_LOG_INFO("Wait few seconds for packets to arrive");
338  handle_rx_tx_pkts(0, nb_queues);
339  DOCA_LOG_INFO("===================================================");
340 
343  return result;
344 }
#define NULL
Definition: __stddef_null.h:26
int32_t result
struct doca_flow_port * init_doca_flow(uint16_t port_id, uint8_t rxq_num)
Definition: flow.c:37
#define unlikely(x)
Definition: utils.h:42
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static doca_error_t add_rss_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
#define MAX_PKTS
DOCA_LOG_REGISTER(FLOW_MARK_SET)
#define WAIT_SECS
static doca_error_t add_match_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status, struct mark_set_config *app_cfg)
static doca_error_t create_rss_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
doca_error_t flow_mark_set(int nb_queues, struct mark_set_config *app_cfg)
static doca_error_t create_match_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe, struct doca_flow_pipe *fwd_pipe, struct mark_set_config *app_cfg)
static void handle_rx_tx_pkts(uint32_t port_id, uint16_t nb_queues)
static uint16_t * rss_queues
Definition: flow_parser.c:114
static struct doca_flow_actions actions
Definition: flow_parser.c:107
#define BE_IPV4_ADDR(a, b, c, d)
Definition: flow_parser.c:64
static struct doca_flow_monitor monitor
Definition: flow_parser.c:108
static struct doca_flow_fwd fwd
Definition: flow_parser.c:109
static struct doca_flow_pipe_entry * entry[MAX_ENTRIES]
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
static struct app_gpu_cfg app_cfg
#define DOCA_HTOBE32(_x)
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_BAD_STATE
Definition: doca_error.h:56
@ DOCA_SUCCESS
Definition: doca_error.h:38
@ DOCA_FLOW_L3_TYPE_IP4
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_destroy(struct doca_flow_pipe_cfg *cfg)
Destroy DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_create(struct doca_flow_pipe_cfg **cfg, struct doca_flow_port *port)
Create DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_actions(struct doca_flow_pipe_cfg *cfg, struct doca_flow_actions *const *actions, struct doca_flow_actions *const *actions_masks, struct doca_flow_action_descs *const *action_descs, size_t nr_actions)
Set pipe's actions, actions mask and actions descriptor.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_monitor(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_monitor *monitor)
Set pipe's monitor.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_add_entry(uint16_t pipe_queue, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_actions *actions, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a pipe.
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
@ DOCA_FLOW_RSS_TCP
Definition: doca_flow.h:770
@ DOCA_FLOW_RSS_IPV4
Definition: doca_flow.h:764
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
Definition: doca_flow.h:615
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_FWD_RSS
Definition: doca_flow.h:742
#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
uint16_t queue_id
Definition: ip_frag_dp.c:1
doca_error_t stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
Definition: flow_common.c:240
doca_error_t init_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin, struct doca_dev *dev_arr[], uint32_t actions_mem_size[])
Definition: flow_common.c:296
doca_error_t set_flow_pipe_cfg(struct doca_flow_pipe_cfg *cfg, const char *name, enum doca_flow_pipe_type type, bool is_root)
Definition: flow_common.c:305
#define NB_ACTIONS_ARR
Definition: flow_common.h:58
#define SHARED_RESOURCE_NUM_VALUES
Definition: flow_common.h:59
#define ACTIONS_MEM_SIZE(nr_queues, entries)
Definition: flow_common.h:66
#define ARRAY_INIT(array, val)
Definition: flow_common.h:71
doca flow actions information
Definition: doca_flow.h:684
struct doca_flow_meta meta
Definition: doca_flow.h:699
uint8_t action_idx
Definition: doca_flow.h:685
forwarding configuration
Definition: doca_flow.h:779
struct doca_flow_pipe * next_pipe
Definition: doca_flow.h:800
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
enum doca_flow_resource_type rss_type
Definition: doca_flow.h:784
struct doca_flow_resource_rss_cfg rss
Definition: doca_flow.h:787
struct doca_flow_header_ip4 ip4
Definition: doca_flow.h:449
enum doca_flow_l3_type l3_type
Definition: doca_flow.h:446
doca flow matcher information
Definition: doca_flow.h:491
struct doca_flow_parser_meta parser_meta
Definition: doca_flow.h:496
struct doca_flow_header_format outer
Definition: doca_flow.h:498
doca_be32_t mark
Definition: doca_flow.h:361
doca monitor action configuration
Definition: doca_flow.h:968
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
user context struct that will be used in entries process callback
Definition: flow_common.h:78
uint32_t nr_counters
Definition: flow_common.h:96
static int nb_ports
Definition: switch_core.c:44
static uint32_t actions_mem_size[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:43
static struct doca_flow_port * ports[FLOW_SWITCH_PORTS_MAX]
Definition: switch_core.c:42