diff options
author | Christian Ehrhardt <christian.ehrhardt@canonical.com> | 2016-07-06 09:22:35 +0200 |
---|---|---|
committer | Christian Ehrhardt <christian.ehrhardt@canonical.com> | 2016-07-06 16:09:40 +0200 |
commit | 8b25d1ad5d2264bdfc2818c7bda74ee2697df6db (patch) | |
tree | 8c3c769777f7e66a2d1ba7dd7651b563cfde370b /examples/ip_pipeline | |
parent | 97f17497d162afdb82c8704bf097f0fee3724b2e (diff) |
Imported Upstream version 16.07-rc1
Change-Id: I40a523e52f12e8496fdd69e902824b0226c303de
Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Diffstat (limited to 'examples/ip_pipeline')
51 files changed, 7313 insertions, 5675 deletions
diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile index 10fe1ba9..58271173 100644 --- a/examples/ip_pipeline/Makefile +++ b/examples/ip_pipeline/Makefile @@ -50,6 +50,7 @@ INC += $(wildcard *.h) $(wildcard pipeline/*.h) # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += parser.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h index 55a98417..6a6fdd97 100644 --- a/examples/ip_pipeline/app.h +++ b/examples/ip_pipeline/app.h @@ -44,12 +44,24 @@ #include <cmdline_parse.h> #include <rte_ethdev.h> +#ifdef RTE_LIBRTE_KNI +#include <rte_kni.h> +#endif #include "cpu_core_map.h" #include "pipeline.h" #define APP_PARAM_NAME_SIZE PIPELINE_NAME_SIZE #define APP_LINK_PCI_BDF_SIZE 16 + +#ifndef APP_LINK_MAX_HWQ_IN +#define APP_LINK_MAX_HWQ_IN 128 +#endif + +#ifndef APP_LINK_MAX_HWQ_OUT +#define APP_LINK_MAX_HWQ_OUT 128 +#endif + struct app_mempool_params { char *name; uint32_t parsed; @@ -69,6 +81,12 @@ struct app_link_params { uint32_t tcp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t udp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ uint32_t sctp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ + uint32_t rss_qs[APP_LINK_MAX_HWQ_IN]; + uint32_t n_rss_qs; + uint64_t rss_proto_ipv4; + uint64_t rss_proto_ipv6; + uint64_t rss_proto_l2; + uint32_t promisc; uint32_t state; /* DOWN = 0, UP = 1 */ uint32_t ip; /* 0 = Invalid */ uint32_t depth; /* Valid only when IP is valid */ @@ -76,7 +94,6 @@ struct app_link_params { char pci_bdf[APP_LINK_PCI_BDF_SIZE]; struct rte_eth_conf conf; - uint8_t promisc; }; struct app_pktq_hwq_in_params { @@ -118,6 +135,22 @@ struct app_pktq_swq_params { uint32_t mempool_indirect_id; }; +struct app_pktq_kni_params { + char *name; + uint32_t parsed; + + uint32_t socket_id; + uint32_t core_id; + uint32_t hyper_th_id; + uint32_t force_bind; + + uint32_t mempool_id; /* Position in the app->mempool_params */ + uint32_t burst_read; + uint32_t burst_write; + uint32_t dropless; + uint64_t n_retries; +}; + #ifndef APP_FILE_NAME_SIZE #define APP_FILE_NAME_SIZE 256 #endif @@ -171,6 +204,7 @@ enum app_pktq_in_type { APP_PKTQ_IN_HWQ, APP_PKTQ_IN_SWQ, APP_PKTQ_IN_TM, + APP_PKTQ_IN_KNI, APP_PKTQ_IN_SOURCE, }; @@ -183,6 +217,7 @@ enum app_pktq_out_type { APP_PKTQ_OUT_HWQ, APP_PKTQ_OUT_SWQ, APP_PKTQ_OUT_TM, + APP_PKTQ_OUT_KNI, APP_PKTQ_OUT_SINK, }; @@ -191,9 +226,7 @@ struct app_pktq_out_params { uint32_t id; /* Position in the appropriate app array */ }; -#ifndef APP_PIPELINE_TYPE_SIZE -#define APP_PIPELINE_TYPE_SIZE 64 -#endif +#define APP_PIPELINE_TYPE_SIZE PIPELINE_TYPE_SIZE #define APP_MAX_PIPELINE_PKTQ_IN PIPELINE_MAX_PORT_IN #define APP_MAX_PIPELINE_PKTQ_OUT PIPELINE_MAX_PORT_OUT @@ -229,6 +262,22 @@ struct app_pipeline_params { uint32_t n_args; }; +struct app_params; + +typedef void (*app_link_op)(struct app_params *app, + uint32_t link_id, + uint32_t up, + void *arg); + +#ifndef APP_MAX_PIPELINES +#define APP_MAX_PIPELINES 64 +#endif + +struct app_link_data { + app_link_op f_link[APP_MAX_PIPELINES]; + void *arg[APP_MAX_PIPELINES]; +}; + struct app_pipeline_data { void *be; void *fe; @@ -247,7 +296,7 @@ struct app_thread_pipeline_data { }; #ifndef APP_MAX_THREAD_PIPELINES -#define APP_MAX_THREAD_PIPELINES 16 +#define APP_MAX_THREAD_PIPELINES 64 #endif #ifndef APP_THREAD_TIMER_PERIOD @@ -272,7 +321,7 @@ struct app_thread_data { uint64_t headroom_time; uint64_t headroom_cycles; double headroom_ratio; -}; +} __rte_cache_aligned; #ifndef APP_MAX_LINKS #define APP_MAX_LINKS 16 @@ -370,6 +419,8 @@ struct app_eal_params { /* Support running on Xen dom0 without hugetlbfs */ uint32_t xen_dom0_present; int xen_dom0; + + uint32_t parsed; }; #ifndef APP_APPNAME_SIZE @@ -380,17 +431,9 @@ struct app_eal_params { #define APP_MAX_MEMPOOLS 8 #endif -#ifndef APP_LINK_MAX_HWQ_IN -#define APP_LINK_MAX_HWQ_IN 64 -#endif +#define APP_MAX_HWQ_IN (APP_MAX_LINKS * APP_LINK_MAX_HWQ_IN) -#ifndef APP_LINK_MAX_HWQ_OUT -#define APP_LINK_MAX_HWQ_OUT 64 -#endif - -#define APP_MAX_HWQ_IN (APP_MAX_LINKS * APP_LINK_MAX_HWQ_IN) - -#define APP_MAX_HWQ_OUT (APP_MAX_LINKS * APP_LINK_MAX_HWQ_OUT) +#define APP_MAX_HWQ_OUT (APP_MAX_LINKS * APP_LINK_MAX_HWQ_OUT) #ifndef APP_MAX_PKTQ_SWQ #define APP_MAX_PKTQ_SWQ 256 @@ -398,24 +441,22 @@ struct app_eal_params { #define APP_MAX_PKTQ_TM APP_MAX_LINKS +#define APP_MAX_PKTQ_KNI APP_MAX_LINKS + #ifndef APP_MAX_PKTQ_SOURCE -#define APP_MAX_PKTQ_SOURCE 16 +#define APP_MAX_PKTQ_SOURCE 64 #endif #ifndef APP_MAX_PKTQ_SINK -#define APP_MAX_PKTQ_SINK 16 +#define APP_MAX_PKTQ_SINK 64 #endif #ifndef APP_MAX_MSGQ -#define APP_MAX_MSGQ 64 -#endif - -#ifndef APP_MAX_PIPELINES -#define APP_MAX_PIPELINES 64 +#define APP_MAX_MSGQ 256 #endif #ifndef APP_EAL_ARGC -#define APP_EAL_ARGC 32 +#define APP_EAL_ARGC 64 #endif #ifndef APP_MAX_PIPELINE_TYPES @@ -453,6 +494,7 @@ struct app_params { struct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT]; struct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ]; struct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM]; + struct app_pktq_kni_params kni_params[APP_MAX_PKTQ_KNI]; struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE]; struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK]; struct app_msgq_params msgq_params[APP_MAX_MSGQ]; @@ -464,6 +506,7 @@ struct app_params { uint32_t n_pktq_hwq_out; uint32_t n_pktq_swq; uint32_t n_pktq_tm; + uint32_t n_pktq_kni; uint32_t n_pktq_source; uint32_t n_pktq_sink; uint32_t n_msgq; @@ -474,8 +517,12 @@ struct app_params { struct cpu_core_map *core_map; uint64_t core_mask; struct rte_mempool *mempool[APP_MAX_MEMPOOLS]; + struct app_link_data link_data[APP_MAX_LINKS]; struct rte_ring *swq[APP_MAX_PKTQ_SWQ]; struct rte_sched_port *tm[APP_MAX_PKTQ_TM]; +#ifdef RTE_LIBRTE_KNI + struct rte_kni *kni[APP_MAX_PKTQ_KNI]; +#endif /* RTE_LIBRTE_KNI */ struct rte_ring *msgq[APP_MAX_MSGQ]; struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES]; struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES]; @@ -529,28 +576,6 @@ do \ sscanf(obj->name, prefix "%" SCNu32, &id); \ while (0) \ -#define APP_PARAM_ADD(obj_array, obj_name) \ -({ \ - ssize_t obj_idx; \ - const ssize_t obj_count = RTE_DIM(obj_array); \ - \ - obj_idx = APP_PARAM_FIND(obj_array, obj_name); \ - if (obj_idx < 0) { \ - for (obj_idx = 0; obj_idx < obj_count; obj_idx++) { \ - if (!APP_PARAM_VALID(&((obj_array)[obj_idx]))) \ - break; \ - } \ - \ - if (obj_idx < obj_count) { \ - (obj_array)[obj_idx].name = strdup(obj_name); \ - if ((obj_array)[obj_idx].name == NULL) \ - obj_idx = -EINVAL; \ - } else \ - obj_idx = -ENOMEM; \ - } \ - obj_idx; \ -}) - #define APP_CHECK(exp, fmt, ...) \ do { \ if (!(exp)) { \ @@ -665,6 +690,41 @@ app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq) return n_readers; } +static inline struct app_pipeline_params * +app_swq_get_reader(struct app_params *app, + struct app_pktq_swq_params *swq, + uint32_t *pktq_in_id) +{ + struct app_pipeline_params *reader = NULL; + uint32_t pos = swq - app->swq_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_readers = 0, id = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); + uint32_t j; + + for (j = 0; j < n_pktq_in; j++) { + struct app_pktq_in_params *pktq = &p->pktq_in[j]; + + if ((pktq->type == APP_PKTQ_IN_SWQ) && + (pktq->id == pos)) { + n_readers++; + reader = p; + id = j; + } + } + } + + if (n_readers != 1) + return NULL; + + *pktq_in_id = id; + return reader; +} + static inline uint32_t app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm) { @@ -690,6 +750,101 @@ app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm) return n_readers; } +static inline struct app_pipeline_params * +app_tm_get_reader(struct app_params *app, + struct app_pktq_tm_params *tm, + uint32_t *pktq_in_id) +{ + struct app_pipeline_params *reader = NULL; + uint32_t pos = tm - app->tm_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_readers = 0, id = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); + uint32_t j; + + for (j = 0; j < n_pktq_in; j++) { + struct app_pktq_in_params *pktq = &p->pktq_in[j]; + + if ((pktq->type == APP_PKTQ_IN_TM) && + (pktq->id == pos)) { + n_readers++; + reader = p; + id = j; + } + } + } + + if (n_readers != 1) + return NULL; + + *pktq_in_id = id; + return reader; +} + +static inline uint32_t +app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni) +{ + uint32_t pos = kni - app->kni_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_readers = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); + uint32_t j; + + for (j = 0; j < n_pktq_in; j++) { + struct app_pktq_in_params *pktq = &p->pktq_in[j]; + + if ((pktq->type == APP_PKTQ_IN_KNI) && + (pktq->id == pos)) + n_readers++; + } + } + + return n_readers; +} + +static inline struct app_pipeline_params * +app_kni_get_reader(struct app_params *app, + struct app_pktq_kni_params *kni, + uint32_t *pktq_in_id) +{ + struct app_pipeline_params *reader = NULL; + uint32_t pos = kni - app->kni_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_readers = 0, id = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); + uint32_t j; + + for (j = 0; j < n_pktq_in; j++) { + struct app_pktq_in_params *pktq = &p->pktq_in[j]; + + if ((pktq->type == APP_PKTQ_IN_KNI) && + (pktq->id == pos)) { + n_readers++; + reader = p; + id = j; + } + } + } + + if (n_readers != 1) + return NULL; + + *pktq_in_id = id; + return reader; +} + static inline uint32_t app_source_get_readers(struct app_params *app, struct app_pktq_source_params *source) @@ -789,6 +944,42 @@ app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq) return n_writers; } +static inline struct app_pipeline_params * +app_swq_get_writer(struct app_params *app, + struct app_pktq_swq_params *swq, + uint32_t *pktq_out_id) +{ + struct app_pipeline_params *writer = NULL; + uint32_t pos = swq - app->swq_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_writers = 0, id = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, + RTE_DIM(p->pktq_out)); + uint32_t j; + + for (j = 0; j < n_pktq_out; j++) { + struct app_pktq_out_params *pktq = &p->pktq_out[j]; + + if ((pktq->type == APP_PKTQ_OUT_SWQ) && + (pktq->id == pos)) { + n_writers++; + writer = p; + id = j; + } + } + } + + if (n_writers != 1) + return NULL; + + *pktq_out_id = id; + return writer; +} + static inline uint32_t app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm) { @@ -815,6 +1006,104 @@ app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm) return n_writers; } +static inline struct app_pipeline_params * +app_tm_get_writer(struct app_params *app, + struct app_pktq_tm_params *tm, + uint32_t *pktq_out_id) +{ + struct app_pipeline_params *writer = NULL; + uint32_t pos = tm - app->tm_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_writers = 0, id = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, + RTE_DIM(p->pktq_out)); + uint32_t j; + + for (j = 0; j < n_pktq_out; j++) { + struct app_pktq_out_params *pktq = &p->pktq_out[j]; + + if ((pktq->type == APP_PKTQ_OUT_TM) && + (pktq->id == pos)) { + n_writers++; + writer = p; + id = j; + } + } + } + + if (n_writers != 1) + return NULL; + + *pktq_out_id = id; + return writer; +} + +static inline uint32_t +app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni) +{ + uint32_t pos = kni - app->kni_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_writers = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, + RTE_DIM(p->pktq_out)); + uint32_t j; + + for (j = 0; j < n_pktq_out; j++) { + struct app_pktq_out_params *pktq = &p->pktq_out[j]; + + if ((pktq->type == APP_PKTQ_OUT_KNI) && + (pktq->id == pos)) + n_writers++; + } + } + + return n_writers; +} + +static inline struct app_pipeline_params * +app_kni_get_writer(struct app_params *app, + struct app_pktq_kni_params *kni, + uint32_t *pktq_out_id) +{ + struct app_pipeline_params *writer = NULL; + uint32_t pos = kni - app->kni_params; + uint32_t n_pipelines = RTE_MIN(app->n_pipelines, + RTE_DIM(app->pipeline_params)); + uint32_t n_writers = 0, id = 0, i; + + for (i = 0; i < n_pipelines; i++) { + struct app_pipeline_params *p = &app->pipeline_params[i]; + uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, + RTE_DIM(p->pktq_out)); + uint32_t j; + + for (j = 0; j < n_pktq_out; j++) { + struct app_pktq_out_params *pktq = &p->pktq_out[j]; + + if ((pktq->type == APP_PKTQ_OUT_KNI) && + (pktq->id == pos)) { + n_writers++; + writer = p; + id = j; + } + } + } + + if (n_writers != 1) + return NULL; + + *pktq_out_id = id; + return writer; +} + static inline uint32_t app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink) { @@ -913,6 +1202,26 @@ app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm) return &app->link_params[link_param_idx]; } +static inline struct app_link_params * +app_get_link_for_kni(struct app_params *app, struct app_pktq_kni_params *p_kni) +{ + char link_name[APP_PARAM_NAME_SIZE]; + uint32_t link_id; + ssize_t link_param_idx; + + sscanf(p_kni->name, "KNI%" PRIu32, &link_id); + sprintf(link_name, "LINK%" PRIu32, link_id); + link_param_idx = APP_PARAM_FIND(app->link_params, link_name); + APP_CHECK((link_param_idx >= 0), + "Cannot find %s for %s", link_name, p_kni->name); + + return &app->link_params[link_param_idx]; +} + +void app_pipeline_params_get(struct app_params *app, + struct app_pipeline_params *p_in, + struct pipeline_params *p_out); + int app_config_init(struct app_params *app); int app_config_args(struct app_params *app, @@ -932,6 +1241,8 @@ int app_config_check(struct app_params *app); int app_init(struct app_params *app); +int app_post_init(struct app_params *app); + int app_thread(void *arg); int app_pipeline_type_register(struct app_params *app, diff --git a/examples/ip_pipeline/config/action.cfg b/examples/ip_pipeline/config/action.cfg new file mode 100644 index 00000000..994ae94a --- /dev/null +++ b/examples/ip_pipeline/config/action.cfg @@ -0,0 +1,68 @@ +; BSD LICENSE +; +; Copyright(c) 2016 Intel Corporation. All rights reserved. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +; ________________ +; RXQ0.0 --->| |---> TXQ0.0 +; | | +; RXQ1.0 --->| |---> TXQ1.0 +; | Flow | +; RXQ2.0 --->| Actions |---> TXQ2.0 +; | | +; RXQ3.0 --->| |---> TXQ3.0 +; |________________| +; +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +[EAL] +log_level = 0 + +[PIPELINE0] +type = MASTER +core = 0 + +[PIPELINE1] +type = FLOW_ACTIONS +core = 1 +pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 +pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 +n_flows = 65536 +n_meters_per_flow = 4 +flow_id_offset = 286; ipdaddr +ip_hdr_offset = 270 +color_offset = 128 diff --git a/examples/ip_pipeline/config/action.sh b/examples/ip_pipeline/config/action.sh new file mode 100644 index 00000000..2986ae60 --- /dev/null +++ b/examples/ip_pipeline/config/action.sh @@ -0,0 +1,119 @@ +# +# run ./config/action.sh +# + +p 1 action flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 0 policer 0 g G y Y r R +p 1 action flow 0 meter 1 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 0 policer 1 g G y Y r R +p 1 action flow 0 meter 2 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 0 policer 2 g G y Y r R +p 1 action flow 0 meter 3 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 0 policer 3 g G y Y r R +p 1 action flow 0 port 0 + +p 1 action flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 1 policer 0 g G y Y r R +p 1 action flow 1 meter 1 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 1 policer 1 g G y Y r R +p 1 action flow 1 meter 2 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 1 policer 2 g G y Y r R +p 1 action flow 1 meter 3 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 1 policer 3 g G y Y r R +p 1 action flow 1 port 1 + +p 1 action flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 2 policer 0 g G y Y r R +p 1 action flow 2 meter 1 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 2 policer 1 g G y Y r R +p 1 action flow 2 meter 2 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 2 policer 2 g G y Y r R +p 1 action flow 2 meter 3 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 2 policer 3 g G y Y r R +p 1 action flow 2 port 2 + +p 1 action flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 3 policer 0 g G y Y r R +p 1 action flow 3 meter 1 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 3 policer 1 g G y Y r R +p 1 action flow 3 meter 2 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 3 policer 2 g G y Y r R +p 1 action flow 3 meter 3 trtcm 1250000000 1250000000 1000000 1000000 +p 1 action flow 3 policer 3 g G y Y r R +p 1 action flow 3 port 3 + +#p 1 action flow bulk ./config/action.txt + +#p 1 action flow ls + +p 1 action flow 0 stats +p 1 action flow 1 stats +p 1 action flow 2 stats +p 1 action flow 3 stats + +p 1 action dscp 0 class 0 color G +p 1 action dscp 1 class 1 color G +p 1 action dscp 2 class 2 color G +p 1 action dscp 3 class 3 color G +p 1 action dscp 4 class 0 color G +p 1 action dscp 5 class 1 color G +p 1 action dscp 6 class 2 color G +p 1 action dscp 7 class 3 color G +p 1 action dscp 8 class 0 color G +p 1 action dscp 9 class 1 color G +p 1 action dscp 10 class 2 color G +p 1 action dscp 11 class 3 color G +p 1 action dscp 12 class 0 color G +p 1 action dscp 13 class 1 color G +p 1 action dscp 14 class 2 color G +p 1 action dscp 15 class 3 color G +p 1 action dscp 16 class 0 color G +p 1 action dscp 17 class 1 color G +p 1 action dscp 18 class 2 color G +p 1 action dscp 19 class 3 color G +p 1 action dscp 20 class 0 color G +p 1 action dscp 21 class 1 color G +p 1 action dscp 22 class 2 color G +p 1 action dscp 23 class 3 color G +p 1 action dscp 24 class 0 color G +p 1 action dscp 25 class 1 color G +p 1 action dscp 26 class 2 color G +p 1 action dscp 27 class 3 color G +p 1 action dscp 27 class 0 color G +p 1 action dscp 29 class 1 color G +p 1 action dscp 30 class 2 color G +p 1 action dscp 31 class 3 color G +p 1 action dscp 32 class 0 color G +p 1 action dscp 33 class 1 color G +p 1 action dscp 34 class 2 color G +p 1 action dscp 35 class 3 color G +p 1 action dscp 36 class 0 color G +p 1 action dscp 37 class 1 color G +p 1 action dscp 38 class 2 color G +p 1 action dscp 39 class 3 color G +p 1 action dscp 40 class 0 color G +p 1 action dscp 41 class 1 color G +p 1 action dscp 42 class 2 color G +p 1 action dscp 43 class 3 color G +p 1 action dscp 44 class 0 color G +p 1 action dscp 45 class 1 color G +p 1 action dscp 46 class 2 color G +p 1 action dscp 47 class 3 color G +p 1 action dscp 48 class 0 color G +p 1 action dscp 49 class 1 color G +p 1 action dscp 50 class 2 color G +p 1 action dscp 51 class 3 color G +p 1 action dscp 52 class 0 color G +p 1 action dscp 53 class 1 color G +p 1 action dscp 54 class 2 color G +p 1 action dscp 55 class 3 color G +p 1 action dscp 56 class 0 color G +p 1 action dscp 57 class 1 color G +p 1 action dscp 58 class 2 color G +p 1 action dscp 59 class 3 color G +p 1 action dscp 60 class 0 color G +p 1 action dscp 61 class 1 color G +p 1 action dscp 62 class 2 color G +p 1 action dscp 63 class 3 color G + +p 1 action dscp ls diff --git a/examples/ip_pipeline/config/action.txt b/examples/ip_pipeline/config/action.txt new file mode 100644 index 00000000..f14207b9 --- /dev/null +++ b/examples/ip_pipeline/config/action.txt @@ -0,0 +1,8 @@ +# +# p <pipelineid> action flow bulk ./config/action.txt +# + +flow 0 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 0 +flow 1 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 1 +flow 2 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 2 +flow 3 meter 0 trtcm 1250000000 1250000000 1000000 1000000 policer 0 g G y Y r R meter 1 trtcm 1250000000 1250000000 1000000 1000000 policer 1 g G y Y r R meter 2 trtcm 1250000000 1250000000 1000000 1000000 policer 2 g G y Y r R meter 3 trtcm 1250000000 1250000000 1000000 1000000 policer 3 g G y Y r R port 3 diff --git a/examples/ip_pipeline/config/edge_router_downstream.cfg b/examples/ip_pipeline/config/edge_router_downstream.cfg index 85bbab8f..c6b4e1f2 100644 --- a/examples/ip_pipeline/config/edge_router_downstream.cfg +++ b/examples/ip_pipeline/config/edge_router_downstream.cfg @@ -1,6 +1,6 @@ ; BSD LICENSE ; -; Copyright(c) 2015 Intel Corporation. All rights reserved. +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without @@ -36,9 +36,9 @@ ; network) contains the following functional blocks: Packet RX & Routing, ; Traffic management and Packet TX. The input packets are assumed to be ; IPv4, while the output packets are Q-in-Q IPv4. - +; ; A simple implementation for this functional pipeline is presented below. - +; ; Packet Rx & Traffic Management Packet Tx ; Routing (Pass-Through) (Pass-Through) ; _____________________ SWQ0 ______________________ SWQ4 _____________________ @@ -50,11 +50,23 @@ ; | | SWQ3 | | SWQ7 | | ; RXQ3.0 --->| |----->| |----->| |---> TXQ3.0 ; |_____________________| |______________________| |_____________________| -; | _|_ ^ _|_ ^ _|_ ^ _|_ ^ -; | |___|||___|||___|||___|| -; +--> SINK0 |___|||___|||___|||___|| -; (route miss) |__| |__| |__| |__| -; TM0 TM1 TM2 TM3 +; | | ^ | ^ | ^ | ^ +; | |__| |__| |__| |__| +; +--> SINK0 TM0 TM1 TM2 TM3 +; (Default) +; +; Input packet: Ethernet/IPv4 +; Output packet: Ethernet/QinQ/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +[EAL] +log_level = 0 [PIPELINE0] type = MASTER @@ -67,7 +79,7 @@ pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 pktq_out = SWQ0 SWQ1 SWQ2 SWQ3 SINK0 encap = ethernet_qinq qinq_sched = test -ip_hdr_offset = 270; mbuf (128) + headroom (128) + ethernet header (14) = 270 +ip_hdr_offset = 270 [PIPELINE2] type = PASS-THROUGH diff --git a/examples/ip_pipeline/config/edge_router_downstream.sh b/examples/ip_pipeline/config/edge_router_downstream.sh index ce46beb5..67c3a0d1 100644 --- a/examples/ip_pipeline/config/edge_router_downstream.sh +++ b/examples/ip_pipeline/config/edge_router_downstream.sh @@ -1,3 +1,7 @@ +# +# run ./config/edge_router_downstream.sh +# + ################################################################################ # Routing: Ether QinQ, ARP off ################################################################################ @@ -6,5 +10,4 @@ p 1 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 qinq 256 257 p 1 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 qinq 258 259 p 1 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 qinq 260 261 p 1 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 qinq 262 263 - -p 1 route ls +#p 1 route ls diff --git a/examples/ip_pipeline/config/edge_router_upstream.cfg b/examples/ip_pipeline/config/edge_router_upstream.cfg index a08c5cce..dea42b95 100644 --- a/examples/ip_pipeline/config/edge_router_upstream.cfg +++ b/examples/ip_pipeline/config/edge_router_upstream.cfg @@ -1,6 +1,6 @@ ; BSD LICENSE ; -; Copyright(c) 2015 Intel Corporation. All rights reserved. +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without @@ -29,6 +29,7 @@ ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ; An edge router typically sits between two networks such as the provider ; core network and the provider access network. A typical packet processing ; pipeline for the upstream traffic (i.e. traffic from access to core @@ -36,10 +37,10 @@ ; Flow classification, Metering, Routing and Packet TX. The input packets ; are assumed to be Q-in-Q IPv4, while the output packets are MPLS IPv4 ; (with variable number of labels per route). - +; ; A simple implementation for this functional pipeline is presented below. - -; Packet Rx & Pass-Through Flow-Classification Flow-Actions Routing +; +; Packet RX & Pass-Through Flow Classification Flow Actions Routing : Firewall ; __________ SWQ0 __________ SWQ4 __________ SWQ8 __________ SWQ12 __________ ; RXQ0.0 --->| |------>| |------>| |------>| |------>| |------> TXQ0.0 @@ -51,8 +52,21 @@ ; RXQ3.0 --->| |------>| |------>| |------>| |------>| |------> TXQ3.0 ; |__________| |__________| |__________| |__________| |__________| ; | | | -; +--> SINK0 (Default) +--> SINK1 (Default) +--> SINK2 (Route Miss) +; +--> SINK0 (Default) +--> SINK1 (Default) +--> SINK2 (Default) +; +; Input packet: Ethernet/QinQ/IPv4 +; Output packet: Ethernet/MPLS/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 QinQ header 270 8 +; 4 IPv4 header 278 20 +[EAL] +log_level = 0 [PIPELINE0] type = MASTER @@ -72,10 +86,10 @@ core = 2 pktq_in = SWQ0 SWQ1 SWQ2 SWQ3 pktq_out = SWQ4 SWQ5 SWQ6 SWQ7 dma_size = 8 -dma_dst_offset = 128; mbuf (128) -dma_src_offset = 268; mbuf (128) + headroom (128) + 1st ethertype offset (12) = 268 +dma_dst_offset = 128 +dma_src_offset = 268; 1st Ethertype offset dma_src_mask = 00000FFF00000FFF; qinq -dma_hash_offset = 136; dma_dst_offset + dma_size = 136 +dma_hash_offset = 136; dma_dst_offset + dma_size [PIPELINE3] type = FLOW_CLASSIFICATION @@ -86,7 +100,7 @@ n_flows = 65536 key_size = 8; dma_size key_offset = 128; dma_dst_offset hash_offset = 136; dma_hash_offset -flowid_offset = 192; mbuf (128) + 64 +flowid_offset = 192 [PIPELINE4] type = FLOW_ACTIONS @@ -96,7 +110,7 @@ pktq_out = SWQ12 SWQ13 SWQ14 SWQ15 n_flows = 65536 n_meters_per_flow = 1 flow_id_offset = 192; flowid_offset -ip_hdr_offset = 278; mbuf (128) + headroom (128) + ethernet (14) + qinq (8) = 278 +ip_hdr_offset = 278 color_offset = 196; flowid_offset + sizeof(flow_id) [PIPELINE5] @@ -106,5 +120,5 @@ pktq_in = SWQ12 SWQ13 SWQ14 SWQ15 pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK2 encap = ethernet_mpls mpls_color_mark = yes -ip_hdr_offset = 278; mbuf (128) + headroom (128) + ethernet (14) + qinq (8) = 278 +ip_hdr_offset = 278 color_offset = 196; flowid_offset + sizeof(flow_id) diff --git a/examples/ip_pipeline/config/edge_router_upstream.sh b/examples/ip_pipeline/config/edge_router_upstream.sh index eeba600c..5d574c1a 100644 --- a/examples/ip_pipeline/config/edge_router_upstream.sh +++ b/examples/ip_pipeline/config/edge_router_upstream.sh @@ -1,24 +1,26 @@ -################################################ -# Firewall Rules:4 for 4 ports -################################################ -p 1 firewall add ipv4 1 0.0.0.0 8 0.0.0.0 10 0 0 0 0 6 1 0 -p 1 firewall add ipv4 1 0.0.0.0 8 0.64.0.0 10 0 0 0 0 6 1 1 -p 1 firewall add ipv4 1 0.0.0.0 8 0.128.0.0 10 0 0 0 0 6 1 2 -p 1 firewall add ipv4 1 0.0.0.0 8 0.192.0.0 10 0 0 0 0 6 1 3 -p 1 firewall add default 4 #SINK0 +# +# run ./config/edge_router_upstream.sh +# +################################################################################ +# Firewall +################################################################################ +p 1 firewall add default 4 #SINK0 +p 1 firewall add bulk ./config/edge_router_upstream_firewall.txt +#p 1 firewall ls ################################################################################ -# Flow classification +# Flow Classification ################################################################################ p 3 flow add default 4 #SINK1 -p 3 flow add qinq all 65536 4 +p 3 flow add qinq bulk ./config/edge_router_upstream_flow.txt +#p 3 flow ls ################################################################################ -# Flow Actions - Metering +# Flow Actions - Metering and Policing ################################################################################ -p 4 flows 65536 meter 0 trtcm 1250000000 1250000000 100000000 100000000 -p 4 flows 65536 ports 4 +p 4 action flow bulk ./config/edge_router_upstream_action.txt +#p 4 action flow ls ################################################################################ # Routing: Ether MPLS, ARP off @@ -28,11 +30,4 @@ p 5 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 mpls 0:1 p 5 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 mpls 10:11 p 5 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 mpls 20:21 p 5 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 mpls 30:31 - -################################################################################ -# List all configurations -################################################################################ -p 1 firewall ls -#p 3 flow ls -#p 4 flow actions ls -p 5 route ls +#p 5 route ls diff --git a/examples/ip_pipeline/config/firewall.cfg b/examples/ip_pipeline/config/firewall.cfg new file mode 100644 index 00000000..2f5dd9f6 --- /dev/null +++ b/examples/ip_pipeline/config/firewall.cfg @@ -0,0 +1,68 @@ +; BSD LICENSE +; +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +; _______________ +; RXQ0.0 --->| |---> TXQ0.0 +; | | +; RXQ1.0 --->| |---> TXQ1.0 +; | Firewall | +; RXQ2.0 --->| |---> TXQ2.0 +; | | +; RXQ3.0 --->| |---> TXQ3.0 +; |_______________| +; | +; +-----------> SINK0 (default rule) +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +[EAL] +log_level = 0 + +[PIPELINE0] +type = MASTER +core = 0 + +[PIPELINE1] +type = FIREWALL +core = 1 +pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 +pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 +n_rules = 4096 +pkt_type = ipv4 +;pkt_type = vlan_ipv4 +;pkt_type = qinq_ipv4 diff --git a/examples/ip_pipeline/config/firewall.sh b/examples/ip_pipeline/config/firewall.sh new file mode 100644 index 00000000..c83857ee --- /dev/null +++ b/examples/ip_pipeline/config/firewall.sh @@ -0,0 +1,13 @@ +# +# run ./config/firewall.sh +# + +p 1 firewall add default 4 #SINK0 +p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 0xF port 0 +p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 0xF port 1 +p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 0xF port 2 +p 1 firewall add priority 1 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 0xF port 3 + +#p 1 firewall add bulk ./config/firewall.txt + +p 1 firewall ls diff --git a/examples/ip_pipeline/config/firewall.txt b/examples/ip_pipeline/config/firewall.txt new file mode 100644 index 00000000..54cfffda --- /dev/null +++ b/examples/ip_pipeline/config/firewall.txt @@ -0,0 +1,9 @@ +# +# p <pipelineid> firewall add bulk ./config/firewall.txt +# p <pipelineid> firewall del bulk ./config/firewall.txt +# + +priority 1 ipv4 0.0.0.0 0 100.0.0.0 10 0 65535 0 65535 6 0xF port 0 +priority 1 ipv4 0.0.0.0 0 100.64.0.0 10 0 65535 0 65535 6 0xF port 1 +priority 1 ipv4 0.0.0.0 0 100.128.0.0 10 0 65535 0 65535 6 0xF port 2 +priority 1 ipv4 0.0.0.0 0 100.192.0.0 10 0 65535 0 65535 6 0xF port 3 diff --git a/examples/ip_pipeline/config/flow.cfg b/examples/ip_pipeline/config/flow.cfg new file mode 100644 index 00000000..6895d393 --- /dev/null +++ b/examples/ip_pipeline/config/flow.cfg @@ -0,0 +1,72 @@ +; BSD LICENSE +; +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +; ________________ +; RXQ0.0 --->| |---> TXQ0.0 +; | | +; RXQ1.0 --->| |---> TXQ1.0 +; | Flow | +; RXQ2.0 --->| Classification |---> TXQ2.0 +; | | +; RXQ3.0 --->| |---> TXQ3.0 +; |________________| +; | +; +-----------> SINK0 (flow lookup miss) +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 QinQ/IPv4/IPv6 header 270 8/20/40 + +[EAL] +log_level = 0 + +[PIPELINE0] +type = MASTER +core = 0 + +[PIPELINE1] +type = FLOW_CLASSIFICATION +core = 1 +pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 +pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 +n_flows = 65536 +;key_size = 8 ; QinQ key size +;key_offset = 270 ; QinQ key offset +;key_mask = 0000FFF00000FFF0 ; QinQ key mask +key_size = 16 ; IPv4 5-tuple key size +key_offset = 278 ; IPv4 5-tuple key offset +key_mask = 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF ; IPv4 5-tuple key mask +flowid_offset = 128 diff --git a/examples/ip_pipeline/config/flow.sh b/examples/ip_pipeline/config/flow.sh new file mode 100644 index 00000000..489c7079 --- /dev/null +++ b/examples/ip_pipeline/config/flow.sh @@ -0,0 +1,25 @@ +# +# run ./config/flow.sh +# + +################################################################################ +# Flow classification (QinQ) +################################################################################ +#p 1 flow add default 4 #SINK0 +#p 1 flow add qinq 100 200 port 0 id 0 +#p 1 flow add qinq 101 201 port 1 id 1 +#p 1 flow add qinq 102 202 port 2 id 2 +#p 1 flow add qinq 103 203 port 3 id 3 + +#p 1 flow add qinq bulk ./config/flow.txt + +################################################################################ +# Flow classification (IPv4 5-tuple) +################################################################################ +p 1 flow add default 4 #SINK0 +p 1 flow add ipv4 100.0.0.10 200.0.0.10 100 200 6 port 0 id 0 +p 1 flow add ipv4 100.0.0.11 200.0.0.11 101 201 6 port 1 id 1 +p 1 flow add ipv4 100.0.0.12 200.0.0.12 102 202 6 port 2 id 2 +p 1 flow add ipv4 100.0.0.13 200.0.0.13 103 203 6 port 3 id 3 + +#p 1 flow add ipv4 bulk ./config/flow.txt diff --git a/examples/ip_pipeline/config/flow.txt b/examples/ip_pipeline/config/flow.txt new file mode 100644 index 00000000..c1a141dd --- /dev/null +++ b/examples/ip_pipeline/config/flow.txt @@ -0,0 +1,17 @@ +# +# p <pipelineid> flow add qinq bulk ./config/flow.txt +# + +#qinq 100 200 port 0 id 0 +#qinq 101 201 port 1 id 1 +#qinq 102 202 port 2 id 2 +#qinq 103 203 port 3 id 3 + +# +# p <pipelineid> flow add ipv4 bulk ./config/flow.txt +# + +ipv4 100.0.0.10 200.0.0.10 100 200 6 port 0 id 0 +ipv4 100.0.0.11 200.0.0.11 101 201 6 port 1 id 1 +ipv4 100.0.0.12 200.0.0.12 102 202 6 port 2 id 2 +ipv4 100.0.0.13 200.0.0.13 103 203 6 port 3 id 3 diff --git a/examples/ip_pipeline/config/kni.cfg b/examples/ip_pipeline/config/kni.cfg new file mode 100644 index 00000000..cea208b4 --- /dev/null +++ b/examples/ip_pipeline/config/kni.cfg @@ -0,0 +1,67 @@ +; BSD LICENSE +; +; Copyright(c) 2016 Intel Corporation. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +; +; ______________ ______________________ +; | | KNI0 | | +; RXQ0.0 --->| |------->|--+ | +; | | KNI1 | | br0 | +; TXQ1.0 <---| |<-------|<-+ | +; | Pass-through | | Linux Kernel | +; | (P1) | | Network Stack | +; | | KNI1 | | +; RXQ1.0 --->| |------->|--+ | +; | | KNI0 | | br0 | +; TXQ0.0 <---| |<-------|<-+ | +; |______________| |______________________| +; +; Insert Linux kernel KNI module: +; [Linux]$ insmod rte_kni.ko +; +; Configure Linux kernel bridge between KNI0 and KNI1 interfaces: +; [Linux]$ ifconfig KNI0 up +; [Linux]$ ifconfig KNI1 up +; [Linux]$ brctl addbr "br0" +; [Linux]$ brctl addif br0 KNI0 +; [Linux]$ brctl addif br0 KNI1 +; [Linux]$ ifconfig br0 up + +[EAL] +log_level = 0 + +[PIPELINE0] +type = MASTER +core = 0 + +[PIPELINE1] +type = PASS-THROUGH +core = 1 +pktq_in = RXQ0.0 KNI1 RXQ1.0 KNI0 +pktq_out = KNI0 TXQ1.0 KNI1 TXQ0.0 diff --git a/examples/ip_pipeline/config/l2fwd.cfg b/examples/ip_pipeline/config/l2fwd.cfg index c743a143..a1df9e6a 100644 --- a/examples/ip_pipeline/config/l2fwd.cfg +++ b/examples/ip_pipeline/config/l2fwd.cfg @@ -1,6 +1,6 @@ ; BSD LICENSE ; -; Copyright(c) 2015 Intel Corporation. All rights reserved. +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without @@ -44,6 +44,9 @@ ; |________________| ; +[EAL] +log_level = 0 + [PIPELINE0] type = MASTER core = 0 diff --git a/examples/ip_pipeline/config/l3fwd.cfg b/examples/ip_pipeline/config/l3fwd.cfg index 5449dc32..02c8f36f 100644 --- a/examples/ip_pipeline/config/l3fwd.cfg +++ b/examples/ip_pipeline/config/l3fwd.cfg @@ -1,6 +1,6 @@ ; BSD LICENSE ; -; Copyright(c) 2015 Intel Corporation. All rights reserved. +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without @@ -50,6 +50,9 @@ ; 2 Ethernet header 256 14 ; 3 IPv4 header 270 20 +[EAL] +log_level = 0 + [PIPELINE0] type = MASTER core = 0 @@ -59,5 +62,7 @@ type = ROUTING core = 1 pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 -encap = ethernet; encap = ethernet / ethernet_qinq / ethernet_mpls +encap = ethernet +;encap = ethernet_qinq +;encap = ethernet_mpls ip_hdr_offset = 270 diff --git a/examples/ip_pipeline/config/l3fwd.sh b/examples/ip_pipeline/config/l3fwd.sh index 27740103..47406aa4 100644 --- a/examples/ip_pipeline/config/l3fwd.sh +++ b/examples/ip_pipeline/config/l3fwd.sh @@ -1,9 +1,33 @@ +# +# run ./config/l3fwd.sh +# + ################################################################################ # Routing: encap = ethernet, arp = off ################################################################################ p 1 route add default 4 #SINK0 -p 1 route add 0.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 -p 1 route add 0.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 -p 1 route add 0.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 -p 1 route add 0.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 +p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 +p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 +p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 +p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 p 1 route ls + +################################################################################ +# Routing: encap = ethernet_qinq, arp = off +################################################################################ +#p 1 route add default 4 #SINK0 +#p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 qinq 1000 2000 +#p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 qinq 1001 2001 +#p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 qinq 1002 2002 +#p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 qinq 1003 2003 +#p 1 route ls + +################################################################################ +# Routing: encap = ethernet_mpls, arp = off +################################################################################ +#p 1 route add default 4 #SINK0 +#p 1 route add 100.0.0.0 10 port 0 ether a0:b0:c0:d0:e0:f0 mpls 1000:2000 +#p 1 route add 100.64.0.0 10 port 1 ether a1:b1:c1:d1:e1:f1 mpls 1001:2001 +#p 1 route add 100.128.0.0 10 port 2 ether a2:b2:c2:d2:e2:f2 mpls 1002:2002 +#p 1 route add 100.192.0.0 10 port 3 ether a3:b3:c3:d3:e3:f3 mpls 1003:2003 +#p 1 route ls diff --git a/examples/ip_pipeline/config/l3fwd_arp.cfg b/examples/ip_pipeline/config/l3fwd_arp.cfg new file mode 100644 index 00000000..2c63c8fd --- /dev/null +++ b/examples/ip_pipeline/config/l3fwd_arp.cfg @@ -0,0 +1,70 @@ +; BSD LICENSE +; +; Copyright(c) 2015-2016 Intel Corporation. All rights reserved. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +; _______________ +; RXQ0.0 --->| |---> TXQ0.0 +; | | +; RXQ1.0 --->| |---> TXQ1.0 +; | Routing | +; RXQ2.0 --->| |---> TXQ2.0 +; | | +; RXQ3.0 --->| |---> TXQ3.0 +; |_______________| +; | +; +-----------> SINK0 (route miss) +; +; Input packet: Ethernet/IPv4 +; +; Packet buffer layout: +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 + +[EAL] +log_level = 0 + +[PIPELINE0] +type = MASTER +core = 0 + +[PIPELINE1] +type = ROUTING +core = 1 +pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 +pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK0 +encap = ethernet +;encap = ethernet_qinq +;encap = ethernet_mpls +n_arp_entries = 1024 +ip_hdr_offset = 270 +arp_key_offset = 128 diff --git a/examples/ip_pipeline/config/l3fwd_arp.sh b/examples/ip_pipeline/config/l3fwd_arp.sh new file mode 100644 index 00000000..20bea582 --- /dev/null +++ b/examples/ip_pipeline/config/l3fwd_arp.sh @@ -0,0 +1,43 @@ +# +# run ./config/l3fwd_arp.sh +# + +################################################################################ +# ARP +################################################################################ +p 1 arp add default 4 #SINK0 +p 1 arp add 0 10.0.0.1 a0:b0:c0:d0:e0:f0 +p 1 arp add 1 11.0.0.1 a1:b1:c1:d1:e1:f1 +p 1 arp add 2 12.0.0.1 a2:b2:c2:d2:e2:f2 +p 1 arp add 3 13.0.0.1 a3:b3:c3:d3:e3:f3 +p 1 arp ls + +################################################################################ +# Routing: encap = ethernet, arp = on +################################################################################ +p 1 route add default 4 #SINK0 +p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 +p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 +p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 +p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 +p 1 route ls + +################################################################################ +# Routing: encap = ethernet_qinq, arp = on +################################################################################ +#p 1 route add default 4 #SINK0 +#p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 qinq 1000 2000 +#p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 qinq 1001 2001 +#p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 qinq 1002 2002 +#p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 qinq 1003 2003 +#p 1 route ls + +################################################################################ +# Routing: encap = ethernet_mpls, arp = on +################################################################################ +#p 1 route add default 4 #SINK0 +#p 1 route add 100.0.0.0 10 port 0 ether 10.0.0.1 mpls 1000:2000 +#p 1 route add 100.64.0.0 10 port 1 ether 11.0.0.1 mpls 1001:2001 +#p 1 route add 100.128.0.0 10 port 2 ether 12.0.0.1 mpls 1002:2002 +#p 1 route add 100.192.0.0 10 port 3 ether 13.0.0.1 mpls 1003:2003 +#p 1 route ls diff --git a/examples/ip_pipeline/config/network_layers.cfg b/examples/ip_pipeline/config/network_layers.cfg new file mode 100644 index 00000000..8054d9fe --- /dev/null +++ b/examples/ip_pipeline/config/network_layers.cfg @@ -0,0 +1,223 @@ +; BSD LICENSE +; +; Copyright(c) 2016 Intel Corporation. All rights reserved. +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +; The diagram below shows how additional protocol components can be plugged into +; the IP layer implemented by the ip_pipeline application. Pick your favorite +; open source components for dynamic ARP, ICMP, UDP or TCP termination, etc and +; connect them through SWQs to the IP infrastructure. +; +; The input packets with local destination are sent to the UDP/TCP applications +; while the input packets with remote destination are routed back to the +; network. Additional features can easily be added to this setup: +; * IP Reassembly: add SWQs with IP reassembly enabled (typically required for +; the input traffic with local destination); +; * IP Fragmentation: add SWQs with IP fragmentation enabled (typically +; required to enforce the MTU for the routed output traffic); +; * Traffic Metering: add Flow Action pipeline instances (e.g. for metering the +; TCP connections or ICMP input traffic); +; * Traffic Management: add TMs for the required output LINKs; +; * Protocol encapsulations (QinQ, MPLS) for the output packets: part of the +; routing pipeline configuration. +; +; _________ _________ +; | | | | +; | UDP | | TCP | +; | App | | App | +; |_________| |_________| +; ^ | ^ | +; __|___V__ __|___V__ +; | | SWQ0 (UDP TX) | | SWQ1 (TCP TX) +; | UDP |-------+ | TCP |------------+ +; | | | | | | +; |_________| | |_________| | +; ^ | ^ | +; | SWQ2 | | SWQ3 | +; | (UDP RX) | | (TCP RX) | +; ____|____ | ____|____ | +; | | | | | | +; RXQ<0..3>.1 ------>|Firewall +--->| | +------>| Flow +--->| | +; (UDP local dest) | (P2) | SINK0 | | | (P3) | SINK1 | +; |_________| (Deny)| | |_________| (RST) | +; RXQ<0..3>.2 -------------------------|-----+ | +; (TCP local dest) | | +; | +------------------------------+ +; | | +; _V_____V_ +; | | +; | Routing | TXQ<0..3>.0 +; RXQ<0..3>.0 ---------------------->| & ARP +-----------------------------> +; (IP remote dest) | (P1) | +; |_________| +; | ^ | +; SWQ4 +-------------+ | | SWQ5 (ARP miss) +; (Route miss) | | +------------+ +; | +-------------+ | +; ___V__|__ SWQ6 ____V____ +; | | (ICMP TX) | | TXQ<0..3>.1 +; RXQ<0..3>.3 ------>| ICMP | +------>| Dyn ARP +-------------> +; (IP local dest) | | | | | +; |_________| | |_________| +; RXQ<0..3>.4 -------------------------------+ +; (ARP) +; +; This configuration file implements the diagram presented below, where the +; dynamic ARP, ICMP, UDP and TCP components have been stubbed out and replaced +; with loop-back and packet drop devices. +; +; _________ _________ +; | | SWQ0 (UDP TX) | | SWQ1 (TCP TX) +; |Loobpack |-------+ |Loopback |------------+ +; | (P4) | | | (P5) | | +; |_________| | |_________| | +; ^ | ^ | +; | SWQ2 | | SWQ3 | +; | (UDP RX) | | (TCP RX) | +; ____|____ | ____|____ | +; | | | | | | +; RXQ<0..3>.1 ------>|Firewall +--->| | +------>| Flow +--->| | +; (UDP local dest) | (P2) | SINK0 | | | (P3) | SINK1 | +; |_________| (Deny)| | |_________| (RST) | +; RXQ<0..3>.2 -------------------------|-----+ | +; (TCP local dest) | | +; | +------------------------------+ +; | | +; _V_____V_ +; | | +; | Routing | TXQ<0..3>.0 +; RXQ<0..3>.0 ---------------------->| & ARP +-----------------------------> +; (IP remote dest) | (P1) | +; |_________| +; | | +; SINK2 |<---+ +--->| SINK3 +; (Route miss) (ARP miss) +; +; _________ _________ +; | | | | +; RXQ<0..3>.3 ------>| Drop +--->| SINK<4..7> +------>| Drop +--->| SINK<8..11> +; (IP local dest) | (P6) | (IP local dest) | | (P7) | (ARP) +; |_________| | |_________| +; RXQ<0..3>.4 ------------------------------------+ +; (ARP) +; +; +; Input packet: Ethernet/IPv4 or Ethernet/ARP +; Output packet: Ethernet/IPv4 or Ethernet/ARP +; +; Packet buffer layout (for input IPv4 packets): +; # Field Name Offset (Bytes) Size (Bytes) +; 0 Mbuf 0 128 +; 1 Headroom 128 128 +; 2 Ethernet header 256 14 +; 3 IPv4 header 270 20 +; 4 ICMP/UDP/TCP header 290 8/8/20 + +[EAL] +log_level = 0 + +[LINK0] +udp_local_q = 1 +tcp_local_q = 2 +ip_local_q = 3 +arp_q = 4 + +[LINK1] +udp_local_q = 1 +tcp_local_q = 2 +ip_local_q = 3 +arp_q = 4 + +[LINK2] +udp_local_q = 1 +tcp_local_q = 2 +ip_local_q = 3 +arp_q = 4 + +[LINK3] +udp_local_q = 1 +tcp_local_q = 2 +ip_local_q = 3 +arp_q = 4 + +[PIPELINE0] +type = MASTER +core = 0 + +[PIPELINE1] +type = ROUTING +core = 1 +pktq_in = RXQ0.0 RXQ1.0 RXQ2.0 RXQ3.0 SWQ0 SWQ1 +pktq_out = TXQ0.0 TXQ1.0 TXQ2.0 TXQ3.0 SINK2 SINK3 +port_local_dest = 4 ; SINK2 (Drop) +n_arp_entries = 1000 +ip_hdr_offset = 270 +arp_key_offset = 128 + +[PIPELINE2] +type = FIREWALL +core = 1 +pktq_in = RXQ0.1 RXQ1.1 RXQ2.1 RXQ3.1 +pktq_out = SWQ2 SINK0 +n_rules = 4096 + +[PIPELINE3] +type = FLOW_CLASSIFICATION +core = 1 +pktq_in = RXQ0.2 RXQ1.2 RXQ2.2 RXQ3.2 +pktq_out = SWQ3 SINK1 +n_flows = 65536 +key_size = 16 ; IPv4 5-tuple key size +key_offset = 278 ; IPv4 5-tuple key offset +key_mask = 00FF0000FFFFFFFFFFFFFFFFFFFFFFFF ; IPv4 5-tuple key mask +flowid_offset = 128 ; Flow ID effectively acts as TCP socket ID + +[PIPELINE4] +type = PASS-THROUGH ; Loop-back (UDP place-holder) +core = 1 +pktq_in = SWQ2 +pktq_out = SWQ0 + +[PIPELINE5] +type = PASS-THROUGH ; Loop-back (TCP place-holder) +core = 1 +pktq_in = SWQ3 +pktq_out = SWQ1 + +[PIPELINE6] +type = PASS-THROUGH ; Drop (ICMP place-holder) +core = 1 +pktq_in = RXQ0.3 RXQ1.3 RXQ2.3 RXQ3.3 +pktq_out = SINK4 SINK5 SINK6 SINK7 + +[PIPELINE7] +type = PASS-THROUGH ; Drop (Dynamic ARP place-holder) +core = 1 +pktq_in = RXQ0.4 RXQ1.4 RXQ2.4 RXQ3.4 +pktq_out = SINK8 SINK9 SINK10 SINK11 diff --git a/examples/ip_pipeline/config/network_layers.sh b/examples/ip_pipeline/config/network_layers.sh new file mode 100644 index 00000000..3b86bebd --- /dev/null +++ b/examples/ip_pipeline/config/network_layers.sh @@ -0,0 +1,79 @@ +# +# run ./config/network_layers.sh +# + +################################################################################ +# Link configuration +################################################################################ +# Routes added implicitly when links are brought UP: +# IP Prefix = 10.0.0.1/16 => (Port 0, Local) +# IP Prefix = 10.0.0.1/32 => (Port 4, Local) +# IP Prefix = 10.1.0.1/16 => (Port 1, Local) +# IP Prefix = 10.1.0.1/32 => (Port 4, Local) +# IP Prefix = 10.2.0.1/16 => (Port 2, Local) +# IP Prefix = 10.2.0.1/32 => (Port 4, Local) +# IP Prefix = 10.3.0.1/16 => (Port 3, Local) +# IP Prefix = 10.3.0.1/32 => (Port 4, Local) +link 0 down +link 1 down +link 2 down +link 3 down +link 0 config 10.0.0.1 16 +link 1 config 10.1.0.1 16 +link 2 config 10.2.0.1 16 +link 3 config 10.3.0.1 16 +link 0 up +link 1 up +link 2 up +link 3 up +#link ls + +################################################################################ +# Static ARP +################################################################################ +p 1 arp add default 5 #SINK3 +p 1 arp add 0 10.0.0.2 a0:b0:c0:d0:e0:f0 +p 1 arp add 1 10.1.0.2 a1:b1:c1:d1:e1:f1 +p 1 arp add 2 10.2.0.2 a2:b2:c2:d2:e2:f2 +p 1 arp add 3 10.3.0.2 a3:b3:c3:d3:e3:f3 +#p 1 arp ls + +################################################################################ +# Routes +################################################################################ +p 1 route add default 4 #SINK2 +p 1 route add 100.0.0.0 16 port 0 ether 10.0.0.2 +p 1 route add 100.1.0.0 16 port 1 ether 10.1.0.2 +p 1 route add 100.2.0.0 16 port 2 ether 10.2.0.2 +p 1 route add 100.3.0.0 16 port 3 ether 10.3.0.2 +#p 1 route ls + +################################################################################ +# Local destination UDP traffic +################################################################################ +# Prio = Lowest: [SA = ANY, DA = ANY, SP = ANY, DP = ANY, PROTO = ANY] => Drop +# Prio = 1 (High): [SA = ANY, DA = 10.0.0.1, SP = ANY, DP = 1000, PROTO = UDP] => Allow +# Prio = 1 (High): [SA = ANY, DA = 10.1.0.1, SP = ANY, DP = 1001, PROTO = UDP] => Allow +# Prio = 1 (High): [SA = ANY, DA = 10.2.0.1, SP = ANY, DP = 1002, PROTO = UDP] => Allow +# Prio = 1 (High): [SA = ANY, DA = 10.3.0.1, SP = ANY, DP = 1003, PROTO = UDP] => Allow +p 1 firewall add default 1 #SINK0 +p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.0.0.1 32 0 65535 1000 1000 17 0xF port 0 +p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.1.0.1 32 0 65535 1001 1001 17 0xF port 0 +p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.2.0.1 32 0 65535 1002 1002 17 0xF port 0 +p 2 firewall add priority 1 ipv4 0.0.0.0 0 10.3.0.1 32 0 65535 1003 1003 17 0xF port 0 +#p 2 firewall ls + +################################################################################ +# Local destination TCP traffic +################################################################################ +# Unknown connection => Drop +# TCP [SA = 100.0.0.10, DA = 10.0.0.1, SP = 1000, DP = 80] => socket ID = 0 +# TCP [SA = 100.1.0.10, DA = 10.1.0.1, SP = 1001, DP = 80] => socket ID = 1 +# TCP [SA = 100.2.0.10, DA = 10.2.0.1, SP = 1002, DP = 80] => socket ID = 2 +# TCP [SA = 100.3.0.10, DA = 10.3.0.1, SP = 1003, DP = 80] => socket ID = 3 +p 3 flow add default 1 #SINK1 +p 3 flow add ipv4 100.0.0.10 10.0.0.1 1000 80 6 port 1 id 0 +p 3 flow add ipv4 100.1.0.10 10.1.0.1 1001 80 6 port 1 id 1 +p 3 flow add ipv4 100.2.0.10 10.2.0.1 1002 80 6 port 1 id 2 +p 3 flow add ipv4 100.3.0.10 10.3.0.1 1003 80 6 port 1 id 3 +#p 3 flow ls diff --git a/examples/ip_pipeline/config/pipeline-to-core-mapping.py b/examples/ip_pipeline/config/pipeline-to-core-mapping.py new file mode 100755 index 00000000..37b131c6 --- /dev/null +++ b/examples/ip_pipeline/config/pipeline-to-core-mapping.py @@ -0,0 +1,936 @@ +#! /usr/bin/python2 + +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# +# This script maps the set of pipelines identified (MASTER pipelines are +# ignored) from the input configuration file to the set of cores +# provided as input argument and creates configuration files for each of +# the mapping combinations. +# + +from __future__ import print_function +import sys +import errno +import os +import re +import array +import itertools +import re +import argparse +from collections import namedtuple + +# default values +enable_stage0_traceout = 1 +enable_stage1_traceout = 1 +enable_stage2_traceout = 1 + +enable_stage1_fileout = 1 +enable_stage2_fileout = 1 + +Constants = namedtuple('Constants', ['MAX_CORES', 'MAX_PIPELINES']) +constants = Constants(16, 64) + +# pattern for physical core +pattern_phycore = '^(s|S)\d(c|C)[1-9][0-9]*$' +reg_phycore = re.compile(pattern_phycore) + + +def popcount(mask): + return bin(mask).count("1") + + +def len2mask(length): + if (length == 0): + return 0 + + if (length > 64): + sys.exit('error: len2mask - length %i > 64. exiting' % length) + + return int('1' * length, 2) + + +def bitstring_write(n, n_bits): + tmpstr = "" + if (n_bits > 64): + return + + i = n_bits - 1 + while (i >= 0): + cond = (n & (1 << i)) + if (cond): + print('1', end='') + tmpstr += '1' + else: + print('0', end='') + tmpstr += '0' + i -= 1 + return tmpstr + + +class Cores0: + + def __init__(self): + self.n_pipelines = 0 + + +class Cores1: + + def __init__(self): + self.pipelines = 0 + self.n_pipelines = 0 + + +class Cores2: + + def __init__(self): + self.pipelines = 0 + self.n_pipelines = 0 + self.counter = 0 + self.counter_max = 0 + self.bitpos = array.array( + "L", itertools.repeat(0, constants.MAX_PIPELINES)) + + +class Context0: + + def __init__(self): + self.cores = [Cores0() for i in range(0, constants.MAX_CORES)] + self.n_cores = 0 + self.n_pipelines = 0 + self.n_pipelines0 = 0 + self.pos = 0 + self.file_comment = "" + self.ctx1 = None + self.ctx2 = None + + def stage0_print(self): + print('printing Context0 obj') + print('c0.cores(n_pipelines) = [ ', end='') + for cores_count in range(0, constants.MAX_CORES): + print(self.cores[cores_count].n_pipelines, end=' ') + print(']') + print('c0.n_cores = %d' % self.n_cores) + print('c0.n_pipelines = %d' % self.n_pipelines) + print('c0.n_pipelines0 = %d' % self.n_pipelines0) + print('c0.pos = %d' % self.pos) + print('c0.file_comment = %s' % self.file_comment) + if (self.ctx1 is not None): + print('c0.ctx1 = ', end='') + print(repr(self.ctx1)) + else: + print('c0.ctx1 = None') + + if (self.ctx2 is not None): + print('c0.ctx2 = ', end='') + print(repr(self.ctx2)) + else: + print('c0.ctx2 = None') + + def stage0_init(self, num_cores, num_pipelines, ctx1, ctx2): + self.n_cores = num_cores + self.n_pipelines = num_pipelines + self.ctx1 = ctx1 + self.ctx2 = ctx2 + + def stage0_process(self): + # stage0 init + self.cores[0].n_pipelines = self.n_pipelines + self.n_pipelines0 = 0 + self.pos = 1 + + while True: + # go forward + while True: + if ((self.pos < self.n_cores) and (self.n_pipelines0 > 0)): + self.cores[self.pos].n_pipelines = min( + self.cores[self.pos - 1].n_pipelines, + self.n_pipelines0) + self.n_pipelines0 -= self.cores[self.pos].n_pipelines + self.pos += 1 + else: + break + + # check solution + if (self.n_pipelines0 == 0): + self.stage0_log() + self.ctx1.stage1_init(self, self.ctx2) # self is object c0 + self.ctx1.stage1_process() + + # go backward + while True: + if (self.pos == 0): + return + + self.pos -= 1 + if ((self.cores[self.pos].n_pipelines > 1) and + (self.pos != (self.n_cores - 1))): + break + + self.n_pipelines0 += self.cores[self.pos].n_pipelines + self.cores[self.pos].n_pipelines = 0 + + # rearm + self.cores[self.pos].n_pipelines -= 1 + self.n_pipelines0 += 1 + self.pos += 1 + + def stage0_log(self): + tmp_file_comment = "" + if(enable_stage0_traceout != 1): + return + + print('STAGE0: ', end='') + tmp_file_comment += 'STAGE0: ' + for cores_count in range(0, self.n_cores): + print('C%d = %d\t' + % (cores_count, + self.cores[cores_count].n_pipelines), end='') + tmp_file_comment += "C{} = {}\t".format( + cores_count, self.cores[cores_count].n_pipelines) + # end for + print('') + self.ctx1.stage0_file_comment = tmp_file_comment + self.ctx2.stage0_file_comment = tmp_file_comment + + +class Context1: + _fileTrace = None + + def __init__(self): + self.cores = [Cores1() for i in range(constants.MAX_CORES)] + self.n_cores = 0 + self.n_pipelines = 0 + self.pos = 0 + self.stage0_file_comment = "" + self.stage1_file_comment = "" + + self.ctx2 = None + self.arr_pipelines2cores = [] + + def stage1_reset(self): + for i in range(constants.MAX_CORES): + self.cores[i].pipelines = 0 + self.cores[i].n_pipelines = 0 + + self.n_cores = 0 + self.n_pipelines = 0 + self.pos = 0 + self.ctx2 = None + # clear list + del self.arr_pipelines2cores[:] + + def stage1_print(self): + print('printing Context1 obj') + print('ctx1.cores(pipelines,n_pipelines) = [ ', end='') + for cores_count in range(0, constants.MAX_CORES): + print('(%d,%d)' % (self.cores[cores_count].pipelines, + self.cores[cores_count].n_pipelines), end=' ') + print(']') + print('ctx1.n_cores = %d' % self.n_cores) + print('ctx1.n_pipelines = %d' % self.n_pipelines) + print('ctx1.pos = %d' % self.pos) + print('ctx1.stage0_file_comment = %s' % self.stage0_file_comment) + print('ctx1.stage1_file_comment = %s' % self.stage1_file_comment) + if (self.ctx2 is not None): + print('ctx1.ctx2 = ', end='') + print(self.ctx2) + else: + print('ctx1.ctx2 = None') + + def stage1_init(self, c0, ctx2): + self.stage1_reset() + self.n_cores = 0 + while (c0.cores[self.n_cores].n_pipelines > 0): + self.n_cores += 1 + + self.n_pipelines = c0.n_pipelines + self.ctx2 = ctx2 + + self.arr_pipelines2cores = [0] * self.n_pipelines + + i = 0 + while (i < self.n_cores): + self.cores[i].n_pipelines = c0.cores[i].n_pipelines + i += 1 + + def stage1_process(self): + pipelines_max = len2mask(self.n_pipelines) + while True: + pos = 0 + overlap = 0 + + if (self.cores[self.pos].pipelines == pipelines_max): + if (self.pos == 0): + return + + self.cores[self.pos].pipelines = 0 + self.pos -= 1 + continue + + self.cores[self.pos].pipelines += 1 + if (popcount(self.cores[self.pos].pipelines) != + self.cores[self.pos].n_pipelines): + continue + + overlap = 0 + pos = 0 + while (pos < self.pos): + if ((self.cores[self.pos].pipelines) & + (self.cores[pos].pipelines)): + overlap = 1 + break + pos += 1 + + if (overlap): + continue + + if ((self.pos > 0) and + ((self.cores[self.pos].n_pipelines) == + (self.cores[self.pos - 1].n_pipelines)) and + ((self.cores[self.pos].pipelines) < + (self.cores[self.pos - 1].pipelines))): + continue + + if (self.pos == self.n_cores - 1): + self.stage1_log() + self.ctx2.stage2_init(self) + self.ctx2.stage2_process() + + if (self.pos == 0): + return + + self.cores[self.pos].pipelines = 0 + self.pos -= 1 + continue + + self.pos += 1 + + def stage1_log(self): + tmp_file_comment = "" + if(enable_stage1_traceout == 1): + print('STAGE1: ', end='') + tmp_file_comment += 'STAGE1: ' + i = 0 + while (i < self.n_cores): + print('C%d = [' % i, end='') + tmp_file_comment += "C{} = [".format(i) + + j = self.n_pipelines - 1 + while (j >= 0): + cond = ((self.cores[i].pipelines) & (1 << j)) + if (cond): + print('1', end='') + tmp_file_comment += '1' + else: + print('0', end='') + tmp_file_comment += '0' + j -= 1 + + print(']\t', end='') + tmp_file_comment += ']\t' + i += 1 + + print('\n', end='') + self.stage1_file_comment = tmp_file_comment + self.ctx2.stage1_file_comment = tmp_file_comment + + # check if file traceing is enabled + if(enable_stage1_fileout != 1): + return + + # spit out the combination to file + self.stage1_process_file() + + def stage1_updateCoresInBuf(self, nPipeline, sCore): + rePipeline = self._fileTrace.arr_pipelines[nPipeline] + rePipeline = rePipeline.replace("[", "\[").replace("]", "\]") + reCore = 'core\s*=\s*((\d*)|(((s|S)\d)?(c|C)[1-9][0-9]*)).*\n' + sSubs = 'core = ' + sCore + '\n' + + reg_pipeline = re.compile(rePipeline) + search_match = reg_pipeline.search(self._fileTrace.in_buf) + + if(search_match): + pos = search_match.start() + substr1 = self._fileTrace.in_buf[:pos] + substr2 = self._fileTrace.in_buf[pos:] + substr2 = re.sub(reCore, sSubs, substr2, 1) + self._fileTrace.in_buf = substr1 + substr2 + + def stage1_process_file(self): + outFileName = os.path.join(self._fileTrace.out_path, + self._fileTrace.prefix_outfile) + outFileName += "_{}CoReS".format(self.n_cores) + + i = 0 # represents core number + while (i < self.n_cores): + j = self.n_pipelines - 1 + pipeline_idx = 0 + while(j >= 0): + cond = ((self.cores[i].pipelines) & (1 << j)) + if (cond): + # update the pipelines array to match the core + # only in case of cond match + self.arr_pipelines2cores[ + pipeline_idx] = fileTrace.in_physical_cores[i] + + j -= 1 + pipeline_idx += 1 + + i += 1 + + # update the in_buf as per the arr_pipelines2cores + for pipeline_idx in range(len(self.arr_pipelines2cores)): + outFileName += "_{}".format(self.arr_pipelines2cores[pipeline_idx]) + self.stage1_updateCoresInBuf( + pipeline_idx, self.arr_pipelines2cores[pipeline_idx]) + + # by now the in_buf is all set to be written to file + outFileName += self._fileTrace.suffix_outfile + outputFile = open(outFileName, "w") + + # write out the comments + strTruncated = ("", "(Truncated)")[self._fileTrace.ncores_truncated] + outputFile.write( + "; =============== Pipeline-to-Core Mapping ================\n" + "; Generated from file {}\n" + "; Input pipelines = {}\n" + "; Input cores = {}\n" + "; N_PIPELINES = {} N_CORES = {} {} hyper_thread = {}\n" + .format( + self._fileTrace.in_file_namepath, + fileTrace.arr_pipelines, + fileTrace.in_physical_cores, + self._fileTrace.n_pipelines, + self._fileTrace.n_cores, + strTruncated, + self._fileTrace.hyper_thread)) + + outputFile.write( + "; {stg0cmt}\n" + "; {stg1cmt}\n" + "; ========================================================\n" + "; \n" + .format( + stg0cmt=self.stage0_file_comment, + stg1cmt=self.stage1_file_comment)) + + # write buffer contents + outputFile.write(self._fileTrace.in_buf) + outputFile.flush() + outputFile.close() + + +class Context2: + _fileTrace = None + + def __init__(self): + self.cores = [Cores2() for i in range(constants.MAX_CORES)] + self.n_cores = 0 + self.n_pipelines = 0 + self.pos = 0 + self.stage0_file_comment = "" + self.stage1_file_comment = "" + self.stage2_file_comment = "" + + # each array entry is a pipeline mapped to core stored as string + # pipeline ranging from 1 to n, however stored in zero based array + self.arr2_pipelines2cores = [] + + def stage2_print(self): + print('printing Context2 obj') + print('ctx2.cores(pipelines, n_pipelines, counter, counter_max) =') + for cores_count in range(0, constants.MAX_CORES): + print('core[%d] = (%d,%d,%d,%d)' % ( + cores_count, + self.cores[cores_count].pipelines, + self.cores[cores_count].n_pipelines, + self.cores[cores_count].counter, + self.cores[cores_count].counter_max)) + + print('ctx2.n_cores = %d' % self.n_cores, end='') + print('ctx2.n_pipelines = %d' % self.n_pipelines, end='') + print('ctx2.pos = %d' % self.pos) + print('ctx2.stage0_file_comment = %s' % + self.self.stage0_file_comment) + print('ctx2.stage1_file_comment = %s' % + self.self.stage1_file_comment) + print('ctx2.stage2_file_comment = %s' % + self.self.stage2_file_comment) + + def stage2_reset(self): + for i in range(0, constants.MAX_CORES): + self.cores[i].pipelines = 0 + self.cores[i].n_pipelines = 0 + self.cores[i].counter = 0 + self.cores[i].counter_max = 0 + + for idx in range(0, constants.MAX_PIPELINES): + self.cores[i].bitpos[idx] = 0 + + self.n_cores = 0 + self.n_pipelines = 0 + self.pos = 0 + # clear list + del self.arr2_pipelines2cores[:] + + def bitpos_load(self, coreidx): + i = j = 0 + while (i < self.n_pipelines): + if ((self.cores[coreidx].pipelines) & + (1 << i)): + self.cores[coreidx].bitpos[j] = i + j += 1 + i += 1 + self.cores[coreidx].n_pipelines = j + + def bitpos_apply(self, in_buf, pos, n_pos): + out = 0 + for i in range(0, n_pos): + out |= (in_buf & (1 << i)) << (pos[i] - i) + + return out + + def stage2_init(self, ctx1): + self.stage2_reset() + self.n_cores = ctx1.n_cores + self.n_pipelines = ctx1.n_pipelines + + self.arr2_pipelines2cores = [''] * self.n_pipelines + + core_idx = 0 + while (core_idx < self.n_cores): + self.cores[core_idx].pipelines = ctx1.cores[core_idx].pipelines + + self.bitpos_load(core_idx) + core_idx += 1 + + def stage2_log(self): + tmp_file_comment = "" + if(enable_stage2_traceout == 1): + print('STAGE2: ', end='') + tmp_file_comment += 'STAGE2: ' + + for i in range(0, self.n_cores): + mask = len2mask(self.cores[i].n_pipelines) + pipelines_ht0 = self.bitpos_apply( + (~self.cores[i].counter) & mask, + self.cores[i].bitpos, + self.cores[i].n_pipelines) + + pipelines_ht1 = self.bitpos_apply( + self.cores[i].counter, + self.cores[i].bitpos, + self.cores[i].n_pipelines) + + print('C%dHT0 = [' % i, end='') + tmp_file_comment += "C{}HT0 = [".format(i) + tmp_file_comment += bitstring_write( + pipelines_ht0, self.n_pipelines) + + print(']\tC%dHT1 = [' % i, end='') + tmp_file_comment += "]\tC{}HT1 = [".format(i) + tmp_file_comment += bitstring_write( + pipelines_ht1, self.n_pipelines) + print(']\t', end='') + tmp_file_comment += ']\t' + + print('') + self.stage2_file_comment = tmp_file_comment + + # check if file traceing is enabled + if(enable_stage2_fileout != 1): + return + # spit out the combination to file + self.stage2_process_file() + + def stage2_updateCoresInBuf(self, nPipeline, sCore): + rePipeline = self._fileTrace.arr_pipelines[nPipeline] + rePipeline = rePipeline.replace("[", "\[").replace("]", "\]") + reCore = 'core\s*=\s*((\d*)|(((s|S)\d)?(c|C)[1-9][0-9]*)).*\n' + sSubs = 'core = ' + sCore + '\n' + + reg_pipeline = re.compile(rePipeline) + search_match = reg_pipeline.search(self._fileTrace.in_buf) + + if(search_match): + pos = search_match.start() + substr1 = self._fileTrace.in_buf[:pos] + substr2 = self._fileTrace.in_buf[pos:] + substr2 = re.sub(reCore, sSubs, substr2, 1) + self._fileTrace.in_buf = substr1 + substr2 + + def pipelines2cores(self, n, n_bits, nCore, bHT): + if (n_bits > 64): + return + + i = n_bits - 1 + pipeline_idx = 0 + while (i >= 0): + cond = (n & (1 << i)) + if (cond): + # update the pipelines array to match the core + # only in case of cond match + # PIPELINE0 and core 0 are reserved + if(bHT): + tmpCore = fileTrace.in_physical_cores[nCore] + 'h' + self.arr2_pipelines2cores[pipeline_idx] = tmpCore + else: + self.arr2_pipelines2cores[pipeline_idx] = \ + fileTrace.in_physical_cores[nCore] + + i -= 1 + pipeline_idx += 1 + + def stage2_process_file(self): + outFileName = os.path.join(self._fileTrace.out_path, + self._fileTrace.prefix_outfile) + outFileName += "_{}CoReS".format(self.n_cores) + + for i in range(0, self.n_cores): + mask = len2mask(self.cores[i].n_pipelines) + pipelines_ht0 = self.bitpos_apply((~self.cores[i].counter) & mask, + self.cores[i].bitpos, + self.cores[i].n_pipelines) + + pipelines_ht1 = self.bitpos_apply(self.cores[i].counter, + self.cores[i].bitpos, + self.cores[i].n_pipelines) + + # update pipelines to core mapping + self.pipelines2cores(pipelines_ht0, self.n_pipelines, i, False) + self.pipelines2cores(pipelines_ht1, self.n_pipelines, i, True) + + # update the in_buf as per the arr_pipelines2cores + for pipeline_idx in range(len(self.arr2_pipelines2cores)): + outFileName += "_{}".format( + self.arr2_pipelines2cores[pipeline_idx]) + self.stage2_updateCoresInBuf( + pipeline_idx, self.arr2_pipelines2cores[pipeline_idx]) + + # by now the in_buf is all set to be written to file + outFileName += self._fileTrace.suffix_outfile + outputFile = open(outFileName, "w") + + # write the file comments + strTruncated = ("", "(Truncated)")[self._fileTrace.ncores_truncated] + outputFile.write( + "; =============== Pipeline-to-Core Mapping ================\n" + "; Generated from file {}\n" + "; Input pipelines = {}\n" + "; Input cores = {}\n" + "; N_PIPELINES = {} N_CORES = {} {} hyper_thread = {} \n" + .format( + self._fileTrace.in_file_namepath, + fileTrace.arr_pipelines, + fileTrace.in_physical_cores, + self._fileTrace.n_pipelines, + self._fileTrace.n_cores, + strTruncated, + self._fileTrace.hyper_thread)) + + outputFile.write( + "; {stg0cmt}\n" + "; {stg1cmt}\n" + "; {stg2cmt}\n" + "; ========================================================\n" + "; \n" + .format( + stg0cmt=self.stage0_file_comment, + stg1cmt=self.stage1_file_comment, + stg2cmt=self.stage2_file_comment)) + + # write the buffer contents + outputFile.write(self._fileTrace.in_buf) + outputFile.flush() + outputFile.close() + + def stage2_process(self): + i = 0 + while(i < self.n_cores): + self.cores[i].counter_max = len2mask( + self.cores[i].n_pipelines - 1) + i += 1 + + self.pos = self.n_cores - 1 + while True: + if (self.pos == self.n_cores - 1): + self.stage2_log() + + if (self.cores[self.pos].counter == + self.cores[self.pos].counter_max): + if (self.pos == 0): + return + + self.cores[self.pos].counter = 0 + self.pos -= 1 + continue + + self.cores[self.pos].counter += 1 + if(self.pos < self.n_cores - 1): + self.pos += 1 + + +class FileTrace: + + def __init__(self, filenamepath): + self.in_file_namepath = os.path.abspath(filenamepath) + self.in_filename = os.path.basename(self.in_file_namepath) + self.in_path = os.path.dirname(self.in_file_namepath) + + filenamesplit = self.in_filename.split('.') + self.prefix_outfile = filenamesplit[0] + self.suffix_outfile = ".cfg" + + # output folder: in the same folder as input file + # create new folder in the name of input file + self.out_path = os.path.join( + os.path.abspath(os.path.dirname(__file__)), + self.prefix_outfile) + + try: + os.makedirs(self.out_path) + except OSError as excep: + if excep.errno == errno.EEXIST and os.path.isdir(self.out_path): + pass + else: + raise + + self.in_buf = None + self.arr_pipelines = [] # holds the positions of search + + self.max_cores = 15 + self.max_pipelines = 15 + + self.in_physical_cores = None + self.hyper_thread = None + + # save the num of pipelines determined from input file + self.n_pipelines = 0 + # save the num of cores input (or the truncated value) + self.n_cores = 0 + self.ncores_truncated = False + + def print_TraceFile(self): + print("self.in_file_namepath = ", self.in_file_namepath) + print("self.in_filename = ", self.in_filename) + print("self.in_path = ", self.in_path) + print("self.out_path = ", self.out_path) + print("self.prefix_outfile = ", self.prefix_outfile) + print("self.suffix_outfile = ", self.suffix_outfile) + print("self.in_buf = ", self.in_buf) + print("self.arr_pipelines =", self.arr_pipelines) + print("self.in_physical_cores", self.in_physical_cores) + print("self.hyper_thread", self.hyper_thread) + + +def process(n_cores, n_pipelines, fileTrace): + '''process and map pipelines, cores.''' + if (n_cores == 0): + sys.exit('N_CORES is 0, exiting') + + if (n_pipelines == 0): + sys.exit('N_PIPELINES is 0, exiting') + + if (n_cores > n_pipelines): + print('\nToo many cores, truncating N_CORES to N_PIPELINES') + n_cores = n_pipelines + fileTrace.ncores_truncated = True + + fileTrace.n_pipelines = n_pipelines + fileTrace.n_cores = n_cores + + strTruncated = ("", "(Truncated)")[fileTrace.ncores_truncated] + print("N_PIPELINES = {}, N_CORES = {} {}" + .format(n_pipelines, n_cores, strTruncated)) + print("---------------------------------------------------------------") + + ctx0_inst = Context0() + ctx1_inst = Context1() + ctx2_inst = Context2() + + # initialize the class variables + ctx1_inst._fileTrace = fileTrace + ctx2_inst._fileTrace = fileTrace + + ctx0_inst.stage0_init(n_cores, n_pipelines, ctx1_inst, ctx2_inst) + ctx0_inst.stage0_process() + + +def validate_core(core): + match = reg_phycore.match(core) + if(match): + return True + else: + return False + + +def validate_phycores(phy_cores): + '''validate physical cores, check if unique.''' + # eat up whitespaces + phy_cores = phy_cores.strip().split(',') + + # check if the core list is unique + if(len(phy_cores) != len(set(phy_cores))): + print('list of physical cores has duplicates') + return None + + for core in phy_cores: + if not validate_core(core): + print('invalid physical core specified.') + return None + return phy_cores + + +def scanconfigfile(fileTrace): + '''scan input file for pipelines, validate then process.''' + # open file + filetoscan = open(fileTrace.in_file_namepath, 'r') + fileTrace.in_buf = filetoscan.read() + + # reset iterator on open file + filetoscan.seek(0) + + # scan input file for pipelines + # master pipelines to be ignored + pattern_pipeline = r'\[PIPELINE\d*\]' + pattern_mastertype = r'type\s*=\s*MASTER' + + pending_pipeline = False + for line in filetoscan: + match_pipeline = re.search(pattern_pipeline, line) + match_type = re.search('type\s*=', line) + match_mastertype = re.search(pattern_mastertype, line) + + if(match_pipeline): + sPipeline = line[match_pipeline.start():match_pipeline.end()] + pending_pipeline = True + elif(match_type): + # found a type definition... + if(match_mastertype is None): + # and this is not a master pipeline... + if(pending_pipeline): + # add it to the list of pipelines to be mapped + fileTrace.arr_pipelines.append(sPipeline) + pending_pipeline = False + else: + # and this is a master pipeline... + # ignore the current and move on to next + sPipeline = "" + pending_pipeline = False + filetoscan.close() + + # validate if pipelines are unique + if(len(fileTrace.arr_pipelines) != len(set(fileTrace.arr_pipelines))): + sys.exit('Error: duplicate pipelines in input file') + + num_pipelines = len(fileTrace.arr_pipelines) + num_cores = len(fileTrace.in_physical_cores) + + print("-------------------Pipeline-to-core mapping--------------------") + print("Input pipelines = {}\nInput cores = {}" + .format(fileTrace.arr_pipelines, fileTrace.in_physical_cores)) + + # input configuration file validations goes here + if (num_cores > fileTrace.max_cores): + sys.exit('Error: number of cores specified > max_cores (%d)' % + fileTrace.max_cores) + + if (num_pipelines > fileTrace.max_pipelines): + sys.exit('Error: number of pipelines in input \ + cfg file > max_pipelines (%d)' % fileTrace.max_pipelines) + + # call process to generate pipeline-to-core mapping, trace and log + process(num_cores, num_pipelines, fileTrace) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='mappipelines') + + reqNamedGrp = parser.add_argument_group('required named args') + reqNamedGrp.add_argument( + '-i', + '--input-file', + type=argparse.FileType('r'), + help='Input config file', + required=True) + + reqNamedGrp.add_argument( + '-pc', + '--physical-cores', + type=validate_phycores, + help='''Enter available CPU cores in + format:\"<core>,<core>,...\" + where each core format: \"s<SOCKETID>c<COREID>\" + where SOCKETID={0..9}, COREID={1-99}''', + required=True) + + # add optional arguments + parser.add_argument( + '-ht', + '--hyper-thread', + help='enable/disable hyper threading. default is ON', + default='ON', + choices=['ON', 'OFF']) + + parser.add_argument( + '-nO', + '--no-output-file', + help='''disable output config file generation. + Output file generation is enabled by default''', + action="store_true") + + args = parser.parse_args() + + if(args.physical_cores is None): + parser.error("invalid physical_cores specified") + + # create object of FileTrace and initialise + fileTrace = FileTrace(args.input_file.name) + fileTrace.in_physical_cores = args.physical_cores + fileTrace.hyper_thread = args.hyper_thread + + if(fileTrace.hyper_thread == 'OFF'): + print("!!!!disabling stage2 HT!!!!") + enable_stage2_traceout = 0 + enable_stage2_fileout = 0 + elif(fileTrace.hyper_thread == 'ON'): + print("!!!!HT enabled. disabling stage1 file generation.!!!!") + enable_stage1_fileout = 0 + + if(args.no_output_file is True): + print("!!!!disabling stage1 and stage2 fileout!!!!") + enable_stage1_fileout = 0 + enable_stage2_fileout = 0 + + scanconfigfile(fileTrace) diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c index fd9ff495..af1b6284 100644 --- a/examples/ip_pipeline/config_check.c +++ b/examples/ip_pipeline/config_check.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 @@ -56,6 +56,26 @@ check_mempools(struct app_params *app) } } +static inline uint32_t +link_rxq_used(struct app_link_params *link, uint32_t q_id) +{ + uint32_t i; + + if ((link->arp_q == q_id) || + (link->tcp_syn_q == q_id) || + (link->ip_local_q == q_id) || + (link->tcp_local_q == q_id) || + (link->udp_local_q == q_id) || + (link->sctp_local_q == q_id)) + return 1; + + for (i = 0; i < link->n_rss_qs; i++) + if (link->rss_qs[i] == q_id) + return 1; + + return 0; +} + static void check_links(struct app_params *app) { @@ -90,14 +110,12 @@ check_links(struct app_params *app) rxq_max = link->udp_local_q; if (link->sctp_local_q > rxq_max) rxq_max = link->sctp_local_q; + for (i = 0; i < link->n_rss_qs; i++) + if (link->rss_qs[i] > rxq_max) + rxq_max = link->rss_qs[i]; for (i = 1; i <= rxq_max; i++) - APP_CHECK(((link->arp_q == i) || - (link->tcp_syn_q == i) || - (link->ip_local_q == i) || - (link->tcp_local_q == i) || - (link->udp_local_q == i) || - (link->sctp_local_q == i)), + APP_CHECK((link_rxq_used(link, i)), "%s RXQs are not contiguous (A)\n", link->name); n_rxq = app_link_get_n_rxq(app, link); @@ -118,7 +136,7 @@ check_links(struct app_params *app) "%s RXQs are not contiguous (C)\n", link->name); } - /* Check that link RXQs are contiguous */ + /* Check that link TXQs are contiguous */ n_txq = app_link_get_n_txq(app, link); APP_CHECK((n_txq), "%s does not have any TXQ\n", link->name); @@ -298,6 +316,29 @@ check_tms(struct app_params *app) } static void +check_knis(struct app_params *app) { + uint32_t i; + + for (i = 0; i < app->n_pktq_kni; i++) { + struct app_pktq_kni_params *p = &app->kni_params[i]; + uint32_t n_readers = app_kni_get_readers(app, p); + uint32_t n_writers = app_kni_get_writers(app, p); + + APP_CHECK((n_readers != 0), + "%s has no reader\n", p->name); + + APP_CHECK((n_readers == 1), + "%s has more than one reader\n", p->name); + + APP_CHECK((n_writers != 0), + "%s has no writer\n", p->name); + + APP_CHECK((n_writers == 1), + "%s has more than one writer\n", p->name); + } +} + +static void check_sources(struct app_params *app) { uint32_t i; @@ -435,6 +476,7 @@ app_config_check(struct app_params *app) check_txqs(app); check_swqs(app); check_tms(app); + check_knis(app); check_sources(app); check_sinks(app); check_msgqs(app); diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index e5efd03e..0adca98f 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -1,4 +1,4 @@ -/*- +/*- * BSD LICENSE * * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. @@ -30,6 +30,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include <stdint.h> #include <stdlib.h> #include <stdio.h> @@ -80,6 +81,11 @@ static const struct app_link_params link_params_default = { .tcp_local_q = 0, .udp_local_q = 0, .sctp_local_q = 0, + .rss_qs = {0}, + .n_rss_qs = 0, + .rss_proto_ipv4 = ETH_RSS_IPV4, + .rss_proto_ipv6 = ETH_RSS_IPV6, + .rss_proto_l2 = 0, .state = 0, .ip = 0, .depth = 0, @@ -103,6 +109,13 @@ static const struct app_link_params link_params_default = { .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ .split_hdr_size = 0, /* Header split buffer size */ }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_key_len = 40, + .rss_hf = 0, + }, + }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, @@ -176,6 +189,20 @@ struct app_pktq_tm_params default_tm_params = { .burst_write = 32, }; +struct app_pktq_kni_params default_kni_params = { + .parsed = 0, + .socket_id = 0, + .core_id = 0, + .hyper_th_id = 0, + .force_bind = 0, + + .mempool_id = 0, + .burst_read = 32, + .burst_write = 32, + .dropless = 0, + .n_retries = 0, +}; + struct app_pktq_source_params default_source_params = { .parsed = 0, .mempool_id = 0, @@ -229,306 +256,136 @@ app_print_usage(char *prgname) rte_exit(0, app_usage, prgname, app_params_default.config_file); } -#define skip_white_spaces(pos) \ -({ \ - __typeof__(pos) _p = (pos); \ - for ( ; isspace(*_p); _p++); \ - _p; \ +#define APP_PARAM_ADD(set, key) \ +({ \ + ssize_t pos = APP_PARAM_FIND(set, key); \ + ssize_t size = RTE_DIM(set); \ + \ + if (pos < 0) { \ + for (pos = 0; pos < size; pos++) { \ + if (!APP_PARAM_VALID(&((set)[pos]))) \ + break; \ + } \ + \ + APP_CHECK((pos < size), \ + "Parse error: size of %s is limited to %u elements",\ + #set, (uint32_t) size); \ + \ + (set)[pos].name = strdup(key); \ + APP_CHECK(((set)[pos].name), \ + "Parse error: no free memory"); \ + } \ + pos; \ }) -#define PARSER_PARAM_ADD_CHECK(result, params_array, section_name) \ -do { \ - APP_CHECK((result != -EINVAL), \ - "Parse error: no free memory"); \ - APP_CHECK((result != -ENOMEM), \ - "Parse error: too many \"%s\" sections", section_name); \ - APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\ - "Parse error: duplicate \"%s\" section", section_name); \ - APP_CHECK((result >= 0), \ - "Parse error in section \"%s\"", section_name); \ -} while (0) - -int -parser_read_arg_bool(const char *p) -{ - p = skip_white_spaces(p); - int result = -EINVAL; - - if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || - ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { - p += 3; - result = 1; - } - - if (((p[0] == 'o') && (p[1] == 'n')) || - ((p[0] == 'O') && (p[1] == 'N'))) { - p += 2; - result = 1; - } +#define APP_PARAM_ADD_LINK_FOR_RXQ(app, rxq_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id, queue_id; \ + \ + sscanf((rxq_name), "RXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - if (((p[0] == 'n') && (p[1] == 'o')) || - ((p[0] == 'N') && (p[1] == 'O'))) { - p += 2; - result = 0; - } +#define APP_PARAM_ADD_LINK_FOR_TXQ(app, txq_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id, queue_id; \ + \ + sscanf((txq_name), "TXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || - ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { - p += 3; - result = 0; - } +#define APP_PARAM_ADD_LINK_FOR_TM(app, tm_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id; \ + \ + sscanf((tm_name), "TM%" SCNu32, &link_id); \ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - p = skip_white_spaces(p); +#define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name) \ +({ \ + char link_name[APP_PARAM_NAME_SIZE]; \ + ssize_t link_param_pos; \ + uint32_t link_id; \ + \ + sscanf((kni_name), "KNI%" SCNu32, &link_id); \ + sprintf(link_name, "LINK%" PRIu32, link_id); \ + link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \ + link_param_pos; \ +}) - if (p[0] != '\0') - return -EINVAL; +#define PARSE_CHECK_DUPLICATE_SECTION(obj) \ +do { \ + APP_CHECK(((obj)->parsed == 0), \ + "Parse error: duplicate \"%s\" section", (obj)->name); \ + (obj)->parsed++; \ +} while (0) - return result; -} +#define PARSE_CHECK_DUPLICATE_SECTION_EAL(obj) \ +do { \ + APP_CHECK(((obj)->parsed == 0), \ + "Parse error: duplicate \"%s\" section", "EAL"); \ + (obj)->parsed++; \ +} while (0) #define PARSE_ERROR(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry) +APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"", section, entry) #define PARSE_ERROR_MESSAGE(exp, section, entry, message) \ -APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s\n", \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s", \ section, entry, message) +#define PARSE_ERROR_NO_ELEMENTS(exp, section, entry) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ + "no elements detected", \ + section, entry) + +#define PARSE_ERROR_TOO_MANY_ELEMENTS(exp, section, entry, max) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ + "maximum number of elements allowed is %u", \ + section, entry, max) + +#define PARSE_ERROR_INVALID_ELEMENT(exp, section, entry, value) \ +APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": " \ + "Invalid element value \"%s\"", \ + section, entry, value) #define PARSE_ERROR_MALLOC(exp) \ -APP_CHECK(exp, "Parse error: no free memory\n") +APP_CHECK(exp, "Parse error: no free memory") #define PARSE_ERROR_SECTION(exp, section) \ APP_CHECK(exp, "Parse error in section \"%s\"", section) #define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section) \ -APP_CHECK(exp, "Parse error in section \"%s\": no entries\n", section) +APP_CHECK(exp, "Parse error in section \"%s\": no entries", section) #define PARSE_WARNING_IGNORED(exp, section, entry) \ do \ if (!(exp)) \ fprintf(stderr, "Parse warning in section \"%s\": " \ - "entry \"%s\" is ignored\n", section, entry); \ + "entry \"%s\" is ignored", section, entry); \ while (0) #define PARSE_ERROR_INVALID(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n",\ +APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"",\ section, entry) #define PARSE_ERROR_DUPLICATE(exp, section, entry) \ -APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n",\ +APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"", \ section, entry) -int -parser_read_uint64(uint64_t *value, const char *p) -{ - char *next; - uint64_t val; - - p = skip_white_spaces(p); - if (!isdigit(*p)) - return -EINVAL; - - val = strtoul(p, &next, 10); - if (p == next) - return -EINVAL; - - p = next; - switch (*p) { - case 'T': - val *= 1024ULL; - /* fall through */ - case 'G': - val *= 1024ULL; - /* fall through */ - case 'M': - val *= 1024ULL; - /* fall through */ - case 'k': - case 'K': - val *= 1024ULL; - p++; - break; - } - - p = skip_white_spaces(p); - if (*p != '\0') - return -EINVAL; - - *value = val; - return 0; -} - -int -parser_read_uint32(uint32_t *value, const char *p) -{ - uint64_t val = 0; - int ret = parser_read_uint64(&val, p); - - if (ret < 0) - return ret; - - if (val > UINT32_MAX) - return -ERANGE; - - *value = val; - return 0; -} - -int -parse_pipeline_core(uint32_t *socket, - uint32_t *core, - uint32_t *ht, - const char *entry) -{ - size_t num_len; - char num[8]; - - uint32_t s = 0, c = 0, h = 0, val; - uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; - const char *next = skip_white_spaces(entry); - char type; - - /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */ - while (*next != '\0') { - /* If everything parsed nothing should left */ - if (s_parsed && c_parsed && h_parsed) - return -EINVAL; - - type = *next; - switch (type) { - case 's': - case 'S': - if (s_parsed || c_parsed || h_parsed) - return -EINVAL; - s_parsed = 1; - next++; - break; - case 'c': - case 'C': - if (c_parsed || h_parsed) - return -EINVAL; - c_parsed = 1; - next++; - break; - case 'h': - case 'H': - if (h_parsed) - return -EINVAL; - h_parsed = 1; - next++; - break; - default: - /* If it start from digit it must be only core id. */ - if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) - return -EINVAL; - - type = 'C'; - } - - for (num_len = 0; *next != '\0'; next++, num_len++) { - if (num_len == RTE_DIM(num)) - return -EINVAL; - - if (!isdigit(*next)) - break; - - num[num_len] = *next; - } - - if (num_len == 0 && type != 'h' && type != 'H') - return -EINVAL; - - if (num_len != 0 && (type == 'h' || type == 'H')) - return -EINVAL; - - num[num_len] = '\0'; - val = strtol(num, NULL, 10); - - h = 0; - switch (type) { - case 's': - case 'S': - s = val; - break; - case 'c': - case 'C': - c = val; - break; - case 'h': - case 'H': - h = 1; - break; - } - } - - *socket = s; - *core = c; - *ht = h; - return 0; -} - -static uint32_t -get_hex_val(char c) -{ - switch (c) { - case '0': case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - return c - '0'; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - return c - 'A' + 10; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - return c - 'a' + 10; - default: - return 0; - } -} - -int -parse_hex_string(char *src, uint8_t *dst, uint32_t *size) -{ - char *c; - uint32_t len, i; - - /* Check input parameters */ - if ((src == NULL) || - (dst == NULL) || - (size == NULL) || - (*size == 0)) - return -1; - - len = strlen(src); - if (((len & 3) != 0) || - (len > (*size) * 2)) - return -1; - *size = len / 2; - - for (c = src; *c != 0; c++) { - if ((((*c) >= '0') && ((*c) <= '9')) || - (((*c) >= 'A') && ((*c) <= 'F')) || - (((*c) >= 'a') && ((*c) <= 'f'))) - continue; - - return -1; - } - - /* Convert chars to bytes */ - for (i = 0; i < *size; i++) - dst[i] = get_hex_val(src[2 * i]) * 16 + - get_hex_val(src[2 * i + 1]); - - return 0; -} - -static size_t -skip_digits(const char *src) -{ - size_t i; - - for (i = 0; isdigit(src[i]); i++); - - return i; -} - static int validate_name(const char *name, const char *prefix, int num) { @@ -584,6 +441,8 @@ parse_eal(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); + PARSE_CHECK_DUPLICATE_SECTION_EAL(p); + for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *entry = &entries[i]; @@ -963,413 +822,162 @@ parse_eal(struct app_params *app, free(entries); } -static int -parse_pipeline_pcap_source(struct app_params *app, - struct app_pipeline_params *p, - const char *file_name, const char *cp_size) -{ - const char *next = NULL; - char *end; - uint32_t i; - int parse_file = 0; - - if (file_name && !cp_size) { - next = file_name; - parse_file = 1; /* parse file path */ - } else if (cp_size && !file_name) { - next = cp_size; - parse_file = 0; /* parse copy size */ - } else - return -EINVAL; - - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - - if (p->n_pktq_in == 0) - return -EINVAL; - - i = 0; - while (*next != '\0') { - uint32_t id; - - if (i >= p->n_pktq_in) - return -EINVAL; - - id = p->pktq_in[i].id; - - end = strchr(next, ' '); - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; - - if (parse_file) { - app->source_params[id].file_name = strdup(name); - if (app->source_params[id].file_name == NULL) - return -ENOMEM; - } else { - if (parser_read_uint32( - &app->source_params[id].n_bytes_per_pkt, - name) != 0) { - if (app->source_params[id]. - file_name != NULL) - free(app->source_params[id]. - file_name); - return -EINVAL; - } - } - - i++; - - if (i == p->n_pktq_in) - return 0; - } - - return -EINVAL; -} - -static int -parse_pipeline_pcap_sink(struct app_params *app, - struct app_pipeline_params *p, - const char *file_name, const char *n_pkts_to_dump) -{ - const char *next = NULL; - char *end; - uint32_t i; - int parse_file = 0; - - if (file_name && !n_pkts_to_dump) { - next = file_name; - parse_file = 1; /* parse file path */ - } else if (n_pkts_to_dump && !file_name) { - next = n_pkts_to_dump; - parse_file = 0; /* parse copy size */ - } else - return -EINVAL; - - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - - if (p->n_pktq_out == 0) - return -EINVAL; - - i = 0; - while (*next != '\0') { - uint32_t id; - - if (i >= p->n_pktq_out) - return -EINVAL; - - id = p->pktq_out[i].id; - - end = strchr(next, ' '); - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; - - if (parse_file) { - app->sink_params[id].file_name = strdup(name); - if (app->sink_params[id].file_name == NULL) - return -ENOMEM; - } else { - if (parser_read_uint32( - &app->sink_params[id].n_pkts_to_dump, - name) != 0) { - if (app->sink_params[id].file_name != - NULL) - free(app->sink_params[id]. - file_name); - return -EINVAL; - } - } - - i++; - - if (i == p->n_pktq_out) - return 0; - } - - return -EINVAL; -} - -static int +static void parse_pipeline_pktq_in(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; + p->n_pktq_in = 0; - while (*next != '\0') { + while (1) { enum app_pktq_in_type type; int id; - char *end_space; - char *end_tab; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - next = skip_white_spaces(next); - if (!next) + if (name == NULL) break; - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); - - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; - - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_pktq_in < RTE_DIM(p->pktq_in)), + p->name, "pktq_in", (uint32_t)RTE_DIM(p->pktq_in)); if (validate_name(name, "RXQ", 2) == 0) { type = APP_PKTQ_IN_HWQ; id = APP_PARAM_ADD(app->hwq_in_params, name); + APP_PARAM_ADD_LINK_FOR_RXQ(app, name); } else if (validate_name(name, "SWQ", 1) == 0) { type = APP_PKTQ_IN_SWQ; id = APP_PARAM_ADD(app->swq_params, name); } else if (validate_name(name, "TM", 1) == 0) { type = APP_PKTQ_IN_TM; id = APP_PARAM_ADD(app->tm_params, name); + APP_PARAM_ADD_LINK_FOR_TM(app, name); + } else if (validate_name(name, "KNI", 1) == 0) { + type = APP_PKTQ_IN_KNI; + id = APP_PARAM_ADD(app->kni_params, name); + APP_PARAM_ADD_LINK_FOR_KNI(app, name); } else if (validate_name(name, "SOURCE", 1) == 0) { type = APP_PKTQ_IN_SOURCE; id = APP_PARAM_ADD(app->source_params, name); } else - return -EINVAL; - - if (id < 0) - return id; + PARSE_ERROR_INVALID_ELEMENT(0, + p->name, "pktq_in", name); p->pktq_in[p->n_pktq_in].type = type; p->pktq_in[p->n_pktq_in].id = (uint32_t) id; p->n_pktq_in++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_pktq_in > 0), p->name, "pktq_in"); } -static int +static void parse_pipeline_pktq_out(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; + p->n_pktq_out = 0; - while (*next != '\0') { + while (1) { enum app_pktq_out_type type; int id; - char *end_space; - char *end_tab; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - next = skip_white_spaces(next); - if (!next) + if (name == NULL) break; - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_pktq_out < RTE_DIM(p->pktq_out)), + p->name, "pktq_out", (uint32_t)RTE_DIM(p->pktq_out)); - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; - - if (!end) - name_len = strlen(next); - else - name_len = end - next; - - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; - - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; if (validate_name(name, "TXQ", 2) == 0) { type = APP_PKTQ_OUT_HWQ; id = APP_PARAM_ADD(app->hwq_out_params, name); + APP_PARAM_ADD_LINK_FOR_TXQ(app, name); } else if (validate_name(name, "SWQ", 1) == 0) { type = APP_PKTQ_OUT_SWQ; id = APP_PARAM_ADD(app->swq_params, name); } else if (validate_name(name, "TM", 1) == 0) { type = APP_PKTQ_OUT_TM; id = APP_PARAM_ADD(app->tm_params, name); + APP_PARAM_ADD_LINK_FOR_TM(app, name); + } else if (validate_name(name, "KNI", 1) == 0) { + type = APP_PKTQ_OUT_KNI; + id = APP_PARAM_ADD(app->kni_params, name); + APP_PARAM_ADD_LINK_FOR_KNI(app, name); } else if (validate_name(name, "SINK", 1) == 0) { type = APP_PKTQ_OUT_SINK; id = APP_PARAM_ADD(app->sink_params, name); } else - return -EINVAL; - - if (id < 0) - return id; + PARSE_ERROR_INVALID_ELEMENT(0, + p->name, "pktq_out", name); p->pktq_out[p->n_pktq_out].type = type; p->pktq_out[p->n_pktq_out].id = id; p->n_pktq_out++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_pktq_out > 0), p->name, "pktq_out"); } -static int +static void parse_pipeline_msgq_in(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - ssize_t idx; - - while (*next != '\0') { - char *end_space; - char *end_tab; - - next = skip_white_spaces(next); - if (!next) - break; - - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); + p->n_msgq_in = 0; - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; + while (1) { + int idx; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - if (!end) - name_len = strlen(next); - else - name_len = end - next; + if (name == NULL) + break; - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_msgq_in < RTE_DIM(p->msgq_in)), + p->name, "msgq_in", (uint32_t)(RTE_DIM(p->msgq_in))); - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; - - if (validate_name(name, "MSGQ", 1) != 0) - return -EINVAL; + PARSE_ERROR_INVALID_ELEMENT( + (validate_name(name, "MSGQ", 1) == 0), + p->name, "msgq_in", name); idx = APP_PARAM_ADD(app->msgq_params, name); - if (idx < 0) - return idx; - p->msgq_in[p->n_msgq_in] = idx; p->n_msgq_in++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_msgq_in > 0), p->name, "msgq_in"); } -static int +static void parse_pipeline_msgq_out(struct app_params *app, struct app_pipeline_params *p, - const char *value) + char *value) { - const char *next = value; - char *end; - char name[APP_PARAM_NAME_SIZE]; - size_t name_len; - ssize_t idx; - - while (*next != '\0') { - char *end_space; - char *end_tab; - - next = skip_white_spaces(next); - if (!next) - break; - - end_space = strchr(next, ' '); - end_tab = strchr(next, ' '); - - if (end_space && (!end_tab)) - end = end_space; - else if ((!end_space) && end_tab) - end = end_tab; - else if (end_space && end_tab) - end = RTE_MIN(end_space, end_tab); - else - end = NULL; + p->n_msgq_out = 0; - if (!end) - name_len = strlen(next); - else - name_len = end - next; + while (1) { + int idx; + char *name = strtok_r(value, PARSE_DELIMITER, &value); - if (name_len == 0 || name_len == sizeof(name)) - return -EINVAL; + if (name == NULL) + break; - strncpy(name, next, name_len); - name[name_len] = '\0'; - next += name_len; - if (*next != '\0') - next++; + PARSE_ERROR_TOO_MANY_ELEMENTS( + (p->n_msgq_out < RTE_DIM(p->msgq_out)), + p->name, "msgq_out", (uint32_t)RTE_DIM(p->msgq_out)); - if (validate_name(name, "MSGQ", 1) != 0) - return -EINVAL; + PARSE_ERROR_INVALID_ELEMENT( + (validate_name(name, "MSGQ", 1) == 0), + p->name, "msgq_out", name); idx = APP_PARAM_ADD(app->msgq_params, name); - if (idx < 0) - return idx; - p->msgq_out[p->n_msgq_out] = idx; p->n_msgq_out++; } - return 0; + PARSE_ERROR_NO_ELEMENTS((p->n_msgq_out > 0), p->name, "msgq_out"); } static void @@ -1392,9 +1000,8 @@ parse_pipeline(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->pipeline_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name); - param = &app->pipeline_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1421,38 +1028,26 @@ parse_pipeline(struct app_params *app, } if (strcmp(ent->name, "pktq_in") == 0) { - int status = parse_pipeline_pktq_in(app, param, - ent->value); + parse_pipeline_pktq_in(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } if (strcmp(ent->name, "pktq_out") == 0) { - int status = parse_pipeline_pktq_out(app, param, - ent->value); + parse_pipeline_pktq_out(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } if (strcmp(ent->name, "msgq_in") == 0) { - int status = parse_pipeline_msgq_in(app, param, - ent->value); + parse_pipeline_msgq_in(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } if (strcmp(ent->name, "msgq_out") == 0) { - int status = parse_pipeline_msgq_out(app, param, - ent->value); + parse_pipeline_msgq_out(app, param, ent->value); - PARSE_ERROR((status == 0), section_name, - ent->name); continue; } @@ -1466,66 +1061,6 @@ parse_pipeline(struct app_params *app, continue; } - if (strcmp(ent->name, "pcap_file_rd") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_source(app, - param, ent->value, NULL); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_source(app, - param, NULL, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_file_wr") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_sink(app, param, - ent->value, NULL); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - - if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) { - int status; - -#ifndef RTE_PORT_PCAP - PARSE_ERROR_INVALID(0, section_name, ent->name); -#endif - - status = parse_pipeline_pcap_sink(app, param, - NULL, ent->value); - - PARSE_ERROR((status == 0), section_name, - ent->name); - continue; - } - /* pipeline type specific items */ APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), "Parse error in section \"%s\": too many " @@ -1541,17 +1076,13 @@ parse_pipeline(struct app_params *app, param->n_args++; } - param->parsed = 1; - snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_in[param->n_msgq_in++] = param_idx; snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; param->msgq_out[param->n_msgq_out++] = param_idx; @@ -1560,7 +1091,6 @@ parse_pipeline(struct app_params *app, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s", @@ -1568,7 +1098,6 @@ parse_pipeline(struct app_params *app, param->core_id, (param->hyper_th_id) ? "h" : ""); param_idx = APP_PARAM_ADD(app->msgq_params, name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, name); app->msgq_params[param_idx].cpu_socket_id = param->socket_id; free(entries); @@ -1593,9 +1122,8 @@ parse_mempool(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->mempool_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name); - param = &app->mempool_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1640,11 +1168,152 @@ parse_mempool(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } +static int +parse_link_rss_qs(struct app_link_params *p, + char *value) +{ + p->n_rss_qs = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (p->n_rss_qs == RTE_DIM(p->rss_qs)) + return -ENOMEM; + + if (parser_read_uint32(&p->rss_qs[p->n_rss_qs++], token)) + return -EINVAL; + } + + return 0; +} + +static int +parse_link_rss_proto_ipv4(struct app_link_params *p, + char *value) +{ + uint64_t mask = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (strcmp(token, "IP") == 0) { + mask |= ETH_RSS_IPV4; + continue; + } + if (strcmp(token, "FRAG") == 0) { + mask |= ETH_RSS_FRAG_IPV4; + continue; + } + if (strcmp(token, "TCP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_TCP; + continue; + } + if (strcmp(token, "UDP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_UDP; + continue; + } + if (strcmp(token, "SCTP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_SCTP; + continue; + } + if (strcmp(token, "OTHER") == 0) { + mask |= ETH_RSS_NONFRAG_IPV4_OTHER; + continue; + } + return -EINVAL; + } + + p->rss_proto_ipv4 = mask; + return 0; +} + +static int +parse_link_rss_proto_ipv6(struct app_link_params *p, + char *value) +{ + uint64_t mask = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (strcmp(token, "IP") == 0) { + mask |= ETH_RSS_IPV6; + continue; + } + if (strcmp(token, "FRAG") == 0) { + mask |= ETH_RSS_FRAG_IPV6; + continue; + } + if (strcmp(token, "TCP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_TCP; + continue; + } + if (strcmp(token, "UDP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_UDP; + continue; + } + if (strcmp(token, "SCTP") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_SCTP; + continue; + } + if (strcmp(token, "OTHER") == 0) { + mask |= ETH_RSS_NONFRAG_IPV6_OTHER; + continue; + } + if (strcmp(token, "IP_EX") == 0) { + mask |= ETH_RSS_IPV6_EX; + continue; + } + if (strcmp(token, "TCP_EX") == 0) { + mask |= ETH_RSS_IPV6_TCP_EX; + continue; + } + if (strcmp(token, "UDP_EX") == 0) { + mask |= ETH_RSS_IPV6_UDP_EX; + continue; + } + return -EINVAL; + } + + p->rss_proto_ipv6 = mask; + return 0; +} + +static int +parse_link_rss_proto_l2(struct app_link_params *p, + char *value) +{ + uint64_t mask = 0; + + while (1) { + char *token = strtok_r(value, PARSE_DELIMITER, &value); + + if (token == NULL) + break; + + if (strcmp(token, "L2") == 0) { + mask |= ETH_RSS_L2_PAYLOAD; + continue; + } + return -EINVAL; + } + + p->rss_proto_l2 = mask; + return 0; +} + static void parse_link(struct app_params *app, const char *section_name, @@ -1653,6 +1322,10 @@ parse_link(struct app_params *app, struct app_link_params *param; struct rte_cfgfile_entry *entries; int n_entries, i; + int rss_qs_present = 0; + int rss_proto_ipv4_present = 0; + int rss_proto_ipv6_present = 0; + int rss_proto_l2_present = 0; int pci_bdf_present = 0; ssize_t param_idx; @@ -1665,9 +1338,8 @@ parse_link(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->link_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name); - param = &app->link_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1707,7 +1379,6 @@ parse_link(struct app_params *app, continue; } - if (strcmp(ent->name, "tcp_local_q") == 0) { int status = parser_read_uint32( ¶m->tcp_local_q, ent->value); @@ -1735,6 +1406,44 @@ parse_link(struct app_params *app, continue; } + if (strcmp(ent->name, "rss_qs") == 0) { + int status = parse_link_rss_qs(param, ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + rss_qs_present = 1; + continue; + } + + if (strcmp(ent->name, "rss_proto_ipv4") == 0) { + int status = + parse_link_rss_proto_ipv4(param, ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + rss_proto_ipv4_present = 1; + continue; + } + + if (strcmp(ent->name, "rss_proto_ipv6") == 0) { + int status = + parse_link_rss_proto_ipv6(param, ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + rss_proto_ipv6_present = 1; + continue; + } + + if (strcmp(ent->name, "rss_proto_l2") == 0) { + int status = parse_link_rss_proto_l2(param, ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + rss_proto_l2_present = 1; + continue; + } + if (strcmp(ent->name, "pci_bdf") == 0) { PARSE_ERROR_DUPLICATE((pci_bdf_present == 0), section_name, ent->name); @@ -1760,7 +1469,28 @@ parse_link(struct app_params *app, "this entry is mandatory (port_mask is not " "provided)"); - param->parsed = 1; + if (rss_proto_ipv4_present) + PARSE_ERROR_MESSAGE((rss_qs_present), + section_name, "rss_proto_ipv4", + "entry not allowed (rss_qs entry is not provided)"); + if (rss_proto_ipv6_present) + PARSE_ERROR_MESSAGE((rss_qs_present), + section_name, "rss_proto_ipv6", + "entry not allowed (rss_qs entry is not provided)"); + if (rss_proto_l2_present) + PARSE_ERROR_MESSAGE((rss_qs_present), + section_name, "rss_proto_l2", + "entry not allowed (rss_qs entry is not provided)"); + if (rss_proto_ipv4_present | + rss_proto_ipv6_present | + rss_proto_l2_present){ + if (rss_proto_ipv4_present == 0) + param->rss_proto_ipv4 = 0; + if (rss_proto_ipv6_present == 0) + param->rss_proto_ipv6 = 0; + if (rss_proto_l2_present == 0) + param->rss_proto_l2 = 0; + } free(entries); } @@ -1784,9 +1514,10 @@ parse_rxq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->hwq_in_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name); - param = &app->hwq_in_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_RXQ(app, section_name); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1798,10 +1529,8 @@ parse_rxq(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_id = idx; continue; } @@ -1828,8 +1557,6 @@ parse_rxq(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -1852,9 +1579,10 @@ parse_txq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->hwq_out_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name); - param = &app->hwq_out_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_TXQ(app, section_name); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -1887,12 +1615,19 @@ parse_txq(struct app_params *app, continue; } + if (strcmp(ent->name, "n_retries") == 0) { + int status = parser_read_uint64(¶m->n_retries, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + /* unrecognized */ PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -1920,9 +1655,8 @@ parse_swq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->swq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name); - param = &app->swq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2050,11 +1784,9 @@ parse_swq(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_direct_id = idx; + mempool_direct_present = 1; continue; } @@ -2066,11 +1798,10 @@ parse_swq(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_indirect_id = idx; + mempool_indirect_present = 1; continue; } @@ -2079,32 +1810,30 @@ parse_swq(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - APP_CHECK(((mtu_present) && + APP_CHECK(((mtu_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"mtu\" is not allowed", section_name); - APP_CHECK(((metadata_size_present) && + APP_CHECK(((metadata_size_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"metadata_size\" is " "not allowed", section_name); - APP_CHECK(((mempool_direct_present) && + APP_CHECK(((mempool_direct_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"mempool_direct\" is " "not allowed", section_name); - APP_CHECK(((mempool_indirect_present) && + APP_CHECK(((mempool_indirect_present == 0) || ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))), "Parse error in section \"%s\": IPv4/IPv6 fragmentation " "is off, therefore entry \"mempool_indirect\" is " "not allowed", section_name); - param->parsed = 1; - free(entries); } @@ -2127,9 +1856,10 @@ parse_tm(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->tm_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name); - param = &app->tm_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_TM(app, section_name); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2162,7 +1892,101 @@ parse_tm(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; + free(entries); +} + +static void +parse_kni(struct app_params *app, + const char *section_name, + struct rte_cfgfile *cfg) +{ + struct app_pktq_kni_params *param; + struct rte_cfgfile_entry *entries; + int n_entries, i; + ssize_t param_idx; + + n_entries = rte_cfgfile_section_num_entries(cfg, section_name); + PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name); + + entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry)); + PARSE_ERROR_MALLOC(entries != NULL); + + rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); + + param_idx = APP_PARAM_ADD(app->kni_params, section_name); + param = &app->kni_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); + + APP_PARAM_ADD_LINK_FOR_KNI(app, section_name); + + for (i = 0; i < n_entries; i++) { + struct rte_cfgfile_entry *ent = &entries[i]; + + if (strcmp(ent->name, "core") == 0) { + int status = parse_pipeline_core( + ¶m->socket_id, + ¶m->core_id, + ¶m->hyper_th_id, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + param->force_bind = 1; + continue; + } + + if (strcmp(ent->name, "mempool") == 0) { + int status = validate_name(ent->value, + "MEMPOOL", 1); + ssize_t idx; + + PARSE_ERROR((status == 0), section_name, + ent->name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); + param->mempool_id = idx; + continue; + } + + if (strcmp(ent->name, "burst_read") == 0) { + int status = parser_read_uint32(¶m->burst_read, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "burst_write") == 0) { + int status = parser_read_uint32(¶m->burst_write, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + if (strcmp(ent->name, "dropless") == 0) { + int status = parser_read_arg_bool(ent->value); + + PARSE_ERROR((status != -EINVAL), section_name, + ent->name); + param->dropless = status; + continue; + } + + if (strcmp(ent->name, "n_retries") == 0) { + int status = parser_read_uint64(¶m->n_retries, + ent->value); + + PARSE_ERROR((status == 0), section_name, + ent->name); + continue; + } + + /* unrecognized */ + PARSE_ERROR_INVALID(0, section_name, ent->name); + } free(entries); } @@ -2188,9 +2012,8 @@ parse_source(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->source_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name); - param = &app->source_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2202,10 +2025,8 @@ parse_source(struct app_params *app, PARSE_ERROR((status == 0), section_name, ent->name); - idx = APP_PARAM_ADD(app->mempool_params, - ent->value); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, - section_name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); param->mempool_id = idx; continue; } @@ -2219,7 +2040,7 @@ parse_source(struct app_params *app, continue; } - if (strcmp(ent->name, "pcap_file_rd")) { + if (strcmp(ent->name, "pcap_file_rd") == 0) { PARSE_ERROR_DUPLICATE((pcap_file_present == 0), section_name, ent->name); @@ -2251,8 +2072,6 @@ parse_source(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2277,14 +2096,13 @@ parse_sink(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->sink_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->sink_params, section_name); - param = &app->sink_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; - if (strcmp(ent->name, "pcap_file_wr")) { + if (strcmp(ent->name, "pcap_file_wr") == 0) { PARSE_ERROR_DUPLICATE((pcap_file_present == 0), section_name, ent->name); @@ -2295,7 +2113,7 @@ parse_sink(struct app_params *app, continue; } - if (strcmp(ent->name, "pcap_n_pkt_wr")) { + if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) { int status; PARSE_ERROR_DUPLICATE((pcap_n_pkt_present == 0), @@ -2314,8 +2132,6 @@ parse_sink(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2338,9 +2154,8 @@ parse_msgq_req_pipeline(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2358,7 +2173,6 @@ parse_msgq_req_pipeline(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; free(entries); } @@ -2381,9 +2195,8 @@ parse_msgq_rsp_pipeline(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2401,8 +2214,6 @@ parse_msgq_rsp_pipeline(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2425,9 +2236,8 @@ parse_msgq(struct app_params *app, rte_cfgfile_section_entries(cfg, section_name, entries, n_entries); param_idx = APP_PARAM_ADD(app->msgq_params, section_name); - PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name); - param = &app->msgq_params[param_idx]; + PARSE_CHECK_DUPLICATE_SECTION(param); for (i = 0; i < n_entries; i++) { struct rte_cfgfile_entry *ent = &entries[i]; @@ -2454,8 +2264,6 @@ parse_msgq(struct app_params *app, PARSE_ERROR_INVALID(0, section_name, ent->name); } - param->parsed = 1; - free(entries); } @@ -2478,6 +2286,7 @@ static const struct config_section cfg_file_scheme[] = { {"TXQ", 2, parse_txq}, {"SWQ", 1, parse_swq}, {"TM", 1, parse_tm}, + {"KNI", 1, parse_kni}, {"SOURCE", 1, parse_source}, {"SINK", 1, parse_sink}, {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline}, @@ -2488,10 +2297,7 @@ static const struct config_section cfg_file_scheme[] = { static void create_implicit_mempools(struct app_params *app) { - ssize_t idx; - - idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); - PARSER_PARAM_ADD_CHECK(idx, app->mempool_params, "start-up"); + APP_PARAM_ADD(app->mempool_params, "MEMPOOL0"); } static void @@ -2510,7 +2316,6 @@ create_implicit_links_from_port_mask(struct app_params *app, snprintf(name, sizeof(name), "LINK%" PRIu32, link_id); idx = APP_PARAM_ADD(app->link_params, name); - PARSER_PARAM_ADD_CHECK(idx, app->link_params, name); app->link_params[idx].pmd_id = pmd_id; link_id++; @@ -2525,6 +2330,11 @@ assign_link_pmd_id_from_pci_bdf(struct app_params *app) for (i = 0; i < app->n_links; i++) { struct app_link_params *link = &app->link_params[i]; + APP_CHECK((strlen(link->pci_bdf)), + "Parse error: %s pci_bdf is not configured " + "(port_mask is not provided)", + link->name); + link->pmd_id = i; } } @@ -2615,28 +2425,12 @@ app_config_parse(struct app_params *app, const char *file_name) APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out); APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq); APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm); + APP_PARAM_COUNT(app->kni_params, app->n_pktq_kni); APP_PARAM_COUNT(app->source_params, app->n_pktq_source); APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink); APP_PARAM_COUNT(app->msgq_params, app->n_msgq); APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines); -#ifdef RTE_PORT_PCAP - for (i = 0; i < (int)app->n_pktq_source; i++) { - struct app_pktq_source_params *p = &app->source_params[i]; - - APP_CHECK((p->file_name), "Parse error: missing " - "mandatory field \"pcap_file_rd\" for \"%s\"", - p->name); - } -#else - for (i = 0; i < (int)app->n_pktq_source; i++) { - struct app_pktq_source_params *p = &app->source_params[i]; - - APP_CHECK((!p->file_name), "Parse error: invalid field " - "\"pcap_file_rd\" for \"%s\"", p->name); - } -#endif - if (app->port_mask == 0) assign_link_pmd_id_from_pci_bdf(app); @@ -2803,6 +2597,84 @@ save_links_params(struct app_params *app, FILE *f) fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q", p->sctp_local_q); + if (p->n_rss_qs) { + uint32_t j; + + /* rss_qs */ + fprintf(f, "rss_qs = "); + for (j = 0; j < p->n_rss_qs; j++) + fprintf(f, "%" PRIu32 " ", p->rss_qs[j]); + fputc('\n', f); + + /* rss_proto_ipv4 */ + if (p->rss_proto_ipv4) { + fprintf(f, "rss_proto_ipv4 = "); + if (p->rss_proto_ipv4 & ETH_RSS_IPV4) + fprintf(f, "IP "); + if (p->rss_proto_ipv4 & ETH_RSS_FRAG_IPV4) + fprintf(f, "FRAG "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_TCP) + fprintf(f, "TCP "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_UDP) + fprintf(f, "UDP "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_SCTP) + fprintf(f, "SCTP "); + if (p->rss_proto_ipv4 & + ETH_RSS_NONFRAG_IPV4_OTHER) + fprintf(f, "OTHER "); + fprintf(f, "\n"); + } else + fprintf(f, "; rss_proto_ipv4 = <NONE>\n"); + + /* rss_proto_ipv6 */ + if (p->rss_proto_ipv6) { + fprintf(f, "rss_proto_ipv6 = "); + if (p->rss_proto_ipv6 & ETH_RSS_IPV6) + fprintf(f, "IP "); + if (p->rss_proto_ipv6 & ETH_RSS_FRAG_IPV6) + fprintf(f, "FRAG "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_TCP) + fprintf(f, "TCP "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_UDP) + fprintf(f, "UDP "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_SCTP) + fprintf(f, "SCTP "); + if (p->rss_proto_ipv6 & + ETH_RSS_NONFRAG_IPV6_OTHER) + fprintf(f, "OTHER "); + if (p->rss_proto_ipv6 & ETH_RSS_IPV6_EX) + fprintf(f, "IP_EX "); + if (p->rss_proto_ipv6 & + ETH_RSS_IPV6_TCP_EX) + fprintf(f, "TCP_EX "); + if (p->rss_proto_ipv6 & + ETH_RSS_IPV6_UDP_EX) + fprintf(f, "UDP_EX "); + fprintf(f, "\n"); + } else + fprintf(f, "; rss_proto_ipv6 = <NONE>\n"); + + /* rss_proto_l2 */ + if (p->rss_proto_l2) { + fprintf(f, "rss_proto_l2 = "); + if (p->rss_proto_l2 & ETH_RSS_L2_PAYLOAD) + fprintf(f, "L2 "); + fprintf(f, "\n"); + } else + fprintf(f, "; rss_proto_l2 = <NONE>\n"); + } else { + fprintf(f, "; rss_qs = <NONE>\n"); + fprintf(f, "; rss_proto_ipv4 = <NONE>\n"); + fprintf(f, "; rss_proto_ipv6 = <NONE>\n"); + fprintf(f, "; rss_proto_l2 = <NONE>\n"); + } + if (strlen(p->pci_bdf)) fprintf(f, "%s = %s\n", "pci_bdf", p->pci_bdf); @@ -2851,6 +2723,7 @@ save_txq_params(struct app_params *app, FILE *f) fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); + fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); fputc('\n', f); } @@ -2916,6 +2789,53 @@ save_tm_params(struct app_params *app, FILE *f) } static void +save_kni_params(struct app_params *app, FILE *f) +{ + struct app_pktq_kni_params *p; + size_t i, count; + + count = RTE_DIM(app->kni_params); + for (i = 0; i < count; i++) { + p = &app->kni_params[i]; + if (!APP_PARAM_VALID(p)) + continue; + + /* section name */ + fprintf(f, "[%s]\n", p->name); + + /* core */ + if (p->force_bind) { + fprintf(f, "; force_bind = 1\n"); + fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n", + p->socket_id, + p->core_id, + (p->hyper_th_id) ? "h" : ""); + } else + fprintf(f, "; force_bind = 0\n"); + + /* mempool */ + fprintf(f, "%s = %s\n", "mempool", + app->mempool_params[p->mempool_id].name); + + /* burst_read */ + fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read); + + /* burst_write */ + fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write); + + /* dropless */ + fprintf(f, "%s = %s\n", + "dropless", + p->dropless ? "yes" : "no"); + + /* n_retries */ + fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); + + fputc('\n', f); + } +} + +static void save_source_params(struct app_params *app, FILE *f) { struct app_pktq_source_params *p; @@ -3022,6 +2942,9 @@ save_pipeline_params(struct app_params *app, FILE *f) case APP_PKTQ_IN_TM: name = app->tm_params[pp->id].name; break; + case APP_PKTQ_IN_KNI: + name = app->kni_params[pp->id].name; + break; case APP_PKTQ_IN_SOURCE: name = app->source_params[pp->id].name; break; @@ -3056,6 +2979,9 @@ save_pipeline_params(struct app_params *app, FILE *f) case APP_PKTQ_OUT_TM: name = app->tm_params[pp->id].name; break; + case APP_PKTQ_OUT_KNI: + name = app->kni_params[pp->id].name; + break; case APP_PKTQ_OUT_SINK: name = app->sink_params[pp->id].name; break; @@ -3141,6 +3067,7 @@ app_config_save(struct app_params *app, const char *file_name) save_txq_params(app, file); save_swq_params(app, file); save_tm_params(app, file); + save_kni_params(app, file); save_source_params(app, file); save_sink_params(app, file); save_msgq_params(app, file); @@ -3156,6 +3083,10 @@ app_config_init(struct app_params *app) memcpy(app, &app_params_default, sizeof(struct app_params)); + /* configure default_source_params */ + default_source_params.file_name = strdup("./config/packets.pcap"); + PARSE_ERROR_MALLOC(default_source_params.file_name != NULL); + for (i = 0; i < RTE_DIM(app->mempool_params); i++) memcpy(&app->mempool_params[i], &mempool_params_default, @@ -3186,6 +3117,11 @@ app_config_init(struct app_params *app) &default_tm_params, sizeof(default_tm_params)); + for (i = 0; i < RTE_DIM(app->kni_params); i++) + memcpy(&app->kni_params[i], + &default_kni_params, + sizeof(default_kni_params)); + for (i = 0; i < RTE_DIM(app->source_params); i++) memcpy(&app->source_params[i], &default_source_params, diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c index 83422e88..cd167f61 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -55,6 +55,8 @@ #define APP_NAME_SIZE 32 +#define APP_RETA_SIZE_MAX (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE) + static void app_init_core_map(struct app_params *app) { @@ -902,6 +904,67 @@ app_get_cpu_socket_id(uint32_t pmd_id) return (status != SOCKET_ID_ANY) ? status : 0; } +static inline int +app_link_rss_enabled(struct app_link_params *cp) +{ + return (cp->n_rss_qs) ? 1 : 0; +} + +static void +app_link_rss_setup(struct app_link_params *cp) +{ + struct rte_eth_dev_info dev_info; + struct rte_eth_rss_reta_entry64 reta_conf[APP_RETA_SIZE_MAX]; + uint32_t i; + int status; + + /* Get RETA size */ + memset(&dev_info, 0, sizeof(dev_info)); + rte_eth_dev_info_get(cp->pmd_id, &dev_info); + + if (dev_info.reta_size == 0) + rte_panic("%s (%u): RSS setup error (null RETA size)\n", + cp->name, cp->pmd_id); + + if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512) + rte_panic("%s (%u): RSS setup error (RETA size too big)\n", + cp->name, cp->pmd_id); + + /* Setup RETA contents */ + memset(reta_conf, 0, sizeof(reta_conf)); + + for (i = 0; i < dev_info.reta_size; i++) + reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX; + + for (i = 0; i < dev_info.reta_size; i++) { + uint32_t reta_id = i / RTE_RETA_GROUP_SIZE; + uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE; + uint32_t rss_qs_pos = i % cp->n_rss_qs; + + reta_conf[reta_id].reta[reta_pos] = + (uint16_t) cp->rss_qs[rss_qs_pos]; + } + + /* RETA update */ + status = rte_eth_dev_rss_reta_update(cp->pmd_id, + reta_conf, + dev_info.reta_size); + if (status != 0) + rte_panic("%s (%u): RSS setup error (RETA update failed)\n", + cp->name, cp->pmd_id); +} + +static void +app_init_link_set_config(struct app_link_params *p) +{ + if (p->n_rss_qs) { + p->conf.rxmode.mq_mode = ETH_MQ_RX_RSS; + p->conf.rx_adv_conf.rss_conf.rss_hf = p->rss_proto_ipv4 | + p->rss_proto_ipv6 | + p->rss_proto_l2; + } +} + static void app_init_link(struct app_params *app) { @@ -917,6 +980,7 @@ app_init_link(struct app_params *app) sscanf(p_link->name, "LINK%" PRIu32, &link_id); n_hwq_in = app_link_get_n_rxq(app, p_link); n_hwq_out = app_link_get_n_txq(app, p_link); + app_init_link_set_config(p_link); APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") " "(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...", @@ -1001,9 +1065,13 @@ app_init_link(struct app_params *app) rte_panic("Cannot start %s (error %" PRId32 ")\n", p_link->name, status); - /* LINK UP */ + /* LINK FILTERS */ app_link_set_arp_filter(app, p_link); app_link_set_tcp_syn_filter(app, p_link); + if (app_link_rss_enabled(p_link)) + app_link_rss_setup(p_link); + + /* LINK UP */ app_link_up_internal(app, p_link); } @@ -1108,6 +1176,111 @@ app_init_tm(struct app_params *app) } } +#ifdef RTE_LIBRTE_KNI +static int +kni_config_network_interface(uint8_t port_id, uint8_t if_up) { + int ret = 0; + + if (port_id >= rte_eth_dev_count()) + return -EINVAL; + + ret = (if_up) ? + rte_eth_dev_set_link_up(port_id) : + rte_eth_dev_set_link_down(port_id); + + return ret; +} + +static int +kni_change_mtu(uint8_t port_id, unsigned new_mtu) { + int ret; + + if (port_id >= rte_eth_dev_count()) + return -EINVAL; + + if (new_mtu > ETHER_MAX_LEN) + return -EINVAL; + + /* Set new MTU */ + ret = rte_eth_dev_set_mtu(port_id, new_mtu); + if (ret < 0) + return ret; + + return 0; +} +#endif /* RTE_LIBRTE_KNI */ + +#ifndef RTE_LIBRTE_KNI +static void +app_init_kni(struct app_params *app) { + if (app->n_pktq_kni == 0) + return; + + rte_panic("Can not init KNI without librte_kni support.\n"); +} +#else +static void +app_init_kni(struct app_params *app) { + uint32_t i; + + if (app->n_pktq_kni == 0) + return; + + rte_kni_init(app->n_pktq_kni); + + for (i = 0; i < app->n_pktq_kni; i++) { + struct app_pktq_kni_params *p_kni = &app->kni_params[i]; + struct app_link_params *p_link; + struct rte_eth_dev_info dev_info; + struct app_mempool_params *mempool_params; + struct rte_mempool *mempool; + struct rte_kni_conf conf; + struct rte_kni_ops ops; + + /* LINK */ + p_link = app_get_link_for_kni(app, p_kni); + memset(&dev_info, 0, sizeof(dev_info)); + rte_eth_dev_info_get(p_link->pmd_id, &dev_info); + + /* MEMPOOL */ + mempool_params = &app->mempool_params[p_kni->mempool_id]; + mempool = app->mempool[p_kni->mempool_id]; + + /* KNI */ + memset(&conf, 0, sizeof(conf)); + snprintf(conf.name, RTE_KNI_NAMESIZE, "%s", p_kni->name); + conf.force_bind = p_kni->force_bind; + if (conf.force_bind) { + int lcore_id; + + lcore_id = cpu_core_map_get_lcore_id(app->core_map, + p_kni->socket_id, + p_kni->core_id, + p_kni->hyper_th_id); + + if (lcore_id < 0) + rte_panic("%s invalid CPU core\n", p_kni->name); + + conf.core_id = (uint32_t) lcore_id; + } + conf.group_id = p_link->pmd_id; + conf.mbuf_size = mempool_params->buffer_size; + conf.addr = dev_info.pci_dev->addr; + conf.id = dev_info.pci_dev->id; + + memset(&ops, 0, sizeof(ops)); + ops.port_id = (uint8_t) p_link->pmd_id; + ops.change_mtu = kni_change_mtu; + ops.config_network_if = kni_config_network_interface; + + APP_LOG(app, HIGH, "Initializing %s ...", p_kni->name); + app->kni[i] = rte_kni_alloc(mempool, &conf, &ops); + if (!app->kni[i]) + rte_panic("%s init error\n", p_kni->name); + } +} +#endif /* RTE_LIBRTE_KNI */ + static void app_init_msgq(struct app_params *app) { @@ -1128,15 +1301,16 @@ app_init_msgq(struct app_params *app) } } -static void app_pipeline_params_get(struct app_params *app, +void app_pipeline_params_get(struct app_params *app, struct app_pipeline_params *p_in, struct pipeline_params *p_out) { uint32_t i; - uint32_t mempool_id; snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name); + snprintf(p_out->type, PIPELINE_TYPE_SIZE, "%s", p_in->type); + p_out->socket_id = (int) p_in->socket_id; p_out->log_level = app->log_level; @@ -1212,34 +1386,35 @@ static void app_pipeline_params_get(struct app_params *app, break; } case APP_PKTQ_IN_TM: + { out->type = PIPELINE_PORT_IN_SCHED_READER; out->params.sched.sched = app->tm[in->id]; out->burst_size = app->tm_params[in->id].burst_read; break; + } +#ifdef RTE_LIBRTE_KNI + case APP_PKTQ_IN_KNI: + { + out->type = PIPELINE_PORT_IN_KNI_READER; + out->params.kni.kni = app->kni[in->id]; + out->burst_size = app->kni_params[in->id].burst_read; + break; + } +#endif /* RTE_LIBRTE_KNI */ case APP_PKTQ_IN_SOURCE: - mempool_id = app->source_params[in->id].mempool_id; + { + uint32_t mempool_id = + app->source_params[in->id].mempool_id; + out->type = PIPELINE_PORT_IN_SOURCE; out->params.source.mempool = app->mempool[mempool_id]; out->burst_size = app->source_params[in->id].burst; - -#ifdef RTE_NEXT_ABI - if (app->source_params[in->id].file_name - != NULL) { - out->params.source.file_name = strdup( - app->source_params[in->id]. - file_name); - if (out->params.source.file_name == NULL) { - out->params.source. - n_bytes_per_pkt = 0; - break; - } - out->params.source.n_bytes_per_pkt = - app->source_params[in->id]. - n_bytes_per_pkt; - } -#endif - + out->params.source.file_name = + app->source_params[in->id].file_name; + out->params.source.n_bytes_per_pkt = + app->source_params[in->id].n_bytes_per_pkt; break; + } default: break; } @@ -1350,7 +1525,8 @@ static void app_pipeline_params_get(struct app_params *app, } break; } - case APP_PKTQ_OUT_TM: { + case APP_PKTQ_OUT_TM: + { struct rte_port_sched_writer_params *params = &out->params.sched; @@ -1360,24 +1536,45 @@ static void app_pipeline_params_get(struct app_params *app, app->tm_params[in->id].burst_write; break; } - case APP_PKTQ_OUT_SINK: - out->type = PIPELINE_PORT_OUT_SINK; - if (app->sink_params[in->id].file_name != NULL) { - out->params.sink.file_name = strdup( - app->sink_params[in->id]. - file_name); - if (out->params.sink.file_name == NULL) { - out->params.sink.max_n_pkts = 0; - break; - } - out->params.sink.max_n_pkts = - app->sink_params[in->id]. - n_pkts_to_dump; +#ifdef RTE_LIBRTE_KNI + case APP_PKTQ_OUT_KNI: + { + struct app_pktq_kni_params *p_kni = + &app->kni_params[in->id]; + + if (p_kni->dropless == 0) { + struct rte_port_kni_writer_params *params = + &out->params.kni; + + out->type = PIPELINE_PORT_OUT_KNI_WRITER; + params->kni = app->kni[in->id]; + params->tx_burst_sz = + app->kni_params[in->id].burst_write; } else { - out->params.sink.file_name = NULL; - out->params.sink.max_n_pkts = 0; + struct rte_port_kni_writer_nodrop_params + *params = &out->params.kni_nodrop; + + out->type = PIPELINE_PORT_OUT_KNI_WRITER_NODROP; + params->kni = app->kni[in->id]; + params->tx_burst_sz = + app->kni_params[in->id].burst_write; + params->n_retries = + app->kni_params[in->id].n_retries; } break; + } +#endif /* RTE_LIBRTE_KNI */ + case APP_PKTQ_OUT_SINK: + { + out->type = PIPELINE_PORT_OUT_SINK; + out->params.sink.file_name = + app->sink_params[in->id].file_name; + out->params.sink.max_n_pkts = + app->sink_params[in->id]. + n_pkts_to_dump; + + break; + } default: break; } @@ -1449,6 +1646,27 @@ app_init_pipelines(struct app_params *app) } static void +app_post_init_pipelines(struct app_params *app) +{ + uint32_t p_id; + + for (p_id = 0; p_id < app->n_pipelines; p_id++) { + struct app_pipeline_params *params = + &app->pipeline_params[p_id]; + struct app_pipeline_data *data = &app->pipeline_data[p_id]; + int status; + + if (data->ptype->fe_ops->f_post_init == NULL) + continue; + + status = data->ptype->fe_ops->f_post_init(data->fe); + if (status) + rte_panic("Pipeline instance \"%s\" front-end " + "post-init error\n", params->name); + } +} + +static void app_init_threads(struct app_params *app) { uint64_t time = rte_get_tsc_cycles(); @@ -1534,6 +1752,7 @@ int app_init(struct app_params *app) app_init_link(app); app_init_swq(app); app_init_tm(app); + app_init_kni(app); app_init_msgq(app); app_pipeline_common_cmd_push(app); @@ -1551,6 +1770,13 @@ int app_init(struct app_params *app) return 0; } +int app_post_init(struct app_params *app) +{ + app_post_init_pipelines(app); + + return 0; +} + static int app_pipeline_type_cmd_push(struct app_params *app, struct pipeline_type *ptype) diff --git a/examples/ip_pipeline/parser.c b/examples/ip_pipeline/parser.c new file mode 100644 index 00000000..689e2065 --- /dev/null +++ b/examples/ip_pipeline/parser.c @@ -0,0 +1,745 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * For my_ether_aton() function: + * + * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org> + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * For inet_pton4() and inet_pton6() functions: + * + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <getopt.h> +#include <errno.h> +#include <stdarg.h> +#include <string.h> +#include <libgen.h> +#include <unistd.h> +#include <sys/wait.h> + +#include <rte_errno.h> +#include <rte_cfgfile.h> +#include <rte_string_fns.h> + +#include "app.h" +#include "parser.h" + +static uint32_t +get_hex_val(char c) +{ + switch (c) { + case '0': case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + return c - '0'; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return c - 'A' + 10; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return c - 'a' + 10; + default: + return 0; + } +} + +int +parser_read_arg_bool(const char *p) +{ + p = skip_white_spaces(p); + int result = -EINVAL; + + if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) || + ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) { + p += 3; + result = 1; + } + + if (((p[0] == 'o') && (p[1] == 'n')) || + ((p[0] == 'O') && (p[1] == 'N'))) { + p += 2; + result = 1; + } + + if (((p[0] == 'n') && (p[1] == 'o')) || + ((p[0] == 'N') && (p[1] == 'O'))) { + p += 2; + result = 0; + } + + if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) || + ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) { + p += 3; + result = 0; + } + + p = skip_white_spaces(p); + + if (p[0] != '\0') + return -EINVAL; + + return result; +} + +int +parser_read_uint64(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = skip_white_spaces(p); + if (!isdigit(*p)) + return -EINVAL; + + val = strtoul(p, &next, 10); + if (p == next) + return -EINVAL; + + p = next; + switch (*p) { + case 'T': + val *= 1024ULL; + /* fall through */ + case 'G': + val *= 1024ULL; + /* fall through */ + case 'M': + val *= 1024ULL; + /* fall through */ + case 'k': + case 'K': + val *= 1024ULL; + p++; + break; + } + + p = skip_white_spaces(p); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint64_hex(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = skip_white_spaces(p); + + val = strtoul(p, &next, 16); + if (p == next) + return -EINVAL; + + p = skip_white_spaces(next); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint32(uint32_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT32_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parser_read_uint32_hex(uint32_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT32_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parser_read_uint16(uint16_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT16_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parser_read_uint16_hex(uint16_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT16_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parser_read_uint8(uint8_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT8_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parser_read_uint8_hex(uint8_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT8_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens) +{ + uint32_t i; + + if ((string == NULL) || + (tokens == NULL) || + (*n_tokens < 1)) + return -EINVAL; + + for (i = 0; i < *n_tokens; i++) { + tokens[i] = strtok_r(string, PARSE_DELIMITER, &string); + if (tokens[i] == NULL) + break; + } + + if ((i == *n_tokens) && + (NULL != strtok_r(string, PARSE_DELIMITER, &string))) + return -E2BIG; + + *n_tokens = i; + return 0; +} + +int +parse_hex_string(char *src, uint8_t *dst, uint32_t *size) +{ + char *c; + uint32_t len, i; + + /* Check input parameters */ + if ((src == NULL) || + (dst == NULL) || + (size == NULL) || + (*size == 0)) + return -1; + + len = strlen(src); + if (((len & 3) != 0) || + (len > (*size) * 2)) + return -1; + *size = len / 2; + + for (c = src; *c != 0; c++) { + if ((((*c) >= '0') && ((*c) <= '9')) || + (((*c) >= 'A') && ((*c) <= 'F')) || + (((*c) >= 'a') && ((*c) <= 'f'))) + continue; + + return -1; + } + + /* Convert chars to bytes */ + for (i = 0; i < *size; i++) + dst[i] = get_hex_val(src[2 * i]) * 16 + + get_hex_val(src[2 * i + 1]); + + return 0; +} + +int +parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels) +{ + uint32_t n_max_labels = *n_labels, count = 0; + + /* Check for void list of labels */ + if (strcmp(string, "<void>") == 0) { + *n_labels = 0; + return 0; + } + + /* At least one label should be present */ + for ( ; (*string != '\0'); ) { + char *next; + int value; + + if (count >= n_max_labels) + return -1; + + if (count > 0) { + if (string[0] != ':') + return -1; + + string++; + } + + value = strtol(string, &next, 10); + if (next == string) + return -1; + string = next; + + labels[count++] = (uint32_t) value; + } + + *n_labels = count; + return 0; +} + +#define INADDRSZ 4 +#define IN6ADDRSZ 16 + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + unsigned int new = *tp * 10 + (pch - digits); + + if (new > 255) + return 0; + if (!saw_digit) { + if (++octets > 4) + return 0; + saw_digit = 1; + } + *tp = (unsigned char)new; + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } else + return 0; + } + if (octets < 4) + return 0; + + memcpy(dst, tmp, INADDRSZ); + return 1; +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; + const char *xdigits = 0, *curtok = 0; + int ch = 0, saw_xdigit = 0, count_xdigit = 0; + unsigned int val = 0; + unsigned dbloct_count = 0; + + memset((tp = tmp), '\0', IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return 0; + curtok = src; + saw_xdigit = count_xdigit = 0; + val = 0; + + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr((xdigits = xdigits_l), ch); + if (pch == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + if (count_xdigit >= 4) + return 0; + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + count_xdigit++; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return 0; + colonp = tp; + continue; + } else if (*src == '\0') { + return 0; + } + if (tp + sizeof(int16_t) > endp) + return 0; + *tp++ = (unsigned char) ((val >> 8) & 0xff); + *tp++ = (unsigned char) (val & 0xff); + saw_xdigit = 0; + count_xdigit = 0; + val = 0; + dbloct_count++; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + dbloct_count += 2; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) { + if (tp + sizeof(int16_t) > endp) + return 0; + *tp++ = (unsigned char) ((val >> 8) & 0xff); + *tp++ = (unsigned char) (val & 0xff); + dbloct_count++; + } + if (colonp != NULL) { + /* if we already have 8 double octets, having a colon means error */ + if (dbloct_count == 8) + return 0; + + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + memcpy(dst, tmp, IN6ADDRSZ); + return 1; +} + +static struct ether_addr * +my_ether_aton(const char *a) +{ + int i; + char *end; + unsigned long o[ETHER_ADDR_LEN]; + static struct ether_addr ether_addr; + + i = 0; + do { + errno = 0; + o[i] = strtoul(a, &end, 16); + if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0)) + return NULL; + a = end + 1; + } while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0); + + /* Junk at the end of line */ + if (end[0] != 0) + return NULL; + + /* Support the format XX:XX:XX:XX:XX:XX */ + if (i == ETHER_ADDR_LEN) { + while (i-- != 0) { + if (o[i] > UINT8_MAX) + return NULL; + ether_addr.addr_bytes[i] = (uint8_t)o[i]; + } + /* Support the format XXXX:XXXX:XXXX */ + } else if (i == ETHER_ADDR_LEN / 2) { + while (i-- != 0) { + if (o[i] > UINT16_MAX) + return NULL; + ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8); + ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff); + } + /* unknown format */ + } else + return NULL; + + return (struct ether_addr *)ðer_addr; +} + +int +parse_ipv4_addr(const char *token, struct in_addr *ipv4) +{ + if (strlen(token) >= INET_ADDRSTRLEN) + return -EINVAL; + + if (inet_pton4(token, (unsigned char *)ipv4) != 1) + return -EINVAL; + + return 0; +} + +int +parse_ipv6_addr(const char *token, struct in6_addr *ipv6) +{ + if (strlen(token) >= INET6_ADDRSTRLEN) + return -EINVAL; + + if (inet_pton6(token, (unsigned char *)ipv6) != 1) + return -EINVAL; + + return 0; +} + +int +parse_mac_addr(const char *token, struct ether_addr *addr) +{ + struct ether_addr *tmp; + + tmp = my_ether_aton(token); + if (tmp == NULL) + return -1; + + memcpy(addr, tmp, sizeof(struct ether_addr)); + return 0; +} + +int +parse_pipeline_core(uint32_t *socket, + uint32_t *core, + uint32_t *ht, + const char *entry) +{ + size_t num_len; + char num[8]; + + uint32_t s = 0, c = 0, h = 0, val; + uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0; + const char *next = skip_white_spaces(entry); + char type; + + /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */ + while (*next != '\0') { + /* If everything parsed nothing should left */ + if (s_parsed && c_parsed && h_parsed) + return -EINVAL; + + type = *next; + switch (type) { + case 's': + case 'S': + if (s_parsed || c_parsed || h_parsed) + return -EINVAL; + s_parsed = 1; + next++; + break; + case 'c': + case 'C': + if (c_parsed || h_parsed) + return -EINVAL; + c_parsed = 1; + next++; + break; + case 'h': + case 'H': + if (h_parsed) + return -EINVAL; + h_parsed = 1; + next++; + break; + default: + /* If it start from digit it must be only core id. */ + if (!isdigit(*next) || s_parsed || c_parsed || h_parsed) + return -EINVAL; + + type = 'C'; + } + + for (num_len = 0; *next != '\0'; next++, num_len++) { + if (num_len == RTE_DIM(num)) + return -EINVAL; + + if (!isdigit(*next)) + break; + + num[num_len] = *next; + } + + if (num_len == 0 && type != 'h' && type != 'H') + return -EINVAL; + + if (num_len != 0 && (type == 'h' || type == 'H')) + return -EINVAL; + + num[num_len] = '\0'; + val = strtol(num, NULL, 10); + + h = 0; + switch (type) { + case 's': + case 'S': + s = val; + break; + case 'c': + case 'C': + c = val; + break; + case 'h': + case 'H': + h = 1; + break; + } + } + + *socket = s; + *core = c; + *ht = h; + return 0; +} diff --git a/examples/ip_pipeline/parser.h b/examples/ip_pipeline/parser.h index 58b59daf..9bd36af3 100644 --- a/examples/ip_pipeline/parser.h +++ b/examples/ip_pipeline/parser.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 @@ -34,17 +34,51 @@ #ifndef __INCLUDE_PARSER_H__ #define __INCLUDE_PARSER_H__ -int -parser_read_arg_bool(const char *p); +#include <stdint.h> -int -parser_read_uint64(uint64_t *value, const char *p); +#include <rte_ip.h> +#include <rte_ether.h> -int -parser_read_uint32(uint32_t *value, const char *p); +#define PARSE_DELIMITER " \f\n\r\t\v" -int -parse_hex_string(char *src, uint8_t *dst, uint32_t *size); +#define skip_white_spaces(pos) \ +({ \ + __typeof__(pos) _p = (pos); \ + for ( ; isspace(*_p); _p++) \ + ; \ + _p; \ +}) -#endif +static inline size_t +skip_digits(const char *src) +{ + size_t i; + + for (i = 0; isdigit(src[i]); i++) + ; + + return i; +} + +int parser_read_arg_bool(const char *p); + +int parser_read_uint64(uint64_t *value, const char *p); +int parser_read_uint32(uint32_t *value, const char *p); +int parser_read_uint16(uint16_t *value, const char *p); +int parser_read_uint8(uint8_t *value, const char *p); +int parser_read_uint64_hex(uint64_t *value, const char *p); +int parser_read_uint32_hex(uint32_t *value, const char *p); +int parser_read_uint16_hex(uint16_t *value, const char *p); +int parser_read_uint8_hex(uint8_t *value, const char *p); + +int parse_hex_string(char *src, uint8_t *dst, uint32_t *size); + +int parse_ipv4_addr(const char *token, struct in_addr *ipv4); +int parse_ipv6_addr(const char *token, struct in6_addr *ipv6); +int parse_mac_addr(const char *token, struct ether_addr *addr); +int parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels); + +int parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens); + +#endif diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h index dab9c36d..14a551db 100644 --- a/examples/ip_pipeline/pipeline.h +++ b/examples/ip_pipeline/pipeline.h @@ -42,13 +42,22 @@ * Pipeline type front-end operations */ -typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, void *arg); +typedef void* (*pipeline_fe_op_init)(struct pipeline_params *params, + void *arg); + +typedef int (*pipeline_fe_op_post_init)(void *pipeline); typedef int (*pipeline_fe_op_free)(void *pipeline); +typedef int (*pipeline_fe_op_track)(struct pipeline_params *params, + uint32_t port_in, + uint32_t *port_out); + struct pipeline_fe_ops { pipeline_fe_op_init f_init; + pipeline_fe_op_post_init f_post_init; pipeline_fe_op_free f_free; + pipeline_fe_op_track f_track; cmdline_parse_ctx_t *cmds; }; diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.c b/examples/ip_pipeline/pipeline/pipeline_common_fe.c index a691d422..cd1d082a 100644 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.c +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.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 @@ -42,12 +42,146 @@ #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> -#include <cmdline_parse_ipaddr.h> -#include <cmdline_parse_etheraddr.h> -#include <cmdline_socket.h> #include <cmdline.h> #include "pipeline_common_fe.h" +#include "parser.h" + +struct app_link_params * +app_pipeline_track_pktq_out_to_link(struct app_params *app, + uint32_t pipeline_id, + uint32_t pktq_out_id) +{ + struct app_pipeline_params *p; + + /* Check input arguments */ + if (app == NULL) + return NULL; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); + if (p == NULL) + return NULL; + + for ( ; ; ) { + struct app_pktq_out_params *pktq_out = + &p->pktq_out[pktq_out_id]; + + switch (pktq_out->type) { + case APP_PKTQ_OUT_HWQ: + { + struct app_pktq_hwq_out_params *hwq_out; + + hwq_out = &app->hwq_out_params[pktq_out->id]; + + return app_get_link_for_txq(app, hwq_out); + } + + case APP_PKTQ_OUT_SWQ: + { + struct pipeline_params pp; + struct pipeline_type *ptype; + struct app_pktq_swq_params *swq; + uint32_t pktq_in_id; + int status; + + swq = &app->swq_params[pktq_out->id]; + p = app_swq_get_reader(app, swq, &pktq_in_id); + if (p == NULL) + return NULL; + + ptype = app_pipeline_type_find(app, p->type); + if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL)) + return NULL; + + app_pipeline_params_get(app, p, &pp); + status = ptype->fe_ops->f_track(&pp, + pktq_in_id, + &pktq_out_id); + if (status) + return NULL; + + break; + } + + case APP_PKTQ_OUT_TM: + { + struct pipeline_params pp; + struct pipeline_type *ptype; + struct app_pktq_tm_params *tm; + uint32_t pktq_in_id; + int status; + + tm = &app->tm_params[pktq_out->id]; + p = app_tm_get_reader(app, tm, &pktq_in_id); + if (p == NULL) + return NULL; + + ptype = app_pipeline_type_find(app, p->type); + if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL)) + return NULL; + + app_pipeline_params_get(app, p, &pp); + status = ptype->fe_ops->f_track(&pp, + pktq_in_id, + &pktq_out_id); + if (status) + return NULL; + + break; + } + + case APP_PKTQ_OUT_KNI: + { + struct pipeline_params pp; + struct pipeline_type *ptype; + struct app_pktq_kni_params *kni; + uint32_t pktq_in_id; + int status; + + kni = &app->kni_params[pktq_out->id]; + p = app_kni_get_reader(app, kni, &pktq_in_id); + if (p == NULL) + return NULL; + + ptype = app_pipeline_type_find(app, p->type); + if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL)) + return NULL; + + app_pipeline_params_get(app, p, &pp); + status = ptype->fe_ops->f_track(&pp, + pktq_in_id, + &pktq_out_id); + if (status) + return NULL; + + break; + } + + case APP_PKTQ_OUT_SINK: + default: + return NULL; + } + } +} + +int +app_pipeline_track_default(struct pipeline_params *p, + uint32_t port_in, + uint32_t *port_out) +{ + /* Check input arguments */ + if ((p == NULL) || + (port_in >= p->n_ports_in) || + (port_out == NULL)) + return -1; + + if (p->n_ports_out == 1) { + *port_out = 0; + return 0; + } + + return -1; +} int app_pipeline_ping(struct app_params *app, @@ -312,6 +446,40 @@ app_pipeline_port_in_disable(struct app_params *app, } int +app_link_set_op(struct app_params *app, + uint32_t link_id, + uint32_t pipeline_id, + app_link_op op, + void *arg) +{ + struct app_pipeline_params *pp; + struct app_link_params *lp; + struct app_link_data *ld; + uint32_t ppos, lpos; + + /* Check input arguments */ + if ((app == NULL) || + (op == NULL)) + return -1; + + APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp); + if (lp == NULL) + return -1; + lpos = lp - app->link_params; + ld = &app->link_data[lpos]; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pp); + if (pp == NULL) + return -1; + ppos = pp - app->pipeline_params; + + ld->f_link[ppos] = op; + ld->arg[ppos] = arg; + + return 0; +} + +int app_link_config(struct app_params *app, uint32_t link_id, uint32_t ip, @@ -382,6 +550,8 @@ app_link_up(struct app_params *app, uint32_t link_id) { struct app_link_params *p; + struct app_link_data *d; + int i; /* Check input arguments */ if (app == NULL) @@ -394,6 +564,8 @@ app_link_up(struct app_params *app, return -1; } + d = &app->link_data[p - app->link_params]; + /* Check link state */ if (p->state) { APP_LOG(app, HIGH, "%s is already UP", p->name); @@ -408,6 +580,11 @@ app_link_up(struct app_params *app, app_link_up_internal(app, p); + /* Callbacks */ + for (i = 0; i < APP_MAX_PIPELINES; i++) + if (d->f_link[i]) + d->f_link[i](app, link_id, 1, d->arg[i]); + return 0; } @@ -416,6 +593,8 @@ app_link_down(struct app_params *app, uint32_t link_id) { struct app_link_params *p; + struct app_link_data *d; + uint32_t i; /* Check input arguments */ if (app == NULL) @@ -428,6 +607,8 @@ app_link_down(struct app_params *app, return -1; } + d = &app->link_data[p - app->link_params]; + /* Check link state */ if (p->state == 0) { APP_LOG(app, HIGH, "%s is already DOWN", p->name); @@ -436,6 +617,11 @@ app_link_down(struct app_params *app, app_link_down_internal(app, p); + /* Callbacks */ + for (i = 0; i < APP_MAX_PIPELINES; i++) + if (d->f_link[i]) + d->f_link[i](app, link_id, 0, d->arg[i]); + return 0; } @@ -464,16 +650,16 @@ cmd_ping_parsed( printf("Command failed\n"); } -cmdline_parse_token_string_t cmd_ping_p_string = +static cmdline_parse_token_string_t cmd_ping_p_string = TOKEN_STRING_INITIALIZER(struct cmd_ping_result, p_string, "p"); -cmdline_parse_token_num_t cmd_ping_pipeline_id = +static cmdline_parse_token_num_t cmd_ping_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_ping_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_ping_ping_string = +static cmdline_parse_token_string_t cmd_ping_ping_string = TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping_string, "ping"); -cmdline_parse_inst_t cmd_ping = { +static cmdline_parse_inst_t cmd_ping = { .f = cmd_ping_parsed, .data = NULL, .help_str = "Pipeline ping", @@ -498,6 +684,7 @@ struct cmd_stats_port_in_result { uint32_t port_in_id; }; + static void cmd_stats_port_in_parsed( void *parsed_result, @@ -531,23 +718,23 @@ cmd_stats_port_in_parsed( stats.stats.n_pkts_drop); } -cmdline_parse_token_string_t cmd_stats_port_in_p_string = +static cmdline_parse_token_string_t cmd_stats_port_in_p_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, p_string, "p"); -cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id = +static cmdline_parse_token_num_t cmd_stats_port_in_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_stats_port_in_stats_string = +static cmdline_parse_token_string_t cmd_stats_port_in_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, stats_string, "stats"); -cmdline_parse_token_string_t cmd_stats_port_in_port_string = +static cmdline_parse_token_string_t cmd_stats_port_in_port_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, port_string, "port"); -cmdline_parse_token_string_t cmd_stats_port_in_in_string = +static cmdline_parse_token_string_t cmd_stats_port_in_in_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_in_result, in_string, "in"); @@ -555,7 +742,7 @@ cmdline_parse_token_string_t cmd_stats_port_in_in_string = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_in_result, port_in_id, UINT32); -cmdline_parse_inst_t cmd_stats_port_in = { +static cmdline_parse_inst_t cmd_stats_port_in = { .f = cmd_stats_port_in_parsed, .data = NULL, .help_str = "Pipeline input port stats", @@ -617,31 +804,31 @@ cmd_stats_port_out_parsed( stats.stats.n_pkts_drop); } -cmdline_parse_token_string_t cmd_stats_port_out_p_string = +static cmdline_parse_token_string_t cmd_stats_port_out_p_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, p_string, "p"); -cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id = +static cmdline_parse_token_num_t cmd_stats_port_out_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_stats_port_out_stats_string = +static cmdline_parse_token_string_t cmd_stats_port_out_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, stats_string, "stats"); -cmdline_parse_token_string_t cmd_stats_port_out_port_string = +static cmdline_parse_token_string_t cmd_stats_port_out_port_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, port_string, "port"); -cmdline_parse_token_string_t cmd_stats_port_out_out_string = +static cmdline_parse_token_string_t cmd_stats_port_out_out_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_port_out_result, out_string, "out"); -cmdline_parse_token_num_t cmd_stats_port_out_port_out_id = +static cmdline_parse_token_num_t cmd_stats_port_out_port_out_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_port_out_result, port_out_id, UINT32); -cmdline_parse_inst_t cmd_stats_port_out = { +static cmdline_parse_inst_t cmd_stats_port_out = { .f = cmd_stats_port_out_parsed, .data = NULL, .help_str = "Pipeline output port stats", @@ -707,26 +894,26 @@ cmd_stats_table_parsed( stats.n_pkts_dropped_lkp_miss); } -cmdline_parse_token_string_t cmd_stats_table_p_string = +static cmdline_parse_token_string_t cmd_stats_table_p_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, p_string, "p"); -cmdline_parse_token_num_t cmd_stats_table_pipeline_id = +static cmdline_parse_token_num_t cmd_stats_table_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_stats_table_stats_string = +static cmdline_parse_token_string_t cmd_stats_table_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, stats_string, "stats"); -cmdline_parse_token_string_t cmd_stats_table_table_string = +static cmdline_parse_token_string_t cmd_stats_table_table_string = TOKEN_STRING_INITIALIZER(struct cmd_stats_table_result, table_string, "table"); -cmdline_parse_token_num_t cmd_stats_table_table_id = +static cmdline_parse_token_num_t cmd_stats_table_table_id = TOKEN_NUM_INITIALIZER(struct cmd_stats_table_result, table_id, UINT32); -cmdline_parse_inst_t cmd_stats_table = { +static cmdline_parse_inst_t cmd_stats_table = { .f = cmd_stats_table_parsed, .data = NULL, .help_str = "Pipeline table stats", @@ -771,31 +958,31 @@ cmd_port_in_enable_parsed( printf("Command failed\n"); } -cmdline_parse_token_string_t cmd_port_in_enable_p_string = +static cmdline_parse_token_string_t cmd_port_in_enable_p_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, p_string, "p"); -cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id = +static cmdline_parse_token_num_t cmd_port_in_enable_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_port_in_enable_port_string = +static cmdline_parse_token_string_t cmd_port_in_enable_port_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, port_string, "port"); -cmdline_parse_token_string_t cmd_port_in_enable_in_string = +static cmdline_parse_token_string_t cmd_port_in_enable_in_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, in_string, "in"); -cmdline_parse_token_num_t cmd_port_in_enable_port_in_id = +static cmdline_parse_token_num_t cmd_port_in_enable_port_in_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_enable_result, port_in_id, UINT32); -cmdline_parse_token_string_t cmd_port_in_enable_enable_string = +static cmdline_parse_token_string_t cmd_port_in_enable_enable_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_enable_result, enable_string, "enable"); -cmdline_parse_inst_t cmd_port_in_enable = { +static cmdline_parse_inst_t cmd_port_in_enable = { .f = cmd_port_in_enable_parsed, .data = NULL, .help_str = "Pipeline input port enable", @@ -841,31 +1028,31 @@ cmd_port_in_disable_parsed( printf("Command failed\n"); } -cmdline_parse_token_string_t cmd_port_in_disable_p_string = +static cmdline_parse_token_string_t cmd_port_in_disable_p_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, p_string, "p"); -cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id = +static cmdline_parse_token_num_t cmd_port_in_disable_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_port_in_disable_port_string = +static cmdline_parse_token_string_t cmd_port_in_disable_port_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, port_string, "port"); -cmdline_parse_token_string_t cmd_port_in_disable_in_string = +static cmdline_parse_token_string_t cmd_port_in_disable_in_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, in_string, "in"); -cmdline_parse_token_num_t cmd_port_in_disable_port_in_id = +static cmdline_parse_token_num_t cmd_port_in_disable_port_in_id = TOKEN_NUM_INITIALIZER(struct cmd_port_in_disable_result, port_in_id, UINT32); -cmdline_parse_token_string_t cmd_port_in_disable_disable_string = +static cmdline_parse_token_string_t cmd_port_in_disable_disable_string = TOKEN_STRING_INITIALIZER(struct cmd_port_in_disable_result, disable_string, "disable"); -cmdline_parse_inst_t cmd_port_in_disable = { +static cmdline_parse_inst_t cmd_port_in_disable = { .f = cmd_port_in_disable_parsed, .data = NULL, .help_str = "Pipeline input port disable", @@ -963,219 +1150,144 @@ print_link_info(struct app_link_params *p) printf("\n"); } -struct cmd_link_config_result { - cmdline_fixed_string_t link_string; - uint32_t link_id; - cmdline_fixed_string_t config_string; - cmdline_ipaddr_t ip; - uint32_t depth; -}; - -static void -cmd_link_config_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_link_config_result *params = parsed_result; - struct app_params *app = data; - int status; - - uint32_t link_id = params->link_id; - uint32_t ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - uint32_t depth = params->depth; - - status = app_link_config(app, link_id, ip, depth); - if (status) - printf("Command failed\n"); - else { - struct app_link_params *p; - - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); - print_link_info(p); - } -} - -cmdline_parse_token_string_t cmd_link_config_link_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, link_string, - "link"); - -cmdline_parse_token_num_t cmd_link_config_link_id = - TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, link_id, UINT32); - -cmdline_parse_token_string_t cmd_link_config_config_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_config_result, config_string, - "config"); - -cmdline_parse_token_ipaddr_t cmd_link_config_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_link_config_result, ip); - -cmdline_parse_token_num_t cmd_link_config_depth = - TOKEN_NUM_INITIALIZER(struct cmd_link_config_result, depth, UINT32); - -cmdline_parse_inst_t cmd_link_config = { - .f = cmd_link_config_parsed, - .data = NULL, - .help_str = "Link configuration", - .tokens = { - (void *)&cmd_link_config_link_string, - (void *)&cmd_link_config_link_id, - (void *)&cmd_link_config_config_string, - (void *)&cmd_link_config_ip, - (void *)&cmd_link_config_depth, - NULL, - }, -}; - /* - * link up + * link + * + * link config: + * link <linkid> config <ipaddr> <depth> + * + * link up: + * link <linkid> up + * + * link down: + * link <linkid> down + * + * link ls: + * link ls */ -struct cmd_link_up_result { +struct cmd_link_result { cmdline_fixed_string_t link_string; - uint32_t link_id; - cmdline_fixed_string_t up_string; + cmdline_multi_string_t multi_string; }; static void -cmd_link_up_parsed( +cmd_link_parsed( void *parsed_result, __attribute__((unused)) struct cmdline *cl, - void *data) + void *data) { - struct cmd_link_up_result *params = parsed_result; + struct cmd_link_result *params = parsed_result; struct app_params *app = data; + + char *tokens[16]; + uint32_t n_tokens = RTE_DIM(tokens); int status; - status = app_link_up(app, params->link_id); - if (status != 0) - printf("Command failed\n"); - else { - struct app_link_params *p; + uint32_t link_id; - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, - p); - print_link_info(p); + status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); + if (status != 0) { + printf(CMD_MSG_TOO_MANY_ARGS, "link"); + return; } -} - -cmdline_parse_token_string_t cmd_link_up_link_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, link_string, - "link"); -cmdline_parse_token_num_t cmd_link_up_link_id = - TOKEN_NUM_INITIALIZER(struct cmd_link_up_result, link_id, UINT32); + /* link ls */ + if ((n_tokens == 1) && (strcmp(tokens[0], "ls") == 0)) { + for (link_id = 0; link_id < app->n_links; link_id++) { + struct app_link_params *p; -cmdline_parse_token_string_t cmd_link_up_up_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_up_result, up_string, "up"); + APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); + print_link_info(p); + } + return; + } /* link ls */ -cmdline_parse_inst_t cmd_link_up = { - .f = cmd_link_up_parsed, - .data = NULL, - .help_str = "Link UP", - .tokens = { - (void *)&cmd_link_up_link_string, - (void *)&cmd_link_up_link_id, - (void *)&cmd_link_up_up_string, - NULL, - }, -}; + if (n_tokens < 2) { + printf(CMD_MSG_MISMATCH_ARGS, "link"); + return; + } -/* - * link down - */ + if (parser_read_uint32(&link_id, tokens[0])) { + printf(CMD_MSG_INVALID_ARG, "linkid"); + return; + } -struct cmd_link_down_result { - cmdline_fixed_string_t link_string; - uint32_t link_id; - cmdline_fixed_string_t down_string; -}; + /* link config */ + if (strcmp(tokens[1], "config") == 0) { + struct in_addr ipaddr_ipv4; + uint32_t depth; -static void -cmd_link_down_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_link_down_result *params = parsed_result; - struct app_params *app = data; - int status; + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "link config"); + return; + } - status = app_link_down(app, params->link_id); - if (status != 0) - printf("Command failed\n"); - else { - struct app_link_params *p; + if (parse_ipv4_addr(tokens[2], &ipaddr_ipv4)) { + printf(CMD_MSG_INVALID_ARG, "ipaddr"); + return; + } - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", params->link_id, - p); - print_link_info(p); - } -} + if (parser_read_uint32(&depth, tokens[3])) { + printf(CMD_MSG_INVALID_ARG, "depth"); + return; + } -cmdline_parse_token_string_t cmd_link_down_link_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, link_string, - "link"); + status = app_link_config(app, + link_id, + rte_be_to_cpu_32(ipaddr_ipv4.s_addr), + depth); + if (status) + printf(CMD_MSG_FAIL, "link config"); -cmdline_parse_token_num_t cmd_link_down_link_id = - TOKEN_NUM_INITIALIZER(struct cmd_link_down_result, link_id, UINT32); + return; + } /* link config */ -cmdline_parse_token_string_t cmd_link_down_down_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_down_result, down_string, - "down"); + /* link up */ + if (strcmp(tokens[1], "up") == 0) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "link up"); + return; + } -cmdline_parse_inst_t cmd_link_down = { - .f = cmd_link_down_parsed, - .data = NULL, - .help_str = "Link DOWN", - .tokens = { - (void *) &cmd_link_down_link_string, - (void *) &cmd_link_down_link_id, - (void *) &cmd_link_down_down_string, - NULL, - }, -}; + status = app_link_up(app, link_id); + if (status) + printf(CMD_MSG_FAIL, "link up"); -/* - * link ls - */ + return; + } /* link up */ -struct cmd_link_ls_result { - cmdline_fixed_string_t link_string; - cmdline_fixed_string_t ls_string; -}; + /* link down */ + if (strcmp(tokens[1], "down") == 0) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "link down"); + return; + } -static void -cmd_link_ls_parsed( - __attribute__((unused)) void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct app_params *app = data; - uint32_t link_id; + status = app_link_down(app, link_id); + if (status) + printf(CMD_MSG_FAIL, "link down"); - for (link_id = 0; link_id < app->n_links; link_id++) { - struct app_link_params *p; + return; + } /* link down */ - APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, p); - print_link_info(p); - } + printf(CMD_MSG_MISMATCH_ARGS, "link"); } -cmdline_parse_token_string_t cmd_link_ls_link_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, link_string, - "link"); +static cmdline_parse_token_string_t cmd_link_link_string = + TOKEN_STRING_INITIALIZER(struct cmd_link_result, link_string, "link"); -cmdline_parse_token_string_t cmd_link_ls_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_link_ls_result, ls_string, "ls"); +static cmdline_parse_token_string_t cmd_link_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_link_result, multi_string, + TOKEN_STRING_MULTI); -cmdline_parse_inst_t cmd_link_ls = { - .f = cmd_link_ls_parsed, +static cmdline_parse_inst_t cmd_link = { + .f = cmd_link_parsed, .data = NULL, - .help_str = "Link list", + .help_str = "link config / up / down / ls", .tokens = { - (void *)&cmd_link_ls_link_string, - (void *)&cmd_link_ls_ls_string, + (void *) &cmd_link_link_string, + (void *) &cmd_link_multi_string, NULL, }, }; @@ -1212,6 +1324,11 @@ static cmdline_parse_inst_t cmd_quit = { /* * run + * + * run <file> + * run <file> [<count> [<interval>]] + <count> default is 1 + * <interval> is measured in milliseconds, default is 1 second */ static void @@ -1233,9 +1350,9 @@ app_run_file( close(fd); } -struct cmd_run_file_result { +struct cmd_run_result { cmdline_fixed_string_t run_string; - char file_name[APP_FILE_NAME_SIZE]; + cmdline_multi_string_t multi_string; }; static void @@ -1244,25 +1361,87 @@ cmd_run_parsed( struct cmdline *cl, __attribute__((unused)) void *data) { - struct cmd_run_file_result *params = parsed_result; + struct cmd_run_result *params = parsed_result; + + char *tokens[16]; + uint32_t n_tokens = RTE_DIM(tokens); + int status; + + char *file_name; + uint32_t count, interval, i; - app_run_file(cl->ctx, params->file_name); + status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); + if (status) { + printf(CMD_MSG_TOO_MANY_ARGS, "run"); + return; + } + + switch (n_tokens) { + case 0: + printf(CMD_MSG_NOT_ENOUGH_ARGS, "run"); + return; + + case 1: + file_name = tokens[0]; + count = 1; + interval = 1000; + break; + + case 2: + file_name = tokens[0]; + + if (parser_read_uint32(&count, tokens[1]) || + (count == 0)) { + printf(CMD_MSG_INVALID_ARG, "count"); + return; + } + + interval = 1000; + break; + + case 3: + file_name = tokens[0]; + + if (parser_read_uint32(&count, tokens[1]) || + (count == 0)) { + printf(CMD_MSG_INVALID_ARG, "count"); + return; + } + + if (parser_read_uint32(&interval, tokens[2]) || + (interval == 0)) { + printf(CMD_MSG_INVALID_ARG, "interval"); + return; + } + break; + + default: + printf(CMD_MSG_MISMATCH_ARGS, "run"); + return; + } + + for (i = 0; i < count; i++) { + app_run_file(cl->ctx, file_name); + if (interval) + usleep(interval * 1000); + } } -cmdline_parse_token_string_t cmd_run_run_string = - TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, run_string, - "run"); +static cmdline_parse_token_string_t cmd_run_run_string = + TOKEN_STRING_INITIALIZER(struct cmd_run_result, run_string, "run"); + +static cmdline_parse_token_string_t cmd_run_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_run_result, multi_string, + TOKEN_STRING_MULTI); -cmdline_parse_token_string_t cmd_run_file_name = - TOKEN_STRING_INITIALIZER(struct cmd_run_file_result, file_name, NULL); -cmdline_parse_inst_t cmd_run = { +static cmdline_parse_inst_t cmd_run = { .f = cmd_run_parsed, .data = NULL, .help_str = "Run CLI script file", .tokens = { (void *) &cmd_run_run_string, - (void *) &cmd_run_file_name, + (void *) &cmd_run_multi_string, NULL, }, }; @@ -1270,12 +1449,7 @@ cmdline_parse_inst_t cmd_run = { static cmdline_parse_ctx_t pipeline_common_cmds[] = { (cmdline_parse_inst_t *) &cmd_quit, (cmdline_parse_inst_t *) &cmd_run, - - (cmdline_parse_inst_t *) &cmd_link_config, - (cmdline_parse_inst_t *) &cmd_link_up, - (cmdline_parse_inst_t *) &cmd_link_down, - (cmdline_parse_inst_t *) &cmd_link_ls, - + (cmdline_parse_inst_t *) &cmd_link, (cmdline_parse_inst_t *) &cmd_ping, (cmdline_parse_inst_t *) &cmd_stats_port_in, (cmdline_parse_inst_t *) &cmd_stats_port_out, diff --git a/examples/ip_pipeline/pipeline/pipeline_common_fe.h b/examples/ip_pipeline/pipeline/pipeline_common_fe.h index cfad963d..ce0bf13e 100644 --- a/examples/ip_pipeline/pipeline/pipeline_common_fe.h +++ b/examples/ip_pipeline/pipeline/pipeline_common_fe.h @@ -182,6 +182,16 @@ app_msg_send_recv(struct app_params *app, return msg_recv; } +struct app_link_params * +app_pipeline_track_pktq_out_to_link(struct app_params *app, + uint32_t pipeline_id, + uint32_t pktq_out_id); + +int +app_pipeline_track_default(struct pipeline_params *params, + uint32_t port_in, + uint32_t *port_out); + int app_pipeline_ping(struct app_params *app, uint32_t pipeline_id); @@ -215,6 +225,13 @@ app_pipeline_port_in_disable(struct app_params *app, uint32_t port_id); int +app_link_set_op(struct app_params *app, + uint32_t link_id, + uint32_t pipeline_id, + app_link_op op, + void *arg); + +int app_link_config(struct app_params *app, uint32_t link_id, uint32_t ip, @@ -231,4 +248,13 @@ app_link_down(struct app_params *app, int app_pipeline_common_cmd_push(struct app_params *app); +#define CMD_MSG_OUT_OF_MEMORY "Not enough memory\n" +#define CMD_MSG_NOT_ENOUGH_ARGS "Not enough arguments for command \"%s\"\n" +#define CMD_MSG_TOO_MANY_ARGS "Too many arguments for command \"%s\"\n" +#define CMD_MSG_MISMATCH_ARGS "Incorrect set of arguments for command \"%s\"\n" +#define CMD_MSG_INVALID_ARG "Invalid value for argument \"%s\"\n" +#define CMD_MSG_ARG_NOT_FOUND "Syntax error: \"%s\" not found\n" +#define CMD_MSG_FILE_ERR "Error in file \"%s\" at line %u\n" +#define CMD_MSG_FAIL "Command \"%s\" failed\n" + #endif diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c index fd897d5c..a82e552d 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c @@ -30,9 +30,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#include <errno.h> #include <stdio.h> #include <string.h> +#include <stdlib.h> +#include <unistd.h> #include <sys/queue.h> #include <netinet/in.h> @@ -43,15 +45,11 @@ #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> -#include <cmdline_parse_ipaddr.h> -#include <cmdline_parse_etheraddr.h> -#include <cmdline_socket.h> #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_firewall.h" - -#define BUF_SIZE 1024 +#include "parser.h" struct app_pipeline_firewall_rule { struct pipeline_firewall_key key; @@ -75,18 +73,6 @@ struct app_pipeline_firewall { void *default_rule_entry_ptr; }; -struct app_pipeline_add_bulk_params { - struct pipeline_firewall_key *keys; - uint32_t n_keys; - uint32_t *priorities; - uint32_t *port_ids; -}; - -struct app_pipeline_del_bulk_params { - struct pipeline_firewall_key *keys; - uint32_t n_keys; -}; - static void print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule) { @@ -272,356 +258,118 @@ app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key) } } -static int -app_pipeline_add_bulk_parse_file(char *filename, - struct app_pipeline_add_bulk_params *params) +int +app_pipeline_firewall_load_file(char *filename, + struct pipeline_firewall_key *keys, + uint32_t *priorities, + uint32_t *port_ids, + uint32_t *n_keys, + uint32_t *line) { - FILE *f; - char file_buf[BUF_SIZE]; - uint32_t i; - int status = 0; + FILE *f = NULL; + char file_buf[1024]; + uint32_t i, l; - f = fopen(filename, "r"); - if (f == NULL) + /* Check input arguments */ + if ((filename == NULL) || + (keys == NULL) || + (priorities == NULL) || + (port_ids == NULL) || + (n_keys == NULL) || + (*n_keys == 0) || + (line == NULL)) { + if (line) + *line = 0; return -1; - - params->n_keys = 0; - while (fgets(file_buf, BUF_SIZE, f) != NULL) - params->n_keys++; - rewind(f); - - if (params->n_keys == 0) { - status = -1; - goto end; - } - - params->keys = rte_malloc(NULL, - params->n_keys * sizeof(struct pipeline_firewall_key), - RTE_CACHE_LINE_SIZE); - if (params->keys == NULL) { - status = -1; - goto end; - } - - params->priorities = rte_malloc(NULL, - params->n_keys * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (params->priorities == NULL) { - status = -1; - goto end; - } - - params->port_ids = rte_malloc(NULL, - params->n_keys * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (params->port_ids == NULL) { - status = -1; - goto end; - } - - i = 0; - while (fgets(file_buf, BUF_SIZE, f) != NULL) { - char *str; - - str = strtok(file_buf, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->priorities[i] = atoi(str); - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; } - params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str); - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.proto = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - /* Need to add 2 to str to skip leading 0x */ - params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->port_ids[i] = atoi(str); - params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE; - - i++; - } - -end: - fclose(f); - return status; -} - -static int -app_pipeline_del_bulk_parse_file(char *filename, - struct app_pipeline_del_bulk_params *params) -{ - FILE *f; - char file_buf[BUF_SIZE]; - uint32_t i; - int status = 0; + /* Open input file */ f = fopen(filename, "r"); - if (f == NULL) + if (f == NULL) { + *line = 0; return -1; - - params->n_keys = 0; - while (fgets(file_buf, BUF_SIZE, f) != NULL) - params->n_keys++; - rewind(f); - - if (params->n_keys == 0) { - status = -1; - goto end; - } - - params->keys = rte_malloc(NULL, - params->n_keys * sizeof(struct pipeline_firewall_key), - RTE_CACHE_LINE_SIZE); - if (params->keys == NULL) { - status = -1; - goto end; } - i = 0; - while (fgets(file_buf, BUF_SIZE, f) != NULL) { - char *str; - - str = strtok(file_buf, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str); - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8; - - str = strtok(NULL, " ."); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - params->keys[i].key.ipv4_5tuple.proto = atoi(str); - - str = strtok(NULL, " "); - if (str == NULL) { - status = -1; - goto end; - } - /* Need to add 2 to str to skip leading 0x */ - params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16); - - params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE; + /* Read file */ + for (i = 0, l = 1; i < *n_keys; l++) { + char *tokens[32]; + uint32_t n_tokens = RTE_DIM(tokens); + + uint32_t priority = 0; + struct in_addr sipaddr; + uint32_t sipdepth = 0; + struct in_addr dipaddr; + uint32_t dipdepth = 0; + uint16_t sport0 = 0; + uint16_t sport1 = 0; + uint16_t dport0 = 0; + uint16_t dport1 = 0; + uint8_t proto = 0; + uint8_t protomask = 0; + uint32_t port_id = 0; + + int status; + + if (fgets(file_buf, sizeof(file_buf), f) == NULL) + break; + + status = parse_tokenize_string(file_buf, tokens, &n_tokens); + if (status) + goto error1; + + if ((n_tokens == 0) || (tokens[0][0] == '#')) + continue; + + if ((n_tokens != 15) || + strcmp(tokens[0], "priority") || + parser_read_uint32(&priority, tokens[1]) || + strcmp(tokens[2], "ipv4") || + parse_ipv4_addr(tokens[3], &sipaddr) || + parser_read_uint32(&sipdepth, tokens[4]) || + parse_ipv4_addr(tokens[5], &dipaddr) || + parser_read_uint32(&dipdepth, tokens[6]) || + parser_read_uint16(&sport0, tokens[7]) || + parser_read_uint16(&sport1, tokens[8]) || + parser_read_uint16(&dport0, tokens[9]) || + parser_read_uint16(&dport1, tokens[10]) || + parser_read_uint8(&proto, tokens[11]) || + parser_read_uint8_hex(&protomask, tokens[12]) || + strcmp(tokens[13], "port") || + parser_read_uint32(&port_id, tokens[14])) + goto error1; + + keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE; + keys[i].key.ipv4_5tuple.src_ip = + rte_be_to_cpu_32(sipaddr.s_addr); + keys[i].key.ipv4_5tuple.src_ip_mask = sipdepth; + keys[i].key.ipv4_5tuple.dst_ip = + rte_be_to_cpu_32(dipaddr.s_addr); + keys[i].key.ipv4_5tuple.dst_ip_mask = dipdepth; + keys[i].key.ipv4_5tuple.src_port_from = sport0; + keys[i].key.ipv4_5tuple.src_port_to = sport1; + keys[i].key.ipv4_5tuple.dst_port_from = dport0; + keys[i].key.ipv4_5tuple.dst_port_to = dport1; + keys[i].key.ipv4_5tuple.proto = proto; + keys[i].key.ipv4_5tuple.proto_mask = protomask; + + port_ids[i] = port_id; + priorities[i] = priority; + + if (app_pipeline_firewall_key_check_and_normalize(&keys[i])) + goto error1; i++; } - for (i = 0; i < params->n_keys; i++) { - if (app_pipeline_firewall_key_check_and_normalize(¶ms->keys[i]) != 0) { - status = -1; - goto end; - } - } + /* Close file */ + *n_keys = i; + fclose(f); + return 0; -end: +error1: + *line = l; fclose(f); - return status; + return -1; } int @@ -804,14 +552,14 @@ app_pipeline_firewall_add_bulk(struct app_params *app, return -1; rules = rte_malloc(NULL, - n_keys * sizeof(struct app_pipeline_firewall_rule *), - RTE_CACHE_LINE_SIZE); + n_keys * sizeof(struct app_pipeline_firewall_rule *), + RTE_CACHE_LINE_SIZE); if (rules == NULL) return -1; new_rules = rte_malloc(NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); + n_keys * sizeof(int), + RTE_CACHE_LINE_SIZE); if (new_rules == NULL) { rte_free(rules); return -1; @@ -834,8 +582,9 @@ app_pipeline_firewall_add_bulk(struct app_params *app, rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]); new_rules[i] = (rules[i] == NULL); if (rules[i] == NULL) { - rules[i] = rte_malloc(NULL, sizeof(*rules[i]), - RTE_CACHE_LINE_SIZE); + rules[i] = rte_malloc(NULL, + sizeof(*rules[i]), + RTE_CACHE_LINE_SIZE); if (rules[i] == NULL) { uint32_t j; @@ -852,8 +601,8 @@ app_pipeline_firewall_add_bulk(struct app_params *app, } keys_found = rte_malloc(NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); + n_keys * sizeof(int), + RTE_CACHE_LINE_SIZE); if (keys_found == NULL) { uint32_t j; @@ -867,8 +616,8 @@ app_pipeline_firewall_add_bulk(struct app_params *app, } entries_ptr = rte_malloc(NULL, - n_keys * sizeof(struct rte_pipeline_table_entry *), - RTE_CACHE_LINE_SIZE); + n_keys * sizeof(struct rte_pipeline_table_entry *), + RTE_CACHE_LINE_SIZE); if (entries_ptr == NULL) { uint32_t j; @@ -883,8 +632,8 @@ app_pipeline_firewall_add_bulk(struct app_params *app, } for (i = 0; i < n_keys; i++) { entries_ptr[i] = rte_malloc(NULL, - sizeof(struct rte_pipeline_table_entry), - RTE_CACHE_LINE_SIZE); + sizeof(struct rte_pipeline_table_entry), + RTE_CACHE_LINE_SIZE); if (entries_ptr[i] == NULL) { uint32_t j; @@ -1030,8 +779,8 @@ app_pipeline_firewall_delete_bulk(struct app_params *app, return -1; rules = rte_malloc(NULL, - n_keys * sizeof(struct app_pipeline_firewall_rule *), - RTE_CACHE_LINE_SIZE); + n_keys * sizeof(struct app_pipeline_firewall_rule *), + RTE_CACHE_LINE_SIZE); if (rules == NULL) return -1; @@ -1044,8 +793,8 @@ app_pipeline_firewall_delete_bulk(struct app_params *app, } keys_found = rte_malloc(NULL, - n_keys * sizeof(int), - RTE_CACHE_LINE_SIZE); + n_keys * sizeof(int), + RTE_CACHE_LINE_SIZE); if (keys_found == NULL) { rte_free(rules); return -1; @@ -1197,668 +946,500 @@ app_pipeline_firewall_delete_default_rule(struct app_params *app, } /* - * p firewall add ipv4 + * firewall + * + * firewall add: + * p <pipelineid> firewall add priority <priority> + * ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth> + * <sport0> <sport1> <dport0> <dport1> <proto> <protomask> + * port <portid> + * Note: <protomask> is a hex value + * + * p <pipelineid> firewall add bulk <file> + * + * firewall add default: + * p <pipelineid> firewall add default <port ID> + * + * firewall del: + * p <pipelineid> firewall del + * ipv4 <sipaddr> <sipdepth> <dipaddr> <dipdepth> + * <sport0> <sport1> <dport0> <dport1> <proto> <protomask> + * + * p <pipelineid> firewall del bulk <file> + * + * firewall del default: + * p <pipelineid> firewall del default + * + * firewall ls: + * p <pipelineid> firewall ls */ -struct cmd_firewall_add_ipv4_result { +struct cmd_firewall_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t ipv4_string; - int32_t priority; - cmdline_ipaddr_t src_ip; - uint32_t src_ip_mask; - cmdline_ipaddr_t dst_ip; - uint32_t dst_ip_mask; - uint16_t src_port_from; - uint16_t src_port_to; - uint16_t dst_port_from; - uint16_t dst_port_to; - uint8_t proto; - uint8_t proto_mask; - uint8_t port_id; + cmdline_multi_string_t multi_string; }; -static void -cmd_firewall_add_ipv4_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, +static void cmd_firewall_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, void *data) { - struct cmd_firewall_add_ipv4_result *params = parsed_result; + struct cmd_firewall_result *params = parsed_result; struct app_params *app = data; - struct pipeline_firewall_key key; int status; - key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; - key.key.ipv4_5tuple.src_ip = rte_bswap32( - (uint32_t) params->src_ip.addr.ipv4.s_addr); - key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask; - key.key.ipv4_5tuple.dst_ip = rte_bswap32( - (uint32_t) params->dst_ip.addr.ipv4.s_addr); - key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask; - key.key.ipv4_5tuple.src_port_from = params->src_port_from; - key.key.ipv4_5tuple.src_port_to = params->src_port_to; - key.key.ipv4_5tuple.dst_port_from = params->dst_port_from; - key.key.ipv4_5tuple.dst_port_to = params->dst_port_to; - key.key.ipv4_5tuple.proto = params->proto; - key.key.ipv4_5tuple.proto_mask = params->proto_mask; - - status = app_pipeline_firewall_add_rule(app, - params->pipeline_id, - &key, - params->priority, - params->port_id); - - if (status != 0) { - printf("Command failed\n"); - return; - } -} - -cmdline_parse_token_string_t cmd_firewall_add_ipv4_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, p_string, - "p"); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, pipeline_id, - UINT32); - -cmdline_parse_token_string_t cmd_firewall_add_ipv4_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, - firewall_string, "firewall"); - -cmdline_parse_token_string_t cmd_firewall_add_ipv4_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, - add_string, "add"); - -cmdline_parse_token_string_t cmd_firewall_add_ipv4_ipv4_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, - ipv4_string, "ipv4"); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_priority = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, priority, - INT32); - -cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_src_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip); + char *tokens[17]; + uint32_t n_tokens = RTE_DIM(tokens); -cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_ip_mask = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip_mask, - UINT32); - -cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_dst_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_ip_mask = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip_mask, - UINT32); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_from = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - src_port_from, UINT16); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_to = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - src_port_to, UINT16); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_from = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - dst_port_from, UINT16); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_to = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - dst_port_to, UINT16); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - proto, UINT8); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto_mask = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - proto_mask, UINT8); - -cmdline_parse_token_num_t cmd_firewall_add_ipv4_port_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, - port_id, UINT8); - -cmdline_parse_inst_t cmd_firewall_add_ipv4 = { - .f = cmd_firewall_add_ipv4_parsed, - .data = NULL, - .help_str = "Firewall rule add", - .tokens = { - (void *) &cmd_firewall_add_ipv4_p_string, - (void *) &cmd_firewall_add_ipv4_pipeline_id, - (void *) &cmd_firewall_add_ipv4_firewall_string, - (void *) &cmd_firewall_add_ipv4_add_string, - (void *) &cmd_firewall_add_ipv4_ipv4_string, - (void *) &cmd_firewall_add_ipv4_priority, - (void *) &cmd_firewall_add_ipv4_src_ip, - (void *) &cmd_firewall_add_ipv4_src_ip_mask, - (void *) &cmd_firewall_add_ipv4_dst_ip, - (void *) &cmd_firewall_add_ipv4_dst_ip_mask, - (void *) &cmd_firewall_add_ipv4_src_port_from, - (void *) &cmd_firewall_add_ipv4_src_port_to, - (void *) &cmd_firewall_add_ipv4_dst_port_from, - (void *) &cmd_firewall_add_ipv4_dst_port_to, - (void *) &cmd_firewall_add_ipv4_proto, - (void *) &cmd_firewall_add_ipv4_proto_mask, - (void *) &cmd_firewall_add_ipv4_port_id, - NULL, - }, -}; - -/* - * p firewall del ipv4 - */ - -struct cmd_firewall_del_ipv4_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t ipv4_string; - cmdline_ipaddr_t src_ip; - uint32_t src_ip_mask; - cmdline_ipaddr_t dst_ip; - uint32_t dst_ip_mask; - uint16_t src_port_from; - uint16_t src_port_to; - uint16_t dst_port_from; - uint16_t dst_port_to; - uint8_t proto; - uint8_t proto_mask; -}; - -static void -cmd_firewall_del_ipv4_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_del_ipv4_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_firewall_key key; - int status; - - key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; - key.key.ipv4_5tuple.src_ip = rte_bswap32( - (uint32_t) params->src_ip.addr.ipv4.s_addr); - key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask; - key.key.ipv4_5tuple.dst_ip = rte_bswap32( - (uint32_t) params->dst_ip.addr.ipv4.s_addr); - key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask; - key.key.ipv4_5tuple.src_port_from = params->src_port_from; - key.key.ipv4_5tuple.src_port_to = params->src_port_to; - key.key.ipv4_5tuple.dst_port_from = params->dst_port_from; - key.key.ipv4_5tuple.dst_port_to = params->dst_port_to; - key.key.ipv4_5tuple.proto = params->proto; - key.key.ipv4_5tuple.proto_mask = params->proto_mask; - - status = app_pipeline_firewall_delete_rule(app, - params->pipeline_id, - &key); - - if (status != 0) { - printf("Command failed\n"); + status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); + if (status) { + printf(CMD_MSG_TOO_MANY_ARGS, "firewall"); return; } -} - -cmdline_parse_token_string_t cmd_firewall_del_ipv4_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, p_string, - "p"); - -cmdline_parse_token_num_t cmd_firewall_del_ipv4_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, pipeline_id, - UINT32); - -cmdline_parse_token_string_t cmd_firewall_del_ipv4_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, - firewall_string, "firewall"); - -cmdline_parse_token_string_t cmd_firewall_del_ipv4_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, - del_string, "del"); -cmdline_parse_token_string_t cmd_firewall_del_ipv4_ipv4_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, - ipv4_string, "ipv4"); - -cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_src_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip); - -cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_ip_mask = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip_mask, - UINT32); - -cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_dst_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip); - -cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_ip_mask = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip_mask, - UINT32); + /* firewall add */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "priority") == 0)) { + struct pipeline_firewall_key key; + uint32_t priority; + struct in_addr sipaddr; + uint32_t sipdepth; + struct in_addr dipaddr; + uint32_t dipdepth; + uint16_t sport0; + uint16_t sport1; + uint16_t dport0; + uint16_t dport1; + uint8_t proto; + uint8_t protomask; + uint32_t port_id; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 16) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall add"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_from = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, - src_port_from, UINT16); + if (parser_read_uint32(&priority, tokens[2])) { + printf(CMD_MSG_INVALID_ARG, "priority"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_to = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_to, - UINT16); + if (strcmp(tokens[3], "ipv4")) { + printf(CMD_MSG_ARG_NOT_FOUND, "ipv4"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_from = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, - dst_port_from, UINT16); + if (parse_ipv4_addr(tokens[4], &sipaddr)) { + printf(CMD_MSG_INVALID_ARG, "sipaddr"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_to = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, - dst_port_to, UINT16); + if (parser_read_uint32(&sipdepth, tokens[5])) { + printf(CMD_MSG_INVALID_ARG, "sipdepth"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, - proto, UINT8); + if (parse_ipv4_addr(tokens[6], &dipaddr)) { + printf(CMD_MSG_INVALID_ARG, "dipaddr"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto_mask = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto_mask, - UINT8); + if (parser_read_uint32(&dipdepth, tokens[7])) { + printf(CMD_MSG_INVALID_ARG, "dipdepth"); + return; + } -cmdline_parse_inst_t cmd_firewall_del_ipv4 = { - .f = cmd_firewall_del_ipv4_parsed, - .data = NULL, - .help_str = "Firewall rule delete", - .tokens = { - (void *) &cmd_firewall_del_ipv4_p_string, - (void *) &cmd_firewall_del_ipv4_pipeline_id, - (void *) &cmd_firewall_del_ipv4_firewall_string, - (void *) &cmd_firewall_del_ipv4_del_string, - (void *) &cmd_firewall_del_ipv4_ipv4_string, - (void *) &cmd_firewall_del_ipv4_src_ip, - (void *) &cmd_firewall_del_ipv4_src_ip_mask, - (void *) &cmd_firewall_del_ipv4_dst_ip, - (void *) &cmd_firewall_del_ipv4_dst_ip_mask, - (void *) &cmd_firewall_del_ipv4_src_port_from, - (void *) &cmd_firewall_del_ipv4_src_port_to, - (void *) &cmd_firewall_del_ipv4_dst_port_from, - (void *) &cmd_firewall_del_ipv4_dst_port_to, - (void *) &cmd_firewall_del_ipv4_proto, - (void *) &cmd_firewall_del_ipv4_proto_mask, - NULL, - }, -}; + if (parser_read_uint16(&sport0, tokens[8])) { + printf(CMD_MSG_INVALID_ARG, "sport0"); + return; + } -/* - * p firewall add bulk - */ + if (parser_read_uint16(&sport1, tokens[9])) { + printf(CMD_MSG_INVALID_ARG, "sport1"); + return; + } -struct cmd_firewall_add_bulk_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t bulk_string; - cmdline_fixed_string_t file_path; -}; + if (parser_read_uint16(&dport0, tokens[10])) { + printf(CMD_MSG_INVALID_ARG, "dport0"); + return; + } -static void -cmd_firewall_add_bulk_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_add_bulk_result *params = parsed_result; - struct app_params *app = data; - int status; + if (parser_read_uint16(&dport1, tokens[11])) { + printf(CMD_MSG_INVALID_ARG, "dport1"); + return; + } - struct app_pipeline_add_bulk_params add_bulk_params; + if (parser_read_uint8(&proto, tokens[12])) { + printf(CMD_MSG_INVALID_ARG, "proto"); + return; + } - status = app_pipeline_add_bulk_parse_file(params->file_path, &add_bulk_params); - if (status != 0) { - printf("Command failed\n"); - goto end; - } + if (parser_read_uint8_hex(&protomask, tokens[13])) { + printf(CMD_MSG_INVALID_ARG, "protomask"); + return; + } - status = app_pipeline_firewall_add_bulk(app, params->pipeline_id, add_bulk_params.keys, - add_bulk_params.n_keys, add_bulk_params.priorities, add_bulk_params.port_ids); - if (status != 0) { - printf("Command failed\n"); - goto end; - } + if (strcmp(tokens[14], "port")) { + printf(CMD_MSG_ARG_NOT_FOUND, "port"); + return; + } -end: - rte_free(add_bulk_params.keys); - rte_free(add_bulk_params.priorities); - rte_free(add_bulk_params.port_ids); -} + if (parser_read_uint32(&port_id, tokens[15])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -cmdline_parse_token_string_t cmd_firewall_add_bulk_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, p_string, - "p"); + key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; + key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr); + key.key.ipv4_5tuple.src_ip_mask = sipdepth; + key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr); + key.key.ipv4_5tuple.dst_ip_mask = dipdepth; + key.key.ipv4_5tuple.src_port_from = sport0; + key.key.ipv4_5tuple.src_port_to = sport1; + key.key.ipv4_5tuple.dst_port_from = dport0; + key.key.ipv4_5tuple.dst_port_to = dport1; + key.key.ipv4_5tuple.proto = proto; + key.key.ipv4_5tuple.proto_mask = protomask; + + status = app_pipeline_firewall_add_rule(app, + params->pipeline_id, + &key, + priority, + port_id); + if (status) + printf(CMD_MSG_FAIL, "firewall add"); -cmdline_parse_token_num_t cmd_firewall_add_bulk_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_bulk_result, pipeline_id, - UINT32); + return; + } /* firewall add */ + + /* firewall add bulk */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "bulk") == 0)) { + struct pipeline_firewall_key *keys; + uint32_t *priorities, *port_ids, n_keys, line; + char *filename; + + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall add bulk"); + return; + } -cmdline_parse_token_string_t cmd_firewall_add_bulk_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, - firewall_string, "firewall"); + filename = tokens[2]; -cmdline_parse_token_string_t cmd_firewall_add_bulk_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, - add_string, "add"); + n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE; + keys = malloc(n_keys * sizeof(struct pipeline_firewall_key)); + if (keys == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + return; + } + memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key)); -cmdline_parse_token_string_t cmd_firewall_add_bulk_bulk_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, - bulk_string, "bulk"); + priorities = malloc(n_keys * sizeof(uint32_t)); + if (priorities == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + free(keys); + return; + } -cmdline_parse_token_string_t cmd_firewall_add_bulk_file_path_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, - file_path, NULL); + port_ids = malloc(n_keys * sizeof(uint32_t)); + if (port_ids == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + free(priorities); + free(keys); + return; + } -cmdline_parse_inst_t cmd_firewall_add_bulk = { - .f = cmd_firewall_add_bulk_parsed, - .data = NULL, - .help_str = "Firewall rule add bulk", - .tokens = { - (void *) &cmd_firewall_add_bulk_p_string, - (void *) &cmd_firewall_add_bulk_pipeline_id, - (void *) &cmd_firewall_add_bulk_firewall_string, - (void *) &cmd_firewall_add_bulk_add_string, - (void *) &cmd_firewall_add_bulk_bulk_string, - (void *) &cmd_firewall_add_bulk_file_path_string, - NULL, - }, -}; + status = app_pipeline_firewall_load_file(filename, + keys, + priorities, + port_ids, + &n_keys, + &line); + if (status != 0) { + printf(CMD_MSG_FILE_ERR, filename, line); + free(port_ids); + free(priorities); + free(keys); + return; + } -/* - * p firewall del bulk - */ + status = app_pipeline_firewall_add_bulk(app, + params->pipeline_id, + keys, + n_keys, + priorities, + port_ids); + if (status) + printf(CMD_MSG_FAIL, "firewall add bulk"); + + free(keys); + free(priorities); + free(port_ids); + return; + } /* firewall add bulk */ -struct cmd_firewall_del_bulk_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t bulk_string; - cmdline_fixed_string_t file_path; -}; + /* firewall add default */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "default") == 0)) { + uint32_t port_id; -static void -cmd_firewall_del_bulk_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_del_bulk_result *params = parsed_result; - struct app_params *app = data; - int status; + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall add default"); + return; + } - struct app_pipeline_del_bulk_params del_bulk_params; + if (parser_read_uint32(&port_id, tokens[2])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } - status = app_pipeline_del_bulk_parse_file(params->file_path, &del_bulk_params); - if (status != 0) { - printf("Command failed\n"); - goto end; - } + status = app_pipeline_firewall_add_default_rule(app, + params->pipeline_id, + port_id); + if (status) + printf(CMD_MSG_FAIL, "firewall add default"); - status = app_pipeline_firewall_delete_bulk(app, params->pipeline_id, - del_bulk_params.keys, del_bulk_params.n_keys); - if (status != 0) { - printf("Command failed\n"); - goto end; - } + return; + } /* firewall add default */ + + /* firewall del */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "ipv4") == 0)) { + struct pipeline_firewall_key key; + struct in_addr sipaddr; + uint32_t sipdepth; + struct in_addr dipaddr; + uint32_t dipdepth; + uint16_t sport0; + uint16_t sport1; + uint16_t dport0; + uint16_t dport1; + uint8_t proto; + uint8_t protomask; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 12) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall del"); + return; + } -end: - rte_free(del_bulk_params.keys); -} + if (parse_ipv4_addr(tokens[2], &sipaddr)) { + printf(CMD_MSG_INVALID_ARG, "sipaddr"); + return; + } -cmdline_parse_token_string_t cmd_firewall_del_bulk_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, p_string, - "p"); + if (parser_read_uint32(&sipdepth, tokens[3])) { + printf(CMD_MSG_INVALID_ARG, "sipdepth"); + return; + } -cmdline_parse_token_num_t cmd_firewall_del_bulk_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_bulk_result, pipeline_id, - UINT32); + if (parse_ipv4_addr(tokens[4], &dipaddr)) { + printf(CMD_MSG_INVALID_ARG, "dipaddr"); + return; + } -cmdline_parse_token_string_t cmd_firewall_del_bulk_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, - firewall_string, "firewall"); + if (parser_read_uint32(&dipdepth, tokens[5])) { + printf(CMD_MSG_INVALID_ARG, "dipdepth"); + return; + } -cmdline_parse_token_string_t cmd_firewall_del_bulk_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, - del_string, "del"); + if (parser_read_uint16(&sport0, tokens[6])) { + printf(CMD_MSG_INVALID_ARG, "sport0"); + return; + } -cmdline_parse_token_string_t cmd_firewall_del_bulk_bulk_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, - bulk_string, "bulk"); + if (parser_read_uint16(&sport1, tokens[7])) { + printf(CMD_MSG_INVALID_ARG, "sport1"); + return; + } -cmdline_parse_token_string_t cmd_firewall_del_bulk_file_path_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, - file_path, NULL); + if (parser_read_uint16(&dport0, tokens[8])) { + printf(CMD_MSG_INVALID_ARG, "dport0"); + return; + } -cmdline_parse_inst_t cmd_firewall_del_bulk = { - .f = cmd_firewall_del_bulk_parsed, - .data = NULL, - .help_str = "Firewall rule del bulk", - .tokens = { - (void *) &cmd_firewall_del_bulk_p_string, - (void *) &cmd_firewall_del_bulk_pipeline_id, - (void *) &cmd_firewall_del_bulk_firewall_string, - (void *) &cmd_firewall_del_bulk_add_string, - (void *) &cmd_firewall_del_bulk_bulk_string, - (void *) &cmd_firewall_del_bulk_file_path_string, - NULL, - }, -}; + if (parser_read_uint16(&dport1, tokens[9])) { + printf(CMD_MSG_INVALID_ARG, "dport1"); + return; + } -/* - * p firewall add default - */ -struct cmd_firewall_add_default_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t default_string; - uint8_t port_id; -}; + if (parser_read_uint8(&proto, tokens[10])) { + printf(CMD_MSG_INVALID_ARG, "proto"); + return; + } -static void -cmd_firewall_add_default_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_add_default_result *params = parsed_result; - struct app_params *app = data; - int status; + if (parser_read_uint8_hex(&protomask, tokens[11])) { + printf(CMD_MSG_INVALID_ARG, "protomask"); + return; + } - status = app_pipeline_firewall_add_default_rule(app, - params->pipeline_id, - params->port_id); + key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; + key.key.ipv4_5tuple.src_ip = rte_be_to_cpu_32(sipaddr.s_addr); + key.key.ipv4_5tuple.src_ip_mask = sipdepth; + key.key.ipv4_5tuple.dst_ip = rte_be_to_cpu_32(dipaddr.s_addr); + key.key.ipv4_5tuple.dst_ip_mask = dipdepth; + key.key.ipv4_5tuple.src_port_from = sport0; + key.key.ipv4_5tuple.src_port_to = sport1; + key.key.ipv4_5tuple.dst_port_from = dport0; + key.key.ipv4_5tuple.dst_port_to = dport1; + key.key.ipv4_5tuple.proto = proto; + key.key.ipv4_5tuple.proto_mask = protomask; + + status = app_pipeline_firewall_delete_rule(app, + params->pipeline_id, + &key); + if (status) + printf(CMD_MSG_FAIL, "firewall del"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -cmdline_parse_token_string_t cmd_firewall_add_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_firewall_add_default_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_firewall_add_default_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, - firewall_string, "firewall"); - -cmdline_parse_token_string_t cmd_firewall_add_default_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, - add_string, "add"); + } /* firewall del */ + + /* firewall del bulk */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "bulk") == 0)) { + struct pipeline_firewall_key *keys; + uint32_t *priorities, *port_ids, n_keys, line; + char *filename; + + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall del bulk"); + return; + } -cmdline_parse_token_string_t cmd_firewall_add_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, - default_string, "default"); + filename = tokens[2]; -cmdline_parse_token_num_t cmd_firewall_add_default_port_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, port_id, - UINT8); + n_keys = APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE; + keys = malloc(n_keys * sizeof(struct pipeline_firewall_key)); + if (keys == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + return; + } + memset(keys, 0, n_keys * sizeof(struct pipeline_firewall_key)); -cmdline_parse_inst_t cmd_firewall_add_default = { - .f = cmd_firewall_add_default_parsed, - .data = NULL, - .help_str = "Firewall default rule add", - .tokens = { - (void *) &cmd_firewall_add_default_p_string, - (void *) &cmd_firewall_add_default_pipeline_id, - (void *) &cmd_firewall_add_default_firewall_string, - (void *) &cmd_firewall_add_default_add_string, - (void *) &cmd_firewall_add_default_default_string, - (void *) &cmd_firewall_add_default_port_id, - NULL, - }, -}; + priorities = malloc(n_keys * sizeof(uint32_t)); + if (priorities == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + free(keys); + return; + } -/* - * p firewall del default - */ -struct cmd_firewall_del_default_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t default_string; -}; + port_ids = malloc(n_keys * sizeof(uint32_t)); + if (port_ids == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + free(priorities); + free(keys); + return; + } -static void -cmd_firewall_del_default_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_del_default_result *params = parsed_result; - struct app_params *app = data; - int status; + status = app_pipeline_firewall_load_file(filename, + keys, + priorities, + port_ids, + &n_keys, + &line); + if (status != 0) { + printf(CMD_MSG_FILE_ERR, filename, line); + free(port_ids); + free(priorities); + free(keys); + return; + } - status = app_pipeline_firewall_delete_default_rule(app, - params->pipeline_id); + status = app_pipeline_firewall_delete_bulk(app, + params->pipeline_id, + keys, + n_keys); + if (status) + printf(CMD_MSG_FAIL, "firewall del bulk"); - if (status != 0) { - printf("Command failed\n"); + free(port_ids); + free(priorities); + free(keys); return; - } -} - -cmdline_parse_token_string_t cmd_firewall_del_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_firewall_del_default_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_default_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_firewall_del_default_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, - firewall_string, "firewall"); - -cmdline_parse_token_string_t cmd_firewall_del_default_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, - del_string, "del"); + } /* firewall del bulk */ + + /* firewall del default */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "default") == 0)) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall del default"); + return; + } -cmdline_parse_token_string_t cmd_firewall_del_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, - default_string, "default"); + status = app_pipeline_firewall_delete_default_rule(app, + params->pipeline_id); + if (status) + printf(CMD_MSG_FAIL, "firewall del default"); -cmdline_parse_inst_t cmd_firewall_del_default = { - .f = cmd_firewall_del_default_parsed, - .data = NULL, - .help_str = "Firewall default rule delete", - .tokens = { - (void *) &cmd_firewall_del_default_p_string, - (void *) &cmd_firewall_del_default_pipeline_id, - (void *) &cmd_firewall_del_default_firewall_string, - (void *) &cmd_firewall_del_default_del_string, - (void *) &cmd_firewall_del_default_default_string, - NULL, - }, -}; + return; -/* - * p firewall ls - */ + } /* firewall del default */ -struct cmd_firewall_ls_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t firewall_string; - cmdline_fixed_string_t ls_string; -}; - -static void -cmd_firewall_ls_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_firewall_ls_result *params = parsed_result; - struct app_params *app = data; - int status; + /* firewall ls */ + if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { + if (n_tokens != 1) { + printf(CMD_MSG_MISMATCH_ARGS, "firewall ls"); + return; + } - status = app_pipeline_firewall_ls(app, params->pipeline_id); + status = app_pipeline_firewall_ls(app, params->pipeline_id); + if (status) + printf(CMD_MSG_FAIL, "firewall ls"); - if (status != 0) { - printf("Command failed\n"); return; - } + } /* firewall ls */ + + printf(CMD_MSG_MISMATCH_ARGS, "firewall"); } -cmdline_parse_token_string_t cmd_firewall_ls_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, p_string, - "p"); +static cmdline_parse_token_string_t cmd_firewall_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, p_string, "p"); -cmdline_parse_token_num_t cmd_firewall_ls_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_firewall_ls_result, pipeline_id, - UINT32); +static cmdline_parse_token_num_t cmd_firewall_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_firewall_ls_firewall_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, - firewall_string, "firewall"); +static cmdline_parse_token_string_t cmd_firewall_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, firewall_string, + "firewall"); -cmdline_parse_token_string_t cmd_firewall_ls_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, ls_string, - "ls"); +static cmdline_parse_token_string_t cmd_firewall_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_result, multi_string, + TOKEN_STRING_MULTI); -cmdline_parse_inst_t cmd_firewall_ls = { - .f = cmd_firewall_ls_parsed, +static cmdline_parse_inst_t cmd_firewall = { + .f = cmd_firewall_parsed, .data = NULL, - .help_str = "Firewall rule list", + .help_str = "firewall add / add bulk / add default / del / del bulk" + " / del default / ls", .tokens = { - (void *) &cmd_firewall_ls_p_string, - (void *) &cmd_firewall_ls_pipeline_id, - (void *) &cmd_firewall_ls_firewall_string, - (void *) &cmd_firewall_ls_ls_string, + (void *) &cmd_firewall_p_string, + (void *) &cmd_firewall_pipeline_id, + (void *) &cmd_firewall_firewall_string, + (void *) &cmd_firewall_multi_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *) &cmd_firewall_add_ipv4, - (cmdline_parse_inst_t *) &cmd_firewall_del_ipv4, - (cmdline_parse_inst_t *) &cmd_firewall_add_bulk, - (cmdline_parse_inst_t *) &cmd_firewall_del_bulk, - (cmdline_parse_inst_t *) &cmd_firewall_add_default, - (cmdline_parse_inst_t *) &cmd_firewall_del_default, - (cmdline_parse_inst_t *) &cmd_firewall_ls, + (cmdline_parse_inst_t *) &cmd_firewall, NULL, }; static struct pipeline_fe_ops pipeline_firewall_fe_ops = { .f_init = app_pipeline_firewall_init, + .f_post_init = NULL, .f_free = app_pipeline_firewall_free, + .f_track = app_pipeline_track_default, .cmds = pipeline_cmds, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h index ccc4e64b..aa79a2a0 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.h +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h @@ -72,6 +72,18 @@ int app_pipeline_firewall_delete_default_rule(struct app_params *app, uint32_t pipeline_id); +#ifndef APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE +#define APP_PIPELINE_FIREWALL_MAX_RULES_IN_FILE 65536 +#endif + +int +app_pipeline_firewall_load_file(char *filename, + struct pipeline_firewall_key *keys, + uint32_t *priorities, + uint32_t *port_ids, + uint32_t *n_keys, + uint32_t *line); + extern struct pipeline_type pipeline_firewall; #endif diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c index e7a8a4c5..b61f3034 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c @@ -565,27 +565,6 @@ pipeline_firewall_free(void *pipeline) } static int -pipeline_firewall_track(void *pipeline, - __rte_unused uint32_t port_in, - uint32_t *port_out) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - if (p->n_ports_in == 1) { - *port_out = 0; - return 0; - } - - return -1; -} - -static int pipeline_firewall_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; @@ -732,7 +711,7 @@ pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg) n_keys = req->n_keys; for (i = 0; i < n_keys; i++) { - entries[i] = rte_malloc(NULL, + entries[i] = rte_zmalloc(NULL, sizeof(struct firewall_table_entry), RTE_CACHE_LINE_SIZE); if (entries[i] == NULL) { @@ -740,7 +719,7 @@ pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg) return rsp; } - params[i] = rte_malloc(NULL, + params[i] = rte_zmalloc(NULL, sizeof(struct rte_table_acl_rule_add_params), RTE_CACHE_LINE_SIZE); if (params[i] == NULL) { @@ -814,7 +793,7 @@ pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg) n_keys = req->n_keys; for (i = 0; i < n_keys; i++) { - params[i] = rte_malloc(NULL, + params[i] = rte_zmalloc(NULL, sizeof(struct rte_table_acl_rule_delete_params), RTE_CACHE_LINE_SIZE); if (params[i] == NULL) { @@ -903,5 +882,4 @@ struct pipeline_be_ops pipeline_firewall_be_ops = { .f_free = pipeline_firewall_free, .f_run = NULL, .f_timer = pipeline_firewall_timer, - .f_track = pipeline_firewall_track, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c index 4012121f..bf12fd7b 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.c @@ -35,6 +35,7 @@ #include <string.h> #include <sys/queue.h> #include <netinet/in.h> +#include <unistd.h> #include <rte_common.h> #include <rte_hexdump.h> @@ -43,13 +44,12 @@ #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> -#include <cmdline_parse_ipaddr.h> -#include <cmdline_parse_etheraddr.h> #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_flow_actions.h" #include "hash_func.h" +#include "parser.h" /* * Flow actions pipeline @@ -689,1121 +689,620 @@ app_pipeline_fa_dscp_ls(struct app_params *app, return 0; } -/* - * Flow meter configuration (single flow) - * - * p <pipeline ID> flow <flow ID> meter <meter ID> trtcm <trtcm params> - */ - -struct cmd_fa_meter_config_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - uint32_t flow_id; - cmdline_fixed_string_t meter_string; - uint32_t meter_id; - cmdline_fixed_string_t trtcm_string; - uint64_t cir; - uint64_t pir; - uint64_t cbs; - uint64_t pbs; -}; - -static void -cmd_fa_meter_config_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_meter_config_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fa_flow_params flow_params; - int status; - - if (params->meter_id >= PIPELINE_FA_N_TC_MAX) { - printf("Command failed\n"); - return; - } - - flow_params.m[params->meter_id].cir = params->cir; - flow_params.m[params->meter_id].pir = params->pir; - flow_params.m[params->meter_id].cbs = params->cbs; - flow_params.m[params->meter_id].pbs = params->pbs; - - status = app_pipeline_fa_flow_config(app, - params->pipeline_id, - params->flow_id, - 1 << params->meter_id, - 0, - 0, - &flow_params); - - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fa_meter_config_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_meter_config_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_meter_config_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result, - flow_string, "flow"); - -cmdline_parse_token_num_t cmd_fa_meter_config_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, - flow_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_meter_config_meter_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result, - meter_string, "meter"); - -cmdline_parse_token_num_t cmd_fa_meter_config_meter_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, - meter_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_meter_config_trtcm_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_result, - trtcm_string, "trtcm"); - -cmdline_parse_token_num_t cmd_fa_meter_config_cir = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cir, UINT64); - -cmdline_parse_token_num_t cmd_fa_meter_config_pir = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pir, UINT64); - -cmdline_parse_token_num_t cmd_fa_meter_config_cbs = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, cbs, UINT64); - -cmdline_parse_token_num_t cmd_fa_meter_config_pbs = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_result, pbs, UINT64); - -cmdline_parse_inst_t cmd_fa_meter_config = { - .f = cmd_fa_meter_config_parsed, - .data = NULL, - .help_str = "Flow meter configuration (single flow) ", - .tokens = { - (void *) &cmd_fa_meter_config_p_string, - (void *) &cmd_fa_meter_config_pipeline_id, - (void *) &cmd_fa_meter_config_flow_string, - (void *) &cmd_fa_meter_config_flow_id, - (void *) &cmd_fa_meter_config_meter_string, - (void *) &cmd_fa_meter_config_meter_id, - (void *) &cmd_fa_meter_config_trtcm_string, - (void *) &cmd_fa_meter_config_cir, - (void *) &cmd_fa_meter_config_pir, - (void *) &cmd_fa_meter_config_cbs, - (void *) &cmd_fa_meter_config_pbs, - NULL, - }, -}; - -/* - * Flow meter configuration (multiple flows) - * - * p <pipeline ID> flows <n_flows> meter <meter ID> trtcm <trtcm params> - */ - -struct cmd_fa_meter_config_bulk_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flows_string; - uint32_t n_flows; - cmdline_fixed_string_t meter_string; - uint32_t meter_id; - cmdline_fixed_string_t trtcm_string; - uint64_t cir; - uint64_t pir; - uint64_t cbs; - uint64_t pbs; -}; - -static void -cmd_fa_meter_config_bulk_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) +int +app_pipeline_fa_load_file(char *filename, + uint32_t *flow_ids, + struct pipeline_fa_flow_params *p, + uint32_t *n_flows, + uint32_t *line) { - struct cmd_fa_meter_config_bulk_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fa_flow_params flow_template, *flow_params; - uint32_t *flow_id; - uint32_t i; + FILE *f = NULL; + char file_buf[1024]; + uint32_t i, l; - if ((params->n_flows == 0) || - (params->meter_id >= PIPELINE_FA_N_TC_MAX)) { - printf("Invalid arguments\n"); - return; - } - - flow_id = (uint32_t *) rte_malloc(NULL, - N_FLOWS_BULK * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (flow_id == NULL) { - printf("Memory allocation failed\n"); - return; - } + /* Check input arguments */ + if ((filename == NULL) || + (flow_ids == NULL) || + (p == NULL) || + (n_flows == NULL) || + (*n_flows == 0) || + (line == NULL)) { + if (line) + *line = 0; + return -1; + } - flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL, - N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params), - RTE_CACHE_LINE_SIZE); - if (flow_params == NULL) { - rte_free(flow_id); - printf("Memory allocation failed\n"); - return; + /* Open input file */ + f = fopen(filename, "r"); + if (f == NULL) { + *line = 0; + return -1; } - memset(&flow_template, 0, sizeof(flow_template)); - flow_template.m[params->meter_id].cir = params->cir; - flow_template.m[params->meter_id].pir = params->pir; - flow_template.m[params->meter_id].cbs = params->cbs; - flow_template.m[params->meter_id].pbs = params->pbs; + /* Read file */ + for (i = 0, l = 1; i < *n_flows; l++) { + char *tokens[64]; + uint32_t n_tokens = RTE_DIM(tokens); - for (i = 0; i < params->n_flows; i++) { - uint32_t pos = i % N_FLOWS_BULK; + int status; - flow_id[pos] = i; - memcpy(&flow_params[pos], - &flow_template, - sizeof(flow_template)); + if (fgets(file_buf, sizeof(file_buf), f) == NULL) + break; - if ((pos == N_FLOWS_BULK - 1) || - (i == params->n_flows - 1)) { - int status; + status = parse_tokenize_string(file_buf, tokens, &n_tokens); + if (status) + goto error1; - status = app_pipeline_fa_flow_config_bulk(app, - params->pipeline_id, - flow_id, - pos + 1, - 1 << params->meter_id, - 0, - 0, - flow_params); + if ((n_tokens == 0) || (tokens[0][0] == '#')) + continue; - if (status != 0) { - printf("Command failed\n"); - break; - } - } + if ((n_tokens != 64) || + /* flow */ + strcmp(tokens[0], "flow") || + parser_read_uint32(&flow_ids[i], tokens[1]) || + + /* meter & policer 0 */ + strcmp(tokens[2], "meter") || + strcmp(tokens[3], "0") || + strcmp(tokens[4], "trtcm") || + parser_read_uint64(&p[i].m[0].cir, tokens[5]) || + parser_read_uint64(&p[i].m[0].pir, tokens[6]) || + parser_read_uint64(&p[i].m[0].cbs, tokens[7]) || + parser_read_uint64(&p[i].m[0].pbs, tokens[8]) || + strcmp(tokens[9], "policer") || + strcmp(tokens[10], "0") || + strcmp(tokens[11], "g") || + string_to_policer_action(tokens[12], + &p[i].p[0].action[e_RTE_METER_GREEN]) || + strcmp(tokens[13], "y") || + string_to_policer_action(tokens[14], + &p[i].p[0].action[e_RTE_METER_YELLOW]) || + strcmp(tokens[15], "r") || + string_to_policer_action(tokens[16], + &p[i].p[0].action[e_RTE_METER_RED]) || + + /* meter & policer 1 */ + strcmp(tokens[17], "meter") || + strcmp(tokens[18], "1") || + strcmp(tokens[19], "trtcm") || + parser_read_uint64(&p[i].m[1].cir, tokens[20]) || + parser_read_uint64(&p[i].m[1].pir, tokens[21]) || + parser_read_uint64(&p[i].m[1].cbs, tokens[22]) || + parser_read_uint64(&p[i].m[1].pbs, tokens[23]) || + strcmp(tokens[24], "policer") || + strcmp(tokens[25], "1") || + strcmp(tokens[26], "g") || + string_to_policer_action(tokens[27], + &p[i].p[1].action[e_RTE_METER_GREEN]) || + strcmp(tokens[28], "y") || + string_to_policer_action(tokens[29], + &p[i].p[1].action[e_RTE_METER_YELLOW]) || + strcmp(tokens[30], "r") || + string_to_policer_action(tokens[31], + &p[i].p[1].action[e_RTE_METER_RED]) || + + /* meter & policer 2 */ + strcmp(tokens[32], "meter") || + strcmp(tokens[33], "2") || + strcmp(tokens[34], "trtcm") || + parser_read_uint64(&p[i].m[2].cir, tokens[35]) || + parser_read_uint64(&p[i].m[2].pir, tokens[36]) || + parser_read_uint64(&p[i].m[2].cbs, tokens[37]) || + parser_read_uint64(&p[i].m[2].pbs, tokens[38]) || + strcmp(tokens[39], "policer") || + strcmp(tokens[40], "2") || + strcmp(tokens[41], "g") || + string_to_policer_action(tokens[42], + &p[i].p[2].action[e_RTE_METER_GREEN]) || + strcmp(tokens[43], "y") || + string_to_policer_action(tokens[44], + &p[i].p[2].action[e_RTE_METER_YELLOW]) || + strcmp(tokens[45], "r") || + string_to_policer_action(tokens[46], + &p[i].p[2].action[e_RTE_METER_RED]) || + + /* meter & policer 3 */ + strcmp(tokens[47], "meter") || + strcmp(tokens[48], "3") || + strcmp(tokens[49], "trtcm") || + parser_read_uint64(&p[i].m[3].cir, tokens[50]) || + parser_read_uint64(&p[i].m[3].pir, tokens[51]) || + parser_read_uint64(&p[i].m[3].cbs, tokens[52]) || + parser_read_uint64(&p[i].m[3].pbs, tokens[53]) || + strcmp(tokens[54], "policer") || + strcmp(tokens[55], "3") || + strcmp(tokens[56], "g") || + string_to_policer_action(tokens[57], + &p[i].p[3].action[e_RTE_METER_GREEN]) || + strcmp(tokens[58], "y") || + string_to_policer_action(tokens[59], + &p[i].p[3].action[e_RTE_METER_YELLOW]) || + strcmp(tokens[60], "r") || + string_to_policer_action(tokens[61], + &p[i].p[3].action[e_RTE_METER_RED]) || + + /* port */ + strcmp(tokens[62], "port") || + parser_read_uint32(&p[i].port_id, tokens[63])) + goto error1; + + i++; } - rte_free(flow_params); - rte_free(flow_id); + /* Close file */ + *n_flows = i; + fclose(f); + return 0; +error1: + *line = l; + fclose(f); + return -1; } -cmdline_parse_token_string_t cmd_fa_meter_config_bulk_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_meter_config_bulk_flows_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - flows_string, "flows"); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_n_flows = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - n_flows, UINT32); - -cmdline_parse_token_string_t cmd_fa_meter_config_bulk_meter_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - meter_string, "meter"); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_meter_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - meter_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_meter_config_bulk_trtcm_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - trtcm_string, "trtcm"); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cir = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - cir, UINT64); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pir = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - pir, UINT64); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_cbs = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - cbs, UINT64); - -cmdline_parse_token_num_t cmd_fa_meter_config_bulk_pbs = - TOKEN_NUM_INITIALIZER(struct cmd_fa_meter_config_bulk_result, - pbs, UINT64); - -cmdline_parse_inst_t cmd_fa_meter_config_bulk = { - .f = cmd_fa_meter_config_bulk_parsed, - .data = NULL, - .help_str = "Flow meter configuration (multiple flows)", - .tokens = { - (void *) &cmd_fa_meter_config_bulk_p_string, - (void *) &cmd_fa_meter_config_bulk_pipeline_id, - (void *) &cmd_fa_meter_config_bulk_flows_string, - (void *) &cmd_fa_meter_config_bulk_n_flows, - (void *) &cmd_fa_meter_config_bulk_meter_string, - (void *) &cmd_fa_meter_config_bulk_meter_id, - (void *) &cmd_fa_meter_config_bulk_trtcm_string, - (void *) &cmd_fa_meter_config_cir, - (void *) &cmd_fa_meter_config_pir, - (void *) &cmd_fa_meter_config_cbs, - (void *) &cmd_fa_meter_config_pbs, - NULL, - }, -}; - /* - * Flow policer configuration (single flow) + * action * - * p <pipeline ID> flow <flow ID> policer <policer ID> - * G <action> Y <action> R <action> + * flow meter, policer and output port configuration: + * p <pipelineid> action flow <flowid> meter <meterid> trtcm <cir> <pir> <cbs> <pbs> * - * <action> = G (green) | Y (yellow) | R (red) | D (drop) - */ - -struct cmd_fa_policer_config_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - uint32_t flow_id; - cmdline_fixed_string_t policer_string; - uint32_t policer_id; - cmdline_fixed_string_t green_string; - cmdline_fixed_string_t g_action; - cmdline_fixed_string_t yellow_string; - cmdline_fixed_string_t y_action; - cmdline_fixed_string_t red_string; - cmdline_fixed_string_t r_action; -}; - -static void -cmd_fa_policer_config_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_policer_config_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fa_flow_params flow_params; - int status; - - if (params->policer_id >= PIPELINE_FA_N_TC_MAX) { - printf("Command failed\n"); - return; - } - - status = string_to_policer_action(params->g_action, - &flow_params.p[params->policer_id].action[e_RTE_METER_GREEN]); - if (status) - printf("Invalid policer green action\n"); - - status = string_to_policer_action(params->y_action, - &flow_params.p[params->policer_id].action[e_RTE_METER_YELLOW]); - if (status) - printf("Invalid policer yellow action\n"); - - status = string_to_policer_action(params->r_action, - &flow_params.p[params->policer_id].action[e_RTE_METER_RED]); - if (status) - printf("Invalid policer red action\n"); - - status = app_pipeline_fa_flow_config(app, - params->pipeline_id, - params->flow_id, - 0, - 1 << params->policer_id, - 0, - &flow_params); - - if (status != 0) - printf("Command failed\n"); - -} - -cmdline_parse_token_string_t cmd_fa_policer_config_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_policer_config_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_config_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - flow_string, "flow"); - -cmdline_parse_token_num_t cmd_fa_policer_config_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result, - flow_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_config_policer_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - policer_string, "policer"); - -cmdline_parse_token_num_t cmd_fa_policer_config_policer_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_result, - policer_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_config_green_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - green_string, "G"); - -cmdline_parse_token_string_t cmd_fa_policer_config_g_action = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - g_action, "R#Y#G#D"); - -cmdline_parse_token_string_t cmd_fa_policer_config_yellow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - yellow_string, "Y"); - -cmdline_parse_token_string_t cmd_fa_policer_config_y_action = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - y_action, "R#Y#G#D"); - -cmdline_parse_token_string_t cmd_fa_policer_config_red_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - red_string, "R"); - -cmdline_parse_token_string_t cmd_fa_policer_config_r_action = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_result, - r_action, "R#Y#G#D"); - -cmdline_parse_inst_t cmd_fa_policer_config = { - .f = cmd_fa_policer_config_parsed, - .data = NULL, - .help_str = "Flow policer configuration (single flow)", - .tokens = { - (void *) &cmd_fa_policer_config_p_string, - (void *) &cmd_fa_policer_config_pipeline_id, - (void *) &cmd_fa_policer_config_flow_string, - (void *) &cmd_fa_policer_config_flow_id, - (void *) &cmd_fa_policer_config_policer_string, - (void *) &cmd_fa_policer_config_policer_id, - (void *) &cmd_fa_policer_config_green_string, - (void *) &cmd_fa_policer_config_g_action, - (void *) &cmd_fa_policer_config_yellow_string, - (void *) &cmd_fa_policer_config_y_action, - (void *) &cmd_fa_policer_config_red_string, - (void *) &cmd_fa_policer_config_r_action, - NULL, - }, -}; - -/* - * Flow policer configuration (multiple flows) + * p <pipelineid> action flow <flowid> policer <policerid> g <gaction> y <yaction> r <raction> + * <action> is one of the following: + * G = recolor to green + * Y = recolor as yellow + * R = recolor as red + * D = drop * - * p <pipeline ID> flows <n_flows> policer <policer ID> - * G <action> Y <action> R <action> + * p <pipelineid> action flow <flowid> port <port ID> * - * <action> = G (green) | Y (yellow) | R (red) | D (drop) - */ + * p <pipelineid> action flow bulk <file> + * + * flow policer stats read: + * p <pipelineid> action flow <flowid> stats + * + * flow ls: + * p <pipelineid> action flow ls + * + * dscp table configuration: + * p <pipelineid> action dscp <dscpid> class <class ID> color <color> + * + * dscp table ls: + * p <pipelineid> action dscp ls +**/ -struct cmd_fa_policer_config_bulk_result { +struct cmd_action_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; - cmdline_fixed_string_t flows_string; - uint32_t n_flows; - cmdline_fixed_string_t policer_string; - uint32_t policer_id; - cmdline_fixed_string_t green_string; - cmdline_fixed_string_t g_action; - cmdline_fixed_string_t yellow_string; - cmdline_fixed_string_t y_action; - cmdline_fixed_string_t red_string; - cmdline_fixed_string_t r_action; + cmdline_fixed_string_t action_string; + cmdline_multi_string_t multi_string; }; static void -cmd_fa_policer_config_bulk_parsed( +cmd_action_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { - struct cmd_fa_policer_config_bulk_result *params = parsed_result; + struct cmd_action_result *params = parsed_result; struct app_params *app = data; - struct pipeline_fa_flow_params flow_template, *flow_params; - uint32_t *flow_id, i; - int status; - if ((params->n_flows == 0) || - (params->policer_id >= PIPELINE_FA_N_TC_MAX)) { - printf("Invalid arguments\n"); - return; - } - - flow_id = (uint32_t *) rte_malloc(NULL, - N_FLOWS_BULK * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (flow_id == NULL) { - printf("Memory allocation failed\n"); - return; - } + char *tokens[16]; + uint32_t n_tokens = RTE_DIM(tokens); + int status; - flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL, - N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params), - RTE_CACHE_LINE_SIZE); - if (flow_params == NULL) { - rte_free(flow_id); - printf("Memory allocation failed\n"); + status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); + if (status != 0) { + printf(CMD_MSG_TOO_MANY_ARGS, "action"); return; } - memset(&flow_template, 0, sizeof(flow_template)); - - status = string_to_policer_action(params->g_action, - &flow_template.p[params->policer_id].action[e_RTE_METER_GREEN]); - if (status) - printf("Invalid policer green action\n"); - - status = string_to_policer_action(params->y_action, - &flow_template.p[params->policer_id].action[e_RTE_METER_YELLOW]); - if (status) - printf("Invalid policer yellow action\n"); - - status = string_to_policer_action(params->r_action, - &flow_template.p[params->policer_id].action[e_RTE_METER_RED]); - if (status) - printf("Invalid policer red action\n"); - - for (i = 0; i < params->n_flows; i++) { - uint32_t pos = i % N_FLOWS_BULK; - - flow_id[pos] = i; - memcpy(&flow_params[pos], &flow_template, - sizeof(flow_template)); - - if ((pos == N_FLOWS_BULK - 1) || - (i == params->n_flows - 1)) { - int status; - - status = app_pipeline_fa_flow_config_bulk(app, - params->pipeline_id, - flow_id, - pos + 1, - 0, - 1 << params->policer_id, - 0, - flow_params); - - if (status != 0) { - printf("Command failed\n"); - - break; - } + /* action flow meter */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "flow") == 0) && + strcmp(tokens[1], "bulk") && + strcmp(tokens[1], "ls") && + (strcmp(tokens[2], "meter") == 0)) { + struct pipeline_fa_flow_params flow_params; + uint32_t flow_id, meter_id; + + if (n_tokens != 9) { + printf(CMD_MSG_MISMATCH_ARGS, "action flow meter"); + return; } - } - - rte_free(flow_params); - rte_free(flow_id); - -} - -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_policer_config_bulk_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_flows_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - flows_string, "flows"); - -cmdline_parse_token_num_t cmd_fa_policer_config_bulk_n_flows = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - n_flows, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_policer_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - policer_string, "policer"); -cmdline_parse_token_num_t cmd_fa_policer_config_bulk_policer_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - policer_id, UINT32); + memset(&flow_params, 0, sizeof(flow_params)); -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_green_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - green_string, "G"); + if (parser_read_uint32(&flow_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_g_action = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - g_action, "R#Y#G#D"); + if (parser_read_uint32(&meter_id, tokens[3]) || + (meter_id >= PIPELINE_FA_N_TC_MAX)) { + printf(CMD_MSG_INVALID_ARG, "meterid"); + return; + } -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_yellow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - yellow_string, "Y"); + if (strcmp(tokens[4], "trtcm")) { + printf(CMD_MSG_ARG_NOT_FOUND, "trtcm"); + return; + } -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_y_action = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - y_action, "R#Y#G#D"); + if (parser_read_uint64(&flow_params.m[meter_id].cir, tokens[5])) { + printf(CMD_MSG_INVALID_ARG, "cir"); + return; + } -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_red_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - red_string, "R"); + if (parser_read_uint64(&flow_params.m[meter_id].pir, tokens[6])) { + printf(CMD_MSG_INVALID_ARG, "pir"); + return; + } -cmdline_parse_token_string_t cmd_fa_policer_config_bulk_r_action = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_config_bulk_result, - r_action, "R#Y#G#D"); + if (parser_read_uint64(&flow_params.m[meter_id].cbs, tokens[7])) { + printf(CMD_MSG_INVALID_ARG, "cbs"); + return; + } -cmdline_parse_inst_t cmd_fa_policer_config_bulk = { - .f = cmd_fa_policer_config_bulk_parsed, - .data = NULL, - .help_str = "Flow policer configuration (multiple flows)", - .tokens = { - (void *) &cmd_fa_policer_config_bulk_p_string, - (void *) &cmd_fa_policer_config_bulk_pipeline_id, - (void *) &cmd_fa_policer_config_bulk_flows_string, - (void *) &cmd_fa_policer_config_bulk_n_flows, - (void *) &cmd_fa_policer_config_bulk_policer_string, - (void *) &cmd_fa_policer_config_bulk_policer_id, - (void *) &cmd_fa_policer_config_bulk_green_string, - (void *) &cmd_fa_policer_config_bulk_g_action, - (void *) &cmd_fa_policer_config_bulk_yellow_string, - (void *) &cmd_fa_policer_config_bulk_y_action, - (void *) &cmd_fa_policer_config_bulk_red_string, - (void *) &cmd_fa_policer_config_bulk_r_action, - NULL, - }, -}; + if (parser_read_uint64(&flow_params.m[meter_id].pbs, tokens[8])) { + printf(CMD_MSG_INVALID_ARG, "pbs"); + return; + } -/* - * Flow output port configuration (single flow) - * - * p <pipeline ID> flow <flow ID> port <port ID> - */ + status = app_pipeline_fa_flow_config(app, + params->pipeline_id, + flow_id, + 1 << meter_id, + 0, + 0, + &flow_params); + if (status) + printf(CMD_MSG_FAIL, "action flow meter"); -struct cmd_fa_output_port_config_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - uint32_t flow_id; - cmdline_fixed_string_t port_string; - uint32_t port_id; -}; + return; + } /* action flow meter */ + + /* action flow policer */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "flow") == 0) && + strcmp(tokens[1], "bulk") && + strcmp(tokens[1], "ls") && + (strcmp(tokens[2], "policer") == 0)) { + struct pipeline_fa_flow_params flow_params; + uint32_t flow_id, policer_id; + + if (n_tokens != 10) { + printf(CMD_MSG_MISMATCH_ARGS, "action flow policer"); + return; + } -static void -cmd_fa_output_port_config_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_output_port_config_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fa_flow_params flow_params; - int status; + memset(&flow_params, 0, sizeof(flow_params)); - flow_params.port_id = params->port_id; + if (parser_read_uint32(&flow_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } - status = app_pipeline_fa_flow_config(app, - params->pipeline_id, - params->flow_id, - 0, - 0, - 1, - &flow_params); + if (parser_read_uint32(&policer_id, tokens[3]) || + (policer_id >= PIPELINE_FA_N_TC_MAX)) { + printf(CMD_MSG_INVALID_ARG, "policerid"); + return; + } - if (status != 0) - printf("Command failed\n"); -} + if (strcmp(tokens[4], "g")) { + printf(CMD_MSG_ARG_NOT_FOUND, "g"); + return; + } -cmdline_parse_token_string_t cmd_fa_output_port_config_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result, - p_string, "p"); + if (string_to_policer_action(tokens[5], + &flow_params.p[policer_id].action[e_RTE_METER_GREEN])) { + printf(CMD_MSG_INVALID_ARG, "gaction"); + return; + } -cmdline_parse_token_num_t cmd_fa_output_port_config_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result, - pipeline_id, UINT32); + if (strcmp(tokens[6], "y")) { + printf(CMD_MSG_ARG_NOT_FOUND, "y"); + return; + } -cmdline_parse_token_string_t cmd_fa_output_port_config_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result, - flow_string, "flow"); + if (string_to_policer_action(tokens[7], + &flow_params.p[policer_id].action[e_RTE_METER_YELLOW])) { + printf(CMD_MSG_INVALID_ARG, "yaction"); + return; + } -cmdline_parse_token_num_t cmd_fa_output_port_config_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result, - flow_id, UINT32); + if (strcmp(tokens[8], "r")) { + printf(CMD_MSG_ARG_NOT_FOUND, "r"); + return; + } -cmdline_parse_token_string_t cmd_fa_output_port_config_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_result, - port_string, "port"); + if (string_to_policer_action(tokens[9], + &flow_params.p[policer_id].action[e_RTE_METER_RED])) { + printf(CMD_MSG_INVALID_ARG, "raction"); + return; + } -cmdline_parse_token_num_t cmd_fa_output_port_config_port_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_result, - port_id, UINT32); + status = app_pipeline_fa_flow_config(app, + params->pipeline_id, + flow_id, + 0, + 1 << policer_id, + 0, + &flow_params); + if (status != 0) + printf(CMD_MSG_FAIL, "action flow policer"); -cmdline_parse_inst_t cmd_fa_output_port_config = { - .f = cmd_fa_output_port_config_parsed, - .data = NULL, - .help_str = "Flow output port configuration (single flow)", - .tokens = { - (void *) &cmd_fa_output_port_config_p_string, - (void *) &cmd_fa_output_port_config_pipeline_id, - (void *) &cmd_fa_output_port_config_flow_string, - (void *) &cmd_fa_output_port_config_flow_id, - (void *) &cmd_fa_output_port_config_port_string, - (void *) &cmd_fa_output_port_config_port_id, - NULL, - }, -}; + return; + } /* action flow policer */ + + /* action flow port */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "flow") == 0) && + strcmp(tokens[1], "bulk") && + strcmp(tokens[1], "ls") && + (strcmp(tokens[2], "port") == 0)) { + struct pipeline_fa_flow_params flow_params; + uint32_t flow_id, port_id; + + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "action flow port"); + return; + } -/* - * Flow output port configuration (multiple flows) - * - * p <pipeline ID> flows <n_flows> ports <n_ports> - */ + memset(&flow_params, 0, sizeof(flow_params)); -struct cmd_fa_output_port_config_bulk_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flows_string; - uint32_t n_flows; - cmdline_fixed_string_t ports_string; - uint32_t n_ports; -}; + if (parser_read_uint32(&flow_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } -static void -cmd_fa_output_port_config_bulk_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_output_port_config_bulk_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fa_flow_params *flow_params; - uint32_t *flow_id; - uint32_t i; + if (parser_read_uint32(&port_id, tokens[3])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } - if (params->n_flows == 0) { - printf("Invalid arguments\n"); - return; - } + flow_params.port_id = port_id; - flow_id = (uint32_t *) rte_malloc(NULL, - N_FLOWS_BULK * sizeof(uint32_t), - RTE_CACHE_LINE_SIZE); - if (flow_id == NULL) { - printf("Memory allocation failed\n"); - return; - } + status = app_pipeline_fa_flow_config(app, + params->pipeline_id, + flow_id, + 0, + 0, + 1, + &flow_params); + if (status) + printf(CMD_MSG_FAIL, "action flow port"); - flow_params = (struct pipeline_fa_flow_params *) rte_malloc(NULL, - N_FLOWS_BULK * sizeof(struct pipeline_fa_flow_params), - RTE_CACHE_LINE_SIZE); - if (flow_params == NULL) { - rte_free(flow_id); - printf("Memory allocation failed\n"); return; - } - - for (i = 0; i < params->n_flows; i++) { - uint32_t pos = i % N_FLOWS_BULK; - uint32_t port_id = i % params->n_ports; - - flow_id[pos] = i; - - memset(&flow_params[pos], 0, sizeof(flow_params[pos])); - flow_params[pos].port_id = port_id; + } /* action flow port */ + + /* action flow stats */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "flow") == 0) && + strcmp(tokens[1], "bulk") && + strcmp(tokens[1], "ls") && + (strcmp(tokens[2], "stats") == 0)) { + struct pipeline_fa_policer_stats stats; + uint32_t flow_id, policer_id; + + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "action flow stats"); + return; + } - if ((pos == N_FLOWS_BULK - 1) || - (i == params->n_flows - 1)) { - int status; + if (parser_read_uint32(&flow_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } - status = app_pipeline_fa_flow_config_bulk(app, + for (policer_id = 0; + policer_id < PIPELINE_FA_N_TC_MAX; + policer_id++) { + status = app_pipeline_fa_flow_policer_stats_read(app, params->pipeline_id, flow_id, - pos + 1, - 0, - 0, + policer_id, 1, - flow_params); - + &stats); if (status != 0) { - printf("Command failed\n"); - - break; + printf(CMD_MSG_FAIL, "action flow stats"); + return; } - } - } - - rte_free(flow_params); - rte_free(flow_id); - -} - -cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_flows_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result, - flows_string, "flows"); - -cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_flows = - TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result, - n_flows, UINT32); - -cmdline_parse_token_string_t cmd_fa_output_port_config_bulk_ports_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_output_port_config_bulk_result, - ports_string, "ports"); - -cmdline_parse_token_num_t cmd_fa_output_port_config_bulk_n_ports = - TOKEN_NUM_INITIALIZER(struct cmd_fa_output_port_config_bulk_result, - n_ports, UINT32); - -cmdline_parse_inst_t cmd_fa_output_port_config_bulk = { - .f = cmd_fa_output_port_config_bulk_parsed, - .data = NULL, - .help_str = "Flow output port configuration (multiple flows)", - .tokens = { - (void *) &cmd_fa_output_port_config_bulk_p_string, - (void *) &cmd_fa_output_port_config_bulk_pipeline_id, - (void *) &cmd_fa_output_port_config_bulk_flows_string, - (void *) &cmd_fa_output_port_config_bulk_n_flows, - (void *) &cmd_fa_output_port_config_bulk_ports_string, - (void *) &cmd_fa_output_port_config_bulk_n_ports, - NULL, - }, -}; - -/* - * Flow DiffServ Code Point (DSCP) translation table configuration - * - * p <pipeline ID> dscp <DSCP ID> class <traffic class ID> color <color> - * - * <color> = G (green) | Y (yellow) | R (red) -*/ -struct cmd_fa_dscp_config_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t dscp_string; - uint32_t dscp_id; - cmdline_fixed_string_t class_string; - uint32_t traffic_class_id; - cmdline_fixed_string_t color_string; - cmdline_fixed_string_t color; - -}; - -static void -cmd_fa_dscp_config_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_dscp_config_result *params = parsed_result; - struct app_params *app = data; - enum rte_meter_color color; - int status; + /* Display stats */ + printf("\tPolicer: %" PRIu32 + "\tPkts G: %" PRIu64 + "\tPkts Y: %" PRIu64 + "\tPkts R: %" PRIu64 + "\tPkts D: %" PRIu64 "\n", + policer_id, + stats.n_pkts[e_RTE_METER_GREEN], + stats.n_pkts[e_RTE_METER_YELLOW], + stats.n_pkts[e_RTE_METER_RED], + stats.n_pkts_drop); + } - status = string_to_color(params->color, &color); - if (status) { - printf("Invalid color\n"); return; - } - - status = app_pipeline_fa_dscp_config(app, - params->pipeline_id, - params->dscp_id, - params->traffic_class_id, - color); - - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fa_dscp_config_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_dscp_config_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_dscp_config_dscp_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result, - dscp_string, "dscp"); - -cmdline_parse_token_num_t cmd_fa_dscp_config_dscp_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result, - dscp_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_dscp_config_class_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result, - class_string, "class"); - -cmdline_parse_token_num_t cmd_fa_dscp_config_traffic_class_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_config_result, - traffic_class_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_dscp_config_color_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result, - color_string, "color"); - -cmdline_parse_token_string_t cmd_fa_dscp_config_color = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_config_result, - color, "G#Y#R"); + } /* action flow stats */ + + /* action flow bulk */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "flow") == 0) && + (strcmp(tokens[1], "bulk") == 0)) { + struct pipeline_fa_flow_params *flow_params; + uint32_t *flow_ids, n_flows, line; + char *filename; + + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "action flow bulk"); + return; + } -cmdline_parse_inst_t cmd_fa_dscp_config = { - .f = cmd_fa_dscp_config_parsed, - .data = NULL, - .help_str = "Flow DSCP translation table configuration", - .tokens = { - (void *) &cmd_fa_dscp_config_p_string, - (void *) &cmd_fa_dscp_config_pipeline_id, - (void *) &cmd_fa_dscp_config_dscp_string, - (void *) &cmd_fa_dscp_config_dscp_id, - (void *) &cmd_fa_dscp_config_class_string, - (void *) &cmd_fa_dscp_config_traffic_class_id, - (void *) &cmd_fa_dscp_config_color_string, - (void *) &cmd_fa_dscp_config_color, - NULL, - }, -}; + filename = tokens[2]; -/* - * Flow policer stats read - * - * p <pipeline ID> flow <flow ID> policer <policer ID> stats - */ + n_flows = APP_PIPELINE_FA_MAX_RECORDS_IN_FILE; + flow_ids = malloc(n_flows * sizeof(uint32_t)); + if (flow_ids == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + return; + } -struct cmd_fa_policer_stats_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - uint32_t flow_id; - cmdline_fixed_string_t policer_string; - uint32_t policer_id; - cmdline_fixed_string_t stats_string; -}; + flow_params = malloc(n_flows * sizeof(struct pipeline_fa_flow_params)); + if (flow_params == NULL) { + printf(CMD_MSG_OUT_OF_MEMORY); + free(flow_ids); + return; + } -static void -cmd_fa_policer_stats_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_policer_stats_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fa_policer_stats stats; - int status; + status = app_pipeline_fa_load_file(filename, + flow_ids, + flow_params, + &n_flows, + &line); + if (status) { + printf(CMD_MSG_FILE_ERR, filename, line); + free(flow_params); + free(flow_ids); + return; + } - status = app_pipeline_fa_flow_policer_stats_read(app, - params->pipeline_id, - params->flow_id, - params->policer_id, - 1, - &stats); - if (status != 0) { - printf("Command failed\n"); + status = app_pipeline_fa_flow_config_bulk(app, + params->pipeline_id, + flow_ids, + n_flows, + 0xF, + 0xF, + 1, + flow_params); + if (status) + printf(CMD_MSG_FAIL, "action flow bulk"); + + free(flow_params); + free(flow_ids); return; - } - - /* Display stats */ - printf("\tPkts G: %" PRIu64 - "\tPkts Y: %" PRIu64 - "\tPkts R: %" PRIu64 - "\tPkts D: %" PRIu64 "\n", - stats.n_pkts[e_RTE_METER_GREEN], - stats.n_pkts[e_RTE_METER_YELLOW], - stats.n_pkts[e_RTE_METER_RED], - stats.n_pkts_drop); -} - -cmdline_parse_token_string_t cmd_fa_policer_stats_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fa_policer_stats_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_stats_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result, - flow_string, "flow"); - -cmdline_parse_token_num_t cmd_fa_policer_stats_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result, - flow_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_stats_policer_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result, - policer_string, "policer"); - -cmdline_parse_token_num_t cmd_fa_policer_stats_policer_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_policer_stats_result, - policer_id, UINT32); - -cmdline_parse_token_string_t cmd_fa_policer_stats_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_policer_stats_result, - stats_string, "stats"); - -cmdline_parse_inst_t cmd_fa_policer_stats = { - .f = cmd_fa_policer_stats_parsed, - .data = NULL, - .help_str = "Flow policer stats read", - .tokens = { - (void *) &cmd_fa_policer_stats_p_string, - (void *) &cmd_fa_policer_stats_pipeline_id, - (void *) &cmd_fa_policer_stats_flow_string, - (void *) &cmd_fa_policer_stats_flow_id, - (void *) &cmd_fa_policer_stats_policer_string, - (void *) &cmd_fa_policer_stats_policer_id, - (void *) &cmd_fa_policer_stats_string, - NULL, - }, -}; - -/* - * Flow list - * - * p <pipeline ID> flow ls - */ + } /* action flow bulk */ + + /* action flow ls */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "flow") == 0) && + (strcmp(tokens[1], "ls") == 0)) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "action flow ls"); + return; + } -struct cmd_fa_flow_ls_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t actions_string; - cmdline_fixed_string_t ls_string; -}; + status = app_pipeline_fa_flow_ls(app, + params->pipeline_id); + if (status) + printf(CMD_MSG_FAIL, "action flow ls"); -static void -cmd_fa_flow_ls_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_flow_ls_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_fa_flow_ls(app, params->pipeline_id); - if (status != 0) - printf("Command failed\n"); -} + return; + } /* action flow ls */ + + /* action dscp */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "dscp") == 0) && + strcmp(tokens[1], "ls")) { + uint32_t dscp_id, tc_id; + enum rte_meter_color color; + + if (n_tokens != 6) { + printf(CMD_MSG_MISMATCH_ARGS, "action dscp"); + return; + } -cmdline_parse_token_string_t cmd_fa_flow_ls_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result, - p_string, "p"); + if (parser_read_uint32(&dscp_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "dscpid"); + return; + } -cmdline_parse_token_num_t cmd_fa_flow_ls_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_flow_ls_result, - pipeline_id, UINT32); + if (strcmp(tokens[2], "class")) { + printf(CMD_MSG_ARG_NOT_FOUND, "class"); + return; + } -cmdline_parse_token_string_t cmd_fa_flow_ls_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result, - flow_string, "flow"); + if (parser_read_uint32(&tc_id, tokens[3])) { + printf(CMD_MSG_INVALID_ARG, "classid"); + return; + } -cmdline_parse_token_string_t cmd_fa_flow_ls_actions_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result, - actions_string, "actions"); + if (strcmp(tokens[4], "color")) { + printf(CMD_MSG_ARG_NOT_FOUND, "color"); + return; + } -cmdline_parse_token_string_t cmd_fa_flow_ls_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_flow_ls_result, - ls_string, "ls"); + if (string_to_color(tokens[5], &color)) { + printf(CMD_MSG_INVALID_ARG, "colorid"); + return; + } -cmdline_parse_inst_t cmd_fa_flow_ls = { - .f = cmd_fa_flow_ls_parsed, - .data = NULL, - .help_str = "Flow actions list", - .tokens = { - (void *) &cmd_fa_flow_ls_p_string, - (void *) &cmd_fa_flow_ls_pipeline_id, - (void *) &cmd_fa_flow_ls_flow_string, - (void *) &cmd_fa_flow_ls_actions_string, - (void *) &cmd_fa_flow_ls_ls_string, - NULL, - }, -}; + status = app_pipeline_fa_dscp_config(app, + params->pipeline_id, + dscp_id, + tc_id, + color); + if (status != 0) + printf(CMD_MSG_FAIL, "action dscp"); -/* - * Flow DiffServ Code Point (DSCP) translation table list - * - * p <pipeline ID> dscp ls - */ + return; + } /* action dscp */ + + /* action dscp ls */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "dscp") == 0) && + (strcmp(tokens[1], "ls") == 0)) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "action dscp ls"); + return; + } -struct cmd_fa_dscp_ls_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t dscp_string; - cmdline_fixed_string_t ls_string; -}; + status = app_pipeline_fa_dscp_ls(app, + params->pipeline_id); + if (status) + printf(CMD_MSG_FAIL, "action dscp ls"); -static void -cmd_fa_dscp_ls_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fa_dscp_ls_result *params = parsed_result; - struct app_params *app = data; - int status; + return; + } /* action dscp ls */ - status = app_pipeline_fa_dscp_ls(app, params->pipeline_id); - if (status != 0) - printf("Command failed\n"); + printf(CMD_MSG_FAIL, "action"); } -cmdline_parse_token_string_t cmd_fa_dscp_ls_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, - p_string, "p"); +static cmdline_parse_token_string_t cmd_action_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_action_result, p_string, "p"); -cmdline_parse_token_num_t cmd_fa_dscp_ls_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fa_dscp_ls_result, - pipeline_id, UINT32); +static cmdline_parse_token_num_t cmd_action_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_action_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_fa_dscp_ls_dscp_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, - dscp_string, "dscp"); +static cmdline_parse_token_string_t cmd_action_action_string = + TOKEN_STRING_INITIALIZER(struct cmd_action_result, action_string, "action"); -cmdline_parse_token_string_t cmd_fa_dscp_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_fa_dscp_ls_result, ls_string, - "ls"); +static cmdline_parse_token_string_t cmd_action_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_action_result, multi_string, + TOKEN_STRING_MULTI); -cmdline_parse_inst_t cmd_fa_dscp_ls = { - .f = cmd_fa_dscp_ls_parsed, +cmdline_parse_inst_t cmd_action = { + .f = cmd_action_parsed, .data = NULL, - .help_str = "Flow DSCP translaton table list", + .help_str = "flow actions (meter, policer, policer stats, dscp table)", .tokens = { - (void *) &cmd_fa_dscp_ls_p_string, - (void *) &cmd_fa_dscp_ls_pipeline_id, - (void *) &cmd_fa_dscp_ls_dscp_string, - (void *) &cmd_fa_dscp_ls_string, + (void *) &cmd_action_p_string, + (void *) &cmd_action_pipeline_id, + (void *) &cmd_action_action_string, + (void *) &cmd_action_multi_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *) &cmd_fa_meter_config, - (cmdline_parse_inst_t *) &cmd_fa_meter_config_bulk, - (cmdline_parse_inst_t *) &cmd_fa_policer_config, - (cmdline_parse_inst_t *) &cmd_fa_policer_config_bulk, - (cmdline_parse_inst_t *) &cmd_fa_output_port_config, - (cmdline_parse_inst_t *) &cmd_fa_output_port_config_bulk, - (cmdline_parse_inst_t *) &cmd_fa_dscp_config, - (cmdline_parse_inst_t *) &cmd_fa_policer_stats, - (cmdline_parse_inst_t *) &cmd_fa_flow_ls, - (cmdline_parse_inst_t *) &cmd_fa_dscp_ls, + (cmdline_parse_inst_t *) &cmd_action, NULL, }; static struct pipeline_fe_ops pipeline_flow_actions_fe_ops = { .f_init = app_pipeline_fa_init, + .f_post_init = NULL, .f_free = app_pipeline_fa_free, + .f_track = app_pipeline_track_default, .cmds = pipeline_cmds, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h index f2cd0cbb..9c609741 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions.h +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions.h @@ -73,6 +73,17 @@ app_pipeline_fa_flow_policer_stats_read(struct app_params *app, int clear, struct pipeline_fa_policer_stats *stats); +#ifndef APP_PIPELINE_FA_MAX_RECORDS_IN_FILE +#define APP_PIPELINE_FA_MAX_RECORDS_IN_FILE 65536 +#endif + +int +app_pipeline_fa_load_file(char *filename, + uint32_t *flow_ids, + struct pipeline_fa_flow_params *p, + uint32_t *n_flows, + uint32_t *line); + extern struct pipeline_type pipeline_flow_actions; #endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c index 3ad3ee63..11fcbb76 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c @@ -760,27 +760,6 @@ pipeline_fa_free(void *pipeline) } static int -pipeline_fa_track(void *pipeline, - __rte_unused uint32_t port_in, - uint32_t *port_out) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - if (p->n_ports_in == 1) { - *port_out = 0; - return 0; - } - - return -1; -} - -static int pipeline_fa_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; @@ -1007,5 +986,4 @@ struct pipeline_be_ops pipeline_flow_actions_be_ops = { .f_free = pipeline_fa_free, .f_run = NULL, .f_timer = pipeline_fa_timer, - .f_track = pipeline_fa_track, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c index 19215748..9ef50cc9 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.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 @@ -35,6 +35,7 @@ #include <string.h> #include <sys/queue.h> #include <netinet/in.h> +#include <unistd.h> #include <rte_common.h> #include <rte_hexdump.h> @@ -43,13 +44,12 @@ #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> -#include <cmdline_parse_ipaddr.h> -#include <cmdline_parse_etheraddr.h> #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_flow_classification.h" #include "hash_func.h" +#include "parser.h" /* * Key conversion @@ -96,9 +96,9 @@ app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in, struct pkt_key_qinq *qinq = key_buffer; qinq->ethertype_svlan = 0; - qinq->svlan = rte_bswap16(key_in->key.qinq.svlan); + qinq->svlan = rte_cpu_to_be_16(key_in->key.qinq.svlan); qinq->ethertype_cvlan = 0; - qinq->cvlan = rte_bswap16(key_in->key.qinq.cvlan); + qinq->cvlan = rte_cpu_to_be_16(key_in->key.qinq.cvlan); if (signature) *signature = (uint32_t) hash_default_key8(qinq, 8, 0); @@ -112,10 +112,10 @@ app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in, ipv4->ttl = 0; ipv4->proto = key_in->key.ipv4_5tuple.proto; ipv4->checksum = 0; - ipv4->ip_src = rte_bswap32(key_in->key.ipv4_5tuple.ip_src); - ipv4->ip_dst = rte_bswap32(key_in->key.ipv4_5tuple.ip_dst); - ipv4->port_src = rte_bswap16(key_in->key.ipv4_5tuple.port_src); - ipv4->port_dst = rte_bswap16(key_in->key.ipv4_5tuple.port_dst); + ipv4->ip_src = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_src); + ipv4->ip_dst = rte_cpu_to_be_32(key_in->key.ipv4_5tuple.ip_dst); + ipv4->port_src = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_src); + ipv4->port_dst = rte_cpu_to_be_16(key_in->key.ipv4_5tuple.port_dst); if (signature) *signature = (uint32_t) hash_default_key16(ipv4, 16, 0); @@ -132,8 +132,8 @@ app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in, ipv6->hop_limit = 0; memcpy(&ipv6->ip_src, &key_in->key.ipv6_5tuple.ip_src, 16); memcpy(&ipv6->ip_dst, &key_in->key.ipv6_5tuple.ip_dst, 16); - ipv6->port_src = rte_bswap16(key_in->key.ipv6_5tuple.port_src); - ipv6->port_dst = rte_bswap16(key_in->key.ipv6_5tuple.port_dst); + ipv6->port_src = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_src); + ipv6->port_dst = rte_cpu_to_be_16(key_in->key.ipv6_5tuple.port_dst); if (signature) *signature = (uint32_t) hash_default_key64(ipv6, 64, 0); @@ -278,6 +278,283 @@ app_pipeline_fc_key_check(struct pipeline_fc_key *key) } int +app_pipeline_fc_load_file_qinq(char *filename, + struct pipeline_fc_key *keys, + uint32_t *port_ids, + uint32_t *flow_ids, + uint32_t *n_keys, + uint32_t *line) +{ + FILE *f = NULL; + char file_buf[1024]; + uint32_t i, l; + + /* Check input arguments */ + if ((filename == NULL) || + (keys == NULL) || + (port_ids == NULL) || + (flow_ids == NULL) || + (n_keys == NULL) || + (*n_keys == 0) || + (line == NULL)) { + if (line) + *line = 0; + return -1; + } + + /* Open input file */ + f = fopen(filename, "r"); + if (f == NULL) { + *line = 0; + return -1; + } + + /* Read file */ + for (i = 0, l = 1; i < *n_keys; l++) { + char *tokens[32]; + uint32_t n_tokens = RTE_DIM(tokens); + + uint16_t svlan, cvlan; + uint32_t portid, flowid; + int status; + + if (fgets(file_buf, sizeof(file_buf), f) == NULL) + break; + + status = parse_tokenize_string(file_buf, tokens, &n_tokens); + if (status) + goto error1; + + if ((n_tokens == 0) || (tokens[0][0] == '#')) + continue; + + if ((n_tokens != 7) || + strcmp(tokens[0], "qinq") || + parser_read_uint16(&svlan, tokens[1]) || + parser_read_uint16(&cvlan, tokens[2]) || + strcmp(tokens[3], "port") || + parser_read_uint32(&portid, tokens[4]) || + strcmp(tokens[5], "id") || + parser_read_uint32(&flowid, tokens[6])) + goto error1; + + keys[i].type = FLOW_KEY_QINQ; + keys[i].key.qinq.svlan = svlan; + keys[i].key.qinq.cvlan = cvlan; + + port_ids[i] = portid; + flow_ids[i] = flowid; + + if (app_pipeline_fc_key_check(&keys[i])) + goto error1; + + i++; + } + + /* Close file */ + *n_keys = i; + fclose(f); + return 0; + +error1: + *line = l; + fclose(f); + return -1; +} + +int +app_pipeline_fc_load_file_ipv4(char *filename, + struct pipeline_fc_key *keys, + uint32_t *port_ids, + uint32_t *flow_ids, + uint32_t *n_keys, + uint32_t *line) +{ + FILE *f = NULL; + char file_buf[1024]; + uint32_t i, l; + + /* Check input arguments */ + if ((filename == NULL) || + (keys == NULL) || + (port_ids == NULL) || + (flow_ids == NULL) || + (n_keys == NULL) || + (*n_keys == 0) || + (line == NULL)) { + if (line) + *line = 0; + return -1; + } + + /* Open input file */ + f = fopen(filename, "r"); + if (f == NULL) { + *line = 0; + return -1; + } + + /* Read file */ + for (i = 0, l = 1; i < *n_keys; l++) { + char *tokens[32]; + uint32_t n_tokens = RTE_DIM(tokens); + + struct in_addr sipaddr, dipaddr; + uint16_t sport, dport; + uint8_t proto; + uint32_t portid, flowid; + int status; + + if (fgets(file_buf, sizeof(file_buf), f) == NULL) + break; + + status = parse_tokenize_string(file_buf, tokens, &n_tokens); + if (status) + goto error2; + + if ((n_tokens == 0) || (tokens[0][0] == '#')) + continue; + + if ((n_tokens != 10) || + strcmp(tokens[0], "ipv4") || + parse_ipv4_addr(tokens[1], &sipaddr) || + parse_ipv4_addr(tokens[2], &dipaddr) || + parser_read_uint16(&sport, tokens[3]) || + parser_read_uint16(&dport, tokens[4]) || + parser_read_uint8(&proto, tokens[5]) || + strcmp(tokens[6], "port") || + parser_read_uint32(&portid, tokens[7]) || + strcmp(tokens[8], "id") || + parser_read_uint32(&flowid, tokens[9])) + goto error2; + + keys[i].type = FLOW_KEY_IPV4_5TUPLE; + keys[i].key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr); + keys[i].key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr); + keys[i].key.ipv4_5tuple.port_src = sport; + keys[i].key.ipv4_5tuple.port_dst = dport; + keys[i].key.ipv4_5tuple.proto = proto; + + port_ids[i] = portid; + flow_ids[i] = flowid; + + if (app_pipeline_fc_key_check(&keys[i])) + goto error2; + + i++; + } + + /* Close file */ + *n_keys = i; + fclose(f); + return 0; + +error2: + *line = l; + fclose(f); + return -1; +} + +int +app_pipeline_fc_load_file_ipv6(char *filename, + struct pipeline_fc_key *keys, + uint32_t *port_ids, + uint32_t *flow_ids, + uint32_t *n_keys, + uint32_t *line) +{ + FILE *f = NULL; + char file_buf[1024]; + uint32_t i, l; + + /* Check input arguments */ + if ((filename == NULL) || + (keys == NULL) || + (port_ids == NULL) || + (flow_ids == NULL) || + (n_keys == NULL) || + (*n_keys == 0) || + (line == NULL)) { + if (line) + *line = 0; + return -1; + } + + /* Open input file */ + f = fopen(filename, "r"); + if (f == NULL) { + *line = 0; + return -1; + } + + /* Read file */ + for (i = 0, l = 1; i < *n_keys; l++) { + char *tokens[32]; + uint32_t n_tokens = RTE_DIM(tokens); + + struct in6_addr sipaddr, dipaddr; + uint16_t sport, dport; + uint8_t proto; + uint32_t portid, flowid; + int status; + + if (fgets(file_buf, sizeof(file_buf), f) == NULL) + break; + + status = parse_tokenize_string(file_buf, tokens, &n_tokens); + if (status) + goto error3; + + if ((n_tokens == 0) || (tokens[0][0] == '#')) + continue; + + if ((n_tokens != 10) || + strcmp(tokens[0], "ipv6") || + parse_ipv6_addr(tokens[1], &sipaddr) || + parse_ipv6_addr(tokens[2], &dipaddr) || + parser_read_uint16(&sport, tokens[3]) || + parser_read_uint16(&dport, tokens[4]) || + parser_read_uint8(&proto, tokens[5]) || + strcmp(tokens[6], "port") || + parser_read_uint32(&portid, tokens[7]) || + strcmp(tokens[8], "id") || + parser_read_uint32(&flowid, tokens[9])) + goto error3; + + keys[i].type = FLOW_KEY_IPV6_5TUPLE; + memcpy(keys[i].key.ipv6_5tuple.ip_src, + sipaddr.s6_addr, + sizeof(sipaddr.s6_addr)); + memcpy(keys[i].key.ipv6_5tuple.ip_dst, + dipaddr.s6_addr, + sizeof(dipaddr.s6_addr)); + keys[i].key.ipv6_5tuple.port_src = sport; + keys[i].key.ipv6_5tuple.port_dst = dport; + keys[i].key.ipv6_5tuple.proto = proto; + + port_ids[i] = portid; + flow_ids[i] = flowid; + + if (app_pipeline_fc_key_check(&keys[i])) + goto error3; + + i++; + } + + /* Close file */ + *n_keys = i; + fclose(f); + return 0; + +error3: + *line = l; + fclose(f); + return -1; +} + + + +int app_pipeline_fc_add(struct app_params *app, uint32_t pipeline_id, struct pipeline_fc_key *key, @@ -896,1315 +1173,728 @@ app_pipeline_fc_ls(struct app_params *app, return 0; } - /* - * flow add qinq - */ - -struct cmd_fc_add_qinq_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t qinq_string; - uint16_t svlan; - uint16_t cvlan; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t flowid_string; - uint32_t flow_id; -}; - -static void -cmd_fc_add_qinq_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_add_qinq_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key key; - int status; - - memset(&key, 0, sizeof(key)); - key.type = FLOW_KEY_QINQ; - key.key.qinq.svlan = params->svlan; - key.key.qinq.cvlan = params->cvlan; - - status = app_pipeline_fc_add(app, - params->pipeline_id, - &key, - params->port, - params->flow_id); - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fc_add_qinq_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, p_string, "p"); - -cmdline_parse_token_num_t cmd_fc_add_qinq_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, pipeline_id, - UINT32); - -cmdline_parse_token_string_t cmd_fc_add_qinq_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flow_string, - "flow"); - -cmdline_parse_token_string_t cmd_fc_add_qinq_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string, - "add"); - -cmdline_parse_token_string_t cmd_fc_add_qinq_qinq_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, qinq_string, - "qinq"); - -cmdline_parse_token_num_t cmd_fc_add_qinq_svlan = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, svlan, UINT16); - -cmdline_parse_token_num_t cmd_fc_add_qinq_cvlan = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, cvlan, UINT16); - -cmdline_parse_token_string_t cmd_fc_add_qinq_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, port_string, - "port"); - -cmdline_parse_token_num_t cmd_fc_add_qinq_port = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT32); - -cmdline_parse_token_string_t cmd_fc_add_qinq_flowid_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flowid_string, - "flowid"); - -cmdline_parse_token_num_t cmd_fc_add_qinq_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, flow_id, UINT32); - -cmdline_parse_inst_t cmd_fc_add_qinq = { - .f = cmd_fc_add_qinq_parsed, - .data = NULL, - .help_str = "Flow add (Q-in-Q)", - .tokens = { - (void *) &cmd_fc_add_qinq_p_string, - (void *) &cmd_fc_add_qinq_pipeline_id, - (void *) &cmd_fc_add_qinq_flow_string, - (void *) &cmd_fc_add_qinq_add_string, - (void *) &cmd_fc_add_qinq_qinq_string, - (void *) &cmd_fc_add_qinq_svlan, - (void *) &cmd_fc_add_qinq_cvlan, - (void *) &cmd_fc_add_qinq_port_string, - (void *) &cmd_fc_add_qinq_port, - (void *) &cmd_fc_add_qinq_flowid_string, - (void *) &cmd_fc_add_qinq_flow_id, - NULL, - }, -}; - -/* - * flow add qinq all + * flow + * + * flow add: + * p <pipelineid> flow add qinq <svlan> <cvlan> port <portid> id <flowid> + * p <pipelineid> flow add qinq bulk <file> + * p <pipelineid> flow add ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid> + * p <pipelineid> flow add ipv4 bulk <file> + * p <pipelineid> flow add ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto> port <port ID> id <flowid> + * p <pipelineid> flow add ipv6 bulk <file> + * + * flow add default: + * p <pipelineid> flow add default <portid> + * + * flow del: + * p <pipelineid> flow del qinq <svlan> <cvlan> + * p <pipelineid> flow del ipv4 <sipaddr> <dipaddr> <sport> <dport> <proto> + * p <pipelineid> flow del ipv6 <sipaddr> <dipaddr> <sport> <dport> <proto> + * + * flow del default: + * p <pipelineid> flow del default + * + * flow ls: + * p <pipelineid> flow ls */ -struct cmd_fc_add_qinq_all_result { +struct cmd_flow_result { cmdline_fixed_string_t p_string; uint32_t pipeline_id; cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t qinq_string; - cmdline_fixed_string_t all_string; - uint32_t n_flows; - uint32_t n_ports; + cmdline_multi_string_t multi_string; }; -#ifndef N_FLOWS_BULK -#define N_FLOWS_BULK 4096 -#endif - static void -cmd_fc_add_qinq_all_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, +cmd_flow_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, void *data) { - struct cmd_fc_add_qinq_all_result *params = parsed_result; + struct cmd_flow_result *results = parsed_result; struct app_params *app = data; - struct pipeline_fc_key *key; - uint32_t *port_id; - uint32_t *flow_id; - uint32_t id; - - /* Check input arguments */ - if (params->n_flows == 0) { - printf("Invalid number of flows\n"); - return; - } - if (params->n_ports == 0) { - printf("Invalid number of output ports\n"); - return; - } - - /* Memory allocation */ - key = rte_zmalloc(NULL, - N_FLOWS_BULK * sizeof(*key), - RTE_CACHE_LINE_SIZE); - if (key == NULL) { - printf("Memory allocation failed\n"); - return; - } - - port_id = rte_malloc(NULL, - N_FLOWS_BULK * sizeof(*port_id), - RTE_CACHE_LINE_SIZE); - if (port_id == NULL) { - rte_free(key); - printf("Memory allocation failed\n"); - return; - } + char *tokens[16]; + uint32_t n_tokens = RTE_DIM(tokens); + int status; - flow_id = rte_malloc(NULL, - N_FLOWS_BULK * sizeof(*flow_id), - RTE_CACHE_LINE_SIZE); - if (flow_id == NULL) { - rte_free(port_id); - rte_free(key); - printf("Memory allocation failed\n"); + status = parse_tokenize_string(results->multi_string, tokens, &n_tokens); + if (status) { + printf(CMD_MSG_TOO_MANY_ARGS, "flow"); return; } - /* Flow add */ - for (id = 0; id < params->n_flows; id++) { - uint32_t pos = id & (N_FLOWS_BULK - 1); - - key[pos].type = FLOW_KEY_QINQ; - key[pos].key.qinq.svlan = id >> 12; - key[pos].key.qinq.cvlan = id & 0xFFF; - - port_id[pos] = id % params->n_ports; - flow_id[pos] = id; - - if ((pos == N_FLOWS_BULK - 1) || - (id == params->n_flows - 1)) { - int status; - - status = app_pipeline_fc_add_bulk(app, - params->pipeline_id, - key, - port_id, - flow_id, - pos + 1); - - if (status != 0) { - printf("Command failed\n"); - - break; - } + /* flow add qinq */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "qinq") == 0) && + strcmp(tokens[2], "bulk")) { + struct pipeline_fc_key key; + uint32_t svlan; + uint32_t cvlan; + uint32_t port_id; + uint32_t flow_id; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 8) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq"); + return; } - } - - /* Memory free */ - rte_free(flow_id); - rte_free(port_id); - rte_free(key); -} -cmdline_parse_token_string_t cmd_fc_add_qinq_all_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, p_string, - "p"); + if (parser_read_uint32(&svlan, tokens[2]) != 0) { + printf(CMD_MSG_INVALID_ARG, "svlan"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_qinq_all_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, pipeline_id, - UINT32); + if (parser_read_uint32(&cvlan, tokens[3]) != 0) { + printf(CMD_MSG_INVALID_ARG, "cvlan"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_qinq_all_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, flow_string, - "flow"); + if (strcmp(tokens[4], "port") != 0) { + printf(CMD_MSG_ARG_NOT_FOUND, "port"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_qinq_all_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, add_string, - "add"); + if (parser_read_uint32(&port_id, tokens[5]) != 0) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_qinq_all_qinq_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, qinq_string, - "qinq"); + if (strcmp(tokens[6], "id") != 0) { + printf(CMD_MSG_ARG_NOT_FOUND, "id"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_qinq_all_all_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, all_string, - "all"); + if (parser_read_uint32(&flow_id, tokens[7]) != 0) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_flows = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_flows, - UINT32); + key.type = FLOW_KEY_QINQ; + key.key.qinq.svlan = svlan; + key.key.qinq.cvlan = cvlan; -cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_ports = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_ports, - UINT32); + status = app_pipeline_fc_add(app, + results->pipeline_id, + &key, + port_id, + flow_id); + if (status) + printf(CMD_MSG_FAIL, "flow add qinq"); -cmdline_parse_inst_t cmd_fc_add_qinq_all = { - .f = cmd_fc_add_qinq_all_parsed, - .data = NULL, - .help_str = "Flow add all (Q-in-Q)", - .tokens = { - (void *) &cmd_fc_add_qinq_all_p_string, - (void *) &cmd_fc_add_qinq_all_pipeline_id, - (void *) &cmd_fc_add_qinq_all_flow_string, - (void *) &cmd_fc_add_qinq_all_add_string, - (void *) &cmd_fc_add_qinq_all_qinq_string, - (void *) &cmd_fc_add_qinq_all_all_string, - (void *) &cmd_fc_add_qinq_all_n_flows, - (void *) &cmd_fc_add_qinq_all_n_ports, - NULL, - }, -}; + return; + } /* flow add qinq */ + + /* flow add ipv4 */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "ipv4") == 0) && + strcmp(tokens[2], "bulk")) { + struct pipeline_fc_key key; + struct in_addr sipaddr; + struct in_addr dipaddr; + uint32_t sport; + uint32_t dport; + uint32_t proto; + uint32_t port_id; + uint32_t flow_id; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 11) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4"); + return; + } -/* - * flow add ipv4_5tuple - */ + if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "sipv4addr"); + return; + } + if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "dipv4addr"); + return; + } -struct cmd_fc_add_ipv4_5tuple_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t ipv4_5tuple_string; - cmdline_ipaddr_t ip_src; - cmdline_ipaddr_t ip_dst; - uint16_t port_src; - uint16_t port_dst; - uint32_t proto; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t flowid_string; - uint32_t flow_id; -}; + if (parser_read_uint32(&sport, tokens[4]) != 0) { + printf(CMD_MSG_INVALID_ARG, "sport"); + return; + } -static void -cmd_fc_add_ipv4_5tuple_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_add_ipv4_5tuple_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key key; - int status; + if (parser_read_uint32(&dport, tokens[5]) != 0) { + printf(CMD_MSG_INVALID_ARG, "dport"); + return; + } - memset(&key, 0, sizeof(key)); - key.type = FLOW_KEY_IPV4_5TUPLE; - key.key.ipv4_5tuple.ip_src = rte_bswap32( - params->ip_src.addr.ipv4.s_addr); - key.key.ipv4_5tuple.ip_dst = rte_bswap32( - params->ip_dst.addr.ipv4.s_addr); - key.key.ipv4_5tuple.port_src = params->port_src; - key.key.ipv4_5tuple.port_dst = params->port_dst; - key.key.ipv4_5tuple.proto = params->proto; - - status = app_pipeline_fc_add(app, - params->pipeline_id, - &key, - params->port, - params->flow_id); - if (status != 0) - printf("Command failed\n"); -} + if (parser_read_uint32(&proto, tokens[6]) != 0) { + printf(CMD_MSG_INVALID_ARG, "proto"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, p_string, - "p"); + if (strcmp(tokens[7], "port") != 0) { + printf(CMD_MSG_ARG_NOT_FOUND, "port"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, pipeline_id, - UINT32); + if (parser_read_uint32(&port_id, tokens[8]) != 0) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, - flow_string, "flow"); + if (strcmp(tokens[9], "id") != 0) { + printf(CMD_MSG_ARG_NOT_FOUND, "id"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, - add_string, "add"); + if (parser_read_uint32(&flow_id, tokens[10]) != 0) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, - ipv4_5tuple_string, "ipv4_5tuple"); + key.type = FLOW_KEY_IPV4_5TUPLE; + key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr); + key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr); + key.key.ipv4_5tuple.port_src = sport; + key.key.ipv4_5tuple.port_dst = dport; + key.key.ipv4_5tuple.proto = proto; + + status = app_pipeline_fc_add(app, + results->pipeline_id, + &key, + port_id, + flow_id); + if (status) + printf(CMD_MSG_FAIL, "flow add ipv4"); -cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src = - TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src); + return; + } /* flow add ipv4 */ + + /* flow add ipv6 */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "ipv6") == 0) && + strcmp(tokens[2], "bulk")) { + struct pipeline_fc_key key; + struct in6_addr sipaddr; + struct in6_addr dipaddr; + uint32_t sport; + uint32_t dport; + uint32_t proto; + uint32_t port_id; + uint32_t flow_id; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 11) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6"); + return; + } -cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst = - TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst); + if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "sipv6addr"); + return; + } + if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "dipv6addr"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_src = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_src, - UINT16); + if (parser_read_uint32(&sport, tokens[4]) != 0) { + printf(CMD_MSG_INVALID_ARG, "sport"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_dst = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_dst, - UINT16); + if (parser_read_uint32(&dport, tokens[5]) != 0) { + printf(CMD_MSG_INVALID_ARG, "dport"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto, - UINT32); + if (parser_read_uint32(&proto, tokens[6]) != 0) { + printf(CMD_MSG_INVALID_ARG, "proto"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_string, - "port"); + if (strcmp(tokens[7], "port") != 0) { + printf(CMD_MSG_ARG_NOT_FOUND, "port"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port, - UINT32); + if (parser_read_uint32(&port_id, tokens[8]) != 0) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flowid_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, - flowid_string, "flowid"); + if (strcmp(tokens[9], "id") != 0) { + printf(CMD_MSG_ARG_NOT_FOUND, "id"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_id, - UINT32); + if (parser_read_uint32(&flow_id, tokens[10]) != 0) { + printf(CMD_MSG_INVALID_ARG, "flowid"); + return; + } -cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple = { - .f = cmd_fc_add_ipv4_5tuple_parsed, - .data = NULL, - .help_str = "Flow add (IPv4 5-tuple)", - .tokens = { - (void *) &cmd_fc_add_ipv4_5tuple_p_string, - (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id, - (void *) &cmd_fc_add_ipv4_5tuple_flow_string, - (void *) &cmd_fc_add_ipv4_5tuple_add_string, - (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string, - (void *) &cmd_fc_add_ipv4_5tuple_ip_src, - (void *) &cmd_fc_add_ipv4_5tuple_ip_dst, - (void *) &cmd_fc_add_ipv4_5tuple_port_src, - (void *) &cmd_fc_add_ipv4_5tuple_port_dst, - (void *) &cmd_fc_add_ipv4_5tuple_proto, - (void *) &cmd_fc_add_ipv4_5tuple_port_string, - (void *) &cmd_fc_add_ipv4_5tuple_port, - (void *) &cmd_fc_add_ipv4_5tuple_flowid_string, - (void *) &cmd_fc_add_ipv4_5tuple_flow_id, - NULL, - }, -}; + key.type = FLOW_KEY_IPV6_5TUPLE; + memcpy(key.key.ipv6_5tuple.ip_src, (void *)&sipaddr, 16); + memcpy(key.key.ipv6_5tuple.ip_dst, (void *)&dipaddr, 16); + key.key.ipv6_5tuple.port_src = sport; + key.key.ipv6_5tuple.port_dst = dport; + key.key.ipv6_5tuple.proto = proto; + + status = app_pipeline_fc_add(app, + results->pipeline_id, + &key, + port_id, + flow_id); + if (status) + printf(CMD_MSG_FAIL, "flow add ipv6"); -/* - * flow add ipv4_5tuple all - */ + return; + } /* flow add ipv6 */ + + /* flow add qinq bulk */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "qinq") == 0) && + (strcmp(tokens[2], "bulk") == 0)) { + struct pipeline_fc_key *keys; + uint32_t *port_ids, *flow_ids, n_keys, line; + char *filename; + + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add qinq bulk"); + return; + } -struct cmd_fc_add_ipv4_5tuple_all_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t ipv4_5tuple_string; - cmdline_fixed_string_t all_string; - uint32_t n_flows; - uint32_t n_ports; -}; + filename = tokens[3]; -static void -cmd_fc_add_ipv4_5tuple_all_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_add_ipv4_5tuple_all_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key *key; - uint32_t *port_id; - uint32_t *flow_id; - uint32_t id; - - /* Check input parameters */ - if (params->n_flows == 0) { - printf("Invalid number of flows\n"); - return; - } + n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE; + keys = malloc(n_keys * sizeof(struct pipeline_fc_key)); + if (keys == NULL) + return; + memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key)); - if (params->n_ports == 0) { - printf("Invalid number of ports\n"); - return; - } + port_ids = malloc(n_keys * sizeof(uint32_t)); + if (port_ids == NULL) { + free(keys); + return; + } - /* Memory allocation */ - key = rte_zmalloc(NULL, - N_FLOWS_BULK * sizeof(*key), - RTE_CACHE_LINE_SIZE); - if (key == NULL) { - printf("Memory allocation failed\n"); - return; - } + flow_ids = malloc(n_keys * sizeof(uint32_t)); + if (flow_ids == NULL) { + free(port_ids); + free(keys); + return; + } - port_id = rte_malloc(NULL, - N_FLOWS_BULK * sizeof(*port_id), - RTE_CACHE_LINE_SIZE); - if (port_id == NULL) { - rte_free(key); - printf("Memory allocation failed\n"); - return; - } + status = app_pipeline_fc_load_file_qinq(filename, + keys, + port_ids, + flow_ids, + &n_keys, + &line); + if (status != 0) { + printf(CMD_MSG_FILE_ERR, filename, line); + free(flow_ids); + free(port_ids); + free(keys); + return; + } - flow_id = rte_malloc(NULL, - N_FLOWS_BULK * sizeof(*flow_id), - RTE_CACHE_LINE_SIZE); - if (flow_id == NULL) { - rte_free(port_id); - rte_free(key); - printf("Memory allocation failed\n"); + status = app_pipeline_fc_add_bulk(app, + results->pipeline_id, + keys, + port_ids, + flow_ids, + n_keys); + if (status) + printf(CMD_MSG_FAIL, "flow add qinq bulk"); + + free(flow_ids); + free(port_ids); + free(keys); return; - } - - /* Flow add */ - for (id = 0; id < params->n_flows; id++) { - uint32_t pos = id & (N_FLOWS_BULK - 1); + } /* flow add qinq bulk */ + + /* flow add ipv4 bulk */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "ipv4") == 0) && + (strcmp(tokens[2], "bulk") == 0)) { + struct pipeline_fc_key *keys; + uint32_t *port_ids, *flow_ids, n_keys, line; + char *filename; + + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv4 bulk"); + return; + } - key[pos].type = FLOW_KEY_IPV4_5TUPLE; - key[pos].key.ipv4_5tuple.ip_src = 0; - key[pos].key.ipv4_5tuple.ip_dst = id; - key[pos].key.ipv4_5tuple.port_src = 0; - key[pos].key.ipv4_5tuple.port_dst = 0; - key[pos].key.ipv4_5tuple.proto = 6; + filename = tokens[3]; - port_id[pos] = id % params->n_ports; - flow_id[pos] = id; + n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE; + keys = malloc(n_keys * sizeof(struct pipeline_fc_key)); + if (keys == NULL) + return; + memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key)); - if ((pos == N_FLOWS_BULK - 1) || - (id == params->n_flows - 1)) { - int status; + port_ids = malloc(n_keys * sizeof(uint32_t)); + if (port_ids == NULL) { + free(keys); + return; + } - status = app_pipeline_fc_add_bulk(app, - params->pipeline_id, - key, - port_id, - flow_id, - pos + 1); + flow_ids = malloc(n_keys * sizeof(uint32_t)); + if (flow_ids == NULL) { + free(port_ids); + free(keys); + return; + } - if (status != 0) { - printf("Command failed\n"); + status = app_pipeline_fc_load_file_ipv4(filename, + keys, + port_ids, + flow_ids, + &n_keys, + &line); + if (status != 0) { + printf(CMD_MSG_FILE_ERR, filename, line); + free(flow_ids); + free(port_ids); + free(keys); + return; + } - break; - } + status = app_pipeline_fc_add_bulk(app, + results->pipeline_id, + keys, + port_ids, + flow_ids, + n_keys); + if (status) + printf(CMD_MSG_FAIL, "flow add ipv4 bulk"); + + free(flow_ids); + free(port_ids); + free(keys); + return; + } /* flow add ipv4 bulk */ + + /* flow add ipv6 bulk */ + if ((n_tokens >= 3) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "ipv6") == 0) && + (strcmp(tokens[2], "bulk") == 0)) { + struct pipeline_fc_key *keys; + uint32_t *port_ids, *flow_ids, n_keys, line; + char *filename; + + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add ipv6 bulk"); + return; } - } - /* Memory free */ - rte_free(flow_id); - rte_free(port_id); - rte_free(key); -} + filename = tokens[3]; -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - p_string, "p"); + n_keys = APP_PIPELINE_FC_MAX_FLOWS_IN_FILE; + keys = malloc(n_keys * sizeof(struct pipeline_fc_key)); + if (keys == NULL) + return; + memset(keys, 0, n_keys * sizeof(struct pipeline_fc_key)); -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - pipeline_id, UINT32); + port_ids = malloc(n_keys * sizeof(uint32_t)); + if (port_ids == NULL) { + free(keys); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - flow_string, "flow"); + flow_ids = malloc(n_keys * sizeof(uint32_t)); + if (flow_ids == NULL) { + free(port_ids); + free(keys); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - add_string, "add"); + status = app_pipeline_fc_load_file_ipv6(filename, + keys, + port_ids, + flow_ids, + &n_keys, + &line); + if (status != 0) { + printf(CMD_MSG_FILE_ERR, filename, line); + free(flow_ids); + free(port_ids); + free(keys); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - ipv4_5tuple_string, "ipv4_5tuple"); + status = app_pipeline_fc_add_bulk(app, + results->pipeline_id, + keys, + port_ids, + flow_ids, + n_keys); + if (status) + printf(CMD_MSG_FAIL, "flow add ipv6 bulk"); + + free(flow_ids); + free(port_ids); + free(keys); + return; + } /* flow add ipv6 bulk */ -cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_all_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - all_string, "all"); + /* flow add default*/ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "default") == 0)) { + uint32_t port_id; -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_flows = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - n_flows, UINT32); + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "flow add default"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_ports = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result, - n_ports, UINT32); + if (parser_read_uint32(&port_id, tokens[2]) != 0) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple_all = { - .f = cmd_fc_add_ipv4_5tuple_all_parsed, - .data = NULL, - .help_str = "Flow add all (IPv4 5-tuple)", - .tokens = { - (void *) &cmd_fc_add_ipv4_5tuple_all_p_string, - (void *) &cmd_fc_add_ipv4_5tuple_all_pipeline_id, - (void *) &cmd_fc_add_ipv4_5tuple_all_flow_string, - (void *) &cmd_fc_add_ipv4_5tuple_all_add_string, - (void *) &cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string, - (void *) &cmd_fc_add_ipv4_5tuple_all_all_string, - (void *) &cmd_fc_add_ipv4_5tuple_all_n_flows, - (void *) &cmd_fc_add_ipv4_5tuple_all_n_ports, - NULL, - }, -}; + status = app_pipeline_fc_add_default(app, + results->pipeline_id, + port_id); + if (status) + printf(CMD_MSG_FAIL, "flow add default"); -/* - * flow add ipv6_5tuple - */ + return; + } /* flow add default */ -struct cmd_fc_add_ipv6_5tuple_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t ipv6_5tuple_string; - cmdline_ipaddr_t ip_src; - cmdline_ipaddr_t ip_dst; - uint16_t port_src; - uint16_t port_dst; - uint32_t proto; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t flowid_string; - uint32_t flow_id; -}; + /* flow del qinq */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "qinq") == 0)) { + struct pipeline_fc_key key; + uint32_t svlan; + uint32_t cvlan; -static void -cmd_fc_add_ipv6_5tuple_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_add_ipv6_5tuple_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key key; - int status; + memset(&key, 0, sizeof(key)); - memset(&key, 0, sizeof(key)); - key.type = FLOW_KEY_IPV6_5TUPLE; - memcpy(key.key.ipv6_5tuple.ip_src, - params->ip_src.addr.ipv6.s6_addr, - 16); - memcpy(key.key.ipv6_5tuple.ip_dst, - params->ip_dst.addr.ipv6.s6_addr, - 16); - key.key.ipv6_5tuple.port_src = params->port_src; - key.key.ipv6_5tuple.port_dst = params->port_dst; - key.key.ipv6_5tuple.proto = params->proto; - - status = app_pipeline_fc_add(app, - params->pipeline_id, - &key, - params->port, - params->flow_id); - if (status != 0) - printf("Command failed\n"); -} + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "flow del qinq"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, - p_string, "p"); + if (parser_read_uint32(&svlan, tokens[2]) != 0) { + printf(CMD_MSG_INVALID_ARG, "svlan"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, pipeline_id, - UINT32); + if (parser_read_uint32(&cvlan, tokens[3]) != 0) { + printf(CMD_MSG_INVALID_ARG, "cvlan"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, - flow_string, "flow"); + key.type = FLOW_KEY_QINQ; + key.key.qinq.svlan = svlan; + key.key.qinq.cvlan = cvlan; -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, - add_string, "add"); + status = app_pipeline_fc_del(app, + results->pipeline_id, + &key); + if (status) + printf(CMD_MSG_FAIL, "flow del qinq"); -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, - ipv6_5tuple_string, "ipv6_5tuple"); + return; + } /* flow del qinq */ + + /* flow del ipv4 */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "ipv4") == 0)) { + struct pipeline_fc_key key; + struct in_addr sipaddr; + struct in_addr dipaddr; + uint32_t sport; + uint32_t dport; + uint32_t proto; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 7) { + printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv4"); + return; + } -cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src = - TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src); + if (parse_ipv4_addr(tokens[2], &sipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "sipv4addr"); + return; + } + if (parse_ipv4_addr(tokens[3], &dipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "dipv4addr"); + return; + } -cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst = - TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst); + if (parser_read_uint32(&sport, tokens[4]) != 0) { + printf(CMD_MSG_INVALID_ARG, "sport"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_src = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_src, - UINT16); + if (parser_read_uint32(&dport, tokens[5]) != 0) { + printf(CMD_MSG_INVALID_ARG, "dport"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_dst = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_dst, - UINT16); + if (parser_read_uint32(&proto, tokens[6]) != 0) { + printf(CMD_MSG_INVALID_ARG, "proto"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto, - UINT32); + key.type = FLOW_KEY_IPV4_5TUPLE; + key.key.ipv4_5tuple.ip_src = rte_be_to_cpu_32(sipaddr.s_addr); + key.key.ipv4_5tuple.ip_dst = rte_be_to_cpu_32(dipaddr.s_addr); + key.key.ipv4_5tuple.port_src = sport; + key.key.ipv4_5tuple.port_dst = dport; + key.key.ipv4_5tuple.proto = proto; -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, - port_string, "port"); + status = app_pipeline_fc_del(app, + results->pipeline_id, + &key); + if (status) + printf(CMD_MSG_FAIL, "flow del ipv4"); -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port, - UINT32); + return; + } /* flow del ipv4 */ + + /* flow del ipv6 */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "ipv6") == 0)) { + struct pipeline_fc_key key; + struct in6_addr sipaddr; + struct in6_addr dipaddr; + uint32_t sport; + uint32_t dport; + uint32_t proto; + + memset(&key, 0, sizeof(key)); + + if (n_tokens != 7) { + printf(CMD_MSG_MISMATCH_ARGS, "flow del ipv6"); + return; + } -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flowid_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, - flowid_string, "flowid"); + if (parse_ipv6_addr(tokens[2], &sipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "sipv6addr"); + return; + } -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_flow_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_id, - UINT32); + if (parse_ipv6_addr(tokens[3], &dipaddr) != 0) { + printf(CMD_MSG_INVALID_ARG, "dipv6addr"); + return; + } -cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple = { - .f = cmd_fc_add_ipv6_5tuple_parsed, - .data = NULL, - .help_str = "Flow add (IPv6 5-tuple)", - .tokens = { - (void *) &cmd_fc_add_ipv6_5tuple_p_string, - (void *) &cmd_fc_add_ipv6_5tuple_pipeline_id, - (void *) &cmd_fc_add_ipv6_5tuple_flow_string, - (void *) &cmd_fc_add_ipv6_5tuple_add_string, - (void *) &cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string, - (void *) &cmd_fc_add_ipv6_5tuple_ip_src, - (void *) &cmd_fc_add_ipv6_5tuple_ip_dst, - (void *) &cmd_fc_add_ipv6_5tuple_port_src, - (void *) &cmd_fc_add_ipv6_5tuple_port_dst, - (void *) &cmd_fc_add_ipv6_5tuple_proto, - (void *) &cmd_fc_add_ipv6_5tuple_port_string, - (void *) &cmd_fc_add_ipv6_5tuple_port, - (void *) &cmd_fc_add_ipv6_5tuple_flowid_string, - (void *) &cmd_fc_add_ipv6_5tuple_flow_id, - NULL, - }, -}; + if (parser_read_uint32(&sport, tokens[4]) != 0) { + printf(CMD_MSG_INVALID_ARG, "sport"); + return; + } -/* - * flow add ipv6_5tuple all - */ + if (parser_read_uint32(&dport, tokens[5]) != 0) { + printf(CMD_MSG_INVALID_ARG, "dport"); + return; + } -struct cmd_fc_add_ipv6_5tuple_all_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t ipv6_5tuple_string; - cmdline_fixed_string_t all_string; - uint32_t n_flows; - uint32_t n_ports; -}; + if (parser_read_uint32(&proto, tokens[6]) != 0) { + printf(CMD_MSG_INVALID_ARG, "proto"); + return; + } -static void -cmd_fc_add_ipv6_5tuple_all_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_add_ipv6_5tuple_all_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key *key; - uint32_t *port_id; - uint32_t *flow_id; - uint32_t id; - - /* Check input parameters */ - if (params->n_flows == 0) { - printf("Invalid number of flows\n"); - return; - } + key.type = FLOW_KEY_IPV6_5TUPLE; + memcpy(key.key.ipv6_5tuple.ip_src, &sipaddr, 16); + memcpy(key.key.ipv6_5tuple.ip_dst, &dipaddr, 16); + key.key.ipv6_5tuple.port_src = sport; + key.key.ipv6_5tuple.port_dst = dport; + key.key.ipv6_5tuple.proto = proto; - if (params->n_ports == 0) { - printf("Invalid number of ports\n"); - return; - } + status = app_pipeline_fc_del(app, + results->pipeline_id, + &key); + if (status) + printf(CMD_MSG_FAIL, "flow del ipv6"); - /* Memory allocation */ - key = rte_zmalloc(NULL, - N_FLOWS_BULK * sizeof(*key), - RTE_CACHE_LINE_SIZE); - if (key == NULL) { - printf("Memory allocation failed\n"); return; - } + } /* flow del ipv6 */ + + /* flow del default*/ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "default") == 0)) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "flow del default"); + return; + } - port_id = rte_malloc(NULL, - N_FLOWS_BULK * sizeof(*port_id), - RTE_CACHE_LINE_SIZE); - if (port_id == NULL) { - rte_free(key); - printf("Memory allocation failed\n"); - return; - } + status = app_pipeline_fc_del_default(app, + results->pipeline_id); + if (status) + printf(CMD_MSG_FAIL, "flow del default"); - flow_id = rte_malloc(NULL, - N_FLOWS_BULK * sizeof(*flow_id), - RTE_CACHE_LINE_SIZE); - if (flow_id == NULL) { - rte_free(port_id); - rte_free(key); - printf("Memory allocation failed\n"); return; - } - - /* Flow add */ - for (id = 0; id < params->n_flows; id++) { - uint32_t pos = id & (N_FLOWS_BULK - 1); - uint32_t *x; - - key[pos].type = FLOW_KEY_IPV6_5TUPLE; - x = (uint32_t *) key[pos].key.ipv6_5tuple.ip_dst; - *x = rte_bswap32(id); - key[pos].key.ipv6_5tuple.proto = 6; - - port_id[pos] = id % params->n_ports; - flow_id[pos] = id; + } /* flow del default */ - if ((pos == N_FLOWS_BULK - 1) || - (id == params->n_flows - 1)) { - int status; - - status = app_pipeline_fc_add_bulk(app, - params->pipeline_id, - key, - port_id, - flow_id, - pos + 1); - - if (status != 0) { - printf("Command failed\n"); - - break; - } + /* flow ls */ + if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { + if (n_tokens != 1) { + printf(CMD_MSG_MISMATCH_ARGS, "flow ls"); + return; } - } - - /* Memory free */ - rte_free(flow_id); - rte_free(port_id); - rte_free(key); -} - -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - flow_string, "flow"); - -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - add_string, "add"); - -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - ipv6_5tuple_string, "ipv6_5tuple"); - -cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_all_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - all_string, "all"); - -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_flows = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - n_flows, UINT32); - -cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_ports = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result, - n_ports, UINT32); - -cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple_all = { - .f = cmd_fc_add_ipv6_5tuple_all_parsed, - .data = NULL, - .help_str = "Flow add all (ipv6 5-tuple)", - .tokens = { - (void *) &cmd_fc_add_ipv6_5tuple_all_p_string, - (void *) &cmd_fc_add_ipv6_5tuple_all_pipeline_id, - (void *) &cmd_fc_add_ipv6_5tuple_all_flow_string, - (void *) &cmd_fc_add_ipv6_5tuple_all_add_string, - (void *) &cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string, - (void *) &cmd_fc_add_ipv6_5tuple_all_all_string, - (void *) &cmd_fc_add_ipv6_5tuple_all_n_flows, - (void *) &cmd_fc_add_ipv6_5tuple_all_n_ports, - NULL, - }, -}; - -/* - * flow del qinq - */ -struct cmd_fc_del_qinq_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t qinq_string; - uint16_t svlan; - uint16_t cvlan; -}; - -static void -cmd_fc_del_qinq_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_del_qinq_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key key; - int status; - - memset(&key, 0, sizeof(key)); - key.type = FLOW_KEY_QINQ; - key.key.qinq.svlan = params->svlan; - key.key.qinq.cvlan = params->cvlan; - status = app_pipeline_fc_del(app, params->pipeline_id, &key); - - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fc_del_qinq_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, p_string, "p"); - -cmdline_parse_token_num_t cmd_fc_del_qinq_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, pipeline_id, - UINT32); - -cmdline_parse_token_string_t cmd_fc_del_qinq_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, flow_string, - "flow"); - -cmdline_parse_token_string_t cmd_fc_del_qinq_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, del_string, - "del"); - -cmdline_parse_token_string_t cmd_fc_del_qinq_qinq_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, qinq_string, - "qinq"); - -cmdline_parse_token_num_t cmd_fc_del_qinq_svlan = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, svlan, UINT16); - -cmdline_parse_token_num_t cmd_fc_del_qinq_cvlan = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, cvlan, UINT16); - -cmdline_parse_inst_t cmd_fc_del_qinq = { - .f = cmd_fc_del_qinq_parsed, - .data = NULL, - .help_str = "Flow delete (Q-in-Q)", - .tokens = { - (void *) &cmd_fc_del_qinq_p_string, - (void *) &cmd_fc_del_qinq_pipeline_id, - (void *) &cmd_fc_del_qinq_flow_string, - (void *) &cmd_fc_del_qinq_del_string, - (void *) &cmd_fc_del_qinq_qinq_string, - (void *) &cmd_fc_del_qinq_svlan, - (void *) &cmd_fc_del_qinq_cvlan, - NULL, - }, -}; - -/* - * flow del ipv4_5tuple - */ - -struct cmd_fc_del_ipv4_5tuple_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t ipv4_5tuple_string; - cmdline_ipaddr_t ip_src; - cmdline_ipaddr_t ip_dst; - uint16_t port_src; - uint16_t port_dst; - uint32_t proto; -}; - -static void -cmd_fc_del_ipv4_5tuple_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_del_ipv4_5tuple_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key key; - int status; - - memset(&key, 0, sizeof(key)); - key.type = FLOW_KEY_IPV4_5TUPLE; - key.key.ipv4_5tuple.ip_src = rte_bswap32( - params->ip_src.addr.ipv4.s_addr); - key.key.ipv4_5tuple.ip_dst = rte_bswap32( - params->ip_dst.addr.ipv4.s_addr); - key.key.ipv4_5tuple.port_src = params->port_src; - key.key.ipv4_5tuple.port_dst = params->port_dst; - key.key.ipv4_5tuple.proto = params->proto; - - status = app_pipeline_fc_del(app, params->pipeline_id, &key); - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - p_string, "p"); -cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - pipeline_id, UINT32); + status = app_pipeline_fc_ls(app, results->pipeline_id); + if (status) + printf(CMD_MSG_FAIL, "flow ls"); -cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - flow_string, "flow"); - -cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - del_string, "del"); - -cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - ipv4_5tuple_string, "ipv4_5tuple"); - -cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_src = - TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - ip_src); - -cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_dst = - TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_dst); - -cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_src = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - port_src, UINT16); - -cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_dst = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - port_dst, UINT16); - -cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_proto = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, - proto, UINT32); - -cmdline_parse_inst_t cmd_fc_del_ipv4_5tuple = { - .f = cmd_fc_del_ipv4_5tuple_parsed, - .data = NULL, - .help_str = "Flow delete (IPv4 5-tuple)", - .tokens = { - (void *) &cmd_fc_del_ipv4_5tuple_p_string, - (void *) &cmd_fc_del_ipv4_5tuple_pipeline_id, - (void *) &cmd_fc_del_ipv4_5tuple_flow_string, - (void *) &cmd_fc_del_ipv4_5tuple_del_string, - (void *) &cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string, - (void *) &cmd_fc_del_ipv4_5tuple_ip_src, - (void *) &cmd_fc_del_ipv4_5tuple_ip_dst, - (void *) &cmd_fc_del_ipv4_5tuple_port_src, - (void *) &cmd_fc_del_ipv4_5tuple_port_dst, - (void *) &cmd_fc_del_ipv4_5tuple_proto, - NULL, - }, -}; - -/* - * flow del ipv6_5tuple - */ - -struct cmd_fc_del_ipv6_5tuple_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t ipv6_5tuple_string; - cmdline_ipaddr_t ip_src; - cmdline_ipaddr_t ip_dst; - uint16_t port_src; - uint16_t port_dst; - uint32_t proto; -}; - -static void -cmd_fc_del_ipv6_5tuple_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_del_ipv6_5tuple_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_fc_key key; - int status; - - memset(&key, 0, sizeof(key)); - key.type = FLOW_KEY_IPV6_5TUPLE; - memcpy(key.key.ipv6_5tuple.ip_src, - params->ip_src.addr.ipv6.s6_addr, - 16); - memcpy(key.key.ipv6_5tuple.ip_dst, - params->ip_dst.addr.ipv6.s6_addr, - 16); - key.key.ipv6_5tuple.port_src = params->port_src; - key.key.ipv6_5tuple.port_dst = params->port_dst; - key.key.ipv6_5tuple.proto = params->proto; - - status = app_pipeline_fc_del(app, params->pipeline_id, &key); - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, - p_string, "p"); - -cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, - pipeline_id, UINT32); - -cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, - flow_string, "flow"); - -cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, - del_string, "del"); - -cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, - ipv6_5tuple_string, "ipv6_5tuple"); - -cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_src = - TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_src); - -cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_dst = - TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_dst); - -cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_src = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_src, - UINT16); - -cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_dst = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_dst, - UINT16); - -cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_proto = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, proto, - UINT32); - -cmdline_parse_inst_t cmd_fc_del_ipv6_5tuple = { - .f = cmd_fc_del_ipv6_5tuple_parsed, - .data = NULL, - .help_str = "Flow delete (IPv6 5-tuple)", - .tokens = { - (void *) &cmd_fc_del_ipv6_5tuple_p_string, - (void *) &cmd_fc_del_ipv6_5tuple_pipeline_id, - (void *) &cmd_fc_del_ipv6_5tuple_flow_string, - (void *) &cmd_fc_del_ipv6_5tuple_del_string, - (void *) &cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string, - (void *) &cmd_fc_del_ipv6_5tuple_ip_src, - (void *) &cmd_fc_del_ipv6_5tuple_ip_dst, - (void *) &cmd_fc_del_ipv6_5tuple_port_src, - (void *) &cmd_fc_del_ipv6_5tuple_port_dst, - (void *) &cmd_fc_del_ipv6_5tuple_proto, - NULL, - }, -}; - -/* - * flow add default - */ - -struct cmd_fc_add_default_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t default_string; - uint32_t port; -}; - -static void -cmd_fc_add_default_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_add_default_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_fc_add_default(app, params->pipeline_id, - params->port); - - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fc_add_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, p_string, - "p"); - -cmdline_parse_token_num_t cmd_fc_add_default_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, pipeline_id, - UINT32); - -cmdline_parse_token_string_t cmd_fc_add_default_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, flow_string, - "flow"); - -cmdline_parse_token_string_t cmd_fc_add_default_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, add_string, - "add"); - -cmdline_parse_token_string_t cmd_fc_add_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, - default_string, "default"); - -cmdline_parse_token_num_t cmd_fc_add_default_port = - TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, port, UINT32); - -cmdline_parse_inst_t cmd_fc_add_default = { - .f = cmd_fc_add_default_parsed, - .data = NULL, - .help_str = "Flow add default", - .tokens = { - (void *) &cmd_fc_add_default_p_string, - (void *) &cmd_fc_add_default_pipeline_id, - (void *) &cmd_fc_add_default_flow_string, - (void *) &cmd_fc_add_default_add_string, - (void *) &cmd_fc_add_default_default_string, - (void *) &cmd_fc_add_default_port, - NULL, - }, -}; - -/* - * flow del default - */ - -struct cmd_fc_del_default_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t default_string; -}; - -static void -cmd_fc_del_default_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_fc_del_default_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_fc_del_default(app, params->pipeline_id); - if (status != 0) - printf("Command failed\n"); -} - -cmdline_parse_token_string_t cmd_fc_del_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, p_string, - "p"); - -cmdline_parse_token_num_t cmd_fc_del_default_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_result, pipeline_id, - UINT32); - -cmdline_parse_token_string_t cmd_fc_del_default_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, flow_string, - "flow"); - -cmdline_parse_token_string_t cmd_fc_del_default_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, del_string, - "del"); - -cmdline_parse_token_string_t cmd_fc_del_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, - default_string, "default"); - -cmdline_parse_inst_t cmd_fc_del_default = { - .f = cmd_fc_del_default_parsed, - .data = NULL, - .help_str = "Flow delete default", - .tokens = { - (void *) &cmd_fc_del_default_p_string, - (void *) &cmd_fc_del_default_pipeline_id, - (void *) &cmd_fc_del_default_flow_string, - (void *) &cmd_fc_del_default_del_string, - (void *) &cmd_fc_del_default_default_string, - NULL, - }, -}; - -/* - * flow ls - */ - -struct cmd_fc_ls_result { - cmdline_fixed_string_t p_string; - uint32_t pipeline_id; - cmdline_fixed_string_t flow_string; - cmdline_fixed_string_t ls_string; -}; - -static void -cmd_fc_ls_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_fc_ls_result *params = parsed_result; - struct app_params *app = data; - int status; + return; + } /* flow ls */ - status = app_pipeline_fc_ls(app, params->pipeline_id); - if (status != 0) - printf("Command failed\n"); + printf(CMD_MSG_MISMATCH_ARGS, "flow"); } -cmdline_parse_token_string_t cmd_fc_ls_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p"); +static cmdline_parse_token_string_t cmd_flow_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_flow_result, p_string, "p"); -cmdline_parse_token_num_t cmd_fc_ls_pipeline_id = - TOKEN_NUM_INITIALIZER(struct cmd_fc_ls_result, pipeline_id, UINT32); +static cmdline_parse_token_num_t cmd_flow_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_flow_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_fc_ls_flow_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, - flow_string, "flow"); +static cmdline_parse_token_string_t cmd_flow_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_flow_result, flow_string, "flow"); -cmdline_parse_token_string_t cmd_fc_ls_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, ls_string, - "ls"); +static cmdline_parse_token_string_t cmd_flow_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_flow_result, multi_string, + TOKEN_STRING_MULTI); -cmdline_parse_inst_t cmd_fc_ls = { - .f = cmd_fc_ls_parsed, +static cmdline_parse_inst_t cmd_flow = { + .f = cmd_flow_parsed, .data = NULL, - .help_str = "Flow list", + .help_str = "flow add / add bulk / add default / del / del default / ls", .tokens = { - (void *) &cmd_fc_ls_p_string, - (void *) &cmd_fc_ls_pipeline_id, - (void *) &cmd_fc_ls_flow_string, - (void *) &cmd_fc_ls_ls_string, + (void *) &cmd_flow_p_string, + (void *) &cmd_flow_pipeline_id, + (void *) &cmd_flow_flow_string, + (void *) &cmd_flow_multi_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *) &cmd_fc_add_qinq, - (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple, - (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple, - - (cmdline_parse_inst_t *) &cmd_fc_del_qinq, - (cmdline_parse_inst_t *) &cmd_fc_del_ipv4_5tuple, - (cmdline_parse_inst_t *) &cmd_fc_del_ipv6_5tuple, - - (cmdline_parse_inst_t *) &cmd_fc_add_default, - (cmdline_parse_inst_t *) &cmd_fc_del_default, - - (cmdline_parse_inst_t *) &cmd_fc_add_qinq_all, - (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple_all, - (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple_all, - - (cmdline_parse_inst_t *) &cmd_fc_ls, + (cmdline_parse_inst_t *) &cmd_flow, NULL, }; static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = { .f_init = app_pipeline_fc_init, + .f_post_init = NULL, .f_free = app_pipeline_fc_free, + .f_track = app_pipeline_track_default, .cmds = pipeline_cmds, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h index 9c775006..6c5ed384 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h @@ -102,6 +102,34 @@ int app_pipeline_fc_del_default(struct app_params *app, uint32_t pipeline_id); +#ifndef APP_PIPELINE_FC_MAX_FLOWS_IN_FILE +#define APP_PIPELINE_FC_MAX_FLOWS_IN_FILE (16 * 1024 * 1024) +#endif + +int +app_pipeline_fc_load_file_qinq(char *filename, + struct pipeline_fc_key *keys, + uint32_t *port_ids, + uint32_t *flow_ids, + uint32_t *n_keys, + uint32_t *line); + +int +app_pipeline_fc_load_file_ipv4(char *filename, + struct pipeline_fc_key *keys, + uint32_t *port_ids, + uint32_t *flow_ids, + uint32_t *n_keys, + uint32_t *line); + +int +app_pipeline_fc_load_file_ipv6(char *filename, + struct pipeline_fc_key *keys, + uint32_t *port_ids, + uint32_t *flow_ids, + uint32_t *n_keys, + uint32_t *line); + extern struct pipeline_type pipeline_flow_classification; #endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c index 70d976d5..8a762bc7 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c @@ -643,27 +643,6 @@ pipeline_fc_free(void *pipeline) } static int -pipeline_fc_track(void *pipeline, - __rte_unused uint32_t port_in, - uint32_t *port_out) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - if (p->n_ports_in == 1) { - *port_out = 0; - return 0; - } - - return -1; -} - -static int pipeline_fc_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; @@ -807,5 +786,4 @@ struct pipeline_be_ops pipeline_flow_classification_be_ops = { .f_free = pipeline_fc_free, .f_run = NULL, .f_timer = pipeline_fc_timer, - .f_track = pipeline_fc_track, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_master.c b/examples/ip_pipeline/pipeline/pipeline_master.c index 1ccdad14..aab58a27 100644 --- a/examples/ip_pipeline/pipeline/pipeline_master.c +++ b/examples/ip_pipeline/pipeline/pipeline_master.c @@ -36,7 +36,9 @@ static struct pipeline_fe_ops pipeline_master_fe_ops = { .f_init = NULL, + .f_post_init = NULL, .f_free = NULL, + .f_track = NULL, .cmds = NULL, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_master_be.c b/examples/ip_pipeline/pipeline/pipeline_master_be.c index ac0cbbc5..9a7c8c13 100644 --- a/examples/ip_pipeline/pipeline/pipeline_master_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_master_be.c @@ -48,6 +48,7 @@ struct pipeline_master { struct app_params *app; struct cmdline *cl; + int post_init_done; int script_file_done; } __rte_cache_aligned; @@ -77,6 +78,7 @@ pipeline_init(__rte_unused struct pipeline_params *params, void *arg) return NULL; } + p->post_init_done = 0; p->script_file_done = 0; if (app->script_file == NULL) p->script_file_done = 1; @@ -102,8 +104,20 @@ static int pipeline_run(void *pipeline) { struct pipeline_master *p = (struct pipeline_master *) pipeline; + struct app_params *app = p->app; int status; +#ifdef RTE_LIBRTE_KNI + uint32_t i; +#endif /* RTE_LIBRTE_KNI */ + /* Application post-init phase */ + if (p->post_init_done == 0) { + app_post_init(app); + + p->post_init_done = 1; + } + + /* Run startup script file */ if (p->script_file_done == 0) { struct app_params *app = p->app; int fd = open(app->script_file, O_RDONLY); @@ -124,6 +138,7 @@ pipeline_run(void *pipeline) p->script_file_done = 1; } + /* Command Line Interface (CLI) */ status = cmdline_poll(p->cl); if (status < 0) rte_panic("CLI poll error (%" PRId32 ")\n", status); @@ -132,6 +147,12 @@ pipeline_run(void *pipeline) rte_exit(0, "Bye!\n"); } +#ifdef RTE_LIBRTE_KNI + /* Handle KNI requests from Linux kernel */ + for (i = 0; i < app->n_pktq_kni; i++) + rte_kni_handle_request(app->kni[i]); +#endif /* RTE_LIBRTE_KNI */ + return 0; } @@ -146,5 +167,4 @@ struct pipeline_be_ops pipeline_master_be_ops = { .f_free = pipeline_free, .f_run = pipeline_run, .f_timer = pipeline_timer, - .f_track = NULL, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough.c b/examples/ip_pipeline/pipeline/pipeline_passthrough.c index fc2cae5e..63ce1472 100644 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough.c +++ b/examples/ip_pipeline/pipeline/pipeline_passthrough.c @@ -34,9 +34,36 @@ #include "pipeline_passthrough.h" #include "pipeline_passthrough_be.h" +static int +app_pipeline_passthrough_track(struct pipeline_params *p, + uint32_t port_in, + uint32_t *port_out) +{ + struct pipeline_passthrough_params pp; + int status; + + /* Check input arguments */ + if ((p == NULL) || + (port_in >= p->n_ports_in) || + (port_out == NULL)) + return -1; + + status = pipeline_passthrough_parse_args(&pp, p); + if (status) + return -1; + + if (pp.lb_hash_enabled) + return -1; + + *port_out = port_in / (p->n_ports_in / p->n_ports_out); + return 0; +} + static struct pipeline_fe_ops pipeline_passthrough_fe_ops = { .f_init = NULL, + .f_post_init = NULL, .f_free = NULL, + .f_track = app_pipeline_passthrough_track, .cmds = NULL, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c index a0d11aea..6146a28f 100644 --- a/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_passthrough_be.c @@ -547,6 +547,18 @@ pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, "dma_src_mask", dma_mask_str); } + if (p->lb_hash_enabled) + PIPELINE_ARG_CHECK((params->n_ports_out > 1), + "Parse error in section \"%s\": entry \"lb\" not " + "allowed for single output port pipeline", + params->name); + else + PIPELINE_ARG_CHECK(((params->n_ports_in >= params->n_ports_out) + && ((params->n_ports_in % params->n_ports_out) == 0)), + "Parse error in section \"%s\": n_ports_in needs to be " + "a multiple of n_ports_out (lb mode disabled)", + params->name); + return 0; } @@ -579,9 +591,7 @@ pipeline_passthrough_init(struct pipeline_params *params, /* Check input arguments */ if ((params == NULL) || (params->n_ports_in == 0) || - (params->n_ports_out == 0) || - (params->n_ports_in < params->n_ports_out) || - (params->n_ports_in % params->n_ports_out)) + (params->n_ports_out == 0)) return NULL; /* Memory allocation */ @@ -702,10 +712,13 @@ pipeline_passthrough_init(struct pipeline_params *params, /* Add entries to tables */ for (i = 0; i < p->n_ports_in; i++) { + uint32_t port_out_id = (p_pt->params.lb_hash_enabled == 0) ? + (i / (p->n_ports_in / p->n_ports_out)) : + 0; + struct rte_pipeline_table_entry default_entry = { .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = p->port_out_id[ - i / (p->n_ports_in / p->n_ports_out)]}, + {.port_id = p->port_out_id[port_out_id]}, }; struct rte_pipeline_table_entry *default_entry_ptr; @@ -780,25 +793,9 @@ pipeline_passthrough_timer(void *pipeline) return 0; } -static int -pipeline_passthrough_track(void *pipeline, uint32_t port_in, uint32_t *port_out) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - *port_out = port_in / p->n_ports_in; - return 0; -} - struct pipeline_be_ops pipeline_passthrough_be_ops = { .f_init = pipeline_passthrough_init, .f_free = pipeline_passthrough_free, .f_run = NULL, .f_timer = pipeline_passthrough_timer, - .f_track = pipeline_passthrough_track, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.c b/examples/ip_pipeline/pipeline/pipeline_routing.c index eab89f2e..3aadbf91 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing.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 @@ -34,12 +34,11 @@ #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> -#include <cmdline_parse_ipaddr.h> -#include <cmdline_parse_etheraddr.h> #include "app.h" #include "pipeline_common_fe.h" #include "pipeline_routing.h" +#include "parser.h" struct app_pipeline_routing_route { struct pipeline_routing_route_key key; @@ -59,8 +58,14 @@ struct app_pipeline_routing_arp_entry { struct pipeline_routing { /* Parameters */ + struct app_params *app; + uint32_t pipeline_id; uint32_t n_ports_in; uint32_t n_ports_out; + struct pipeline_routing_params rp; + + /* Links */ + uint32_t link_id[PIPELINE_MAX_PORT_OUT]; /* Routes */ TAILQ_HEAD(, app_pipeline_routing_route) routes; @@ -79,12 +84,151 @@ struct pipeline_routing { void *default_arp_entry_ptr; }; +static int +app_pipeline_routing_find_link(struct pipeline_routing *p, + uint32_t link_id, + uint32_t *port_id) +{ + uint32_t i; + + for (i = 0; i < p->n_ports_out; i++) + if (p->link_id[i] == link_id) { + *port_id = i; + return 0; + } + + return -1; +} + +static void +app_pipeline_routing_link_op(__rte_unused struct app_params *app, + uint32_t link_id, + uint32_t up, + void *arg) +{ + struct pipeline_routing_route_key key0, key1; + struct pipeline_routing *p = arg; + struct app_link_params *lp; + uint32_t port_id, netmask; + int status; + + if (app == NULL) + return; + + APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp); + if (lp == NULL) + return; + + status = app_pipeline_routing_find_link(p, + link_id, + &port_id); + if (status) + return; + + netmask = (~0U) << (32 - lp->depth); + + /* Local network (directly attached network) */ + key0.type = PIPELINE_ROUTING_ROUTE_IPV4; + key0.key.ipv4.ip = lp->ip & netmask; + key0.key.ipv4.depth = lp->depth; + + /* Local termination */ + key1.type = PIPELINE_ROUTING_ROUTE_IPV4; + key1.key.ipv4.ip = lp->ip; + key1.key.ipv4.depth = 32; + + if (up) { + struct pipeline_routing_route_data data0, data1; + + /* Local network (directly attached network) */ + memset(&data0, 0, sizeof(data0)); + data0.flags = PIPELINE_ROUTING_ROUTE_LOCAL | + PIPELINE_ROUTING_ROUTE_ARP; + if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) + data0.flags |= PIPELINE_ROUTING_ROUTE_QINQ; + if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) { + data0.flags |= PIPELINE_ROUTING_ROUTE_MPLS; + data0.l2.mpls.n_labels = 1; + } + data0.port_id = port_id; + + if (p->rp.n_arp_entries) + app_pipeline_routing_add_route(app, + p->pipeline_id, + &key0, + &data0); + + /* Local termination */ + memset(&data1, 0, sizeof(data1)); + data1.flags = PIPELINE_ROUTING_ROUTE_LOCAL | + PIPELINE_ROUTING_ROUTE_ARP; + if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) + data1.flags |= PIPELINE_ROUTING_ROUTE_QINQ; + if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) { + data1.flags |= PIPELINE_ROUTING_ROUTE_MPLS; + data1.l2.mpls.n_labels = 1; + } + data1.port_id = p->rp.port_local_dest; + + app_pipeline_routing_add_route(app, + p->pipeline_id, + &key1, + &data1); + } else { + /* Local network (directly attached network) */ + if (p->rp.n_arp_entries) + app_pipeline_routing_delete_route(app, + p->pipeline_id, + &key0); + + /* Local termination */ + app_pipeline_routing_delete_route(app, + p->pipeline_id, + &key1); + } +} + +static int +app_pipeline_routing_set_link_op( + struct app_params *app, + struct pipeline_routing *p) +{ + uint32_t port_id; + + for (port_id = 0; port_id < p->n_ports_out; port_id++) { + struct app_link_params *link; + uint32_t link_id; + int status; + + link = app_pipeline_track_pktq_out_to_link(app, + p->pipeline_id, + port_id); + if (link == NULL) + continue; + + link_id = link - app->link_params; + p->link_id[port_id] = link_id; + + status = app_link_set_op(app, + link_id, + p->pipeline_id, + app_pipeline_routing_link_op, + (void *) p); + if (status) + return status; + } + + return 0; +} + static void * -pipeline_routing_init(struct pipeline_params *params, - __rte_unused void *arg) +app_pipeline_routing_init(struct pipeline_params *params, + void *arg) { + struct app_params *app = (struct app_params *) arg; struct pipeline_routing *p; - uint32_t size; + uint32_t pipeline_id, size; + int status; /* Check input arguments */ if ((params == NULL) || @@ -92,6 +236,8 @@ pipeline_routing_init(struct pipeline_params *params, (params->n_ports_out == 0)) return NULL; + APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id); + /* Memory allocation */ size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing)); p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); @@ -99,19 +245,40 @@ pipeline_routing_init(struct pipeline_params *params, return NULL; /* Initialization */ + p->app = app; + p->pipeline_id = pipeline_id; p->n_ports_in = params->n_ports_in; p->n_ports_out = params->n_ports_out; + status = pipeline_routing_parse_args(&p->rp, params); + if (status) { + rte_free(p); + return NULL; + } TAILQ_INIT(&p->routes); p->n_routes = 0; TAILQ_INIT(&p->arp_entries); p->n_arp_entries = 0; + app_pipeline_routing_set_link_op(app, p); + return p; } static int +app_pipeline_routing_post_init(void *pipeline) +{ + struct pipeline_routing *p = pipeline; + + /* Check input arguments */ + if (p == NULL) + return -1; + + return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id); +} + +static int app_pipeline_routing_free(void *pipeline) { struct pipeline_routing *p = pipeline; @@ -198,7 +365,9 @@ print_route(const struct app_pipeline_routing_route *route) key->depth, route->data.port_id); - if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP) + if (route->data.flags & PIPELINE_ROUTING_ROUTE_LOCAL) + printf(", Local"); + else if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP) printf( ", Next Hop IP = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32, @@ -383,8 +552,6 @@ app_pipeline_routing_add_route(struct app_params *app, p->n_routes++; } - print_route(entry); - /* Message buffer free */ app_msg_free(app, rsp); return 0; @@ -677,8 +844,6 @@ app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id, p->n_arp_entries++; } - print_arp_entry(entry); - /* Message buffer free */ app_msg_free(app, rsp); return 0; @@ -853,1382 +1018,600 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app, return 0; } -static int -parse_labels(char *string, uint32_t *labels, uint32_t *n_labels) +int +app_pipeline_routing_set_macaddr(struct app_params *app, + uint32_t pipeline_id) { - uint32_t n_max_labels = *n_labels, count = 0; - - /* Check for void list of labels */ - if (strcmp(string, "<void>") == 0) { - *n_labels = 0; - return 0; - } + struct app_pipeline_params *p; + struct pipeline_routing_set_macaddr_msg_req *req; + struct pipeline_routing_set_macaddr_msg_rsp *rsp; + uint32_t port_id; - /* At least one label should be present */ - for ( ; (*string != '\0'); ) { - char *next; - int value; + /* Check input arguments */ + if (app == NULL) + return -EINVAL; - if (count >= n_max_labels) - return -1; + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p); + if (p == NULL) + return -EINVAL; - if (count > 0) { - if (string[0] != ':') - return -1; + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) + return -ENOMEM; - string++; - } + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR; - value = strtol(string, &next, 10); - if (next == string) - return -1; - string = next; + memset(req->macaddr, 0, sizeof(req->macaddr)); + for (port_id = 0; port_id < p->n_pktq_out; port_id++) { + struct app_link_params *link; - labels[count++] = (uint32_t) value; + link = app_pipeline_track_pktq_out_to_link(app, + pipeline_id, + port_id); + if (link) + req->macaddr[port_id] = link->mac_addr; } - *n_labels = count; - return 0; -} - -/* - * route add (mpls = no, qinq = no, arp = no) - */ - -struct cmd_route_add1_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_ipaddr_t ip; - uint32_t depth; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t ether_string; - struct ether_addr macaddr; -}; - -static void -cmd_route_add1_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_add1_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; - int status; - - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; - - route_data.flags = 0; - route_data.port_id = params->port; - route_data.ethernet.macaddr = params->macaddr; - - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); + if (rsp == NULL) + return -ETIMEDOUT; - if (status != 0) { - printf("Command failed\n"); - return; + /* Read response and write entry */ + if (rsp->status) { + app_msg_free(app, rsp); + return rsp->status; } -} - -static cmdline_parse_token_string_t cmd_route_add1_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_add1_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add1_result, p, UINT32); -static cmdline_parse_token_string_t cmd_route_add1_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_add1_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, add_string, - "add"); - -static cmdline_parse_token_ipaddr_t cmd_route_add1_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add1_result, ip); - -static cmdline_parse_token_num_t cmd_route_add1_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_add1_result, depth, UINT32); - -static cmdline_parse_token_string_t cmd_route_add1_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, port_string, - "port"); - -static cmdline_parse_token_num_t cmd_route_add1_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add1_result, port, UINT32); - -static cmdline_parse_token_string_t cmd_route_add1_ether_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add1_result, ether_string, - "ether"); - -static cmdline_parse_token_etheraddr_t cmd_route_add1_macaddr = - TOKEN_ETHERADDR_INITIALIZER(struct cmd_route_add1_result, macaddr); - -static cmdline_parse_inst_t cmd_route_add1 = { - .f = cmd_route_add1_parsed, - .data = NULL, - .help_str = "Route add (mpls = no, qinq = no, arp = no)", - .tokens = { - (void *)&cmd_route_add1_p_string, - (void *)&cmd_route_add1_p, - (void *)&cmd_route_add1_route_string, - (void *)&cmd_route_add1_add_string, - (void *)&cmd_route_add1_ip, - (void *)&cmd_route_add1_depth, - (void *)&cmd_route_add1_port_string, - (void *)&cmd_route_add1_port, - (void *)&cmd_route_add1_ether_string, - (void *)&cmd_route_add1_macaddr, - NULL, - }, -}; - -/* - * route add (mpls = no, qinq = no, arp = yes) - */ - -struct cmd_route_add2_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_ipaddr_t ip; - uint32_t depth; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t ether_string; - cmdline_ipaddr_t nh_ip; -}; - -static void -cmd_route_add2_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_add2_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; - int status; - - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; - - route_data.flags = PIPELINE_ROUTING_ROUTE_ARP; - route_data.port_id = params->port; - route_data.ethernet.ip = - rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr); - - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); + /* Free response */ + app_msg_free(app, rsp); - if (status != 0) { - printf("Command failed\n"); - return; - } + return 0; } -static cmdline_parse_token_string_t cmd_route_add2_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_add2_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add2_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_add2_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_add2_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, add_string, - "add"); - -static cmdline_parse_token_ipaddr_t cmd_route_add2_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add2_result, ip); - -static cmdline_parse_token_num_t cmd_route_add2_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_add2_result, depth, UINT32); - -static cmdline_parse_token_string_t cmd_route_add2_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, port_string, - "port"); - -static cmdline_parse_token_num_t cmd_route_add2_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add2_result, port, UINT32); - -static cmdline_parse_token_string_t cmd_route_add2_ether_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add2_result, ether_string, - "ether"); - -static cmdline_parse_token_ipaddr_t cmd_route_add2_nh_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add2_result, nh_ip); - -static cmdline_parse_inst_t cmd_route_add2 = { - .f = cmd_route_add2_parsed, - .data = NULL, - .help_str = "Route add (mpls = no, qinq = no, arp = yes)", - .tokens = { - (void *)&cmd_route_add2_p_string, - (void *)&cmd_route_add2_p, - (void *)&cmd_route_add2_route_string, - (void *)&cmd_route_add2_add_string, - (void *)&cmd_route_add2_ip, - (void *)&cmd_route_add2_depth, - (void *)&cmd_route_add2_port_string, - (void *)&cmd_route_add2_port, - (void *)&cmd_route_add2_ether_string, - (void *)&cmd_route_add2_nh_ip, - NULL, - }, -}; - /* - * route add (mpls = no, qinq = yes, arp = no) + * route + * + * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF): + * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> + * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> + * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan> + * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan> + * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels> + * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels> + * + * route add default: + * p <pipelineid> route add default <portid> + * + * route del: + * p <pipelineid> route del <ipaddr> <depth> + * + * route del default: + * p <pipelineid> route del default + * + * route ls: + * p <pipelineid> route ls */ -struct cmd_route_add3_result { +struct cmd_route_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_ipaddr_t ip; - uint32_t depth; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t ether_string; - struct ether_addr macaddr; - cmdline_fixed_string_t qinq_string; - uint32_t svlan; - uint32_t cvlan; + cmdline_multi_string_t multi_string; }; static void -cmd_route_add3_parsed( +cmd_route_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { - struct cmd_route_add3_result *params = parsed_result; + struct cmd_route_result *params = parsed_result; struct app_params *app = data; - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; - int status; - - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; - - route_data.flags = PIPELINE_ROUTING_ROUTE_QINQ; - route_data.port_id = params->port; - route_data.ethernet.macaddr = params->macaddr; - route_data.l2.qinq.svlan = params->svlan; - route_data.l2.qinq.cvlan = params->cvlan; - - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); - - if (status != 0) { - printf("Command failed\n"); - return; - } -} -static cmdline_parse_token_string_t cmd_route_add3_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_add3_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_add3_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_add3_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, add_string, - "add"); - -static cmdline_parse_token_ipaddr_t cmd_route_add3_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add3_result, ip); - -static cmdline_parse_token_num_t cmd_route_add3_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, depth, UINT32); - -static cmdline_parse_token_string_t cmd_route_add3_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, port_string, - "port"); - -static cmdline_parse_token_num_t cmd_route_add3_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, port, UINT32); - -static cmdline_parse_token_string_t cmd_route_add3_ether_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, ether_string, - "ether"); - -static cmdline_parse_token_etheraddr_t cmd_route_add3_macaddr = - TOKEN_ETHERADDR_INITIALIZER(struct cmd_route_add3_result, macaddr); - -static cmdline_parse_token_string_t cmd_route_add3_qinq_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add3_result, qinq_string, - "qinq"); - -static cmdline_parse_token_num_t cmd_route_add3_svlan = - TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, svlan, UINT32); - -static cmdline_parse_token_num_t cmd_route_add3_cvlan = - TOKEN_NUM_INITIALIZER(struct cmd_route_add3_result, cvlan, UINT32); - -static cmdline_parse_inst_t cmd_route_add3 = { - .f = cmd_route_add3_parsed, - .data = NULL, - .help_str = "Route add (qinq = yes, arp = no)", - .tokens = { - (void *)&cmd_route_add3_p_string, - (void *)&cmd_route_add3_p, - (void *)&cmd_route_add3_route_string, - (void *)&cmd_route_add3_add_string, - (void *)&cmd_route_add3_ip, - (void *)&cmd_route_add3_depth, - (void *)&cmd_route_add3_port_string, - (void *)&cmd_route_add3_port, - (void *)&cmd_route_add3_ether_string, - (void *)&cmd_route_add3_macaddr, - (void *)&cmd_route_add3_qinq_string, - (void *)&cmd_route_add3_svlan, - (void *)&cmd_route_add3_cvlan, - NULL, - }, -}; - -/* - * route add (mpls = no, qinq = yes, arp = yes) - */ - -struct cmd_route_add4_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_ipaddr_t ip; - uint32_t depth; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t ether_string; - cmdline_ipaddr_t nh_ip; - cmdline_fixed_string_t qinq_string; - uint32_t svlan; - uint32_t cvlan; -}; - -static void -cmd_route_add4_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_add4_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; + char *tokens[16]; + uint32_t n_tokens = RTE_DIM(tokens); int status; - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; - - route_data.flags = PIPELINE_ROUTING_ROUTE_QINQ | - PIPELINE_ROUTING_ROUTE_ARP; - route_data.port_id = params->port; - route_data.ethernet.ip = - rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr); - route_data.l2.qinq.svlan = params->svlan; - route_data.l2.qinq.cvlan = params->cvlan; - - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); - + status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); if (status != 0) { - printf("Command failed\n"); + printf(CMD_MSG_TOO_MANY_ARGS, "route"); return; } -} - -static cmdline_parse_token_string_t cmd_route_add4_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_add4_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, p, UINT32); -static cmdline_parse_token_string_t cmd_route_add4_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_add4_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, add_string, - "add"); - -static cmdline_parse_token_ipaddr_t cmd_route_add4_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add4_result, ip); + /* route add */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + strcmp(tokens[1], "default")) { + struct pipeline_routing_route_key key; + struct pipeline_routing_route_data route_data; + struct in_addr ipv4, nh_ipv4; + struct ether_addr mac_addr; + uint32_t depth, port_id, svlan, cvlan, i; + uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX]; + uint32_t n_labels = RTE_DIM(mpls_labels); + + memset(&key, 0, sizeof(key)); + memset(&route_data, 0, sizeof(route_data)); + + if (n_tokens < 7) { + printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add"); + return; + } -static cmdline_parse_token_num_t cmd_route_add4_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, depth, UINT32); + if (parse_ipv4_addr(tokens[1], &ipv4)) { + printf(CMD_MSG_INVALID_ARG, "ipaddr"); + return; + } -static cmdline_parse_token_string_t cmd_route_add4_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, port_string, - "port"); + if (parser_read_uint32(&depth, tokens[2])) { + printf(CMD_MSG_INVALID_ARG, "depth"); + return; + } -static cmdline_parse_token_num_t cmd_route_add4_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, port, UINT32); + if (strcmp(tokens[3], "port")) { + printf(CMD_MSG_ARG_NOT_FOUND, "port"); + return; + } -static cmdline_parse_token_string_t cmd_route_add4_ether_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, ether_string, - "ether"); + if (parser_read_uint32(&port_id, tokens[4])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -static cmdline_parse_token_ipaddr_t cmd_route_add4_nh_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add4_result, nh_ip); + if (strcmp(tokens[5], "ether")) { + printf(CMD_MSG_ARG_NOT_FOUND, "ether"); + return; + } -static cmdline_parse_token_string_t cmd_route_add4_qinq_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add4_result, qinq_string, - "qinq"); + if (parse_mac_addr(tokens[6], &mac_addr)) { + if (parse_ipv4_addr(tokens[6], &nh_ipv4)) { + printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr"); + return; + } -static cmdline_parse_token_num_t cmd_route_add4_svlan = - TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, svlan, UINT32); + route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP; + } -static cmdline_parse_token_num_t cmd_route_add4_cvlan = - TOKEN_NUM_INITIALIZER(struct cmd_route_add4_result, cvlan, UINT32); + if (n_tokens > 7) { + if (strcmp(tokens[7], "mpls") == 0) { + if (n_tokens != 9) { + printf(CMD_MSG_MISMATCH_ARGS, "route add mpls"); + return; + } + + if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) { + printf(CMD_MSG_INVALID_ARG, "mpls labels"); + return; + } + + route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS; + } else if (strcmp(tokens[7], "qinq") == 0) { + if (n_tokens != 10) { + printf(CMD_MSG_MISMATCH_ARGS, "route add qinq"); + return; + } + + if (parser_read_uint32(&svlan, tokens[8])) { + printf(CMD_MSG_INVALID_ARG, "svlan"); + return; + } + if (parser_read_uint32(&cvlan, tokens[9])) { + printf(CMD_MSG_INVALID_ARG, "cvlan"); + return; + } + + route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ; + } else { + printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq"); + return; + } + } -static cmdline_parse_inst_t cmd_route_add4 = { - .f = cmd_route_add4_parsed, - .data = NULL, - .help_str = "Route add (qinq = yes, arp = yes)", - .tokens = { - (void *)&cmd_route_add4_p_string, - (void *)&cmd_route_add4_p, - (void *)&cmd_route_add4_route_string, - (void *)&cmd_route_add4_add_string, - (void *)&cmd_route_add4_ip, - (void *)&cmd_route_add4_depth, - (void *)&cmd_route_add4_port_string, - (void *)&cmd_route_add4_port, - (void *)&cmd_route_add4_ether_string, - (void *)&cmd_route_add4_nh_ip, - (void *)&cmd_route_add4_qinq_string, - (void *)&cmd_route_add4_svlan, - (void *)&cmd_route_add4_cvlan, - NULL, - }, -}; + switch (route_data.flags) { + case 0: + route_data.port_id = port_id; + route_data.ethernet.macaddr = mac_addr; + break; -/* - * route add (mpls = yes, qinq = no, arp = no) - */ + case PIPELINE_ROUTING_ROUTE_ARP: + route_data.port_id = port_id; + route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr); + break; -struct cmd_route_add5_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_ipaddr_t ip; - uint32_t depth; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t ether_string; - struct ether_addr macaddr; - cmdline_fixed_string_t mpls_string; - cmdline_fixed_string_t mpls_labels; -}; + case PIPELINE_ROUTING_ROUTE_MPLS: + route_data.port_id = port_id; + route_data.ethernet.macaddr = mac_addr; + for (i = 0; i < n_labels; i++) + route_data.l2.mpls.labels[i] = mpls_labels[i]; + route_data.l2.mpls.n_labels = n_labels; + break; -static void -cmd_route_add5_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_add5_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; - uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX]; - uint32_t n_labels = RTE_DIM(mpls_labels); - uint32_t i; - int status; + case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP: + route_data.port_id = port_id; + route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr); + for (i = 0; i < n_labels; i++) + route_data.l2.mpls.labels[i] = mpls_labels[i]; + route_data.l2.mpls.n_labels = n_labels; + break; - /* Parse MPLS labels */ - status = parse_labels(params->mpls_labels, mpls_labels, &n_labels); - if (status) { - printf("MPLS labels parse error\n"); - return; - } + case PIPELINE_ROUTING_ROUTE_QINQ: + route_data.port_id = port_id; + route_data.ethernet.macaddr = mac_addr; + route_data.l2.qinq.svlan = svlan; + route_data.l2.qinq.cvlan = cvlan; + break; - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; + case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP: + default: + route_data.port_id = port_id; + route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr); + route_data.l2.qinq.svlan = svlan; + route_data.l2.qinq.cvlan = cvlan; + break; + } - route_data.flags = PIPELINE_ROUTING_ROUTE_MPLS; - route_data.port_id = params->port; - route_data.ethernet.macaddr = params->macaddr; - for (i = 0; i < n_labels; i++) - route_data.l2.mpls.labels[i] = mpls_labels[i]; - route_data.l2.mpls.n_labels = n_labels; + key.type = PIPELINE_ROUTING_ROUTE_IPV4; + key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); + key.key.ipv4.depth = depth; - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); + status = app_pipeline_routing_add_route(app, + params->p, + &key, + &route_data); + if (status != 0) + printf(CMD_MSG_FAIL, "route add"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_route_add5_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_add5_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add5_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_add5_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_add5_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, add_string, - "add"); - -static cmdline_parse_token_ipaddr_t cmd_route_add5_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add5_result, ip); + } /* route add */ -static cmdline_parse_token_num_t cmd_route_add5_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_add5_result, depth, UINT32); + /* route add default */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "default") == 0)) { + uint32_t port_id; -static cmdline_parse_token_string_t cmd_route_add5_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, port_string, - "port"); - -static cmdline_parse_token_num_t cmd_route_add5_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add5_result, port, UINT32); - -static cmdline_parse_token_string_t cmd_route_add5_ether_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, ether_string, - "ether"); - -static cmdline_parse_token_etheraddr_t cmd_route_add5_macaddr = - TOKEN_ETHERADDR_INITIALIZER(struct cmd_route_add5_result, macaddr); - -static cmdline_parse_token_string_t cmd_route_add5_mpls_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, mpls_string, - "mpls"); - -static cmdline_parse_token_string_t cmd_route_add5_mpls_labels = - TOKEN_STRING_INITIALIZER(struct cmd_route_add5_result, mpls_labels, - NULL); - -static cmdline_parse_inst_t cmd_route_add5 = { - .f = cmd_route_add5_parsed, - .data = NULL, - .help_str = "Route add (mpls = yes, arp = no)", - .tokens = { - (void *)&cmd_route_add5_p_string, - (void *)&cmd_route_add5_p, - (void *)&cmd_route_add5_route_string, - (void *)&cmd_route_add5_add_string, - (void *)&cmd_route_add5_ip, - (void *)&cmd_route_add5_depth, - (void *)&cmd_route_add5_port_string, - (void *)&cmd_route_add5_port, - (void *)&cmd_route_add5_ether_string, - (void *)&cmd_route_add5_macaddr, - (void *)&cmd_route_add5_mpls_string, - (void *)&cmd_route_add5_mpls_labels, - NULL, - }, -}; - -/* - * route add (mpls = yes, qinq = no, arp = yes) - */ - -struct cmd_route_add6_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_ipaddr_t ip; - uint32_t depth; - cmdline_fixed_string_t port_string; - uint32_t port; - cmdline_fixed_string_t ether_string; - cmdline_ipaddr_t nh_ip; - cmdline_fixed_string_t mpls_string; - cmdline_fixed_string_t mpls_labels; -}; - -static void -cmd_route_add6_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_add6_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing_route_key key; - struct pipeline_routing_route_data route_data; - uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX]; - uint32_t n_labels = RTE_DIM(mpls_labels); - uint32_t i; - int status; + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "route add default"); + return; + } - /* Parse MPLS labels */ - status = parse_labels(params->mpls_labels, mpls_labels, &n_labels); - if (status) { - printf("MPLS labels parse error\n"); - return; - } + if (parser_read_uint32(&port_id, tokens[2])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; - - route_data.flags = PIPELINE_ROUTING_ROUTE_MPLS | - PIPELINE_ROUTING_ROUTE_ARP; - route_data.port_id = params->port; - route_data.ethernet.ip = - rte_bswap32((uint32_t) params->nh_ip.addr.ipv4.s_addr); - for (i = 0; i < n_labels; i++) - route_data.l2.mpls.labels[i] = mpls_labels[i]; - route_data.l2.mpls.n_labels = n_labels; - - status = app_pipeline_routing_add_route(app, - params->p, - &key, - &route_data); + status = app_pipeline_routing_add_default_route(app, + params->p, + port_id); + if (status != 0) + printf(CMD_MSG_FAIL, "route add default"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_route_add6_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_add6_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add6_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_add6_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_add6_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, add_string, - "add"); - -static cmdline_parse_token_ipaddr_t cmd_route_add6_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add6_result, ip); - -static cmdline_parse_token_num_t cmd_route_add6_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_add6_result, depth, UINT32); - -static cmdline_parse_token_string_t cmd_route_add6_port_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, port_string, - "port"); + } /* route add default */ -static cmdline_parse_token_num_t cmd_route_add6_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add6_result, port, UINT32); + /* route del*/ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + strcmp(tokens[1], "default")) { + struct pipeline_routing_route_key key; + struct in_addr ipv4; + uint32_t depth; -static cmdline_parse_token_string_t cmd_route_add6_ether_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, ether_string, - "ether"); - -static cmdline_parse_token_ipaddr_t cmd_route_add6_nh_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_add6_result, nh_ip); - -static cmdline_parse_token_string_t cmd_route_add6_mpls_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, mpls_string, - "mpls"); - -static cmdline_parse_token_string_t cmd_route_add6_mpls_labels = - TOKEN_STRING_INITIALIZER(struct cmd_route_add6_result, mpls_labels, - NULL); - -static cmdline_parse_inst_t cmd_route_add6 = { - .f = cmd_route_add6_parsed, - .data = NULL, - .help_str = "Route add (mpls = yes, arp = yes)", - .tokens = { - (void *)&cmd_route_add6_p_string, - (void *)&cmd_route_add6_p, - (void *)&cmd_route_add6_route_string, - (void *)&cmd_route_add6_add_string, - (void *)&cmd_route_add6_ip, - (void *)&cmd_route_add6_depth, - (void *)&cmd_route_add6_port_string, - (void *)&cmd_route_add6_port, - (void *)&cmd_route_add6_ether_string, - (void *)&cmd_route_add6_nh_ip, - (void *)&cmd_route_add6_mpls_string, - (void *)&cmd_route_add6_mpls_labels, - NULL, - }, -}; + memset(&key, 0, sizeof(key)); -/* - * route del - */ - -struct cmd_route_del_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t del_string; - cmdline_ipaddr_t ip; - uint32_t depth; -}; + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "route del"); + return; + } -static void -cmd_route_del_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_del_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing_route_key key; + if (parse_ipv4_addr(tokens[1], &ipv4)) { + printf(CMD_MSG_INVALID_ARG, "ipaddr"); + return; + } - int status; + if (parser_read_uint32(&depth, tokens[2])) { + printf(CMD_MSG_INVALID_ARG, "depth"); + return; + } - /* Create route */ - key.type = PIPELINE_ROUTING_ROUTE_IPV4; - key.key.ipv4.ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - key.key.ipv4.depth = params->depth; + key.type = PIPELINE_ROUTING_ROUTE_IPV4; + key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); + key.key.ipv4.depth = depth; - status = app_pipeline_routing_delete_route(app, params->p, &key); + status = app_pipeline_routing_delete_route(app, params->p, &key); + if (status != 0) + printf(CMD_MSG_FAIL, "route del"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_route_del_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_del_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_del_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, route_string, - "route"); - -static cmdline_parse_token_string_t cmd_route_del_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_result, del_string, - "del"); - -static cmdline_parse_token_ipaddr_t cmd_route_del_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_route_del_result, ip); - -static cmdline_parse_token_num_t cmd_route_del_depth = - TOKEN_NUM_INITIALIZER(struct cmd_route_del_result, depth, UINT32); - -static cmdline_parse_inst_t cmd_route_del = { - .f = cmd_route_del_parsed, - .data = NULL, - .help_str = "Route delete", - .tokens = { - (void *)&cmd_route_del_p_string, - (void *)&cmd_route_del_p, - (void *)&cmd_route_del_route_string, - (void *)&cmd_route_del_del_string, - (void *)&cmd_route_del_ip, - (void *)&cmd_route_del_depth, - NULL, - }, -}; - -/* - * route add default - */ - -struct cmd_route_add_default_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t default_string; - uint32_t port; -}; - -static void -cmd_route_add_default_parsed( - void *parsed_result, - __attribute__((unused)) struct cmdline *cl, - void *data) -{ - struct cmd_route_add_default_result *params = parsed_result; - struct app_params *app = data; - int status; + } /* route del */ + + /* route del default */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "default") == 0)) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "route del default"); + return; + } - status = app_pipeline_routing_add_default_route(app, params->p, - params->port); + status = app_pipeline_routing_delete_default_route(app, + params->p); + if (status != 0) + printf(CMD_MSG_FAIL, "route del default"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_route_add_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, p_string, - "p"); + } /* route del default */ -static cmdline_parse_token_num_t cmd_route_add_default_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_add_default_result, p, UINT32); - -cmdline_parse_token_string_t cmd_route_add_default_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, - route_string, "route"); - -cmdline_parse_token_string_t cmd_route_add_default_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, - add_string, "add"); - -cmdline_parse_token_string_t cmd_route_add_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_add_default_result, - default_string, "default"); - -cmdline_parse_token_num_t cmd_route_add_default_port = - TOKEN_NUM_INITIALIZER(struct cmd_route_add_default_result, - port, UINT32); - -cmdline_parse_inst_t cmd_route_add_default = { - .f = cmd_route_add_default_parsed, - .data = NULL, - .help_str = "Route default set", - .tokens = { - (void *)&cmd_route_add_default_p_string, - (void *)&cmd_route_add_default_p, - (void *)&cmd_route_add_default_route_string, - (void *)&cmd_route_add_default_add_string, - (void *)&cmd_route_add_default_default_string, - (void *)&cmd_route_add_default_port, - NULL, - }, -}; - -/* - * route del default - */ - -struct cmd_route_del_default_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t default_string; -}; - -static void -cmd_route_del_default_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_del_default_result *params = parsed_result; - struct app_params *app = data; - int status; + /* route ls */ + if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { + if (n_tokens != 1) { + printf(CMD_MSG_MISMATCH_ARGS, "route ls"); + return; + } - status = app_pipeline_routing_delete_default_route(app, params->p); + status = app_pipeline_routing_route_ls(app, params->p); + if (status != 0) + printf(CMD_MSG_FAIL, "route ls"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_route_del_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_route_del_default_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_del_default_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_route_del_default_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, - route_string, "route"); - -static cmdline_parse_token_string_t cmd_route_del_default_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, - del_string, "del"); - -static cmdline_parse_token_string_t cmd_route_del_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_del_default_result, - default_string, "default"); - - -static cmdline_parse_inst_t cmd_route_del_default = { - .f = cmd_route_del_default_parsed, - .data = NULL, - .help_str = "Route default clear", - .tokens = { - (void *)&cmd_route_del_default_p_string, - (void *)&cmd_route_del_default_p, - (void *)&cmd_route_del_default_route_string, - (void *)&cmd_route_del_default_del_string, - (void *)&cmd_route_del_default_default_string, - NULL, - }, -}; - -/* - * route ls - */ - -struct cmd_route_ls_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t route_string; - cmdline_fixed_string_t ls_string; -}; - -static void -cmd_route_ls_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_route_ls_result *params = parsed_result; - struct app_params *app = data; - int status; - - status = app_pipeline_routing_route_ls(app, params->p); + } /* route ls */ - if (status != 0) { - printf("Command failed\n"); - return; - } + printf(CMD_MSG_MISMATCH_ARGS, "route"); } -static cmdline_parse_token_string_t cmd_route_ls_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, p_string, "p"); +static cmdline_parse_token_string_t cmd_route_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p"); -static cmdline_parse_token_num_t cmd_route_ls_p = - TOKEN_NUM_INITIALIZER(struct cmd_route_ls_result, p, UINT32); +static cmdline_parse_token_num_t cmd_route_p = + TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32); -static cmdline_parse_token_string_t cmd_route_ls_route_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, - route_string, "route"); +static cmdline_parse_token_string_t cmd_route_route_string = + TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route"); -static cmdline_parse_token_string_t cmd_route_ls_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_route_ls_result, ls_string, - "ls"); +static cmdline_parse_token_string_t cmd_route_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string, + TOKEN_STRING_MULTI); -static cmdline_parse_inst_t cmd_route_ls = { - .f = cmd_route_ls_parsed, +static cmdline_parse_inst_t cmd_route = { + .f = cmd_route_parsed, .data = NULL, - .help_str = "Route list", + .help_str = "route add / add default / del / del default / ls", .tokens = { - (void *)&cmd_route_ls_p_string, - (void *)&cmd_route_ls_p, - (void *)&cmd_route_ls_route_string, - (void *)&cmd_route_ls_ls_string, + (void *)&cmd_route_p_string, + (void *)&cmd_route_p, + (void *)&cmd_route_route_string, + (void *)&cmd_route_multi_string, NULL, }, }; /* - * arp add + * arp + * + * arp add: + * p <pipelineid> arp add <portid> <ipaddr> <macaddr> + * + * arp add default: + * p <pipelineid> arp add default <portid> + * + * arp del: + * p <pipelineid> arp del <portid> <ipaddr> + * + * arp del default: + * p <pipelineid> arp del default + * + * arp ls: + * p <pipelineid> arp ls */ -struct cmd_arp_add_result { +struct cmd_arp_result { cmdline_fixed_string_t p_string; uint32_t p; cmdline_fixed_string_t arp_string; - cmdline_fixed_string_t add_string; - uint32_t port_id; - cmdline_ipaddr_t ip; - struct ether_addr macaddr; - + cmdline_multi_string_t multi_string; }; static void -cmd_arp_add_parsed( +cmd_arp_parsed( void *parsed_result, __rte_unused struct cmdline *cl, void *data) { - struct cmd_arp_add_result *params = parsed_result; + struct cmd_arp_result *params = parsed_result; struct app_params *app = data; - struct pipeline_routing_arp_key key; + char *tokens[16]; + uint32_t n_tokens = RTE_DIM(tokens); int status; - key.type = PIPELINE_ROUTING_ARP_IPV4; - key.key.ipv4.port_id = params->port_id; - key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr); - - status = app_pipeline_routing_add_arp_entry(app, - params->p, - &key, - ¶ms->macaddr); - + status = parse_tokenize_string(params->multi_string, tokens, &n_tokens); if (status != 0) { - printf("Command failed\n"); + printf(CMD_MSG_TOO_MANY_ARGS, "arp"); return; } -} - -static cmdline_parse_token_string_t cmd_arp_add_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_arp_add_p = - TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_arp_add_arp_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, arp_string, "arp"); -static cmdline_parse_token_string_t cmd_arp_add_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_result, add_string, "add"); + /* arp add */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + strcmp(tokens[1], "default")) { + struct pipeline_routing_arp_key key; + struct in_addr ipv4; + struct ether_addr mac_addr; + uint32_t port_id; -static cmdline_parse_token_num_t cmd_arp_add_port_id = - TOKEN_NUM_INITIALIZER(struct cmd_arp_add_result, port_id, UINT32); - -static cmdline_parse_token_ipaddr_t cmd_arp_add_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_arp_add_result, ip); - -static cmdline_parse_token_etheraddr_t cmd_arp_add_macaddr = - TOKEN_ETHERADDR_INITIALIZER(struct cmd_arp_add_result, macaddr); - -static cmdline_parse_inst_t cmd_arp_add = { - .f = cmd_arp_add_parsed, - .data = NULL, - .help_str = "ARP add", - .tokens = { - (void *)&cmd_arp_add_p_string, - (void *)&cmd_arp_add_p, - (void *)&cmd_arp_add_arp_string, - (void *)&cmd_arp_add_add_string, - (void *)&cmd_arp_add_port_id, - (void *)&cmd_arp_add_ip, - (void *)&cmd_arp_add_macaddr, - NULL, - }, -}; + memset(&key, 0, sizeof(key)); -/* - * arp del - */ + if (n_tokens != 4) { + printf(CMD_MSG_MISMATCH_ARGS, "arp add"); + return; + } -struct cmd_arp_del_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t arp_string; - cmdline_fixed_string_t del_string; - uint32_t port_id; - cmdline_ipaddr_t ip; -}; + if (parser_read_uint32(&port_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -static void -cmd_arp_del_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_arp_del_result *params = parsed_result; - struct app_params *app = data; + if (parse_ipv4_addr(tokens[2], &ipv4)) { + printf(CMD_MSG_INVALID_ARG, "ipaddr"); + return; + } - struct pipeline_routing_arp_key key; - int status; + if (parse_mac_addr(tokens[3], &mac_addr)) { + printf(CMD_MSG_INVALID_ARG, "macaddr"); + return; + } - key.type = PIPELINE_ROUTING_ARP_IPV4; - key.key.ipv4.ip = rte_cpu_to_be_32(params->ip.addr.ipv4.s_addr); - key.key.ipv4.port_id = params->port_id; + key.type = PIPELINE_ROUTING_ARP_IPV4; + key.key.ipv4.port_id = port_id; + key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); - status = app_pipeline_routing_delete_arp_entry(app, params->p, &key); + status = app_pipeline_routing_add_arp_entry(app, + params->p, + &key, + &mac_addr); + if (status != 0) + printf(CMD_MSG_FAIL, "arp add"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_arp_del_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, p_string, - "p"); + } /* arp add */ -static cmdline_parse_token_num_t cmd_arp_del_p = - TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_arp_del_arp_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, arp_string, "arp"); - -static cmdline_parse_token_string_t cmd_arp_del_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_result, del_string, "del"); - -static cmdline_parse_token_num_t cmd_arp_del_port_id = - TOKEN_NUM_INITIALIZER(struct cmd_arp_del_result, port_id, UINT32); - -static cmdline_parse_token_ipaddr_t cmd_arp_del_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_arp_del_result, ip); - -static cmdline_parse_inst_t cmd_arp_del = { - .f = cmd_arp_del_parsed, - .data = NULL, - .help_str = "ARP delete", - .tokens = { - (void *)&cmd_arp_del_p_string, - (void *)&cmd_arp_del_p, - (void *)&cmd_arp_del_arp_string, - (void *)&cmd_arp_del_del_string, - (void *)&cmd_arp_del_port_id, - (void *)&cmd_arp_del_ip, - NULL, - }, -}; - -/* - * arp add default - */ - -struct cmd_arp_add_default_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t arp_string; - cmdline_fixed_string_t add_string; - cmdline_fixed_string_t default_string; - uint32_t port_id; -}; + /* arp add default */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "add") == 0) && + (strcmp(tokens[1], "default") == 0)) { + uint32_t port_id; -static void -cmd_arp_add_default_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_arp_add_default_result *params = parsed_result; - struct app_params *app = data; + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "arp add default"); + return; + } - int status; + if (parser_read_uint32(&port_id, tokens[2])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } - status = app_pipeline_routing_add_default_arp_entry(app, - params->p, - params->port_id); + status = app_pipeline_routing_add_default_arp_entry(app, + params->p, + port_id); + if (status != 0) + printf(CMD_MSG_FAIL, "arp add default"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_arp_add_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_arp_add_default_p = - TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_arp_add_default_arp_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, arp_string, - "arp"); - -static cmdline_parse_token_string_t cmd_arp_add_default_add_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, add_string, - "add"); + } /* arp add default */ -static cmdline_parse_token_string_t cmd_arp_add_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_add_default_result, - default_string, "default"); + /* arp del*/ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + strcmp(tokens[1], "default")) { + struct pipeline_routing_arp_key key; + struct in_addr ipv4; + uint32_t port_id; -static cmdline_parse_token_num_t cmd_arp_add_default_port_id = - TOKEN_NUM_INITIALIZER(struct cmd_arp_add_default_result, port_id, - UINT32); + memset(&key, 0, sizeof(key)); -static cmdline_parse_inst_t cmd_arp_add_default = { - .f = cmd_arp_add_default_parsed, - .data = NULL, - .help_str = "ARP add default", - .tokens = { - (void *)&cmd_arp_add_default_p_string, - (void *)&cmd_arp_add_default_p, - (void *)&cmd_arp_add_default_arp_string, - (void *)&cmd_arp_add_default_add_string, - (void *)&cmd_arp_add_default_default_string, - (void *)&cmd_arp_add_default_port_id, - NULL, - }, -}; - -/* - * arp del default - */ + if (n_tokens != 3) { + printf(CMD_MSG_MISMATCH_ARGS, "arp del"); + return; + } -struct cmd_arp_del_default_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t arp_string; - cmdline_fixed_string_t del_string; - cmdline_fixed_string_t default_string; -}; + if (parser_read_uint32(&port_id, tokens[1])) { + printf(CMD_MSG_INVALID_ARG, "portid"); + return; + } -static void -cmd_arp_del_default_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_arp_del_default_result *params = parsed_result; - struct app_params *app = data; + if (parse_ipv4_addr(tokens[2], &ipv4)) { + printf(CMD_MSG_INVALID_ARG, "ipaddr"); + return; + } - int status; + key.type = PIPELINE_ROUTING_ARP_IPV4; + key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr); + key.key.ipv4.port_id = port_id; - status = app_pipeline_routing_delete_default_arp_entry(app, params->p); + status = app_pipeline_routing_delete_arp_entry(app, + params->p, + &key); + if (status != 0) + printf(CMD_MSG_FAIL, "arp del"); - if (status != 0) { - printf("Command failed\n"); return; - } -} - -static cmdline_parse_token_string_t cmd_arp_del_default_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, p_string, - "p"); - -static cmdline_parse_token_num_t cmd_arp_del_default_p = - TOKEN_NUM_INITIALIZER(struct cmd_arp_del_default_result, p, UINT32); - -static cmdline_parse_token_string_t cmd_arp_del_default_arp_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, arp_string, - "arp"); - -static cmdline_parse_token_string_t cmd_arp_del_default_del_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, del_string, - "del"); - -static cmdline_parse_token_string_t cmd_arp_del_default_default_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_del_default_result, - default_string, "default"); - -static cmdline_parse_inst_t cmd_arp_del_default = { - .f = cmd_arp_del_default_parsed, - .data = NULL, - .help_str = "ARP delete default", - .tokens = { - (void *)&cmd_arp_del_default_p_string, - (void *)&cmd_arp_del_default_p, - (void *)&cmd_arp_del_default_arp_string, - (void *)&cmd_arp_del_default_del_string, - (void *)&cmd_arp_del_default_default_string, - NULL, - }, -}; + } /* arp del */ + + /* arp del default */ + if ((n_tokens >= 2) && + (strcmp(tokens[0], "del") == 0) && + (strcmp(tokens[1], "default") == 0)) { + if (n_tokens != 2) { + printf(CMD_MSG_MISMATCH_ARGS, "arp del default"); + return; + } + + status = app_pipeline_routing_delete_default_arp_entry(app, + params->p); + if (status != 0) + printf(CMD_MSG_FAIL, "arp del default"); + + return; + } /* arp del default */ + + /* arp ls */ + if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) { + if (n_tokens != 1) { + printf(CMD_MSG_MISMATCH_ARGS, "arp ls"); + return; + } -/* - * arp ls - */ + status = app_pipeline_routing_arp_ls(app, params->p); + if (status != 0) + printf(CMD_MSG_FAIL, "arp ls"); -struct cmd_arp_ls_result { - cmdline_fixed_string_t p_string; - uint32_t p; - cmdline_fixed_string_t arp_string; - cmdline_fixed_string_t ls_string; -}; - -static void -cmd_arp_ls_parsed( - void *parsed_result, - __rte_unused struct cmdline *cl, - void *data) -{ - struct cmd_arp_ls_result *params = parsed_result; - struct app_params *app = data; - struct pipeline_routing *p; - - p = app_pipeline_data_fe(app, params->p, &pipeline_routing); - if (p == NULL) return; + } /* arp ls */ - app_pipeline_routing_arp_ls(app, params->p); + printf(CMD_MSG_FAIL, "arp"); } -static cmdline_parse_token_string_t cmd_arp_ls_p_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, p_string, - "p"); +static cmdline_parse_token_string_t cmd_arp_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p"); -static cmdline_parse_token_num_t cmd_arp_ls_p = - TOKEN_NUM_INITIALIZER(struct cmd_arp_ls_result, p, UINT32); +static cmdline_parse_token_num_t cmd_arp_p = + TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32); -static cmdline_parse_token_string_t cmd_arp_ls_arp_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, arp_string, - "arp"); +static cmdline_parse_token_string_t cmd_arp_arp_string = + TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp"); -static cmdline_parse_token_string_t cmd_arp_ls_ls_string = - TOKEN_STRING_INITIALIZER(struct cmd_arp_ls_result, ls_string, - "ls"); +static cmdline_parse_token_string_t cmd_arp_multi_string = + TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string, + TOKEN_STRING_MULTI); -static cmdline_parse_inst_t cmd_arp_ls = { - .f = cmd_arp_ls_parsed, +static cmdline_parse_inst_t cmd_arp = { + .f = cmd_arp_parsed, .data = NULL, - .help_str = "ARP list", + .help_str = "arp add / add default / del / del default / ls", .tokens = { - (void *)&cmd_arp_ls_p_string, - (void *)&cmd_arp_ls_p, - (void *)&cmd_arp_ls_arp_string, - (void *)&cmd_arp_ls_ls_string, + (void *)&cmd_arp_p_string, + (void *)&cmd_arp_p, + (void *)&cmd_arp_arp_string, + (void *)&cmd_arp_multi_string, NULL, }, }; static cmdline_parse_ctx_t pipeline_cmds[] = { - (cmdline_parse_inst_t *)&cmd_route_add1, - (cmdline_parse_inst_t *)&cmd_route_add2, - (cmdline_parse_inst_t *)&cmd_route_add3, - (cmdline_parse_inst_t *)&cmd_route_add4, - (cmdline_parse_inst_t *)&cmd_route_add5, - (cmdline_parse_inst_t *)&cmd_route_add6, - (cmdline_parse_inst_t *)&cmd_route_del, - (cmdline_parse_inst_t *)&cmd_route_add_default, - (cmdline_parse_inst_t *)&cmd_route_del_default, - (cmdline_parse_inst_t *)&cmd_route_ls, - (cmdline_parse_inst_t *)&cmd_arp_add, - (cmdline_parse_inst_t *)&cmd_arp_del, - (cmdline_parse_inst_t *)&cmd_arp_add_default, - (cmdline_parse_inst_t *)&cmd_arp_del_default, - (cmdline_parse_inst_t *)&cmd_arp_ls, + (cmdline_parse_inst_t *)&cmd_route, + (cmdline_parse_inst_t *)&cmd_arp, NULL, }; static struct pipeline_fe_ops pipeline_routing_fe_ops = { - .f_init = pipeline_routing_init, + .f_init = app_pipeline_routing_init, + .f_post_init = app_pipeline_routing_post_init, .f_free = app_pipeline_routing_free, + .f_track = app_pipeline_track_default, .cmds = pipeline_cmds, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing.h b/examples/ip_pipeline/pipeline/pipeline_routing.h index fa41642b..0197449b 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing.h +++ b/examples/ip_pipeline/pipeline/pipeline_routing.h @@ -86,6 +86,13 @@ app_pipeline_routing_delete_default_arp_entry(struct app_params *app, uint32_t pipeline_id); /* + * SETTINGS + */ +int +app_pipeline_routing_set_macaddr(struct app_params *app, + uint32_t pipeline_id); + +/* * Pipeline type */ extern struct pipeline_type pipeline_routing; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.c b/examples/ip_pipeline/pipeline/pipeline_routing_be.c index bc5bf7a5..21ac7888 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.c @@ -65,7 +65,9 @@ ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32)) -#define MAC_SRC_DEFAULT 0x112233445566ULL +/* Network Byte Order (NBO) */ +#define SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr, ethertype) \ + (((uint64_t) macaddr) | (((uint64_t) rte_cpu_to_be_16(ethertype)) << 48)) #ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s #define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256 @@ -75,6 +77,7 @@ struct pipeline_routing { struct pipeline p; struct pipeline_routing_params params; pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS]; + uint64_t macaddr[PIPELINE_MAX_PORT_OUT]; } __rte_cache_aligned; /* @@ -132,6 +135,10 @@ static void * pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg); +static void * +pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, + void *msg); + static pipeline_msg_req_handler custom_handlers[] = { [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] = pipeline_routing_msg_req_route_add_handler, @@ -149,6 +156,8 @@ static pipeline_msg_req_handler custom_handlers[] = { pipeline_routing_msg_req_arp_add_default_handler, [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] = pipeline_routing_msg_req_arp_del_default_handler, + [PIPELINE_ROUTING_MSG_REQ_SET_MACADDR] = + pipeline_routing_msg_req_set_macaddr_handler, }; /* @@ -921,6 +930,7 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p, struct pipeline_params *params) { uint32_t n_routes_present = 0; + uint32_t port_local_dest_present = 0; uint32_t encap_present = 0; uint32_t qinq_sched_present = 0; uint32_t mpls_color_mark_present = 0; @@ -933,6 +943,7 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p, /* default values */ p->n_routes = PIPELINE_ROUTING_N_ROUTES_DEFAULT; + p->port_local_dest = params->n_ports_out - 1; p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET; p->qinq_sched = 0; p->mpls_color_mark = 0; @@ -962,6 +973,23 @@ pipeline_routing_parse_args(struct pipeline_routing_params *p, continue; } + /* port_local_dest */ + if (strcmp(arg_name, "port_local_dest") == 0) { + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + port_local_dest_present == 0, params->name, + arg_name); + port_local_dest_present = 1; + + status = parser_read_uint32(&p->port_local_dest, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && + (p->port_local_dest < params->n_ports_out)), + params->name, arg_name, arg_value); + + continue; + } /* encap */ if (strcmp(arg_name, "encap") == 0) { @@ -1419,27 +1447,6 @@ pipeline_routing_free(void *pipeline) } static int -pipeline_routing_track(void *pipeline, - __rte_unused uint32_t port_in, - uint32_t *port_out) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - if (p->n_ports_in == 1) { - *port_out = 0; - return 0; - } - - return -1; -} - -static int pipeline_routing_timer(void *pipeline) { struct pipeline *p = (struct pipeline *) pipeline; @@ -1534,7 +1541,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether - ARP off */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) && (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t macaddr_dst; uint64_t ethertype = ETHER_TYPE_IPv4; @@ -1542,7 +1549,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) macaddr_dst = rte_bswap64(macaddr_dst << 16); entry_arp0.slab[0] = - rte_bswap64((macaddr_src << 16) | ethertype); + SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype); entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; entry_arp0.slab[1] = rte_bswap64(macaddr_dst); @@ -1556,11 +1563,11 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether - ARP on */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) && p_rt->params.n_arp_entries) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t ethertype = ETHER_TYPE_IPv4; - entry_arp1.slab[0] = rte_bswap64((macaddr_src << 16) | - ethertype); + entry_arp1.slab[0] = + SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype); entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; entry_arp1.data_offset = entry_arp1.slab_offset[0] - 6 @@ -1571,7 +1578,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether QinQ - ARP off */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t macaddr_dst; uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4; uint64_t ethertype_vlan = 0x8100; @@ -1588,8 +1595,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) ethertype_ipv4); entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; - entry_arp0.slab[1] = rte_bswap64((macaddr_src << 16) | - ethertype_qinq); + entry_arp0.slab[1] = + SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq); entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8; entry_arp0.slab[2] = rte_bswap64(macaddr_dst); @@ -1603,7 +1610,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether QinQ - ARP on */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) && p_rt->params.n_arp_entries) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4; uint64_t ethertype_vlan = 0x8100; uint64_t ethertype_qinq = 0x9100; @@ -1616,8 +1623,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) ethertype_ipv4); entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8; - entry_arp1.slab[1] = rte_bswap64((macaddr_src << 16) | - ethertype_qinq); + entry_arp1.slab[1] = + SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq); entry_arp1.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8; entry_arp1.data_offset = entry_arp1.slab_offset[1] - 6 @@ -1628,7 +1635,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether MPLS - ARP off */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && (p_rt->params.n_arp_entries == 0)) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t macaddr_dst; uint64_t ethertype_mpls = 0x8847; @@ -1697,8 +1704,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) return rsp; } - entry_arp0.slab[2] = rte_bswap64((macaddr_src << 16) | - ethertype_mpls); + entry_arp0.slab[2] = + SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls); entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset - (n_labels * 4 + 8); @@ -1714,7 +1721,7 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) /* Ether MPLS - ARP on */ if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) && p_rt->params.n_arp_entries) { - uint64_t macaddr_src = MAC_SRC_DEFAULT; + uint64_t macaddr_src = p_rt->macaddr[req->data.port_id]; uint64_t ethertype_mpls = 0x8847; uint64_t label0 = req->data.l2.mpls.labels[0]; @@ -1779,8 +1786,8 @@ pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg) return rsp; } - entry_arp1.slab[2] = rte_bswap64((macaddr_src << 16) | - ethertype_mpls); + entry_arp1.slab[2] = + SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls); entry_arp1.slab_offset[2] = p_rt->params.ip_hdr_offset - (n_labels * 4 + 8); @@ -1961,10 +1968,25 @@ pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg) return rsp; } +void * +pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, void *msg) +{ + struct pipeline_routing *p_rt = (struct pipeline_routing *) p; + struct pipeline_routing_set_macaddr_msg_req *req = msg; + struct pipeline_routing_set_macaddr_msg_rsp *rsp = msg; + uint32_t port_id; + + for (port_id = 0; port_id < p->n_ports_out; port_id++) + p_rt->macaddr[port_id] = req->macaddr[port_id]; + + rsp->status = 0; + + return rsp; +} + struct pipeline_be_ops pipeline_routing_be_ops = { .f_init = pipeline_routing_init, .f_free = pipeline_routing_free, .f_run = NULL, .f_timer = pipeline_routing_timer, - .f_track = pipeline_routing_track, }; diff --git a/examples/ip_pipeline/pipeline/pipeline_routing_be.h b/examples/ip_pipeline/pipeline/pipeline_routing_be.h index ec767b24..12763427 100644 --- a/examples/ip_pipeline/pipeline/pipeline_routing_be.h +++ b/examples/ip_pipeline/pipeline/pipeline_routing_be.h @@ -54,6 +54,7 @@ enum pipeline_routing_encap { struct pipeline_routing_params { /* routing */ uint32_t n_routes; + uint32_t port_local_dest; /* routing packet encapsulation */ enum pipeline_routing_encap encap; @@ -160,6 +161,7 @@ enum pipeline_routing_msg_req_type { PIPELINE_ROUTING_MSG_REQ_ARP_DEL, PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT, PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT, + PIPELINE_ROUTING_MSG_REQ_SET_MACADDR, PIPELINE_ROUTING_MSG_REQS }; @@ -291,6 +293,20 @@ struct pipeline_routing_arp_delete_default_msg_rsp { int status; }; +/* + * MSG SET MACADDR + */ +struct pipeline_routing_set_macaddr_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_routing_msg_req_type subtype; + + uint64_t macaddr[PIPELINE_MAX_PORT_OUT]; +}; + +struct pipeline_routing_set_macaddr_msg_rsp { + int status; +}; + extern struct pipeline_be_ops pipeline_routing_be_ops; #endif diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h index f4ff262e..b562472b 100644 --- a/examples/ip_pipeline/pipeline_be.h +++ b/examples/ip_pipeline/pipeline_be.h @@ -40,6 +40,9 @@ #include <rte_port_ras.h> #include <rte_port_sched.h> #include <rte_port_source_sink.h> +#ifdef RTE_LIBRTE_KNI +#include <rte_port_kni.h> +#endif #include <rte_pipeline.h> enum pipeline_port_in_type { @@ -49,6 +52,7 @@ enum pipeline_port_in_type { PIPELINE_PORT_IN_RING_READER_IPV4_FRAG, PIPELINE_PORT_IN_RING_READER_IPV6_FRAG, PIPELINE_PORT_IN_SCHED_READER, + PIPELINE_PORT_IN_KNI_READER, PIPELINE_PORT_IN_SOURCE, }; @@ -61,6 +65,9 @@ struct pipeline_port_in_params { struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag; struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag; struct rte_port_sched_reader_params sched; +#ifdef RTE_LIBRTE_KNI + struct rte_port_kni_reader_params kni; +#endif struct rte_port_source_params source; } params; uint32_t burst_size; @@ -82,6 +89,10 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params *p) return (void *) &p->params.ring_ipv6_frag; case PIPELINE_PORT_IN_SCHED_READER: return (void *) &p->params.sched; +#ifdef RTE_LIBRTE_KNI + case PIPELINE_PORT_IN_KNI_READER: + return (void *) &p->params.kni; +#endif case PIPELINE_PORT_IN_SOURCE: return (void *) &p->params.source; default: @@ -105,6 +116,10 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params *p) return &rte_port_ring_reader_ipv6_frag_ops; case PIPELINE_PORT_IN_SCHED_READER: return &rte_port_sched_reader_ops; +#ifdef RTE_LIBRTE_KNI + case PIPELINE_PORT_IN_KNI_READER: + return &rte_port_kni_reader_ops; +#endif case PIPELINE_PORT_IN_SOURCE: return &rte_port_source_ops; default: @@ -122,6 +137,8 @@ enum pipeline_port_out_type { PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS, PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS, PIPELINE_PORT_OUT_SCHED_WRITER, + PIPELINE_PORT_OUT_KNI_WRITER, + PIPELINE_PORT_OUT_KNI_WRITER_NODROP, PIPELINE_PORT_OUT_SINK, }; @@ -137,6 +154,10 @@ struct pipeline_port_out_params { struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras; struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras; struct rte_port_sched_writer_params sched; +#ifdef RTE_LIBRTE_KNI + struct rte_port_kni_writer_params kni; + struct rte_port_kni_writer_nodrop_params kni_nodrop; +#endif struct rte_port_sink_params sink; } params; }; @@ -163,6 +184,12 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params *p) return (void *) &p->params.ring_ipv6_ras; case PIPELINE_PORT_OUT_SCHED_WRITER: return (void *) &p->params.sched; +#ifdef RTE_LIBRTE_KNI + case PIPELINE_PORT_OUT_KNI_WRITER: + return (void *) &p->params.kni; + case PIPELINE_PORT_OUT_KNI_WRITER_NODROP: + return (void *) &p->params.kni_nodrop; +#endif case PIPELINE_PORT_OUT_SINK: return (void *) &p->params.sink; default: @@ -192,6 +219,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p) return &rte_port_ring_writer_ipv6_ras_ops; case PIPELINE_PORT_OUT_SCHED_WRITER: return &rte_port_sched_writer_ops; +#ifdef RTE_LIBRTE_KNI + case PIPELINE_PORT_OUT_KNI_WRITER: + return &rte_port_kni_writer_ops; + case PIPELINE_PORT_OUT_KNI_WRITER_NODROP: + return &rte_port_kni_writer_nodrop_ops; +#endif case PIPELINE_PORT_OUT_SINK: return &rte_port_sink_ops; default: @@ -200,15 +233,19 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p) } #ifndef PIPELINE_NAME_SIZE -#define PIPELINE_NAME_SIZE 32 +#define PIPELINE_NAME_SIZE 64 +#endif + +#ifndef PIPELINE_TYPE_SIZE +#define PIPELINE_TYPE_SIZE 64 #endif #ifndef PIPELINE_MAX_PORT_IN -#define PIPELINE_MAX_PORT_IN 16 +#define PIPELINE_MAX_PORT_IN 64 #endif #ifndef PIPELINE_MAX_PORT_OUT -#define PIPELINE_MAX_PORT_OUT 16 +#define PIPELINE_MAX_PORT_OUT 64 #endif #ifndef PIPELINE_MAX_TABLES @@ -224,11 +261,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p) #endif #ifndef PIPELINE_MAX_ARGS -#define PIPELINE_MAX_ARGS 32 +#define PIPELINE_MAX_ARGS 64 #endif struct pipeline_params { char name[PIPELINE_NAME_SIZE]; + char type[PIPELINE_TYPE_SIZE]; struct pipeline_port_in_params port_in[PIPELINE_MAX_PORT_IN]; struct pipeline_port_out_params port_out[PIPELINE_MAX_PORT_OUT]; @@ -261,16 +299,11 @@ typedef int (*pipeline_be_op_run)(void *pipeline); typedef int (*pipeline_be_op_timer)(void *pipeline); -typedef int (*pipeline_be_op_track)(void *pipeline, - uint32_t port_in, - uint32_t *port_out); - struct pipeline_be_ops { pipeline_be_op_init f_init; pipeline_be_op_free f_free; pipeline_be_op_run f_run; pipeline_be_op_timer f_timer; - pipeline_be_op_track f_track; }; /* Pipeline specific config parse error messages */ diff --git a/examples/ip_pipeline/thread_fe.c b/examples/ip_pipeline/thread_fe.c index 4a435f7c..6c547ca5 100644 --- a/examples/ip_pipeline/thread_fe.c +++ b/examples/ip_pipeline/thread_fe.c @@ -5,10 +5,6 @@ #include <cmdline_parse.h> #include <cmdline_parse_num.h> #include <cmdline_parse_string.h> -#include <cmdline_parse_ipaddr.h> -#include <cmdline_parse_etheraddr.h> -#include <cmdline_socket.h> -#include <cmdline.h> #include "thread.h" #include "thread_fe.h" @@ -85,6 +81,9 @@ app_pipeline_enable(struct app_params *app, p_params = &app->pipeline_params[pipeline_id]; p_type = app_pipeline_type_find(app, p_params->type); + if (p_type == NULL) + return -1; + if (p->enabled == 1) return -1; @@ -259,26 +258,26 @@ cmd_pipeline_enable_parsed( printf("Command failed\n"); } -cmdline_parse_token_string_t cmd_pipeline_enable_t_string = +static cmdline_parse_token_string_t cmd_pipeline_enable_t_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_string, "t"); -cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string = +static cmdline_parse_token_string_t cmd_pipeline_enable_t_id_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, t_id_string, NULL); -cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string = +static cmdline_parse_token_string_t cmd_pipeline_enable_pipeline_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_string, "pipeline"); -cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id = +static cmdline_parse_token_num_t cmd_pipeline_enable_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_pipeline_enable_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_pipeline_enable_enable_string = +static cmdline_parse_token_string_t cmd_pipeline_enable_enable_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_enable_result, enable_string, "enable"); -cmdline_parse_inst_t cmd_pipeline_enable = { +static cmdline_parse_inst_t cmd_pipeline_enable = { .f = cmd_pipeline_enable_parsed, .data = NULL, .help_str = "Enable pipeline on specified core", @@ -333,26 +332,26 @@ cmd_pipeline_disable_parsed( printf("Command failed\n"); } -cmdline_parse_token_string_t cmd_pipeline_disable_t_string = +static cmdline_parse_token_string_t cmd_pipeline_disable_t_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_string, "t"); -cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string = +static cmdline_parse_token_string_t cmd_pipeline_disable_t_id_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, t_id_string, NULL); -cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string = +static cmdline_parse_token_string_t cmd_pipeline_disable_pipeline_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_string, "pipeline"); -cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id = +static cmdline_parse_token_num_t cmd_pipeline_disable_pipeline_id = TOKEN_NUM_INITIALIZER(struct cmd_pipeline_disable_result, pipeline_id, UINT32); -cmdline_parse_token_string_t cmd_pipeline_disable_disable_string = +static cmdline_parse_token_string_t cmd_pipeline_disable_disable_string = TOKEN_STRING_INITIALIZER(struct cmd_pipeline_disable_result, disable_string, "disable"); -cmdline_parse_inst_t cmd_pipeline_disable = { +static cmdline_parse_inst_t cmd_pipeline_disable = { .f = cmd_pipeline_disable_parsed, .data = NULL, .help_str = "Disable pipeline on specified core", @@ -405,19 +404,19 @@ cmd_thread_headroom_parsed( printf("Command failed\n"); } -cmdline_parse_token_string_t cmd_thread_headroom_t_string = +static cmdline_parse_token_string_t cmd_thread_headroom_t_string = TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result, t_string, "t"); -cmdline_parse_token_string_t cmd_thread_headroom_t_id_string = +static cmdline_parse_token_string_t cmd_thread_headroom_t_id_string = TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result, t_id_string, NULL); -cmdline_parse_token_string_t cmd_thread_headroom_headroom_string = +static cmdline_parse_token_string_t cmd_thread_headroom_headroom_string = TOKEN_STRING_INITIALIZER(struct cmd_thread_headroom_result, headroom_string, "headroom"); -cmdline_parse_inst_t cmd_thread_headroom = { +static cmdline_parse_inst_t cmd_thread_headroom = { .f = cmd_thread_headroom_parsed, .data = NULL, .help_str = "Display thread headroom", |