NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_fwd_target_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 <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 
35 DOCA_LOG_REGISTER(FLOW_FWD_TARGET);
36 
37 /*
38  * Create DOCA Flow pipe with 5 tuple match that forwards the matched traffic to the other port
39  *
40  * @port [in]: port of the pipe
41  * @port_id [in]: port ID of the pipe
42  * @target [in]: target for fwd miss traffic
43  * @pipe [out]: created pipe pointer
44  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
45  */
46 static doca_error_t create_ipv4_pipe(struct doca_flow_port *port,
47  int port_id,
48  struct doca_flow_target *target,
49  struct doca_flow_pipe **pipe)
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_fwd fwd_miss;
55  struct doca_flow_pipe_cfg *pipe_cfg;
57 
58  memset(&match, 0, sizeof(match));
59  memset(&actions, 0, sizeof(actions));
60  memset(&fwd, 0, sizeof(fwd));
61 
62  /* 5 tuple match */
67  match.outer.ip4.src_ip = 0xffffffff;
68  match.outer.ip4.dst_ip = 0xffffffff;
69  match.outer.tcp.l4_port.src_port = 0xffff;
70  match.outer.tcp.l4_port.dst_port = 0xffff;
71 
72  actions_arr[0] = &actions;
73 
74  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
75  if (result != DOCA_SUCCESS) {
76  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
77  return result;
78  }
79 
80  result = set_flow_pipe_cfg(pipe_cfg, "IPv4_PIPE", DOCA_FLOW_PIPE_BASIC, false);
81  if (result != DOCA_SUCCESS) {
82  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
83  goto destroy_pipe_cfg;
84  }
85  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
86  if (result != DOCA_SUCCESS) {
87  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
88  goto destroy_pipe_cfg;
89  }
90  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, NB_ACTIONS_ARR);
91  if (result != DOCA_SUCCESS) {
92  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
93  goto destroy_pipe_cfg;
94  }
95 
96  /* forwarding traffic to other port */
98  fwd.port_id = port_id ^ 1;
99 
100  /* forwarding miss traffic to kernel */
102  fwd_miss.target = target;
103 
104  result = doca_flow_pipe_create(pipe_cfg, &fwd, &fwd_miss, pipe);
106  doca_flow_pipe_cfg_destroy(pipe_cfg);
107  return result;
108 }
109 
110 /*
111  * Add DOCA Flow pipe entry to the ipv4 pipe
112  *
113  * @pipe [in]: pipe of the entry
114  * @status [in]: user context for adding entry
115  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
116  */
117 static doca_error_t add_ipv4_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
118 {
119  struct doca_flow_match match;
120  struct doca_flow_actions actions;
121  struct doca_flow_pipe_entry *entry;
123 
124  /* example 5-tuple to forward */
125  doca_be32_t dst_ip_addr = BE_IPV4_ADDR(8, 8, 8, 8);
126  doca_be32_t src_ip_addr = BE_IPV4_ADDR(1, 2, 3, 4);
127  doca_be16_t dst_port = rte_cpu_to_be_16(80);
128  doca_be16_t src_port = rte_cpu_to_be_16(1234);
129 
130  memset(&match, 0, sizeof(match));
131  memset(&actions, 0, sizeof(actions));
132 
133  match.outer.ip4.dst_ip = dst_ip_addr;
134  match.outer.ip4.src_ip = src_ip_addr;
137 
138  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry);
139  if (result != DOCA_SUCCESS)
140  return result;
141 
142  return DOCA_SUCCESS;
143 }
144 
145 /*
146  * Create DOCA Flow control pipe
147  *
148  * @port [in]: port of the pipe
149  * @pipe [out]: created pipe pointer
150  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
151  */
152 static doca_error_t create_main_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
153 {
154  struct doca_flow_pipe_cfg *pipe_cfg;
156 
157  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
158  if (result != DOCA_SUCCESS) {
159  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
160  return result;
161  }
162 
163  result = set_flow_pipe_cfg(pipe_cfg, "CONTROL_PIPE", DOCA_FLOW_PIPE_CONTROL, true);
164  if (result != DOCA_SUCCESS) {
165  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
166  goto destroy_pipe_cfg;
167  }
168 
169  result = doca_flow_pipe_create(pipe_cfg, NULL, NULL, pipe);
171  doca_flow_pipe_cfg_destroy(pipe_cfg);
172  return result;
173 }
174 
175 /*
176  * Add DOCA Flow pipe entry to the control pipe that forwards ipv4 traffic to next pipe
177  *
178  * @pipe [in]: pipe of the entry
179  * @next_pipe [in]: next pipe to forward the matched traffic
180  * @status [in]: user context for adding entry
181  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
182  */
183 static doca_error_t add_main_pipe_entry(struct doca_flow_pipe *pipe,
184  struct doca_flow_pipe *next_pipe,
185  struct entries_status *status)
186 {
187  struct doca_flow_match match;
188  struct doca_flow_fwd fwd;
189 
190  memset(&match, 0, sizeof(match));
191  memset(&fwd, 0, sizeof(fwd));
192 
194 
197 
199  0,
200  pipe,
201  &match,
202  NULL,
203  NULL,
204  NULL,
205  NULL,
206  NULL,
207  NULL,
208  &fwd,
209  status,
210  NULL);
211 }
212 
213 /*
214  * Run flow_fwd_target sample
215  *
216  * @nb_queues [in]: number of queues the sample will use
217  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
218  */
220 {
221  const int nb_ports = 2;
222  struct flow_resources resource = {0};
223  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
224  struct doca_flow_port *ports[nb_ports];
225  struct doca_dev *dev_arr[nb_ports];
226  uint32_t actions_mem_size[nb_ports];
227  struct doca_flow_pipe *main_pipe;
228  struct doca_flow_pipe *ipv4_pipe;
229  struct doca_flow_target *kernel_target;
230  struct entries_status status;
231  int num_of_entries = 2;
233  int port_id;
234 
235  result = init_doca_flow(nb_queues, "vnf,isolated,hws", &resource, nr_shared_resources);
236  if (result != DOCA_SUCCESS) {
237  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
238  return result;
239  }
240 
241  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
242  ARRAY_INIT(actions_mem_size, ACTIONS_MEM_SIZE(nb_queues, num_of_entries));
244  if (result != DOCA_SUCCESS) {
245  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
247  return result;
248  }
249 
251  if (result != DOCA_SUCCESS) {
252  DOCA_LOG_ERR("Failed to get kernel target: %s", doca_error_get_descr(result));
254  return result;
255  }
256 
257  for (port_id = 0; port_id < nb_ports; port_id++) {
258  memset(&status, 0, sizeof(status));
259 
260  result = create_ipv4_pipe(ports[port_id], port_id, kernel_target, &ipv4_pipe);
261  if (result != DOCA_SUCCESS) {
262  DOCA_LOG_ERR("Failed to create ipv4 pipe: %s", doca_error_get_descr(result));
265  return result;
266  }
267 
268  result = add_ipv4_pipe_entry(ipv4_pipe, &status);
269  if (result != DOCA_SUCCESS) {
270  DOCA_LOG_ERR("Failed to add entry: %s", doca_error_get_descr(result));
273  return result;
274  }
275 
276  result = create_main_pipe(ports[port_id], &main_pipe);
277  if (result != DOCA_SUCCESS) {
278  DOCA_LOG_ERR("Failed to create main pipe: %s", doca_error_get_descr(result));
281  return result;
282  }
283 
284  result = add_main_pipe_entry(main_pipe, ipv4_pipe, &status);
285  if (result != DOCA_SUCCESS) {
286  DOCA_LOG_ERR("Failed to add entry: %s", doca_error_get_descr(result));
289  return result;
290  }
291 
292  result = doca_flow_entries_process(ports[port_id], 0, DEFAULT_TIMEOUT_US, num_of_entries);
293  if (result != DOCA_SUCCESS) {
294  DOCA_LOG_ERR("Failed to process entries: %s", doca_error_get_descr(result));
297  return result;
298  }
299 
300  if (status.nb_processed != num_of_entries || status.failure) {
301  DOCA_LOG_ERR("Failed to process entries");
304  return DOCA_ERROR_BAD_STATE;
305  }
306  }
307 
308  DOCA_LOG_INFO("Wait few seconds for packets to arrive");
309  sleep(5);
310 
313  return result;
314 }
#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
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static doca_error_t add_main_pipe_entry(struct doca_flow_pipe *pipe, struct doca_flow_pipe *next_pipe, struct entries_status *status)
DOCA_LOG_REGISTER(FLOW_FWD_TARGET)
static doca_error_t add_ipv4_pipe_entry(struct doca_flow_pipe *pipe, struct entries_status *status)
static doca_error_t create_main_pipe(struct doca_flow_port *port, struct doca_flow_pipe **pipe)
doca_error_t flow_fwd_target(int nb_queues)
static doca_error_t create_ipv4_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_target *target, struct doca_flow_pipe **pipe)
static struct doca_flow_fwd fwd_miss
Definition: flow_parser.c:110
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_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
#define DOCA_HTOBE16(_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
#define DOCA_FLOW_ETHER_TYPE_IPV4
Definition: doca_flow_net.h:57
@ DOCA_FLOW_L4_TYPE_EXT_TCP
@ 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_control_add_entry(uint16_t pipe_queue, uint32_t priority, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_match *match_mask, const struct doca_flow_match_condition *condition, const struct doca_flow_actions *actions, const struct doca_flow_actions *actions_mask, const struct doca_flow_action_descs *action_descs, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a control pipe.
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_get_target(enum doca_flow_target_type type, struct doca_flow_target **target)
Get doca flow forward target.
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_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_PIPE_CONTROL
Definition: doca_flow.h:223
@ DOCA_FLOW_PIPE_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_TARGET_KERNEL
Definition: doca_flow.h:733
@ DOCA_FLOW_FWD_PORT
Definition: doca_flow.h:744
@ DOCA_FLOW_FWD_TARGET
Definition: doca_flow.h:750
@ DOCA_FLOW_FWD_PIPE
Definition: doca_flow.h:746
@ DOCA_FLOW_L4_META_TCP
Definition: doca_flow.h:308
#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
uint32_t doca_be32_t
Definition: doca_types.h:121
uint16_t doca_be16_t
Declare DOCA endianity types.
Definition: doca_types.h:120
uint16_t src_port
Definition: packets.h:0
uint16_t dst_port
Definition: packets.h: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
forwarding configuration
Definition: doca_flow.h:779
struct doca_flow_pipe * next_pipe
Definition: doca_flow.h:800
struct doca_flow_pipe * pipe
Definition: doca_flow.h:806
struct doca_flow_target * target
Definition: doca_flow.h:812
uint16_t port_id
Definition: doca_flow.h:795
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
struct doca_flow_header_ip4 ip4
Definition: doca_flow.h:449
enum doca_flow_l4_type_ext l4_type_ext
Definition: doca_flow.h:454
struct doca_flow_header_eth eth
Definition: doca_flow.h:440
enum doca_flow_l3_type l3_type
Definition: doca_flow.h:446
struct doca_flow_header_tcp tcp
Definition: doca_flow.h:461
struct doca_flow_header_l4_port l4_port
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
enum doca_flow_l3_meta outer_l3_type
Definition: doca_flow.h:382
enum doca_flow_l4_meta outer_l4_type
Definition: doca_flow.h:383
user context struct that will be used in entries process callback
Definition: flow_common.h:78
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