From: Jasvinder Singh Date: Tue, 8 Mar 2016 18:07:48 +0000 (+0000) Subject: pipeline: support packet redirection at action handlers X-Git-Tag: spdx-start~7513 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=88ac2fd99fa06419c5b95ad662dc1e618bd8ac49;p=dpdk.git 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 Acked-by: Cristian Dumitrescu --- diff --git a/app/test-pipeline/pipeline_acl.c b/app/test-pipeline/pipeline_acl.c index f163e55ae9..22d5f362a7 100644 --- a/app/test-pipeline/pipeline_acl.c +++ b/app/test-pipeline/pipeline_acl.c @@ -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, }; diff --git a/app/test-pipeline/pipeline_hash.c b/app/test-pipeline/pipeline_hash.c index 8b888d7953..f8aac0d818 100644 --- a/app/test-pipeline/pipeline_hash.c +++ b/app/test-pipeline/pipeline_hash.c @@ -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, }; diff --git a/app/test-pipeline/pipeline_lpm.c b/app/test-pipeline/pipeline_lpm.c index 2d7bc012c7..916abd42b6 100644 --- a/app/test-pipeline/pipeline_lpm.c +++ b/app/test-pipeline/pipeline_lpm.c @@ -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, }; diff --git a/app/test-pipeline/pipeline_lpm_ipv6.c b/app/test-pipeline/pipeline_lpm_ipv6.c index c895b624cd..3352e89df7 100644 --- a/app/test-pipeline/pipeline_lpm_ipv6.c +++ b/app/test-pipeline/pipeline_lpm_ipv6.c @@ -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, }; diff --git a/app/test-pipeline/pipeline_stub.c b/app/test-pipeline/pipeline_stub.c index 0ad6f9b8ff..ba710ca6ae 100644 --- a/app/test-pipeline/pipeline_stub.c +++ b/app/test-pipeline/pipeline_stub.c @@ -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, }; diff --git a/app/test/test_table_acl.c b/app/test/test_table_acl.c index 38e3a8ee6e..b3bfda4ccc 100644 --- a/app/test/test_table_acl.c +++ b/app/test/test_table_acl.c @@ -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); diff --git a/app/test/test_table_pipeline.c b/app/test/test_table_pipeline.c index ff07cdaeed..4bcce2bf2e 100644 --- a/app/test/test_table_pipeline.c +++ b/app/test/test_table_pipeline.c @@ -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__); diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index 52878114a2..f033bbc869 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -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. diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst index ab49608317..aa9eabce47 100644 --- a/doc/guides/rel_notes/release_16_04.rst +++ b/doc/guides/rel_notes/release_16_04.rst @@ -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 diff --git a/examples/ip_pipeline/pipeline/pipeline_actions_common.h b/examples/ip_pipeline/pipeline/pipeline_actions_common.h index aa1dd59a37..73cf562ae8 100644 --- a/examples/ip_pipeline/pipeline/pipeline_actions_common.h +++ b/examples/ip_pipeline/pipeline/pipeline_actions_common.h @@ -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 + +#include +#include +#include +#include + #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; \ } diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c index 1981cc75ed..e7a8a4c5cc 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c @@ -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, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c index 0dfdb0569b..3ad3ee63c9 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c @@ -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, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c index c528dfb4bb..60e9c39575 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c @@ -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, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c index 630de3b234..3e3fdd0870 100644 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c @@ -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, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c index 4fb6b597e1..8342b7b7dd 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c @@ -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, }; diff --git a/lib/librte_pipeline/Makefile b/lib/librte_pipeline/Makefile index 1166d3c783..822fd41c97 100644 --- a/lib/librte_pipeline/Makefile +++ b/lib/librte_pipeline/Makefile @@ -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 diff --git a/lib/librte_pipeline/rte_pipeline.c b/lib/librte_pipeline/rte_pipeline.c index d625fd25ed..b7a02d6e34 100644 --- a/lib/librte_pipeline/rte_pipeline.c +++ b/lib/librte_pipeline/rte_pipeline.c @@ -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]; + p->pkts_mask = pkts_mask; + /* Output port user actions */ - if (port_out->f_action_bulk != NULL) { - uint64_t mask = pkts_mask; + if (port_out->f_action != NULL) { + port_out->f_action(p, p->pkts, pkts_mask, port_out->arg_ah); - 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); + 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; - - 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; - - /* 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; + struct rte_port_in *port_in = p->port_in_next; + uint32_t n_pkts, table_id; + + if (port_in == NULL) + return 0; - /* Input port user actions */ - if (port_in->f_action != NULL) { - uint64_t mask = pkts_mask; + /* 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; + } - 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); - } + 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; - /* 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); - } - } - } + /* 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 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]); + /* 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); } - /* 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 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); + } } - /* Table reserved action PORT */ - rte_pipeline_action_handler_port(p, - p->action_mask0[RTE_PIPELINE_ACTION_PORT]); + /* 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 action PORT META */ - rte_pipeline_action_handler_port_meta(p, - p->action_mask0[RTE_PIPELINE_ACTION_PORT_META]); + /* 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); + } - /* Table reserved action DROP */ - rte_pipeline_action_handler_drop(p, - p->action_mask0[RTE_PIPELINE_ACTION_DROP]); + /* 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; } - return 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; } diff --git a/lib/librte_pipeline/rte_pipeline.h b/lib/librte_pipeline/rte_pipeline.h index 7302a62060..0b02969a58 100644 --- a/lib/librte_pipeline/rte_pipeline.h +++ b/lib/librte_pipeline/rte_pipeline.h @@ -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; };