1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
8 #include <rte_malloc.h>
10 #include <rte_common.h>
11 #include <rte_malloc.h>
13 #include "rte_table_action.h"
16 * RTE_TABLE_ACTION_FWD
18 #define fwd_data rte_pipeline_table_entry
21 fwd_apply(struct fwd_data *data,
22 struct rte_table_action_fwd_params *p)
24 data->action = p->action;
26 if (p->action == RTE_PIPELINE_ACTION_PORT)
27 data->port_id = p->id;
29 if (p->action == RTE_PIPELINE_ACTION_TABLE)
30 data->table_id = p->id;
39 action_valid(enum rte_table_action_type action)
42 case RTE_TABLE_ACTION_FWD:
50 #define RTE_TABLE_ACTION_MAX 64
54 struct rte_table_action_common_config common;
58 action_cfg_size(enum rte_table_action_type action)
67 action_cfg_get(struct ap_config *ap_config __rte_unused,
68 enum rte_table_action_type type)
77 action_cfg_set(struct ap_config *ap_config,
78 enum rte_table_action_type type,
81 void *dst = action_cfg_get(ap_config, type);
84 memcpy(dst, action_cfg, action_cfg_size(type));
86 ap_config->action_mask |= 1LLU << type;
90 size_t offset[RTE_TABLE_ACTION_MAX];
95 action_data_size(enum rte_table_action_type action,
96 struct ap_config *ap_config __rte_unused)
99 case RTE_TABLE_ACTION_FWD:
100 return sizeof(struct fwd_data);
109 action_data_offset_set(struct ap_data *ap_data,
110 struct ap_config *ap_config)
112 uint64_t action_mask = ap_config->action_mask;
116 memset(ap_data->offset, 0, sizeof(ap_data->offset));
119 for (action = 0; action < RTE_TABLE_ACTION_MAX; action++)
120 if (action_mask & (1LLU << action)) {
121 ap_data->offset[action] = offset;
122 offset += action_data_size((enum rte_table_action_type)action,
126 ap_data->total_size = offset;
129 struct rte_table_action_profile {
130 struct ap_config cfg;
135 struct rte_table_action_profile *
136 rte_table_action_profile_create(struct rte_table_action_common_config *common)
138 struct rte_table_action_profile *ap;
140 /* Check input arguments */
144 /* Memory allocation */
145 ap = calloc(1, sizeof(struct rte_table_action_profile));
150 memcpy(&ap->cfg.common, common, sizeof(*common));
157 rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
158 enum rte_table_action_type type,
161 /* Check input arguments */
162 if ((profile == NULL) ||
164 (action_valid(type) == 0) ||
165 (profile->cfg.action_mask & (1LLU << type)) ||
166 ((action_cfg_size(type) == 0) && action_config) ||
167 (action_cfg_size(type) && (action_config == NULL)))
171 action_cfg_set(&profile->cfg, type, action_config);
177 rte_table_action_profile_freeze(struct rte_table_action_profile *profile)
182 profile->cfg.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
183 action_data_offset_set(&profile->data, &profile->cfg);
190 rte_table_action_profile_free(struct rte_table_action_profile *profile)
199 struct rte_table_action {
200 struct ap_config cfg;
204 struct rte_table_action *
205 rte_table_action_create(struct rte_table_action_profile *profile,
208 struct rte_table_action *action;
210 /* Check input arguments */
211 if ((profile == NULL) ||
212 (profile->frozen == 0))
215 /* Memory allocation */
216 action = rte_zmalloc_socket(NULL,
217 sizeof(struct rte_table_action),
224 memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg));
225 memcpy(&action->data, &profile->data, sizeof(profile->data));
230 static __rte_always_inline void *
231 action_data_get(void *data,
232 struct rte_table_action *action,
233 enum rte_table_action_type type)
235 size_t offset = action->data.offset[type];
236 uint8_t *data_bytes = data;
238 return &data_bytes[offset];
242 rte_table_action_apply(struct rte_table_action *action,
244 enum rte_table_action_type type,
249 /* Check input arguments */
250 if ((action == NULL) ||
252 (action_valid(type) == 0) ||
253 ((action->cfg.action_mask & (1LLU << type)) == 0) ||
254 (action_params == NULL))
258 action_data = action_data_get(data, action, type);
261 case RTE_TABLE_ACTION_FWD:
262 return fwd_apply(action_data,
270 static __rte_always_inline uint64_t
271 pkt_work(struct rte_mbuf *mbuf __rte_unused,
272 struct rte_pipeline_table_entry *table_entry __rte_unused,
273 uint64_t time __rte_unused,
274 struct rte_table_action *action __rte_unused,
275 struct ap_config *cfg __rte_unused)
280 static __rte_always_inline uint64_t
281 pkt4_work(struct rte_mbuf **mbufs __rte_unused,
282 struct rte_pipeline_table_entry **table_entries __rte_unused,
283 uint64_t time __rte_unused,
284 struct rte_table_action *action __rte_unused,
285 struct ap_config *cfg __rte_unused)
290 static __rte_always_inline int
291 ah(struct rte_pipeline *p,
292 struct rte_mbuf **pkts,
294 struct rte_pipeline_table_entry **entries,
295 struct rte_table_action *action,
296 struct ap_config *cfg)
298 uint64_t pkts_drop_mask = 0;
301 if ((pkts_mask & (pkts_mask + 1)) == 0) {
302 uint64_t n_pkts = __builtin_popcountll(pkts_mask);
305 for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) {
308 drop_mask = pkt4_work(&pkts[i],
314 pkts_drop_mask |= drop_mask << i;
317 for ( ; i < n_pkts; i++) {
320 drop_mask = pkt_work(pkts[i],
326 pkts_drop_mask |= drop_mask << i;
329 for ( ; pkts_mask; ) {
330 uint32_t pos = __builtin_ctzll(pkts_mask);
331 uint64_t pkt_mask = 1LLU << pos;
334 drop_mask = pkt_work(pkts[pos],
340 pkts_mask &= ~pkt_mask;
341 pkts_drop_mask |= drop_mask << pos;
344 rte_pipeline_ah_packet_drop(p, pkts_drop_mask);
350 ah_default(struct rte_pipeline *p,
351 struct rte_mbuf **pkts,
353 struct rte_pipeline_table_entry **entries,
356 struct rte_table_action *action = arg;
366 static rte_pipeline_table_action_handler_hit
367 ah_selector(struct rte_table_action *action)
369 if (action->cfg.action_mask == (1LLU << RTE_TABLE_ACTION_FWD))
376 rte_table_action_table_params_get(struct rte_table_action *action,
377 struct rte_pipeline_table_params *params)
379 rte_pipeline_table_action_handler_hit f_action_hit;
382 /* Check input arguments */
383 if ((action == NULL) ||
387 f_action_hit = ah_selector(action);
388 total_size = rte_align32pow2(action->data.total_size);
391 params->f_action_hit = f_action_hit;
392 params->f_action_miss = NULL;
393 params->arg_ah = (f_action_hit) ? action : NULL;
394 params->action_data_size = total_size -
395 sizeof(struct rte_pipeline_table_entry);
401 rte_table_action_free(struct rte_table_action *action)