NVIDIA DOCA SDK Data Center on a Chip Framework Documentation
flow_multi_actions_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 <rte_byteorder.h>
30 
31 #include <doca_log.h>
32 #include <doca_flow.h>
33 
34 #include "flow_common.h"
35 
36 DOCA_LOG_REGISTER(FLOW_MULTI_ACTIONS);
37 
38 /*
39  * Create DOCA Flow pipe with match on source IP address, and two different actions on actions array
40  *
41  * @port [in]: port of the pipe
42  * @port_id [in]: port ID of the pipe
43  * @pipe [out]: created pipe pointer
44  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
45  */
46 static doca_error_t create_multi_actions_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_pipe **pipe)
47 {
48  struct doca_flow_match match;
49  int nb_actions = 2;
50  struct doca_flow_actions actions0, actions1, *actions_arr[nb_actions];
51  struct doca_flow_fwd fwd;
52  struct doca_flow_pipe_cfg *pipe_cfg;
54 
55  memset(&match, 0, sizeof(match));
56  memset(&actions0, 0, sizeof(actions0));
57  memset(&actions1, 0, sizeof(actions1));
58  memset(&fwd, 0, sizeof(fwd));
59 
62  match.outer.ip4.src_ip = 0xffffffff;
63 
65  fwd.port_id = port_id ^ 1;
66 
67  /* set changeable modify source mac address for actions0 */
68  SET_MAC_ADDR(actions0.outer.eth.src_mac, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
69 
70  /* set changeable modify source IP address for actions1 */
72  actions1.outer.ip4.src_ip = 0xffffffff;
73  actions_arr[0] = &actions0;
74  actions_arr[1] = &actions1;
75 
76  result = doca_flow_pipe_cfg_create(&pipe_cfg, port);
77  if (result != DOCA_SUCCESS) {
78  DOCA_LOG_ERR("Failed to create doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
79  return result;
80  }
81 
82  result = set_flow_pipe_cfg(pipe_cfg, "MODIFY_HEADER_PIPE", DOCA_FLOW_PIPE_BASIC, true);
83  if (result != DOCA_SUCCESS) {
84  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg: %s", doca_error_get_descr(result));
85  goto destroy_pipe_cfg;
86  }
87  result = doca_flow_pipe_cfg_set_match(pipe_cfg, &match, NULL);
88  if (result != DOCA_SUCCESS) {
89  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg match: %s", doca_error_get_descr(result));
90  goto destroy_pipe_cfg;
91  }
92  result = doca_flow_pipe_cfg_set_actions(pipe_cfg, actions_arr, NULL, NULL, nb_actions);
93  if (result != DOCA_SUCCESS) {
94  DOCA_LOG_ERR("Failed to set doca_flow_pipe_cfg actions: %s", doca_error_get_descr(result));
95  goto destroy_pipe_cfg;
96  }
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 /*
105  * Add DOCA Flow pipe entries to the pipe with different action on each entry
106  *
107  * @pipe [in]: pipe of the entry
108  * @status [in]: user context for adding entry
109  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
110  */
111 static doca_error_t add_multi_actions_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
112 {
113  struct doca_flow_match match;
114  struct doca_flow_actions actions;
115  struct doca_flow_pipe_entry *entry0, *entry1;
117  doca_be32_t src_ip_addr;
118  doca_be32_t mod_src_ip_addr = BE_IPV4_ADDR(1, 2, 3, 4);
119 
120  memset(&match, 0, sizeof(match));
121  memset(&actions, 0, sizeof(actions));
122 
123  src_ip_addr = BE_IPV4_ADDR(1, 1, 1, 1);
124  match.outer.ip4.src_ip = src_ip_addr;
125 
126  actions.action_idx = 0;
127  /* modify source mac address */
128  SET_MAC_ADDR(actions.outer.eth.src_mac, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff);
129 
130  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry0);
131  if (result != DOCA_SUCCESS) {
132  DOCA_LOG_ERR("Failed to add first entry: %s", doca_error_get_descr(result));
133  return result;
134  }
135 
136  src_ip_addr = BE_IPV4_ADDR(2, 2, 2, 2);
137  match.outer.ip4.src_ip = src_ip_addr;
138 
139  actions.action_idx = 1;
140  /* modify source IP address */
141  actions.outer.ip4.src_ip = mod_src_ip_addr;
142 
143  result = doca_flow_pipe_add_entry(0, pipe, &match, &actions, NULL, NULL, 0, status, &entry1);
144  if (result != DOCA_SUCCESS) {
145  DOCA_LOG_ERR("Failed to add second entry: %s", doca_error_get_descr(result));
146  return result;
147  }
148 
149  return DOCA_SUCCESS;
150 }
151 
152 /*
153  * Run flow_multi_actions sample
154  *
155  * @nb_queues [in]: number of queues the sample will use
156  * @return: DOCA_SUCCESS on success and DOCA_ERROR otherwise.
157  */
159 {
160  int nb_ports = 2;
161  struct flow_resources resource = {0};
162  uint32_t nr_shared_resources[SHARED_RESOURCE_NUM_VALUES] = {0};
163  struct doca_flow_port *ports[nb_ports];
164  struct doca_dev *dev_arr[nb_ports];
165  uint32_t actions_mem_size[nb_ports];
166  struct doca_flow_pipe *pipe;
167  struct entries_status status;
168  int num_of_entries = 2;
170  int port_id;
171 
172  result = init_doca_flow(nb_queues, "vnf,hws", &resource, nr_shared_resources);
173  if (result != DOCA_SUCCESS) {
174  DOCA_LOG_ERR("Failed to init DOCA Flow: %s", doca_error_get_descr(result));
175  return result;
176  }
177 
178  memset(dev_arr, 0, sizeof(struct doca_dev *) * nb_ports);
179  ARRAY_INIT(actions_mem_size, ACTIONS_MEM_SIZE(nb_queues, num_of_entries));
181  if (result != DOCA_SUCCESS) {
182  DOCA_LOG_ERR("Failed to init DOCA ports: %s", doca_error_get_descr(result));
184  return result;
185  }
186 
187  for (port_id = 0; port_id < nb_ports; port_id++) {
188  memset(&status, 0, sizeof(status));
189 
190  result = create_multi_actions_pipe(ports[port_id], port_id, &pipe);
191  if (result != DOCA_SUCCESS) {
192  DOCA_LOG_ERR("Failed to create pipe: %s", doca_error_get_descr(result));
195  return result;
196  }
197 
198  result = add_multi_actions_pipe_entries(pipe, &status);
199  if (result != DOCA_SUCCESS) {
202  return result;
203  }
204 
205  result = doca_flow_entries_process(ports[port_id], 0, DEFAULT_TIMEOUT_US, num_of_entries);
206  if (result != DOCA_SUCCESS) {
207  DOCA_LOG_ERR("Failed to process entries: %s", doca_error_get_descr(result));
210  return result;
211  }
212 
213  if (status.nb_processed != num_of_entries || status.failure) {
214  DOCA_LOG_ERR("Failed to process entries");
217  return DOCA_ERROR_BAD_STATE;
218  }
219  }
220 
221  DOCA_LOG_INFO("Wait few seconds for packets to arrive");
222  sleep(5);
223 
226  return result;
227 }
#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 SET_MAC_ADDR(addr, a, b, c, d, e, f)
Definition: flow_common.h:60
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static doca_error_t add_multi_actions_pipe_entries(struct doca_flow_pipe *pipe, struct entries_status *status)
static doca_error_t create_multi_actions_pipe(struct doca_flow_port *port, int port_id, struct doca_flow_pipe **pipe)
DOCA_LOG_REGISTER(FLOW_MULTI_ACTIONS)
doca_error_t flow_multi_actions(int nb_queues)
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
#define DEFAULT_TIMEOUT_US
Definition: flow_skeleton.c:36
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_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_BASIC
Definition: doca_flow.h:221
@ DOCA_FLOW_L3_META_IPV4
Definition: doca_flow.h:296
@ DOCA_FLOW_FWD_PORT
Definition: doca_flow.h:744
#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
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 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_header_format outer
Definition: doca_flow.h:703
uint8_t action_idx
Definition: doca_flow.h:685
forwarding configuration
Definition: doca_flow.h:779
uint16_t port_id
Definition: doca_flow.h:795
enum doca_flow_fwd_type type
Definition: doca_flow.h:780
uint8_t src_mac[DOCA_FLOW_ETHER_ADDR_LEN]
struct doca_flow_header_ip4 ip4
Definition: doca_flow.h:449
struct doca_flow_header_eth eth
Definition: doca_flow.h:440
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
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
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