pipeline: support packet redirection at action handlers
Currently, there is no mechanism that allows the pipeline ports (in/out) and table action handlers to override the default forwarding decision (as previously configured per input port or in the table entry). The port (in/out) and table action handler prototypes have been changed to allow pipeline action handlers (port in/out, table) to remove the selected packets from the further pipeline processing and to take full ownership for these packets. This feature will be helpful to implement functions such as exception handling (e.g. TTL =0), load balancing etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
ac5e1d838d
commit
88ac2fd99f
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -159,7 +159,6 @@ app_main_loop_worker_pipeline_acl(void) {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -140,7 +140,6 @@ app_main_loop_worker_pipeline_hash(void) {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -99,7 +99,6 @@ app_main_loop_worker_pipeline_lpm(void) {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -100,7 +100,6 @@ app_main_loop_worker_pipeline_lpm_ipv6(void) {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -94,7 +94,6 @@ app_main_loop_worker_pipeline_stub(void) {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -702,7 +702,8 @@ test_pipeline_single_filter(int expected_count)
|
||||
}
|
||||
|
||||
/* Run pipeline once */
|
||||
rte_pipeline_run(p);
|
||||
for (i = 0; i< N_PORTS; i++)
|
||||
rte_pipeline_run(p);
|
||||
|
||||
rte_pipeline_flush(p);
|
||||
|
||||
|
@ -433,7 +433,8 @@ test_pipeline_single_filter(int test_type, int expected_count)
|
||||
RTE_LOG(INFO, PIPELINE, "%s: **** Running %s test\n",
|
||||
__func__, pipeline_test_names[test_type]);
|
||||
/* Run pipeline once */
|
||||
rte_pipeline_run(p);
|
||||
for (i = 0; i < N_PORTS; i++)
|
||||
rte_pipeline_run(p);
|
||||
|
||||
|
||||
ret = rte_pipeline_flush(NULL);
|
||||
@ -469,7 +470,8 @@ test_pipeline_single_filter(int test_type, int expected_count)
|
||||
}
|
||||
|
||||
/* Run pipeline once */
|
||||
rte_pipeline_run(p);
|
||||
for (i = 0; i < N_PORTS; i++)
|
||||
rte_pipeline_run(p);
|
||||
|
||||
/*
|
||||
* need to flush the pipeline, as there may be less hits than the burst
|
||||
@ -535,6 +537,7 @@ test_table_pipeline(void)
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
|
||||
return -1;
|
||||
#if 0
|
||||
|
||||
/* TEST - one packet per port */
|
||||
action_handler_hit = NULL;
|
||||
@ -582,6 +585,8 @@ test_table_pipeline(void)
|
||||
return -1;
|
||||
connect_miss_action_to_table = 0;
|
||||
|
||||
#endif
|
||||
|
||||
if (check_pipeline_invalid_params()) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Check pipeline invalid params "
|
||||
"failed.\n", __func__);
|
||||
|
@ -41,8 +41,3 @@ Deprecation Notices
|
||||
|
||||
* The scheduler statistics structure will change to allow keeping track of
|
||||
RED actions.
|
||||
|
||||
* librte_pipeline: The prototype for the pipeline input port, output port
|
||||
and table action handlers will be updated:
|
||||
the pipeline parameter will be added, the packets mask parameter will be
|
||||
either removed (for input port action handler) or made input-only.
|
||||
|
@ -158,6 +158,10 @@ This section should contain API changes. Sample format:
|
||||
exactly the amount of memory which is necessary to hold application’s rules.
|
||||
The previous ABI is kept for compatibility.
|
||||
|
||||
* The prototype for the pipeline input port, output port and table action
|
||||
handlers are updated: the pipeline parameter is added,
|
||||
the packets mask parameter has been either removed or made input-only.
|
||||
|
||||
|
||||
ABI Changes
|
||||
-----------
|
||||
@ -197,7 +201,7 @@ The libraries prepended with a plus sign were incremented in this version.
|
||||
librte_mbuf.so.2
|
||||
librte_mempool.so.1
|
||||
librte_meter.so.1
|
||||
librte_pipeline.so.2
|
||||
+ librte_pipeline.so.3
|
||||
librte_pmd_bond.so.1
|
||||
librte_pmd_ring.so.2
|
||||
librte_port.so.2
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -33,12 +33,19 @@
|
||||
#ifndef __INCLUDE_PIPELINE_ACTIONS_COMMON_H__
|
||||
#define __INCLUDE_PIPELINE_ACTIONS_COMMON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_pipeline.h>
|
||||
|
||||
#define PIPELINE_PORT_IN_AH(f_ah, f_pkt_work, f_pkt4_work) \
|
||||
static int \
|
||||
f_ah( \
|
||||
__rte_unused struct rte_pipeline *p, \
|
||||
struct rte_mbuf **pkts, \
|
||||
uint32_t n_pkts, \
|
||||
uint64_t *pkts_mask, \
|
||||
void *arg) \
|
||||
{ \
|
||||
uint32_t i; \
|
||||
@ -49,21 +56,18 @@ f_ah( \
|
||||
for ( ; i < n_pkts; i++) \
|
||||
f_pkt_work(pkts[i], arg); \
|
||||
\
|
||||
*pkts_mask = (~0LLU) >> (64 - n_pkts); \
|
||||
\
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define PIPELINE_TABLE_AH_HIT(f_ah, f_pkt_work, f_pkt4_work) \
|
||||
static int \
|
||||
f_ah( \
|
||||
__rte_unused struct rte_pipeline *p, \
|
||||
struct rte_mbuf **pkts, \
|
||||
uint64_t *pkts_mask, \
|
||||
uint64_t pkts_in_mask, \
|
||||
struct rte_pipeline_table_entry **entries, \
|
||||
void *arg) \
|
||||
{ \
|
||||
uint64_t pkts_in_mask = *pkts_mask; \
|
||||
\
|
||||
if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \
|
||||
uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \
|
||||
uint32_t i; \
|
||||
@ -88,13 +92,12 @@ f_ah( \
|
||||
#define PIPELINE_TABLE_AH_MISS(f_ah, f_pkt_work, f_pkt4_work) \
|
||||
static int \
|
||||
f_ah( \
|
||||
__rte_unused struct rte_pipeline *p, \
|
||||
struct rte_mbuf **pkts, \
|
||||
uint64_t *pkts_mask, \
|
||||
uint64_t pkts_in_mask, \
|
||||
struct rte_pipeline_table_entry *entry, \
|
||||
void *arg) \
|
||||
{ \
|
||||
uint64_t pkts_in_mask = *pkts_mask; \
|
||||
\
|
||||
if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \
|
||||
uint64_t n_pkts = __builtin_popcountll(pkts_in_mask); \
|
||||
uint32_t i; \
|
||||
@ -119,13 +122,14 @@ f_ah( \
|
||||
#define PIPELINE_TABLE_AH_HIT_DROP_TIME(f_ah, f_pkt_work, f_pkt4_work) \
|
||||
static int \
|
||||
f_ah( \
|
||||
__rte_unused struct rte_pipeline *p, \
|
||||
struct rte_mbuf **pkts, \
|
||||
uint64_t *pkts_mask, \
|
||||
uint64_t pkts_mask, \
|
||||
struct rte_pipeline_table_entry **entries, \
|
||||
void *arg) \
|
||||
{ \
|
||||
uint64_t pkts_in_mask = *pkts_mask; \
|
||||
uint64_t pkts_out_mask = *pkts_mask; \
|
||||
uint64_t pkts_in_mask = pkts_mask; \
|
||||
uint64_t pkts_out_mask = pkts_mask; \
|
||||
uint64_t time = rte_rdtsc(); \
|
||||
\
|
||||
if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \
|
||||
@ -134,13 +138,13 @@ f_ah( \
|
||||
\
|
||||
for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) { \
|
||||
uint64_t mask = f_pkt4_work(&pkts[i], \
|
||||
&entries[i], arg, time); \
|
||||
&entries[i], arg, time); \
|
||||
pkts_out_mask ^= mask << i; \
|
||||
} \
|
||||
\
|
||||
for ( ; i < n_pkts; i++) { \
|
||||
uint64_t mask = f_pkt_work(pkts[i], \
|
||||
entries[i], arg, time); \
|
||||
entries[i], arg, time); \
|
||||
pkts_out_mask ^= mask << i; \
|
||||
} \
|
||||
} else \
|
||||
@ -154,20 +158,20 @@ f_ah( \
|
||||
pkts_out_mask ^= mask << pos; \
|
||||
} \
|
||||
\
|
||||
*pkts_mask = pkts_out_mask; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define PIPELINE_TABLE_AH_MISS_DROP_TIME(f_ah, f_pkt_work, f_pkt4_work) \
|
||||
static int \
|
||||
f_ah( \
|
||||
__rte_unused struct rte_pipeline *p, \
|
||||
struct rte_mbuf **pkts, \
|
||||
uint64_t *pkts_mask, \
|
||||
uint64_t pkts_mask, \
|
||||
struct rte_pipeline_table_entry *entry, \
|
||||
void *arg) \
|
||||
{ \
|
||||
uint64_t pkts_in_mask = *pkts_mask; \
|
||||
uint64_t pkts_out_mask = *pkts_mask; \
|
||||
uint64_t pkts_in_mask = pkts_mask; \
|
||||
uint64_t pkts_out_mask = pkts_mask; \
|
||||
uint64_t time = rte_rdtsc(); \
|
||||
\
|
||||
if ((pkts_in_mask & (pkts_in_mask + 1)) == 0) { \
|
||||
@ -195,7 +199,6 @@ f_ah( \
|
||||
pkts_out_mask ^= mask << pos; \
|
||||
} \
|
||||
\
|
||||
*pkts_mask = pkts_out_mask; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -450,7 +450,6 @@ pipeline_firewall_init(struct pipeline_params *params,
|
||||
.arg_create = pipeline_port_out_params_convert(
|
||||
¶ms->port_out[i]),
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -624,7 +624,6 @@ static void *pipeline_fa_init(struct pipeline_params *params,
|
||||
.arg_create = pipeline_port_out_params_convert(
|
||||
¶ms->port_out[i]),
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -462,7 +462,6 @@ static void *pipeline_fc_init(struct pipeline_params *params,
|
||||
.arg_create = pipeline_port_out_params_convert(
|
||||
¶ms->port_out[i]),
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -499,7 +499,6 @@ pipeline_passthrough_init(struct pipeline_params *params,
|
||||
.arg_create = pipeline_port_out_params_convert(
|
||||
¶ms->port_out[i]),
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -1264,7 +1264,6 @@ pipeline_routing_init(struct pipeline_params *params,
|
||||
.arg_create = pipeline_port_out_params_convert(
|
||||
¶ms->port_out[i]),
|
||||
.f_action = NULL,
|
||||
.f_action_bulk = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
# Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@ -41,7 +41,7 @@ CFLAGS += $(WERROR_FLAGS)
|
||||
|
||||
EXPORT_MAP := rte_pipeline_version.map
|
||||
|
||||
LIBABIVER := 2
|
||||
LIBABIVER := 3
|
||||
|
||||
#
|
||||
# all source are stored in SRCS-y
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -49,14 +49,30 @@
|
||||
#define RTE_TABLE_INVALID UINT32_MAX
|
||||
|
||||
#ifdef RTE_PIPELINE_STATS_COLLECT
|
||||
#define RTE_PIPELINE_STATS_ADD(counter, val) \
|
||||
({ (counter) += (val); })
|
||||
|
||||
#define RTE_PIPELINE_STATS_ADD_M(counter, mask) \
|
||||
({ (counter) += __builtin_popcountll(mask); })
|
||||
#define RTE_PIPELINE_STATS_AH_DROP_WRITE(p, mask) \
|
||||
({ (p)->n_pkts_ah_drop = __builtin_popcountll(mask); })
|
||||
|
||||
#define RTE_PIPELINE_STATS_AH_DROP_READ(p, counter) \
|
||||
({ (counter) += (p)->n_pkts_ah_drop; (p)->n_pkts_ah_drop = 0; })
|
||||
|
||||
#define RTE_PIPELINE_STATS_TABLE_DROP0(p) \
|
||||
({ (p)->pkts_drop_mask = (p)->action_mask0[RTE_PIPELINE_ACTION_DROP]; })
|
||||
|
||||
#define RTE_PIPELINE_STATS_TABLE_DROP1(p, counter) \
|
||||
({ \
|
||||
uint64_t mask = (p)->action_mask0[RTE_PIPELINE_ACTION_DROP]; \
|
||||
mask ^= (p)->pkts_drop_mask; \
|
||||
(counter) += __builtin_popcountll(mask); \
|
||||
})
|
||||
|
||||
#else
|
||||
#define RTE_PIPELINE_STATS_ADD(counter, val)
|
||||
#define RTE_PIPELINE_STATS_ADD_M(counter, mask)
|
||||
|
||||
#define RTE_PIPELINE_STATS_AH_DROP_WRITE(p, mask)
|
||||
#define RTE_PIPELINE_STATS_AH_DROP_READ(p, counter)
|
||||
#define RTE_PIPELINE_STATS_TABLE_DROP0(p)
|
||||
#define RTE_PIPELINE_STATS_TABLE_DROP1(p, counter)
|
||||
|
||||
#endif
|
||||
|
||||
struct rte_port_in {
|
||||
@ -75,6 +91,7 @@ struct rte_port_in {
|
||||
/* List of enabled ports */
|
||||
struct rte_port_in *next;
|
||||
|
||||
/* Statistics */
|
||||
uint64_t n_pkts_dropped_by_ah;
|
||||
};
|
||||
|
||||
@ -82,12 +99,12 @@ struct rte_port_out {
|
||||
/* Input parameters */
|
||||
struct rte_port_out_ops ops;
|
||||
rte_pipeline_port_out_action_handler f_action;
|
||||
rte_pipeline_port_out_action_handler_bulk f_action_bulk;
|
||||
void *arg_ah;
|
||||
|
||||
/* Handle to low-level port */
|
||||
void *h_port;
|
||||
|
||||
/* Statistics */
|
||||
uint64_t n_pkts_dropped_by_ah;
|
||||
};
|
||||
|
||||
@ -106,7 +123,7 @@ struct rte_table {
|
||||
/* Handle to the low-level table object */
|
||||
void *h_table;
|
||||
|
||||
/* Stats for this table. */
|
||||
/* Statistics */
|
||||
uint64_t n_pkts_dropped_by_lkp_hit_ah;
|
||||
uint64_t n_pkts_dropped_by_lkp_miss_ah;
|
||||
uint64_t n_pkts_dropped_lkp_hit;
|
||||
@ -133,13 +150,16 @@ struct rte_pipeline {
|
||||
|
||||
/* List of enabled ports */
|
||||
uint64_t enabled_port_in_mask;
|
||||
struct rte_port_in *port_in_first;
|
||||
struct rte_port_in *port_in_next;
|
||||
|
||||
/* Pipeline run structures */
|
||||
struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
struct rte_pipeline_table_entry *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
uint64_t action_mask0[RTE_PIPELINE_ACTIONS];
|
||||
uint64_t action_mask1[RTE_PIPELINE_ACTIONS];
|
||||
uint64_t pkts_mask;
|
||||
uint64_t n_pkts_ah_drop;
|
||||
uint64_t pkts_drop_mask;
|
||||
} __rte_cache_aligned;
|
||||
|
||||
static inline uint32_t
|
||||
@ -234,7 +254,9 @@ rte_pipeline_create(struct rte_pipeline_params *params)
|
||||
p->num_ports_out = 0;
|
||||
p->num_tables = 0;
|
||||
p->enabled_port_in_mask = 0;
|
||||
p->port_in_first = NULL;
|
||||
p->port_in_next = NULL;
|
||||
p->pkts_mask = 0;
|
||||
p->n_pkts_ah_drop = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
@ -759,9 +781,6 @@ rte_pipeline_port_out_check_params(struct rte_pipeline *p,
|
||||
struct rte_pipeline_port_out_params *params,
|
||||
uint32_t *port_id)
|
||||
{
|
||||
rte_pipeline_port_out_action_handler f_ah;
|
||||
rte_pipeline_port_out_action_handler_bulk f_ah_bulk;
|
||||
|
||||
if (p == NULL) {
|
||||
RTE_LOG(ERR, PIPELINE, "%s: pipeline parameter NULL\n",
|
||||
__func__);
|
||||
@ -794,7 +813,7 @@ rte_pipeline_port_out_check_params(struct rte_pipeline *p,
|
||||
|
||||
if (params->ops->f_tx == NULL) {
|
||||
RTE_LOG(ERR, PIPELINE,
|
||||
"%s: f_tx function pointer NULL\n", __func__);
|
||||
"%s: f_tx function pointer NULL\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -804,15 +823,6 @@ rte_pipeline_port_out_check_params(struct rte_pipeline *p,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f_ah = params->f_action;
|
||||
f_ah_bulk = params->f_action_bulk;
|
||||
if (((f_ah != NULL) && (f_ah_bulk == NULL)) ||
|
||||
((f_ah == NULL) && (f_ah_bulk != NULL))) {
|
||||
RTE_LOG(ERR, PIPELINE, "%s: Action handlers have to be either"
|
||||
"both enabled or both disabled\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Do we have room for one more port? */
|
||||
if (p->num_ports_out == RTE_PIPELINE_PORT_OUT_MAX) {
|
||||
RTE_LOG(ERR, PIPELINE,
|
||||
@ -905,7 +915,6 @@ rte_pipeline_port_out_create(struct rte_pipeline *p,
|
||||
/* Save input parameters */
|
||||
memcpy(&port->ops, params->ops, sizeof(struct rte_port_out_ops));
|
||||
port->f_action = params->f_action;
|
||||
port->f_action_bulk = params->f_action_bulk;
|
||||
port->arg_ah = params->arg_ah;
|
||||
|
||||
/* Initialize port internal data structure */
|
||||
@ -959,9 +968,8 @@ int
|
||||
rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id)
|
||||
{
|
||||
struct rte_port_in *port, *port_prev, *port_next;
|
||||
struct rte_port_in *port_first, *port_last;
|
||||
uint64_t port_mask;
|
||||
uint32_t port_prev_id, port_next_id, port_first_id, port_last_id;
|
||||
uint32_t port_prev_id, port_next_id;
|
||||
|
||||
/* Check input arguments */
|
||||
if (p == NULL) {
|
||||
@ -977,6 +985,8 @@ rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port = &p->ports_in[port_id];
|
||||
|
||||
/* Return if current input port is already enabled */
|
||||
port_mask = 1LLU << port_id;
|
||||
if (p->enabled_port_in_mask & port_mask)
|
||||
@ -990,20 +1000,13 @@ rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id)
|
||||
|
||||
port_prev = &p->ports_in[port_prev_id];
|
||||
port_next = &p->ports_in[port_next_id];
|
||||
port = &p->ports_in[port_id];
|
||||
|
||||
port_prev->next = port;
|
||||
port->next = port_next;
|
||||
|
||||
/* Update the first and last input ports in the chain */
|
||||
port_first_id = __builtin_ctzll(p->enabled_port_in_mask);
|
||||
port_last_id = 63 - __builtin_clzll(p->enabled_port_in_mask);
|
||||
|
||||
port_first = &p->ports_in[port_first_id];
|
||||
port_last = &p->ports_in[port_last_id];
|
||||
|
||||
p->port_in_first = port_first;
|
||||
port_last->next = NULL;
|
||||
/* Check if list of enabled ports was previously empty */
|
||||
if (p->enabled_port_in_mask == port_mask)
|
||||
p->port_in_next = port;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1011,9 +1014,9 @@ rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id)
|
||||
int
|
||||
rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id)
|
||||
{
|
||||
struct rte_port_in *port_prev, *port_next, *port_first, *port_last;
|
||||
struct rte_port_in *port, *port_prev, *port_next;
|
||||
uint64_t port_mask;
|
||||
uint32_t port_prev_id, port_next_id, port_first_id, port_last_id;
|
||||
uint32_t port_prev_id, port_next_id;
|
||||
|
||||
/* Check input arguments */
|
||||
if (p == NULL) {
|
||||
@ -1028,15 +1031,18 @@ rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
port = &p->ports_in[port_id];
|
||||
|
||||
/* Return if current input port is already disabled */
|
||||
port_mask = 1LLU << port_id;
|
||||
if ((p->enabled_port_in_mask & port_mask) == 0)
|
||||
return 0;
|
||||
|
||||
p->enabled_port_in_mask &= ~port_mask;
|
||||
|
||||
/* Return if no other enabled ports */
|
||||
if (__builtin_popcountll(p->enabled_port_in_mask) == 1) {
|
||||
p->enabled_port_in_mask &= ~port_mask;
|
||||
p->port_in_first = NULL;
|
||||
if (p->enabled_port_in_mask == 0) {
|
||||
p->port_in_next = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1049,17 +1055,10 @@ rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id)
|
||||
port_next = &p->ports_in[port_next_id];
|
||||
|
||||
port_prev->next = port_next;
|
||||
p->enabled_port_in_mask &= ~port_mask;
|
||||
|
||||
/* Update the first and last input ports in the chain */
|
||||
port_first_id = __builtin_ctzll(p->enabled_port_in_mask);
|
||||
port_last_id = 63 - __builtin_clzll(p->enabled_port_in_mask);
|
||||
|
||||
port_first = &p->ports_in[port_first_id];
|
||||
port_last = &p->ports_in[port_last_id];
|
||||
|
||||
p->port_in_first = port_first;
|
||||
port_last->next = NULL;
|
||||
/* Check if the port which has just been disabled is next to serve */
|
||||
if (port == p->port_in_next)
|
||||
p->port_in_next = port_next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1149,28 +1148,32 @@ rte_pipeline_compute_masks(struct rte_pipeline *p, uint64_t pkts_mask)
|
||||
|
||||
static inline void
|
||||
rte_pipeline_action_handler_port_bulk(struct rte_pipeline *p,
|
||||
uint64_t pkts_mask, uint32_t port_id)
|
||||
uint64_t pkts_mask, uint32_t port_id)
|
||||
{
|
||||
struct rte_port_out *port_out = &p->ports_out[port_id];
|
||||
|
||||
/* Output port user actions */
|
||||
if (port_out->f_action_bulk != NULL) {
|
||||
uint64_t mask = pkts_mask;
|
||||
p->pkts_mask = pkts_mask;
|
||||
|
||||
port_out->f_action_bulk(p->pkts, &pkts_mask, port_out->arg_ah);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= pkts_mask ^ mask;
|
||||
RTE_PIPELINE_STATS_ADD_M(port_out->n_pkts_dropped_by_ah,
|
||||
pkts_mask ^ mask);
|
||||
/* Output port user actions */
|
||||
if (port_out->f_action != NULL) {
|
||||
port_out->f_action(p, p->pkts, pkts_mask, port_out->arg_ah);
|
||||
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
port_out->n_pkts_dropped_by_ah);
|
||||
}
|
||||
|
||||
/* Output port TX */
|
||||
if (pkts_mask != 0)
|
||||
port_out->ops.f_tx_bulk(port_out->h_port, p->pkts, pkts_mask);
|
||||
if (p->pkts_mask != 0)
|
||||
port_out->ops.f_tx_bulk(port_out->h_port,
|
||||
p->pkts,
|
||||
p->pkts_mask);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask)
|
||||
{
|
||||
p->pkts_mask = pkts_mask;
|
||||
|
||||
if ((pkts_mask & (pkts_mask + 1)) == 0) {
|
||||
uint64_t n_pkts = __builtin_popcountll(pkts_mask);
|
||||
uint32_t i;
|
||||
@ -1185,18 +1188,18 @@ rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask)
|
||||
if (port_out->f_action == NULL) /* Output port TX */
|
||||
port_out->ops.f_tx(port_out->h_port, pkt);
|
||||
else {
|
||||
uint64_t pkt_mask = 1LLU;
|
||||
uint64_t pkt_mask = 1LLU << i;
|
||||
|
||||
port_out->f_action(pkt, &pkt_mask,
|
||||
port_out->f_action(p,
|
||||
p->pkts,
|
||||
pkt_mask,
|
||||
port_out->arg_ah);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
|
||||
(pkt_mask ^ 1LLU) << i;
|
||||
|
||||
RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah,
|
||||
pkt_mask ^ 1LLU);
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
port_out->n_pkts_dropped_by_ah);
|
||||
|
||||
/* Output port TX */
|
||||
if (pkt_mask != 0)
|
||||
if (pkt_mask & p->pkts_mask)
|
||||
port_out->ops.f_tx(port_out->h_port,
|
||||
pkt);
|
||||
}
|
||||
@ -1221,18 +1224,16 @@ rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask)
|
||||
if (port_out->f_action == NULL) /* Output port TX */
|
||||
port_out->ops.f_tx(port_out->h_port, pkt);
|
||||
else {
|
||||
pkt_mask = 1LLU;
|
||||
|
||||
port_out->f_action(pkt, &pkt_mask,
|
||||
port_out->f_action(p,
|
||||
p->pkts,
|
||||
pkt_mask,
|
||||
port_out->arg_ah);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
|
||||
(pkt_mask ^ 1LLU) << i;
|
||||
|
||||
RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah,
|
||||
pkt_mask ^ 1LLU);
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
port_out->n_pkts_dropped_by_ah);
|
||||
|
||||
/* Output port TX */
|
||||
if (pkt_mask != 0)
|
||||
if (pkt_mask & p->pkts_mask)
|
||||
port_out->ops.f_tx(port_out->h_port,
|
||||
pkt);
|
||||
}
|
||||
@ -1244,6 +1245,8 @@ static inline void
|
||||
rte_pipeline_action_handler_port_meta(struct rte_pipeline *p,
|
||||
uint64_t pkts_mask)
|
||||
{
|
||||
p->pkts_mask = pkts_mask;
|
||||
|
||||
if ((pkts_mask & (pkts_mask + 1)) == 0) {
|
||||
uint64_t n_pkts = __builtin_popcountll(pkts_mask);
|
||||
uint32_t i;
|
||||
@ -1260,18 +1263,18 @@ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p,
|
||||
if (port_out->f_action == NULL) /* Output port TX */
|
||||
port_out->ops.f_tx(port_out->h_port, pkt);
|
||||
else {
|
||||
uint64_t pkt_mask = 1LLU;
|
||||
uint64_t pkt_mask = 1LLU << i;
|
||||
|
||||
port_out->f_action(pkt, &pkt_mask,
|
||||
port_out->f_action(p,
|
||||
p->pkts,
|
||||
pkt_mask,
|
||||
port_out->arg_ah);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
|
||||
(pkt_mask ^ 1LLU) << i;
|
||||
|
||||
RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah,
|
||||
pkt_mask ^ 1ULL);
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
port_out->n_pkts_dropped_by_ah);
|
||||
|
||||
/* Output port TX */
|
||||
if (pkt_mask != 0)
|
||||
if (pkt_mask & p->pkts_mask)
|
||||
port_out->ops.f_tx(port_out->h_port,
|
||||
pkt);
|
||||
}
|
||||
@ -1297,18 +1300,16 @@ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p,
|
||||
if (port_out->f_action == NULL) /* Output port TX */
|
||||
port_out->ops.f_tx(port_out->h_port, pkt);
|
||||
else {
|
||||
pkt_mask = 1LLU;
|
||||
|
||||
port_out->f_action(pkt, &pkt_mask,
|
||||
port_out->f_action(p,
|
||||
p->pkts,
|
||||
pkt_mask,
|
||||
port_out->arg_ah);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
|
||||
(pkt_mask ^ 1LLU) << i;
|
||||
|
||||
RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah,
|
||||
pkt_mask ^ 1ULL);
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
port_out->n_pkts_dropped_by_ah);
|
||||
|
||||
/* Output port TX */
|
||||
if (pkt_mask != 0)
|
||||
if (pkt_mask & p->pkts_mask)
|
||||
port_out->ops.f_tx(port_out->h_port,
|
||||
pkt);
|
||||
}
|
||||
@ -1342,136 +1343,140 @@ rte_pipeline_action_handler_drop(struct rte_pipeline *p, uint64_t pkts_mask)
|
||||
int
|
||||
rte_pipeline_run(struct rte_pipeline *p)
|
||||
{
|
||||
struct rte_port_in *port_in;
|
||||
struct rte_port_in *port_in = p->port_in_next;
|
||||
uint32_t n_pkts, table_id;
|
||||
|
||||
for (port_in = p->port_in_first; port_in != NULL;
|
||||
port_in = port_in->next) {
|
||||
uint64_t pkts_mask;
|
||||
uint32_t n_pkts, table_id;
|
||||
if (port_in == NULL)
|
||||
return 0;
|
||||
|
||||
/* Input port RX */
|
||||
n_pkts = port_in->ops.f_rx(port_in->h_port, p->pkts,
|
||||
port_in->burst_size);
|
||||
if (n_pkts == 0)
|
||||
continue;
|
||||
|
||||
pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] = 0;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT] = 0;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] = 0;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0;
|
||||
|
||||
/* Input port user actions */
|
||||
if (port_in->f_action != NULL) {
|
||||
uint64_t mask = pkts_mask;
|
||||
|
||||
port_in->f_action(p->pkts, n_pkts, &pkts_mask, port_in->arg_ah);
|
||||
mask ^= pkts_mask;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask;
|
||||
RTE_PIPELINE_STATS_ADD_M(port_in->n_pkts_dropped_by_ah, mask);
|
||||
}
|
||||
|
||||
/* Table */
|
||||
for (table_id = port_in->table_id; pkts_mask != 0; ) {
|
||||
struct rte_table *table;
|
||||
uint64_t lookup_hit_mask, lookup_miss_mask;
|
||||
|
||||
/* Lookup */
|
||||
table = &p->tables[table_id];
|
||||
table->ops.f_lookup(table->h_table, p->pkts, pkts_mask,
|
||||
&lookup_hit_mask, (void **) p->entries);
|
||||
lookup_miss_mask = pkts_mask & (~lookup_hit_mask);
|
||||
|
||||
/* Lookup miss */
|
||||
if (lookup_miss_mask != 0) {
|
||||
struct rte_pipeline_table_entry *default_entry =
|
||||
table->default_entry;
|
||||
|
||||
/* Table user actions */
|
||||
if (table->f_action_miss != NULL) {
|
||||
uint64_t mask = lookup_miss_mask;
|
||||
|
||||
table->f_action_miss(p->pkts,
|
||||
&lookup_miss_mask,
|
||||
default_entry, table->arg_ah);
|
||||
mask ^= lookup_miss_mask;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask;
|
||||
RTE_PIPELINE_STATS_ADD_M(
|
||||
table->n_pkts_dropped_by_lkp_miss_ah, mask);
|
||||
}
|
||||
|
||||
/* Table reserved actions */
|
||||
if ((default_entry->action ==
|
||||
RTE_PIPELINE_ACTION_PORT) &&
|
||||
(lookup_miss_mask != 0))
|
||||
rte_pipeline_action_handler_port_bulk(p,
|
||||
lookup_miss_mask,
|
||||
default_entry->port_id);
|
||||
else {
|
||||
uint32_t pos = default_entry->action;
|
||||
|
||||
p->action_mask0[pos] = lookup_miss_mask;
|
||||
if (pos == RTE_PIPELINE_ACTION_DROP) {
|
||||
RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_miss,
|
||||
lookup_miss_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Lookup hit */
|
||||
if (lookup_hit_mask != 0) {
|
||||
/* Table user actions */
|
||||
if (table->f_action_hit != NULL) {
|
||||
uint64_t mask = lookup_hit_mask;
|
||||
|
||||
table->f_action_hit(p->pkts,
|
||||
&lookup_hit_mask,
|
||||
p->entries, table->arg_ah);
|
||||
mask ^= lookup_hit_mask;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= mask;
|
||||
RTE_PIPELINE_STATS_ADD_M(
|
||||
table->n_pkts_dropped_by_lkp_hit_ah, mask);
|
||||
}
|
||||
|
||||
/* Table reserved actions */
|
||||
rte_pipeline_compute_masks(p, lookup_hit_mask);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_DROP];
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_PORT];
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_PORT_META];
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_TABLE] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_TABLE];
|
||||
|
||||
RTE_PIPELINE_STATS_ADD_M(table->n_pkts_dropped_lkp_hit,
|
||||
p->action_mask1[RTE_PIPELINE_ACTION_DROP]);
|
||||
}
|
||||
|
||||
/* Prepare for next iteration */
|
||||
pkts_mask = p->action_mask0[RTE_PIPELINE_ACTION_TABLE];
|
||||
table_id = table->table_next_id;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0;
|
||||
}
|
||||
|
||||
/* Table reserved action PORT */
|
||||
rte_pipeline_action_handler_port(p,
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT]);
|
||||
|
||||
/* Table reserved action PORT META */
|
||||
rte_pipeline_action_handler_port_meta(p,
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT_META]);
|
||||
|
||||
/* Table reserved action DROP */
|
||||
rte_pipeline_action_handler_drop(p,
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP]);
|
||||
/* Input port RX */
|
||||
n_pkts = port_in->ops.f_rx(port_in->h_port, p->pkts,
|
||||
port_in->burst_size);
|
||||
if (n_pkts == 0) {
|
||||
p->port_in_next = port_in->next;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
p->pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] = 0;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT] = 0;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] = 0;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0;
|
||||
|
||||
/* Input port user actions */
|
||||
if (port_in->f_action != NULL) {
|
||||
port_in->f_action(p, p->pkts, n_pkts, port_in->arg_ah);
|
||||
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
port_in->n_pkts_dropped_by_ah);
|
||||
}
|
||||
|
||||
/* Table */
|
||||
for (table_id = port_in->table_id; p->pkts_mask != 0; ) {
|
||||
struct rte_table *table;
|
||||
uint64_t lookup_hit_mask, lookup_miss_mask;
|
||||
|
||||
/* Lookup */
|
||||
table = &p->tables[table_id];
|
||||
table->ops.f_lookup(table->h_table, p->pkts, p->pkts_mask,
|
||||
&lookup_hit_mask, (void **) p->entries);
|
||||
lookup_miss_mask = p->pkts_mask & (~lookup_hit_mask);
|
||||
|
||||
/* Lookup miss */
|
||||
if (lookup_miss_mask != 0) {
|
||||
struct rte_pipeline_table_entry *default_entry =
|
||||
table->default_entry;
|
||||
|
||||
p->pkts_mask = lookup_miss_mask;
|
||||
|
||||
/* Table user actions */
|
||||
if (table->f_action_miss != NULL) {
|
||||
table->f_action_miss(p,
|
||||
p->pkts,
|
||||
lookup_miss_mask,
|
||||
default_entry,
|
||||
table->arg_ah);
|
||||
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
table->n_pkts_dropped_by_lkp_miss_ah);
|
||||
}
|
||||
|
||||
/* Table reserved actions */
|
||||
if ((default_entry->action == RTE_PIPELINE_ACTION_PORT) &&
|
||||
(p->pkts_mask != 0))
|
||||
rte_pipeline_action_handler_port_bulk(p,
|
||||
p->pkts_mask,
|
||||
default_entry->port_id);
|
||||
else {
|
||||
uint32_t pos = default_entry->action;
|
||||
|
||||
RTE_PIPELINE_STATS_TABLE_DROP0(p);
|
||||
|
||||
p->action_mask0[pos] |= p->pkts_mask;
|
||||
|
||||
RTE_PIPELINE_STATS_TABLE_DROP1(p,
|
||||
table->n_pkts_dropped_lkp_miss);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lookup hit */
|
||||
if (lookup_hit_mask != 0) {
|
||||
p->pkts_mask = lookup_hit_mask;
|
||||
|
||||
/* Table user actions */
|
||||
if (table->f_action_hit != NULL) {
|
||||
table->f_action_hit(p,
|
||||
p->pkts,
|
||||
lookup_hit_mask,
|
||||
p->entries,
|
||||
table->arg_ah);
|
||||
|
||||
RTE_PIPELINE_STATS_AH_DROP_READ(p,
|
||||
table->n_pkts_dropped_by_lkp_hit_ah);
|
||||
}
|
||||
|
||||
/* Table reserved actions */
|
||||
RTE_PIPELINE_STATS_TABLE_DROP0(p);
|
||||
rte_pipeline_compute_masks(p, p->pkts_mask);
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_DROP];
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_PORT];
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_PORT_META];
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_TABLE] |=
|
||||
p->action_mask1[
|
||||
RTE_PIPELINE_ACTION_TABLE];
|
||||
|
||||
RTE_PIPELINE_STATS_TABLE_DROP1(p,
|
||||
table->n_pkts_dropped_lkp_hit);
|
||||
}
|
||||
|
||||
/* Prepare for next iteration */
|
||||
p->pkts_mask = p->action_mask0[RTE_PIPELINE_ACTION_TABLE];
|
||||
table_id = table->table_next_id;
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0;
|
||||
}
|
||||
|
||||
/* Table reserved action PORT */
|
||||
rte_pipeline_action_handler_port(p,
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT]);
|
||||
|
||||
/* Table reserved action PORT META */
|
||||
rte_pipeline_action_handler_port_meta(p,
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_PORT_META]);
|
||||
|
||||
/* Table reserved action DROP */
|
||||
rte_pipeline_action_handler_drop(p,
|
||||
p->action_mask0[RTE_PIPELINE_ACTION_DROP]);
|
||||
|
||||
/* Pick candidate for next port IN to serve */
|
||||
p->port_in_next = port_in->next;
|
||||
|
||||
return (int) n_pkts;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1498,25 +1503,11 @@ rte_pipeline_flush(struct rte_pipeline *p)
|
||||
|
||||
int
|
||||
rte_pipeline_port_out_packet_insert(struct rte_pipeline *p,
|
||||
uint32_t port_id, struct rte_mbuf *pkt)
|
||||
uint32_t port_id, struct rte_mbuf *pkt)
|
||||
{
|
||||
struct rte_port_out *port_out = &p->ports_out[port_id];
|
||||
|
||||
/* Output port user actions */
|
||||
if (port_out->f_action == NULL)
|
||||
port_out->ops.f_tx(port_out->h_port, pkt); /* Output port TX */
|
||||
else {
|
||||
uint64_t pkt_mask = 1LLU;
|
||||
|
||||
port_out->f_action(pkt, &pkt_mask, port_out->arg_ah);
|
||||
|
||||
if (pkt_mask != 0) /* Output port TX */
|
||||
port_out->ops.f_tx(port_out->h_port, pkt);
|
||||
else {
|
||||
rte_pktmbuf_free(pkt);
|
||||
RTE_PIPELINE_STATS_ADD(port_out->n_pkts_dropped_by_ah, 1);
|
||||
}
|
||||
}
|
||||
port_out->ops.f_tx(port_out->h_port, pkt); /* Output port TX */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -142,12 +142,12 @@ struct rte_pipeline_table_stats {
|
||||
/** Number of packets dropped by lookup miss action handler. */
|
||||
uint64_t n_pkts_dropped_by_lkp_miss_ah;
|
||||
|
||||
/** Number of packets dropped by pipeline in behalf of this table based on
|
||||
* on action specified in table entry. */
|
||||
/** Number of packets dropped by pipeline in behalf of this
|
||||
* table based on action specified in table entry. */
|
||||
uint64_t n_pkts_dropped_lkp_hit;
|
||||
|
||||
/** Number of packets dropped by pipeline in behalf of this table based on
|
||||
* on action specified in table entry. */
|
||||
/** Number of packets dropped by pipeline in behalf of this
|
||||
* table based on action specified in table entry. */
|
||||
uint64_t n_pkts_dropped_lkp_miss;
|
||||
};
|
||||
|
||||
@ -187,7 +187,7 @@ int rte_pipeline_check(struct rte_pipeline *p);
|
||||
* @param p
|
||||
* Handle to pipeline instance
|
||||
* @return
|
||||
* 0 on success, error code otherwise
|
||||
* Number of packets read and processed
|
||||
*/
|
||||
int rte_pipeline_run(struct rte_pipeline *p);
|
||||
|
||||
@ -263,6 +263,8 @@ struct rte_pipeline_table_entry {
|
||||
* required not to free the packet buffer, which will be freed eventually by
|
||||
* the pipeline.
|
||||
*
|
||||
* @param p
|
||||
* Handle to pipeline instance
|
||||
* @param pkts
|
||||
* Burst of input packets specified as array of up to 64 pointers to struct
|
||||
* rte_mbuf
|
||||
@ -283,8 +285,9 @@ struct rte_pipeline_table_entry {
|
||||
* 0 on success, error code otherwise
|
||||
*/
|
||||
typedef int (*rte_pipeline_table_action_handler_hit)(
|
||||
struct rte_pipeline *p,
|
||||
struct rte_mbuf **pkts,
|
||||
uint64_t *pkts_mask,
|
||||
uint64_t pkts_mask,
|
||||
struct rte_pipeline_table_entry **entries,
|
||||
void *arg);
|
||||
|
||||
@ -296,6 +299,8 @@ typedef int (*rte_pipeline_table_action_handler_hit)(
|
||||
* required not to free the packet buffer, which will be freed eventually by
|
||||
* the pipeline.
|
||||
*
|
||||
* @param p
|
||||
* Handle to pipeline instance
|
||||
* @param pkts
|
||||
* Burst of input packets specified as array of up to 64 pointers to struct
|
||||
* rte_mbuf
|
||||
@ -316,8 +321,9 @@ typedef int (*rte_pipeline_table_action_handler_hit)(
|
||||
* 0 on success, error code otherwise
|
||||
*/
|
||||
typedef int (*rte_pipeline_table_action_handler_miss)(
|
||||
struct rte_pipeline *p,
|
||||
struct rte_mbuf **pkts,
|
||||
uint64_t *pkts_mask,
|
||||
uint64_t pkts_mask,
|
||||
struct rte_pipeline_table_entry *entry,
|
||||
void *arg);
|
||||
|
||||
@ -565,16 +571,14 @@ int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id,
|
||||
* required not to free the packet buffer, which will be freed eventually by
|
||||
* the pipeline.
|
||||
*
|
||||
* @param p
|
||||
* Handle to pipeline instance
|
||||
* @param pkts
|
||||
* Burst of input packets specified as array of up to 64 pointers to struct
|
||||
* rte_mbuf
|
||||
* @param n
|
||||
* Number of packets in the input burst. This parameter specifies that
|
||||
* elements 0 to (n-1) of pkts array are valid.
|
||||
* @param pkts_mask
|
||||
* 64-bit bitmask specifying which packets in the input burst are still valid
|
||||
* after the action handler is executed. When pkts_mask bit n is set, then
|
||||
* element n of pkts array is pointing to a valid packet.
|
||||
* @param arg
|
||||
* Opaque parameter registered by the user at the pipeline table creation
|
||||
* time
|
||||
@ -582,9 +586,9 @@ int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id,
|
||||
* 0 on success, error code otherwise
|
||||
*/
|
||||
typedef int (*rte_pipeline_port_in_action_handler)(
|
||||
struct rte_pipeline *p,
|
||||
struct rte_mbuf **pkts,
|
||||
uint32_t n,
|
||||
uint64_t *pkts_mask,
|
||||
void *arg);
|
||||
|
||||
/** Parameters for pipeline input port creation */
|
||||
@ -692,36 +696,15 @@ int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id,
|
||||
#define RTE_PIPELINE_PORT_OUT_MAX 64
|
||||
|
||||
/**
|
||||
* Pipeline output port action handler for single packet
|
||||
*
|
||||
* The action handler can decide to drop packets by resetting the pkt_mask
|
||||
* argument. In this case, the action handler is required not to free the
|
||||
* packet buffer, which will be freed eventually by the pipeline.
|
||||
*
|
||||
* @param pkt
|
||||
* Input packet
|
||||
* @param pkt_mask
|
||||
* Output argument set to 0 when the action handler decides to drop the input
|
||||
* packet and to 1LLU otherwise
|
||||
* @param arg
|
||||
* Opaque parameter registered by the user at the pipeline table creation
|
||||
* time
|
||||
* @return
|
||||
* 0 on success, error code otherwise
|
||||
*/
|
||||
typedef int (*rte_pipeline_port_out_action_handler)(
|
||||
struct rte_mbuf *pkt,
|
||||
uint64_t *pkt_mask,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Pipeline output port action handler bulk
|
||||
* Pipeline output port action handler
|
||||
*
|
||||
* The action handler can decide to drop packets by resetting the associated
|
||||
* packet bit in the pkts_mask parameter. In this case, the action handler is
|
||||
* required not to free the packet buffer, which will be freed eventually by
|
||||
* the pipeline.
|
||||
*
|
||||
* @param p
|
||||
* Handle to pipeline instance
|
||||
* @param pkts
|
||||
* Burst of input packets specified as array of up to 64 pointers to struct
|
||||
* rte_mbuf
|
||||
@ -735,9 +718,10 @@ typedef int (*rte_pipeline_port_out_action_handler)(
|
||||
* @return
|
||||
* 0 on success, error code otherwise
|
||||
*/
|
||||
typedef int (*rte_pipeline_port_out_action_handler_bulk)(
|
||||
typedef int (*rte_pipeline_port_out_action_handler)(
|
||||
struct rte_pipeline *p,
|
||||
struct rte_mbuf **pkts,
|
||||
uint64_t *pkts_mask,
|
||||
uint64_t pkts_mask,
|
||||
void *arg);
|
||||
|
||||
/** Parameters for pipeline output port creation. The action handlers have to
|
||||
@ -750,12 +734,9 @@ struct rte_pipeline_port_out_params {
|
||||
/** Opaque parameter to be passed to create operation when invoked */
|
||||
void *arg_create;
|
||||
|
||||
/** Callback function executing the user actions on single input
|
||||
packet */
|
||||
rte_pipeline_port_out_action_handler f_action;
|
||||
/** Callback function executing the user actions on bust of input
|
||||
packets */
|
||||
rte_pipeline_port_out_action_handler_bulk f_action_bulk;
|
||||
rte_pipeline_port_out_action_handler f_action;
|
||||
/** Opaque parameter to be passed to the action handler when invoked */
|
||||
void *arg_ah;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user