examples/ip_pipeline: fix resource leak
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_flow_classification.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/queue.h>
37 #include <netinet/in.h>
38
39 #include <rte_common.h>
40 #include <rte_hexdump.h>
41 #include <rte_malloc.h>
42 #include <cmdline_rdline.h>
43 #include <cmdline_parse.h>
44 #include <cmdline_parse_num.h>
45 #include <cmdline_parse_string.h>
46 #include <cmdline_parse_ipaddr.h>
47 #include <cmdline_parse_etheraddr.h>
48
49 #include "app.h"
50 #include "pipeline_common_fe.h"
51 #include "pipeline_flow_classification.h"
52 #include "hash_func.h"
53
54 /*
55  * Key conversion
56  */
57
58 struct pkt_key_qinq {
59         uint16_t ethertype_svlan;
60         uint16_t svlan;
61         uint16_t ethertype_cvlan;
62         uint16_t cvlan;
63 } __attribute__((__packed__));
64
65 struct pkt_key_ipv4_5tuple {
66         uint8_t ttl;
67         uint8_t proto;
68         uint16_t checksum;
69         uint32_t ip_src;
70         uint32_t ip_dst;
71         uint16_t port_src;
72         uint16_t port_dst;
73 } __attribute__((__packed__));
74
75 struct pkt_key_ipv6_5tuple {
76         uint16_t payload_length;
77         uint8_t proto;
78         uint8_t hop_limit;
79         uint8_t ip_src[16];
80         uint8_t ip_dst[16];
81         uint16_t port_src;
82         uint16_t port_dst;
83 } __attribute__((__packed__));
84
85 static int
86 app_pipeline_fc_key_convert(struct pipeline_fc_key *key_in,
87         uint8_t *key_out,
88         uint32_t *signature)
89 {
90         uint8_t buffer[PIPELINE_FC_FLOW_KEY_MAX_SIZE];
91         void *key_buffer = (key_out) ? key_out : buffer;
92
93         switch (key_in->type) {
94         case FLOW_KEY_QINQ:
95         {
96                 struct pkt_key_qinq *qinq = key_buffer;
97
98                 qinq->ethertype_svlan = 0;
99                 qinq->svlan = rte_bswap16(key_in->key.qinq.svlan);
100                 qinq->ethertype_cvlan = 0;
101                 qinq->cvlan = rte_bswap16(key_in->key.qinq.cvlan);
102
103                 if (signature)
104                         *signature = (uint32_t) hash_default_key8(qinq, 8, 0);
105                 return 0;
106         }
107
108         case FLOW_KEY_IPV4_5TUPLE:
109         {
110                 struct pkt_key_ipv4_5tuple *ipv4 = key_buffer;
111
112                 ipv4->ttl = 0;
113                 ipv4->proto = key_in->key.ipv4_5tuple.proto;
114                 ipv4->checksum = 0;
115                 ipv4->ip_src = rte_bswap32(key_in->key.ipv4_5tuple.ip_src);
116                 ipv4->ip_dst = rte_bswap32(key_in->key.ipv4_5tuple.ip_dst);
117                 ipv4->port_src = rte_bswap16(key_in->key.ipv4_5tuple.port_src);
118                 ipv4->port_dst = rte_bswap16(key_in->key.ipv4_5tuple.port_dst);
119
120                 if (signature)
121                         *signature = (uint32_t) hash_default_key16(ipv4, 16, 0);
122                 return 0;
123         }
124
125         case FLOW_KEY_IPV6_5TUPLE:
126         {
127                 struct pkt_key_ipv6_5tuple *ipv6 = key_buffer;
128
129                 memset(ipv6, 0, 64);
130                 ipv6->payload_length = 0;
131                 ipv6->proto = key_in->key.ipv6_5tuple.proto;
132                 ipv6->hop_limit = 0;
133                 memcpy(&ipv6->ip_src, &key_in->key.ipv6_5tuple.ip_src, 16);
134                 memcpy(&ipv6->ip_dst, &key_in->key.ipv6_5tuple.ip_dst, 16);
135                 ipv6->port_src = rte_bswap16(key_in->key.ipv6_5tuple.port_src);
136                 ipv6->port_dst = rte_bswap16(key_in->key.ipv6_5tuple.port_dst);
137
138                 if (signature)
139                         *signature = (uint32_t) hash_default_key64(ipv6, 64, 0);
140                 return 0;
141         }
142
143         default:
144                 return -1;
145         }
146 }
147
148 /*
149  * Flow classification pipeline
150  */
151
152 struct app_pipeline_fc_flow {
153         struct pipeline_fc_key key;
154         uint32_t port_id;
155         uint32_t signature;
156         void *entry_ptr;
157
158         TAILQ_ENTRY(app_pipeline_fc_flow) node;
159 };
160
161 #define N_BUCKETS                                65536
162
163 struct app_pipeline_fc {
164         /* Parameters */
165         uint32_t n_ports_in;
166         uint32_t n_ports_out;
167
168         /* Flows */
169         TAILQ_HEAD(, app_pipeline_fc_flow) flows[N_BUCKETS];
170         uint32_t n_flows;
171
172         /* Default flow */
173         uint32_t default_flow_present;
174         uint32_t default_flow_port_id;
175         void *default_flow_entry_ptr;
176 };
177
178 static struct app_pipeline_fc_flow *
179 app_pipeline_fc_flow_find(struct app_pipeline_fc *p,
180         struct pipeline_fc_key *key)
181 {
182         struct app_pipeline_fc_flow *f;
183         uint32_t signature, bucket_id;
184
185         app_pipeline_fc_key_convert(key, NULL, &signature);
186         bucket_id = signature & (N_BUCKETS - 1);
187
188         TAILQ_FOREACH(f, &p->flows[bucket_id], node)
189                 if ((signature == f->signature) &&
190                         (memcmp(key,
191                                 &f->key,
192                                 sizeof(struct pipeline_fc_key)) == 0))
193                         return f;
194
195         return NULL;
196 }
197
198 static void*
199 app_pipeline_fc_init(struct pipeline_params *params,
200         __rte_unused void *arg)
201 {
202         struct app_pipeline_fc *p;
203         uint32_t size, i;
204
205         /* Check input arguments */
206         if ((params == NULL) ||
207                 (params->n_ports_in == 0) ||
208                 (params->n_ports_out == 0))
209                 return NULL;
210
211         /* Memory allocation */
212         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fc));
213         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
214         if (p == NULL)
215                 return NULL;
216
217         /* Initialization */
218         p->n_ports_in = params->n_ports_in;
219         p->n_ports_out = params->n_ports_out;
220
221         for (i = 0; i < N_BUCKETS; i++)
222                 TAILQ_INIT(&p->flows[i]);
223         p->n_flows = 0;
224
225         return (void *) p;
226 }
227
228 static int
229 app_pipeline_fc_free(void *pipeline)
230 {
231         struct app_pipeline_fc *p = pipeline;
232         uint32_t i;
233
234         /* Check input arguments */
235         if (p == NULL)
236                 return -1;
237
238         /* Free resources */
239         for (i = 0; i < N_BUCKETS; i++)
240                 while (!TAILQ_EMPTY(&p->flows[i])) {
241                         struct app_pipeline_fc_flow *flow;
242
243                         flow = TAILQ_FIRST(&p->flows[i]);
244                         TAILQ_REMOVE(&p->flows[i], flow, node);
245                         rte_free(flow);
246                 }
247
248         rte_free(p);
249         return 0;
250 }
251
252 static int
253 app_pipeline_fc_key_check(struct pipeline_fc_key *key)
254 {
255         switch (key->type) {
256         case FLOW_KEY_QINQ:
257         {
258                 uint16_t svlan = key->key.qinq.svlan;
259                 uint16_t cvlan = key->key.qinq.cvlan;
260
261                 if ((svlan & 0xF000) ||
262                         (cvlan & 0xF000))
263                         return -1;
264
265                 return 0;
266         }
267
268         case FLOW_KEY_IPV4_5TUPLE:
269                 return 0;
270
271         case FLOW_KEY_IPV6_5TUPLE:
272                 return 0;
273
274         default:
275                 return -1;
276         }
277 }
278
279 int
280 app_pipeline_fc_add(struct app_params *app,
281         uint32_t pipeline_id,
282         struct pipeline_fc_key *key,
283         uint32_t port_id)
284 {
285         struct app_pipeline_fc *p;
286         struct app_pipeline_fc_flow *flow;
287
288         struct pipeline_fc_add_msg_req *req;
289         struct pipeline_fc_add_msg_rsp *rsp;
290
291         uint32_t signature;
292         int new_flow;
293
294         /* Check input arguments */
295         if ((app == NULL) ||
296                 (key == NULL))
297                 return -1;
298
299         p = app_pipeline_data_fe(app, pipeline_id);
300         if (p == NULL)
301                 return -1;
302
303         if (port_id >= p->n_ports_out)
304                 return -1;
305
306         if (app_pipeline_fc_key_check(key) != 0)
307                 return -1;
308
309         /* Find existing flow or allocate new flow */
310         flow = app_pipeline_fc_flow_find(p, key);
311         new_flow = (flow == NULL);
312         if (flow == NULL) {
313                 flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE);
314
315                 if (flow == NULL)
316                         return -1;
317         }
318
319         /* Allocate and write request */
320         req = app_msg_alloc(app);
321         if (req == NULL)
322                 return -1;
323
324         req->type = PIPELINE_MSG_REQ_CUSTOM;
325         req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD;
326         app_pipeline_fc_key_convert(key, req->key, &signature);
327         req->port_id = port_id;
328
329         /* Send request and wait for response */
330         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
331         if (rsp == NULL) {
332                 if (new_flow)
333                         rte_free(flow);
334                 return -1;
335         }
336
337         /* Read response and write flow */
338         if (rsp->status ||
339                 (rsp->entry_ptr == NULL) ||
340                 ((new_flow == 0) && (rsp->key_found == 0)) ||
341                 ((new_flow == 1) && (rsp->key_found == 1))) {
342                 app_msg_free(app, rsp);
343                 if (new_flow)
344                         rte_free(flow);
345                 return -1;
346         }
347
348         memset(&flow->key, 0, sizeof(flow->key));
349         memcpy(&flow->key, key, sizeof(flow->key));
350         flow->port_id = port_id;
351         flow->signature = signature;
352         flow->entry_ptr = rsp->entry_ptr;
353
354         /* Commit rule */
355         if (new_flow) {
356                 uint32_t bucket_id = signature & (N_BUCKETS - 1);
357
358                 TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow, node);
359                 p->n_flows++;
360         }
361
362         /* Free response */
363         app_msg_free(app, rsp);
364
365         return 0;
366 }
367
368 int
369 app_pipeline_fc_add_bulk(struct app_params *app,
370         uint32_t pipeline_id,
371         struct pipeline_fc_key *key,
372         uint32_t *port_id,
373         uint32_t n_keys)
374 {
375         struct app_pipeline_fc *p;
376         struct pipeline_fc_add_bulk_msg_req *req;
377         struct pipeline_fc_add_bulk_msg_rsp *rsp;
378
379         struct app_pipeline_fc_flow **flow;
380         uint32_t *signature;
381         int *new_flow;
382         struct pipeline_fc_add_bulk_flow_req *flow_req;
383         struct pipeline_fc_add_bulk_flow_rsp *flow_rsp;
384
385         uint32_t i;
386         int status;
387
388         /* Check input arguments */
389         if ((app == NULL) ||
390                 (key == NULL) ||
391                 (port_id == NULL) ||
392                 (n_keys == 0))
393                 return -1;
394
395         p = app_pipeline_data_fe(app, pipeline_id);
396         if (p == NULL)
397                 return -1;
398
399         for (i = 0; i < n_keys; i++)
400                 if (port_id[i] >= p->n_ports_out)
401                         return -1;
402
403         for (i = 0; i < n_keys; i++)
404                 if (app_pipeline_fc_key_check(&key[i]) != 0)
405                         return -1;
406
407         /* Memory allocation */
408         flow = rte_malloc(NULL,
409                 n_keys * sizeof(struct app_pipeline_fc_flow *),
410                 RTE_CACHE_LINE_SIZE);
411         if (flow == NULL)
412                 return -1;
413
414         signature = rte_malloc(NULL,
415                 n_keys * sizeof(uint32_t),
416                 RTE_CACHE_LINE_SIZE);
417         if (signature == NULL) {
418                 rte_free(flow);
419                 return -1;
420         }
421
422         new_flow = rte_malloc(
423                 NULL,
424                 n_keys * sizeof(int),
425                 RTE_CACHE_LINE_SIZE);
426         if (new_flow == NULL) {
427                 rte_free(signature);
428                 rte_free(flow);
429                 return -1;
430         }
431
432         flow_req = rte_malloc(NULL,
433                 n_keys * sizeof(struct pipeline_fc_add_bulk_flow_req),
434                 RTE_CACHE_LINE_SIZE);
435         if (flow_req == NULL) {
436                 rte_free(new_flow);
437                 rte_free(signature);
438                 rte_free(flow);
439                 return -1;
440         }
441
442         flow_rsp = rte_malloc(NULL,
443                 n_keys * sizeof(struct pipeline_fc_add_bulk_flow_rsp),
444                 RTE_CACHE_LINE_SIZE);
445         if (flow_req == NULL) {
446                 rte_free(flow_req);
447                 rte_free(new_flow);
448                 rte_free(signature);
449                 rte_free(flow);
450                 return -1;
451         }
452
453         /* Find existing flow or allocate new flow */
454         for (i = 0; i < n_keys; i++) {
455                 flow[i] = app_pipeline_fc_flow_find(p, &key[i]);
456                 new_flow[i] = (flow[i] == NULL);
457                 if (flow[i] == NULL) {
458                         flow[i] = rte_zmalloc(NULL,
459                                 sizeof(struct app_pipeline_fc_flow),
460                                 RTE_CACHE_LINE_SIZE);
461
462                         if (flow[i] == NULL) {
463                                 uint32_t j;
464
465                                 for (j = 0; j < i; j++)
466                                         if (new_flow[j])
467                                                 rte_free(flow[j]);
468
469                                 rte_free(flow_rsp);
470                                 rte_free(flow_req);
471                                 rte_free(new_flow);
472                                 rte_free(signature);
473                                 rte_free(flow);
474                                 return -1;
475                         }
476                 }
477         }
478
479         /* Allocate and write request */
480         req = app_msg_alloc(app);
481         if (req == NULL) {
482                 for (i = 0; i < n_keys; i++)
483                         if (new_flow[i])
484                                 rte_free(flow[i]);
485
486                 rte_free(flow_rsp);
487                 rte_free(flow_req);
488                 rte_free(new_flow);
489                 rte_free(signature);
490                 rte_free(flow);
491                 return -1;
492         }
493
494         for (i = 0; i < n_keys; i++) {
495                 app_pipeline_fc_key_convert(&key[i],
496                         flow_req[i].key,
497                         &signature[i]);
498                 flow_req[i].port_id = port_id[i];
499         }
500
501         req->type = PIPELINE_MSG_REQ_CUSTOM;
502         req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_BULK;
503         req->req = flow_req;
504         req->rsp = flow_rsp;
505         req->n_keys = n_keys;
506
507         /* Send request and wait for response */
508         rsp = app_msg_send_recv(app, pipeline_id, req, 10000);
509         if (rsp == NULL) {
510                 for (i = 0; i < n_keys; i++)
511                         if (new_flow[i])
512                                 rte_free(flow[i]);
513
514                 rte_free(flow_rsp);
515                 rte_free(flow_req);
516                 rte_free(new_flow);
517                 rte_free(signature);
518                 rte_free(flow);
519                 return -1;
520         }
521
522         /* Read response */
523         status = 0;
524
525         for (i = 0; i < rsp->n_keys; i++)
526                 if ((flow_rsp[i].entry_ptr == NULL) ||
527                         ((new_flow[i] == 0) && (flow_rsp[i].key_found == 0)) ||
528                         ((new_flow[i] == 1) && (flow_rsp[i].key_found == 1)))
529                         status = -1;
530
531         if (rsp->n_keys < n_keys)
532                 status = -1;
533
534         /* Commit flows */
535         for (i = 0; i < rsp->n_keys; i++) {
536                 memcpy(&flow[i]->key, &key[i], sizeof(flow[i]->key));
537                 flow[i]->port_id = port_id[i];
538                 flow[i]->signature = signature[i];
539                 flow[i]->entry_ptr = flow_rsp[i].entry_ptr;
540
541                 if (new_flow[i]) {
542                         uint32_t bucket_id = signature[i] & (N_BUCKETS - 1);
543
544                         TAILQ_INSERT_TAIL(&p->flows[bucket_id], flow[i], node);
545                         p->n_flows++;
546                 }
547         }
548
549         /* Free resources */
550         app_msg_free(app, rsp);
551
552         for (i = rsp->n_keys; i < n_keys; i++)
553                 if (new_flow[i])
554                         rte_free(flow[i]);
555
556         rte_free(flow_rsp);
557         rte_free(flow_req);
558         rte_free(new_flow);
559         rte_free(signature);
560         rte_free(flow);
561
562         return status;
563 }
564
565 int
566 app_pipeline_fc_del(struct app_params *app,
567         uint32_t pipeline_id,
568         struct pipeline_fc_key *key)
569 {
570         struct app_pipeline_fc *p;
571         struct app_pipeline_fc_flow *flow;
572
573         struct pipeline_fc_del_msg_req *req;
574         struct pipeline_fc_del_msg_rsp *rsp;
575
576         uint32_t signature, bucket_id;
577
578         /* Check input arguments */
579         if ((app == NULL) ||
580                 (key == NULL))
581                 return -1;
582
583         p = app_pipeline_data_fe(app, pipeline_id);
584         if (p == NULL)
585                 return -1;
586
587         if (app_pipeline_fc_key_check(key) != 0)
588                 return -1;
589
590         /* Find rule */
591         flow = app_pipeline_fc_flow_find(p, key);
592         if (flow == NULL)
593                 return 0;
594
595         /* Allocate and write request */
596         req = app_msg_alloc(app);
597         if (req == NULL)
598                 return -1;
599
600         req->type = PIPELINE_MSG_REQ_CUSTOM;
601         req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL;
602         app_pipeline_fc_key_convert(key, req->key, &signature);
603
604         /* Send request and wait for response */
605         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
606         if (rsp == NULL)
607                 return -1;
608
609         /* Read response */
610         if (rsp->status || !rsp->key_found) {
611                 app_msg_free(app, rsp);
612                 return -1;
613         }
614
615         /* Remove rule */
616         bucket_id = signature & (N_BUCKETS - 1);
617         TAILQ_REMOVE(&p->flows[bucket_id], flow, node);
618         p->n_flows--;
619         rte_free(flow);
620
621         /* Free response */
622         app_msg_free(app, rsp);
623
624         return 0;
625 }
626
627 int
628 app_pipeline_fc_add_default(struct app_params *app,
629         uint32_t pipeline_id,
630         uint32_t port_id)
631 {
632         struct app_pipeline_fc *p;
633
634         struct pipeline_fc_add_default_msg_req *req;
635         struct pipeline_fc_add_default_msg_rsp *rsp;
636
637         /* Check input arguments */
638         if (app == NULL)
639                 return -1;
640
641         p = app_pipeline_data_fe(app, pipeline_id);
642         if (p == NULL)
643                 return -1;
644
645         if (port_id >= p->n_ports_out)
646                 return -1;
647
648         /* Allocate and write request */
649         req = app_msg_alloc(app);
650         if (req == NULL)
651                 return -1;
652
653         req->type = PIPELINE_MSG_REQ_CUSTOM;
654         req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT;
655         req->port_id = port_id;
656
657         /* Send request and wait for response */
658         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
659         if (rsp == NULL)
660                 return -1;
661
662         /* Read response and write flow */
663         if (rsp->status || (rsp->entry_ptr == NULL)) {
664                 app_msg_free(app, rsp);
665                 return -1;
666         }
667
668         p->default_flow_port_id = port_id;
669         p->default_flow_entry_ptr = rsp->entry_ptr;
670
671         /* Commit route */
672         p->default_flow_present = 1;
673
674         /* Free response */
675         app_msg_free(app, rsp);
676
677         return 0;
678 }
679
680 int
681 app_pipeline_fc_del_default(struct app_params *app,
682         uint32_t pipeline_id)
683 {
684         struct app_pipeline_fc *p;
685
686         struct pipeline_fc_del_default_msg_req *req;
687         struct pipeline_fc_del_default_msg_rsp *rsp;
688
689         /* Check input arguments */
690         if (app == NULL)
691                 return -1;
692
693         p = app_pipeline_data_fe(app, pipeline_id);
694         if (p == NULL)
695                 return -EINVAL;
696
697         /* Allocate and write request */
698         req = app_msg_alloc(app);
699         if (req == NULL)
700                 return -1;
701
702         req->type = PIPELINE_MSG_REQ_CUSTOM;
703         req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT;
704
705         /* Send request and wait for response */
706         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
707         if (rsp == NULL)
708                 return -1;
709
710         /* Read response */
711         if (rsp->status) {
712                 app_msg_free(app, rsp);
713                 return -1;
714         }
715
716         /* Commit route */
717         p->default_flow_present = 0;
718
719         /* Free response */
720         app_msg_free(app, rsp);
721
722         return 0;
723 }
724
725 /*
726  * Flow ls
727  */
728
729 static void
730 print_fc_qinq_flow(struct app_pipeline_fc_flow *flow)
731 {
732         printf("(SVLAN = %" PRIu32 ", "
733                 "CVLAN = %" PRIu32 ") => "
734                 "Port = %" PRIu32 " "
735                 "(signature = 0x%08" PRIx32 ", "
736                 "entry_ptr = %p)\n",
737
738                 flow->key.key.qinq.svlan,
739                 flow->key.key.qinq.cvlan,
740                 flow->port_id,
741                 flow->signature,
742                 flow->entry_ptr);
743 }
744
745 static void
746 print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow)
747 {
748         printf("(SA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", "
749                    "DA = %" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 ", "
750                    "SP = %" PRIu32 ", "
751                    "DP = %" PRIu32 ", "
752                    "Proto = %" PRIu32 ") => "
753                    "Port = %" PRIu32 " "
754                    "(signature = 0x%08" PRIx32 ", "
755                    "entry_ptr = %p)\n",
756
757                    (flow->key.key.ipv4_5tuple.ip_src >> 24) & 0xFF,
758                    (flow->key.key.ipv4_5tuple.ip_src >> 16) & 0xFF,
759                    (flow->key.key.ipv4_5tuple.ip_src >> 8) & 0xFF,
760                    flow->key.key.ipv4_5tuple.ip_src & 0xFF,
761
762                    (flow->key.key.ipv4_5tuple.ip_dst >> 24) & 0xFF,
763                    (flow->key.key.ipv4_5tuple.ip_dst >> 16) & 0xFF,
764                    (flow->key.key.ipv4_5tuple.ip_dst >> 8) & 0xFF,
765                    flow->key.key.ipv4_5tuple.ip_dst & 0xFF,
766
767                    flow->key.key.ipv4_5tuple.port_src,
768                    flow->key.key.ipv4_5tuple.port_dst,
769
770                    flow->key.key.ipv4_5tuple.proto,
771
772                    flow->port_id,
773                    flow->signature,
774                    flow->entry_ptr);
775 }
776
777 static void
778 print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow) {
779         printf("(SA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
780                 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
781                 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
782                 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", "
783                 "DA = %02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
784                 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
785                 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32
786                 ":%02" PRIx32 "%02" PRIx32 ":%02" PRIx32 "%02" PRIx32 ", "
787                 "SP = %" PRIu32 ", "
788                 "DP = %" PRIu32 " "
789                 "Proto = %" PRIu32 " "
790                 "=> Port = %" PRIu32 " "
791                 "(signature = 0x%08" PRIx32 ", "
792                 "entry_ptr = %p)\n",
793
794                 flow->key.key.ipv6_5tuple.ip_src[0],
795                 flow->key.key.ipv6_5tuple.ip_src[1],
796                 flow->key.key.ipv6_5tuple.ip_src[2],
797                 flow->key.key.ipv6_5tuple.ip_src[3],
798                 flow->key.key.ipv6_5tuple.ip_src[4],
799                 flow->key.key.ipv6_5tuple.ip_src[5],
800                 flow->key.key.ipv6_5tuple.ip_src[6],
801                 flow->key.key.ipv6_5tuple.ip_src[7],
802                 flow->key.key.ipv6_5tuple.ip_src[8],
803                 flow->key.key.ipv6_5tuple.ip_src[9],
804                 flow->key.key.ipv6_5tuple.ip_src[10],
805                 flow->key.key.ipv6_5tuple.ip_src[11],
806                 flow->key.key.ipv6_5tuple.ip_src[12],
807                 flow->key.key.ipv6_5tuple.ip_src[13],
808                 flow->key.key.ipv6_5tuple.ip_src[14],
809                 flow->key.key.ipv6_5tuple.ip_src[15],
810
811                 flow->key.key.ipv6_5tuple.ip_dst[0],
812                 flow->key.key.ipv6_5tuple.ip_dst[1],
813                 flow->key.key.ipv6_5tuple.ip_dst[2],
814                 flow->key.key.ipv6_5tuple.ip_dst[3],
815                 flow->key.key.ipv6_5tuple.ip_dst[4],
816                 flow->key.key.ipv6_5tuple.ip_dst[5],
817                 flow->key.key.ipv6_5tuple.ip_dst[6],
818                 flow->key.key.ipv6_5tuple.ip_dst[7],
819                 flow->key.key.ipv6_5tuple.ip_dst[8],
820                 flow->key.key.ipv6_5tuple.ip_dst[9],
821                 flow->key.key.ipv6_5tuple.ip_dst[10],
822                 flow->key.key.ipv6_5tuple.ip_dst[11],
823                 flow->key.key.ipv6_5tuple.ip_dst[12],
824                 flow->key.key.ipv6_5tuple.ip_dst[13],
825                 flow->key.key.ipv6_5tuple.ip_dst[14],
826                 flow->key.key.ipv6_5tuple.ip_dst[15],
827
828                 flow->key.key.ipv6_5tuple.port_src,
829                 flow->key.key.ipv6_5tuple.port_dst,
830
831                 flow->key.key.ipv6_5tuple.proto,
832
833                 flow->port_id,
834                 flow->signature,
835                 flow->entry_ptr);
836 }
837
838 static void
839 print_fc_flow(struct app_pipeline_fc_flow *flow)
840 {
841         switch (flow->key.type) {
842         case FLOW_KEY_QINQ:
843                 print_fc_qinq_flow(flow);
844                 break;
845
846         case FLOW_KEY_IPV4_5TUPLE:
847                 print_fc_ipv4_5tuple_flow(flow);
848                 break;
849
850         case FLOW_KEY_IPV6_5TUPLE:
851                 print_fc_ipv6_5tuple_flow(flow);
852                 break;
853         }
854 }
855
856 static int
857 app_pipeline_fc_ls(struct app_params *app,
858                 uint32_t pipeline_id)
859 {
860         struct app_pipeline_fc *p;
861         struct app_pipeline_fc_flow *flow;
862         uint32_t i;
863
864         /* Check input arguments */
865         if (app == NULL)
866                 return -1;
867
868         p = app_pipeline_data_fe(app, pipeline_id);
869         if (p == NULL)
870                 return -1;
871
872         for (i = 0; i < N_BUCKETS; i++)
873                 TAILQ_FOREACH(flow, &p->flows[i], node)
874                         print_fc_flow(flow);
875
876         if (p->default_flow_present)
877                 printf("Default flow: port %" PRIu32 " (entry ptr = %p)\n",
878                         p->default_flow_port_id,
879                         p->default_flow_entry_ptr);
880         else
881                 printf("Default: DROP\n");
882
883         return 0;
884 }
885
886 /*
887  * flow add qinq
888  */
889
890 struct cmd_fc_add_qinq_result {
891         cmdline_fixed_string_t p_string;
892         uint32_t pipeline_id;
893         cmdline_fixed_string_t flow_string;
894         cmdline_fixed_string_t add_string;
895         cmdline_fixed_string_t qinq_string;
896         uint16_t svlan;
897         uint16_t cvlan;
898         uint32_t port;
899 };
900
901 static void
902 cmd_fc_add_qinq_parsed(
903         void *parsed_result,
904         __rte_unused struct cmdline *cl,
905         void *data)
906 {
907         struct cmd_fc_add_qinq_result *params = parsed_result;
908         struct app_params *app = data;
909         struct pipeline_fc_key key;
910         int status;
911
912         memset(&key, 0, sizeof(key));
913         key.type = FLOW_KEY_QINQ;
914         key.key.qinq.svlan = params->svlan;
915         key.key.qinq.cvlan = params->cvlan;
916
917         status = app_pipeline_fc_add(app,
918                 params->pipeline_id,
919                 &key,
920                 params->port);
921         if (status != 0)
922                 printf("Command failed\n");
923 }
924
925 cmdline_parse_token_string_t cmd_fc_add_qinq_p_string =
926         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, p_string, "p");
927
928 cmdline_parse_token_num_t cmd_fc_add_qinq_pipeline_id =
929         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, pipeline_id,
930                 UINT32);
931
932 cmdline_parse_token_string_t cmd_fc_add_qinq_flow_string =
933         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flow_string,
934                 "flow");
935
936 cmdline_parse_token_string_t cmd_fc_add_qinq_add_string =
937         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string,
938                 "add");
939
940 cmdline_parse_token_string_t cmd_fc_add_qinq_qinq_string =
941         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, qinq_string,
942                 "qinq");
943
944 cmdline_parse_token_num_t cmd_fc_add_qinq_svlan =
945         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, svlan, UINT16);
946
947 cmdline_parse_token_num_t cmd_fc_add_qinq_cvlan =
948         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, cvlan, UINT16);
949
950 cmdline_parse_token_num_t cmd_fc_add_qinq_port =
951         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT32);
952
953 cmdline_parse_inst_t cmd_fc_add_qinq = {
954         .f = cmd_fc_add_qinq_parsed,
955         .data = NULL,
956         .help_str = "Flow add (Q-in-Q)",
957         .tokens = {
958                 (void *) &cmd_fc_add_qinq_p_string,
959                 (void *) &cmd_fc_add_qinq_pipeline_id,
960                 (void *) &cmd_fc_add_qinq_flow_string,
961                 (void *) &cmd_fc_add_qinq_add_string,
962                 (void *) &cmd_fc_add_qinq_qinq_string,
963                 (void *) &cmd_fc_add_qinq_svlan,
964                 (void *) &cmd_fc_add_qinq_cvlan,
965                 (void *) &cmd_fc_add_qinq_port,
966                 NULL,
967         },
968 };
969
970 /*
971  * flow add qinq all
972  */
973
974 struct cmd_fc_add_qinq_all_result {
975         cmdline_fixed_string_t p_string;
976         uint32_t pipeline_id;
977         cmdline_fixed_string_t flow_string;
978         cmdline_fixed_string_t add_string;
979         cmdline_fixed_string_t qinq_string;
980         cmdline_fixed_string_t all_string;
981         uint32_t n_flows;
982         uint32_t n_ports;
983 };
984
985 #ifndef N_FLOWS_BULK
986 #define N_FLOWS_BULK                                    4096
987 #endif
988
989 static void
990 cmd_fc_add_qinq_all_parsed(
991         void *parsed_result,
992         __rte_unused struct cmdline *cl,
993         void *data)
994 {
995         struct cmd_fc_add_qinq_all_result *params = parsed_result;
996         struct app_params *app = data;
997         struct pipeline_fc_key *key;
998         uint32_t *port_id;
999         uint32_t flow_id;
1000
1001         key = rte_zmalloc(NULL,
1002                 N_FLOWS_BULK * sizeof(*key),
1003                 RTE_CACHE_LINE_SIZE);
1004         if (key == NULL) {
1005                 printf("Memory allocation failed\n");
1006                 return;
1007         }
1008
1009         port_id = rte_malloc(NULL,
1010                 N_FLOWS_BULK * sizeof(*port_id),
1011                 RTE_CACHE_LINE_SIZE);
1012         if (port_id == NULL) {
1013                 rte_free(key);
1014                 printf("Memory allocation failed\n");
1015                 return;
1016         }
1017
1018         for (flow_id = 0; flow_id < params->n_flows; flow_id++) {
1019                 uint32_t pos = flow_id & (N_FLOWS_BULK - 1);
1020
1021                 key[pos].type = FLOW_KEY_QINQ;
1022                 key[pos].key.qinq.svlan = flow_id >> 12;
1023                 key[pos].key.qinq.cvlan = flow_id & 0xFFF;
1024
1025                 port_id[pos] = flow_id % params->n_ports;
1026
1027                 if ((pos == N_FLOWS_BULK - 1) ||
1028                         (flow_id == params->n_flows - 1)) {
1029                         int status;
1030
1031                         status = app_pipeline_fc_add_bulk(app,
1032                                 params->pipeline_id,
1033                                 key,
1034                                 port_id,
1035                                 pos + 1);
1036
1037                         if (status != 0) {
1038                                 printf("Command failed\n");
1039
1040                                 break;
1041                         }
1042                 }
1043         }
1044
1045         rte_free(port_id);
1046         rte_free(key);
1047 }
1048
1049 cmdline_parse_token_string_t cmd_fc_add_qinq_all_p_string =
1050         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, p_string,
1051                 "p");
1052
1053 cmdline_parse_token_num_t cmd_fc_add_qinq_all_pipeline_id =
1054         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, pipeline_id,
1055                 UINT32);
1056
1057 cmdline_parse_token_string_t cmd_fc_add_qinq_all_flow_string =
1058         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, flow_string,
1059                 "flow");
1060
1061 cmdline_parse_token_string_t cmd_fc_add_qinq_all_add_string =
1062         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, add_string,
1063                 "add");
1064
1065 cmdline_parse_token_string_t cmd_fc_add_qinq_all_qinq_string =
1066         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, qinq_string,
1067                 "qinq");
1068
1069 cmdline_parse_token_string_t cmd_fc_add_qinq_all_all_string =
1070         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_all_result, all_string,
1071                 "all");
1072
1073 cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_flows =
1074         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_flows,
1075                 UINT32);
1076
1077 cmdline_parse_token_num_t cmd_fc_add_qinq_all_n_ports =
1078         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_all_result, n_ports,
1079                 UINT32);
1080
1081 cmdline_parse_inst_t cmd_fc_add_qinq_all = {
1082         .f = cmd_fc_add_qinq_all_parsed,
1083         .data = NULL,
1084         .help_str = "Flow add all (Q-in-Q)",
1085         .tokens = {
1086                 (void *) &cmd_fc_add_qinq_all_p_string,
1087                 (void *) &cmd_fc_add_qinq_all_pipeline_id,
1088                 (void *) &cmd_fc_add_qinq_all_flow_string,
1089                 (void *) &cmd_fc_add_qinq_all_add_string,
1090                 (void *) &cmd_fc_add_qinq_all_qinq_string,
1091                 (void *) &cmd_fc_add_qinq_all_all_string,
1092                 (void *) &cmd_fc_add_qinq_all_n_flows,
1093                 (void *) &cmd_fc_add_qinq_all_n_ports,
1094                 NULL,
1095         },
1096 };
1097
1098 /*
1099  * flow add ipv4_5tuple
1100  */
1101
1102 struct cmd_fc_add_ipv4_5tuple_result {
1103         cmdline_fixed_string_t p_string;
1104         uint32_t pipeline_id;
1105         cmdline_fixed_string_t flow_string;
1106         cmdline_fixed_string_t add_string;
1107         cmdline_fixed_string_t ipv4_5tuple_string;
1108         cmdline_ipaddr_t ip_src;
1109         cmdline_ipaddr_t ip_dst;
1110         uint16_t port_src;
1111         uint16_t port_dst;
1112         uint32_t proto;
1113         uint32_t port;
1114 };
1115
1116 static void
1117 cmd_fc_add_ipv4_5tuple_parsed(
1118         void *parsed_result,
1119         __rte_unused struct cmdline *cl,
1120         void *data)
1121 {
1122         struct cmd_fc_add_ipv4_5tuple_result *params = parsed_result;
1123         struct app_params *app = data;
1124         struct pipeline_fc_key key;
1125         int status;
1126
1127         memset(&key, 0, sizeof(key));
1128         key.type = FLOW_KEY_IPV4_5TUPLE;
1129         key.key.ipv4_5tuple.ip_src = rte_bswap32(
1130                 params->ip_src.addr.ipv4.s_addr);
1131         key.key.ipv4_5tuple.ip_dst = rte_bswap32(
1132                 params->ip_dst.addr.ipv4.s_addr);
1133         key.key.ipv4_5tuple.port_src = params->port_src;
1134         key.key.ipv4_5tuple.port_dst = params->port_dst;
1135         key.key.ipv4_5tuple.proto = params->proto;
1136
1137         status = app_pipeline_fc_add(app,
1138                 params->pipeline_id,
1139                 &key,
1140                 params->port);
1141         if (status != 0)
1142                 printf("Command failed\n");
1143 }
1144
1145 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_p_string =
1146         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, p_string,
1147                 "p");
1148
1149 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_pipeline_id =
1150         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, pipeline_id,
1151                 UINT32);
1152
1153 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flow_string =
1154         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result,
1155                 flow_string, "flow");
1156
1157 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_add_string =
1158         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result,
1159                 add_string, "add");
1160
1161 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string =
1162         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result,
1163                 ipv4_5tuple_string, "ipv4_5tuple");
1164
1165 cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src =
1166         TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src);
1167
1168 cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst =
1169         TOKEN_IPV4_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst);
1170
1171 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_src =
1172         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_src,
1173                 UINT16);
1174
1175 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_dst =
1176         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_dst,
1177                 UINT16);
1178
1179 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto =
1180         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto,
1181                 UINT32);
1182
1183 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port =
1184         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port,
1185                 UINT32);
1186
1187 cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple = {
1188         .f = cmd_fc_add_ipv4_5tuple_parsed,
1189         .data = NULL,
1190         .help_str = "Flow add (IPv4 5-tuple)",
1191         .tokens = {
1192                 (void *) &cmd_fc_add_ipv4_5tuple_p_string,
1193                 (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id,
1194                 (void *) &cmd_fc_add_ipv4_5tuple_flow_string,
1195                 (void *) &cmd_fc_add_ipv4_5tuple_add_string,
1196                 (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string,
1197                 (void *) &cmd_fc_add_ipv4_5tuple_ip_src,
1198                 (void *) &cmd_fc_add_ipv4_5tuple_ip_dst,
1199                 (void *) &cmd_fc_add_ipv4_5tuple_port_src,
1200                 (void *) &cmd_fc_add_ipv4_5tuple_port_dst,
1201                 (void *) &cmd_fc_add_ipv4_5tuple_proto,
1202                 (void *) &cmd_fc_add_ipv4_5tuple_port,
1203                 NULL,
1204         },
1205 };
1206
1207 /*
1208  * flow add ipv4_5tuple all
1209  */
1210
1211 struct cmd_fc_add_ipv4_5tuple_all_result {
1212         cmdline_fixed_string_t p_string;
1213         uint32_t pipeline_id;
1214         cmdline_fixed_string_t flow_string;
1215         cmdline_fixed_string_t add_string;
1216         cmdline_fixed_string_t ipv4_5tuple_string;
1217         cmdline_fixed_string_t all_string;
1218         uint32_t n_flows;
1219         uint32_t n_ports;
1220 };
1221
1222 static void
1223 cmd_fc_add_ipv4_5tuple_all_parsed(
1224         void *parsed_result,
1225         __rte_unused struct cmdline *cl,
1226         void *data)
1227 {
1228         struct cmd_fc_add_ipv4_5tuple_all_result *params = parsed_result;
1229         struct app_params *app = data;
1230         struct pipeline_fc_key *key;
1231         uint32_t *port_id;
1232         uint32_t flow_id;
1233
1234         key = rte_zmalloc(NULL,
1235                 N_FLOWS_BULK * sizeof(*key),
1236                 RTE_CACHE_LINE_SIZE);
1237         if (key == NULL) {
1238                 printf("Memory allocation failed\n");
1239                 return;
1240         }
1241
1242         port_id = rte_malloc(NULL,
1243                 N_FLOWS_BULK * sizeof(*port_id),
1244                 RTE_CACHE_LINE_SIZE);
1245         if (port_id == NULL) {
1246                 rte_free(key);
1247                 printf("Memory allocation failed\n");
1248                 return;
1249         }
1250
1251         for (flow_id = 0; flow_id < params->n_flows; flow_id++) {
1252                 uint32_t pos = flow_id & (N_FLOWS_BULK - 1);
1253
1254                 key[pos].type = FLOW_KEY_IPV4_5TUPLE;
1255                 key[pos].key.ipv4_5tuple.ip_src = 0;
1256                 key[pos].key.ipv4_5tuple.ip_dst = flow_id;
1257                 key[pos].key.ipv4_5tuple.port_src = 0;
1258                 key[pos].key.ipv4_5tuple.port_dst = 0;
1259                 key[pos].key.ipv4_5tuple.proto = 6;
1260
1261                 port_id[pos] = flow_id % params->n_ports;
1262
1263                 if ((pos == N_FLOWS_BULK - 1) ||
1264                         (flow_id == params->n_flows - 1)) {
1265                         int status;
1266
1267                         status = app_pipeline_fc_add_bulk(app,
1268                                 params->pipeline_id,
1269                                 key,
1270                                 port_id,
1271                                 pos + 1);
1272
1273                         if (status != 0) {
1274                                 printf("Command failed\n");
1275
1276                                 break;
1277                         }
1278                 }
1279         }
1280
1281         rte_free(port_id);
1282         rte_free(key);
1283 }
1284
1285 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_p_string =
1286         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1287                 p_string, "p");
1288
1289 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_pipeline_id =
1290         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1291                 pipeline_id, UINT32);
1292
1293 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_flow_string =
1294         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1295                 flow_string, "flow");
1296
1297 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_add_string =
1298         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1299                 add_string, "add");
1300
1301 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string =
1302         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1303                 ipv4_5tuple_string, "ipv4_5tuple");
1304
1305 cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_all_all_string =
1306         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1307                 all_string, "all");
1308
1309 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_flows =
1310         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1311                 n_flows, UINT32);
1312
1313 cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_all_n_ports =
1314         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_all_result,
1315                 n_ports, UINT32);
1316
1317 cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple_all = {
1318         .f = cmd_fc_add_ipv4_5tuple_all_parsed,
1319         .data = NULL,
1320         .help_str = "Flow add all (IPv4 5-tuple)",
1321         .tokens = {
1322                 (void *) &cmd_fc_add_ipv4_5tuple_all_p_string,
1323                 (void *) &cmd_fc_add_ipv4_5tuple_all_pipeline_id,
1324                 (void *) &cmd_fc_add_ipv4_5tuple_all_flow_string,
1325                 (void *) &cmd_fc_add_ipv4_5tuple_all_add_string,
1326                 (void *) &cmd_fc_add_ipv4_5tuple_all_ipv4_5tuple_string,
1327                 (void *) &cmd_fc_add_ipv4_5tuple_all_all_string,
1328                 (void *) &cmd_fc_add_ipv4_5tuple_all_n_flows,
1329                 (void *) &cmd_fc_add_ipv4_5tuple_all_n_ports,
1330                 NULL,
1331         },
1332 };
1333
1334 /*
1335  * flow add ipv6_5tuple
1336  */
1337
1338 struct cmd_fc_add_ipv6_5tuple_result {
1339         cmdline_fixed_string_t p_string;
1340         uint32_t pipeline_id;
1341         cmdline_fixed_string_t flow_string;
1342         cmdline_fixed_string_t add_string;
1343         cmdline_fixed_string_t ipv6_5tuple_string;
1344         cmdline_ipaddr_t ip_src;
1345         cmdline_ipaddr_t ip_dst;
1346         uint16_t port_src;
1347         uint16_t port_dst;
1348         uint32_t proto;
1349         uint32_t port;
1350 };
1351
1352 static void
1353 cmd_fc_add_ipv6_5tuple_parsed(
1354         void *parsed_result,
1355         __rte_unused struct cmdline *cl,
1356         void *data)
1357 {
1358         struct cmd_fc_add_ipv6_5tuple_result *params = parsed_result;
1359         struct app_params *app = data;
1360         struct pipeline_fc_key key;
1361         int status;
1362
1363         memset(&key, 0, sizeof(key));
1364         key.type = FLOW_KEY_IPV6_5TUPLE;
1365         memcpy(key.key.ipv6_5tuple.ip_src,
1366                 params->ip_src.addr.ipv6.s6_addr,
1367                 16);
1368         memcpy(key.key.ipv6_5tuple.ip_dst,
1369                 params->ip_dst.addr.ipv6.s6_addr,
1370                 16);
1371         key.key.ipv6_5tuple.port_src = params->port_src;
1372         key.key.ipv6_5tuple.port_dst = params->port_dst;
1373         key.key.ipv6_5tuple.proto = params->proto;
1374
1375         status = app_pipeline_fc_add(app,
1376                 params->pipeline_id,
1377                 &key,
1378                 params->port);
1379         if (status != 0)
1380                 printf("Command failed\n");
1381 }
1382
1383 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_p_string =
1384         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result,
1385                 p_string, "p");
1386
1387 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_pipeline_id =
1388         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, pipeline_id,
1389                 UINT32);
1390
1391 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flow_string =
1392         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result,
1393                 flow_string, "flow");
1394
1395 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_add_string =
1396         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result,
1397                 add_string, "add");
1398
1399 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string =
1400         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result,
1401                 ipv6_5tuple_string, "ipv6_5tuple");
1402
1403 cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src =
1404         TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src);
1405
1406 cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst =
1407         TOKEN_IPV6_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst);
1408
1409 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_src =
1410         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_src,
1411                 UINT16);
1412
1413 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_dst =
1414         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_dst,
1415                 UINT16);
1416
1417 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto =
1418         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto,
1419                 UINT32);
1420
1421 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port =
1422         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port,
1423                 UINT32);
1424
1425 cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple = {
1426         .f = cmd_fc_add_ipv6_5tuple_parsed,
1427         .data = NULL,
1428         .help_str = "Flow add (IPv6 5-tuple)",
1429         .tokens = {
1430                 (void *) &cmd_fc_add_ipv6_5tuple_p_string,
1431                 (void *) &cmd_fc_add_ipv6_5tuple_pipeline_id,
1432                 (void *) &cmd_fc_add_ipv6_5tuple_flow_string,
1433                 (void *) &cmd_fc_add_ipv6_5tuple_add_string,
1434                 (void *) &cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string,
1435                 (void *) &cmd_fc_add_ipv6_5tuple_ip_src,
1436                 (void *) &cmd_fc_add_ipv6_5tuple_ip_dst,
1437                 (void *) &cmd_fc_add_ipv6_5tuple_port_src,
1438                 (void *) &cmd_fc_add_ipv6_5tuple_port_dst,
1439                 (void *) &cmd_fc_add_ipv6_5tuple_proto,
1440                 (void *) &cmd_fc_add_ipv6_5tuple_port,
1441                 NULL,
1442         },
1443 };
1444
1445 /*
1446  * flow add ipv6_5tuple all
1447  */
1448
1449 struct cmd_fc_add_ipv6_5tuple_all_result {
1450         cmdline_fixed_string_t p_string;
1451         uint32_t pipeline_id;
1452         cmdline_fixed_string_t flow_string;
1453         cmdline_fixed_string_t add_string;
1454         cmdline_fixed_string_t ipv6_5tuple_string;
1455         cmdline_fixed_string_t all_string;
1456         uint32_t n_flows;
1457         uint32_t n_ports;
1458 };
1459
1460 static void
1461 cmd_fc_add_ipv6_5tuple_all_parsed(
1462         void *parsed_result,
1463         __rte_unused struct cmdline *cl,
1464         void *data)
1465 {
1466         struct cmd_fc_add_ipv6_5tuple_all_result *params = parsed_result;
1467         struct app_params *app = data;
1468         struct pipeline_fc_key *key;
1469         uint32_t *port_id;
1470         uint32_t flow_id;
1471
1472         key = rte_zmalloc(NULL,
1473                 N_FLOWS_BULK * sizeof(*key),
1474                 RTE_CACHE_LINE_SIZE);
1475         if (key == NULL) {
1476                 printf("Memory allocation failed\n");
1477                 return;
1478         }
1479
1480         port_id = rte_malloc(NULL,
1481                 N_FLOWS_BULK * sizeof(*port_id),
1482                 RTE_CACHE_LINE_SIZE);
1483         if (port_id == NULL) {
1484                 rte_free(key);
1485                 printf("Memory allocation failed\n");
1486                 return;
1487         }
1488
1489         for (flow_id = 0; flow_id < params->n_flows; flow_id++) {
1490                 uint32_t pos = flow_id & (N_FLOWS_BULK - 1);
1491                 uint32_t *x;
1492
1493                 key[pos].type = FLOW_KEY_IPV6_5TUPLE;
1494                 x = (uint32_t *) key[pos].key.ipv6_5tuple.ip_dst;
1495                 *x = rte_bswap32(flow_id);
1496                 key[pos].key.ipv6_5tuple.proto = 6;
1497
1498                 port_id[pos] = flow_id % params->n_ports;
1499
1500                 if ((pos == N_FLOWS_BULK - 1) ||
1501                         (flow_id == params->n_flows - 1)) {
1502                         int status;
1503
1504                         status = app_pipeline_fc_add_bulk(app,
1505                                 params->pipeline_id,
1506                                 key,
1507                                 port_id,
1508                                 pos + 1);
1509
1510                         if (status != 0) {
1511                                 printf("Command failed\n");
1512
1513                                 break;
1514                         }
1515                 }
1516         }
1517
1518         rte_free(port_id);
1519         rte_free(key);
1520 }
1521
1522 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_p_string =
1523         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1524                 p_string, "p");
1525
1526 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_pipeline_id =
1527         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1528                 pipeline_id, UINT32);
1529
1530 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_flow_string =
1531         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1532                 flow_string, "flow");
1533
1534 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_add_string =
1535         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1536                 add_string, "add");
1537
1538 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string =
1539         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1540                 ipv6_5tuple_string, "ipv6_5tuple");
1541
1542 cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_all_all_string =
1543         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1544                 all_string, "all");
1545
1546 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_flows =
1547         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1548                 n_flows, UINT32);
1549
1550 cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_all_n_ports =
1551         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_all_result,
1552                 n_ports, UINT32);
1553
1554 cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple_all = {
1555         .f = cmd_fc_add_ipv6_5tuple_all_parsed,
1556         .data = NULL,
1557         .help_str = "Flow add all (ipv6 5-tuple)",
1558         .tokens = {
1559                 (void *) &cmd_fc_add_ipv6_5tuple_all_p_string,
1560                 (void *) &cmd_fc_add_ipv6_5tuple_all_pipeline_id,
1561                 (void *) &cmd_fc_add_ipv6_5tuple_all_flow_string,
1562                 (void *) &cmd_fc_add_ipv6_5tuple_all_add_string,
1563                 (void *) &cmd_fc_add_ipv6_5tuple_all_ipv6_5tuple_string,
1564                 (void *) &cmd_fc_add_ipv6_5tuple_all_all_string,
1565                 (void *) &cmd_fc_add_ipv6_5tuple_all_n_flows,
1566                 (void *) &cmd_fc_add_ipv6_5tuple_all_n_ports,
1567                 NULL,
1568         },
1569 };
1570
1571 /*
1572  * flow del qinq
1573  */
1574 struct cmd_fc_del_qinq_result {
1575         cmdline_fixed_string_t p_string;
1576         uint32_t pipeline_id;
1577         cmdline_fixed_string_t flow_string;
1578         cmdline_fixed_string_t del_string;
1579         cmdline_fixed_string_t qinq_string;
1580         uint16_t svlan;
1581         uint16_t cvlan;
1582 };
1583
1584 static void
1585 cmd_fc_del_qinq_parsed(
1586         void *parsed_result,
1587         __rte_unused struct cmdline *cl,
1588         void *data)
1589 {
1590         struct cmd_fc_del_qinq_result *params = parsed_result;
1591         struct app_params *app = data;
1592         struct pipeline_fc_key key;
1593         int status;
1594
1595         memset(&key, 0, sizeof(key));
1596         key.type = FLOW_KEY_QINQ;
1597         key.key.qinq.svlan = params->svlan;
1598         key.key.qinq.cvlan = params->cvlan;
1599         status = app_pipeline_fc_del(app, params->pipeline_id, &key);
1600
1601         if (status != 0)
1602                 printf("Command failed\n");
1603 }
1604
1605 cmdline_parse_token_string_t cmd_fc_del_qinq_p_string =
1606         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, p_string, "p");
1607
1608 cmdline_parse_token_num_t cmd_fc_del_qinq_pipeline_id =
1609         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, pipeline_id,
1610                 UINT32);
1611
1612 cmdline_parse_token_string_t cmd_fc_del_qinq_flow_string =
1613         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, flow_string,
1614                 "flow");
1615
1616 cmdline_parse_token_string_t cmd_fc_del_qinq_del_string =
1617         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, del_string,
1618                 "del");
1619
1620 cmdline_parse_token_string_t cmd_fc_del_qinq_qinq_string =
1621         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, qinq_string,
1622                 "qinq");
1623
1624 cmdline_parse_token_num_t cmd_fc_del_qinq_svlan =
1625         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, svlan, UINT16);
1626
1627 cmdline_parse_token_num_t cmd_fc_del_qinq_cvlan =
1628         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, cvlan, UINT16);
1629
1630 cmdline_parse_inst_t cmd_fc_del_qinq = {
1631         .f = cmd_fc_del_qinq_parsed,
1632         .data = NULL,
1633         .help_str = "Flow delete (Q-in-Q)",
1634         .tokens = {
1635                 (void *) &cmd_fc_del_qinq_p_string,
1636                 (void *) &cmd_fc_del_qinq_pipeline_id,
1637                 (void *) &cmd_fc_del_qinq_flow_string,
1638                 (void *) &cmd_fc_del_qinq_del_string,
1639                 (void *) &cmd_fc_del_qinq_qinq_string,
1640                 (void *) &cmd_fc_del_qinq_svlan,
1641                 (void *) &cmd_fc_del_qinq_cvlan,
1642                 NULL,
1643         },
1644 };
1645
1646 /*
1647  * flow del ipv4_5tuple
1648  */
1649
1650 struct cmd_fc_del_ipv4_5tuple_result {
1651         cmdline_fixed_string_t p_string;
1652         uint32_t pipeline_id;
1653         cmdline_fixed_string_t flow_string;
1654         cmdline_fixed_string_t del_string;
1655         cmdline_fixed_string_t ipv4_5tuple_string;
1656         cmdline_ipaddr_t ip_src;
1657         cmdline_ipaddr_t ip_dst;
1658         uint16_t port_src;
1659         uint16_t port_dst;
1660         uint32_t proto;
1661 };
1662
1663 static void
1664 cmd_fc_del_ipv4_5tuple_parsed(
1665         void *parsed_result,
1666         __rte_unused struct cmdline *cl,
1667         void *data)
1668 {
1669         struct cmd_fc_del_ipv4_5tuple_result *params = parsed_result;
1670         struct app_params *app = data;
1671         struct pipeline_fc_key key;
1672         int status;
1673
1674         memset(&key, 0, sizeof(key));
1675         key.type = FLOW_KEY_IPV4_5TUPLE;
1676         key.key.ipv4_5tuple.ip_src = rte_bswap32(
1677                 params->ip_src.addr.ipv4.s_addr);
1678         key.key.ipv4_5tuple.ip_dst = rte_bswap32(
1679                 params->ip_dst.addr.ipv4.s_addr);
1680         key.key.ipv4_5tuple.port_src = params->port_src;
1681         key.key.ipv4_5tuple.port_dst = params->port_dst;
1682         key.key.ipv4_5tuple.proto = params->proto;
1683
1684         status = app_pipeline_fc_del(app, params->pipeline_id, &key);
1685         if (status != 0)
1686                 printf("Command failed\n");
1687 }
1688
1689 cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_p_string =
1690         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1691                 p_string, "p");
1692
1693 cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_pipeline_id =
1694         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1695                 pipeline_id, UINT32);
1696
1697 cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_flow_string =
1698         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1699                 flow_string, "flow");
1700
1701 cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_del_string =
1702         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1703                 del_string, "del");
1704
1705 cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string =
1706         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1707                 ipv4_5tuple_string, "ipv4_5tuple");
1708
1709 cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_src =
1710         TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1711                 ip_src);
1712
1713 cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_dst =
1714         TOKEN_IPV4_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_dst);
1715
1716 cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_src =
1717         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1718                 port_src, UINT16);
1719
1720 cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_dst =
1721         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1722                 port_dst, UINT16);
1723
1724 cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_proto =
1725         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result,
1726                 proto, UINT32);
1727
1728 cmdline_parse_inst_t cmd_fc_del_ipv4_5tuple = {
1729         .f = cmd_fc_del_ipv4_5tuple_parsed,
1730         .data = NULL,
1731         .help_str = "Flow delete (IPv4 5-tuple)",
1732         .tokens = {
1733                 (void *) &cmd_fc_del_ipv4_5tuple_p_string,
1734                 (void *) &cmd_fc_del_ipv4_5tuple_pipeline_id,
1735                 (void *) &cmd_fc_del_ipv4_5tuple_flow_string,
1736                 (void *) &cmd_fc_del_ipv4_5tuple_del_string,
1737                 (void *) &cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string,
1738                 (void *) &cmd_fc_del_ipv4_5tuple_ip_src,
1739                 (void *) &cmd_fc_del_ipv4_5tuple_ip_dst,
1740                 (void *) &cmd_fc_del_ipv4_5tuple_port_src,
1741                 (void *) &cmd_fc_del_ipv4_5tuple_port_dst,
1742                 (void *) &cmd_fc_del_ipv4_5tuple_proto,
1743                 NULL,
1744         },
1745 };
1746
1747 /*
1748  * flow del ipv6_5tuple
1749  */
1750
1751 struct cmd_fc_del_ipv6_5tuple_result {
1752         cmdline_fixed_string_t p_string;
1753         uint32_t pipeline_id;
1754         cmdline_fixed_string_t flow_string;
1755         cmdline_fixed_string_t del_string;
1756         cmdline_fixed_string_t ipv6_5tuple_string;
1757         cmdline_ipaddr_t ip_src;
1758         cmdline_ipaddr_t ip_dst;
1759         uint16_t port_src;
1760         uint16_t port_dst;
1761         uint32_t proto;
1762 };
1763
1764 static void
1765 cmd_fc_del_ipv6_5tuple_parsed(
1766         void *parsed_result,
1767         __rte_unused struct cmdline *cl,
1768         void *data)
1769 {
1770         struct cmd_fc_del_ipv6_5tuple_result *params = parsed_result;
1771         struct app_params *app = data;
1772         struct pipeline_fc_key key;
1773         int status;
1774
1775         memset(&key, 0, sizeof(key));
1776         key.type = FLOW_KEY_IPV6_5TUPLE;
1777         memcpy(key.key.ipv6_5tuple.ip_src,
1778                 params->ip_src.addr.ipv6.s6_addr,
1779                 16);
1780         memcpy(key.key.ipv6_5tuple.ip_dst,
1781                 params->ip_dst.addr.ipv6.s6_addr,
1782                 16);
1783         key.key.ipv6_5tuple.port_src = params->port_src;
1784         key.key.ipv6_5tuple.port_dst = params->port_dst;
1785         key.key.ipv6_5tuple.proto = params->proto;
1786
1787         status = app_pipeline_fc_del(app, params->pipeline_id, &key);
1788         if (status != 0)
1789                 printf("Command failed\n");
1790 }
1791
1792 cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_p_string =
1793         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result,
1794                 p_string, "p");
1795
1796 cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_pipeline_id =
1797         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result,
1798                 pipeline_id, UINT32);
1799
1800 cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_flow_string =
1801         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result,
1802                 flow_string, "flow");
1803
1804 cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_del_string =
1805         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result,
1806                 del_string, "del");
1807
1808 cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string =
1809         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result,
1810                 ipv6_5tuple_string, "ipv6_5tuple");
1811
1812 cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_src =
1813         TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_src);
1814
1815 cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_dst =
1816         TOKEN_IPV6_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_dst);
1817
1818 cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_src =
1819         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_src,
1820                 UINT16);
1821
1822 cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_dst =
1823         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_dst,
1824                 UINT16);
1825
1826 cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_proto =
1827         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, proto,
1828                 UINT32);
1829
1830 cmdline_parse_inst_t cmd_fc_del_ipv6_5tuple = {
1831         .f = cmd_fc_del_ipv6_5tuple_parsed,
1832         .data = NULL,
1833         .help_str = "Flow delete (IPv6 5-tuple)",
1834         .tokens = {
1835                 (void *) &cmd_fc_del_ipv6_5tuple_p_string,
1836                 (void *) &cmd_fc_del_ipv6_5tuple_pipeline_id,
1837                 (void *) &cmd_fc_del_ipv6_5tuple_flow_string,
1838                 (void *) &cmd_fc_del_ipv6_5tuple_del_string,
1839                 (void *) &cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string,
1840                 (void *) &cmd_fc_del_ipv6_5tuple_ip_src,
1841                 (void *) &cmd_fc_del_ipv6_5tuple_ip_dst,
1842                 (void *) &cmd_fc_del_ipv6_5tuple_port_src,
1843                 (void *) &cmd_fc_del_ipv6_5tuple_port_dst,
1844                 (void *) &cmd_fc_del_ipv6_5tuple_proto,
1845                 NULL,
1846         },
1847 };
1848
1849 /*
1850  * flow add default
1851  */
1852
1853 struct cmd_fc_add_default_result {
1854         cmdline_fixed_string_t p_string;
1855         uint32_t pipeline_id;
1856         cmdline_fixed_string_t flow_string;
1857         cmdline_fixed_string_t add_string;
1858         cmdline_fixed_string_t default_string;
1859         uint32_t port;
1860 };
1861
1862 static void
1863 cmd_fc_add_default_parsed(
1864         void *parsed_result,
1865         __rte_unused struct cmdline *cl,
1866         void *data)
1867 {
1868         struct cmd_fc_add_default_result *params = parsed_result;
1869         struct app_params *app = data;
1870         int status;
1871
1872         status = app_pipeline_fc_add_default(app, params->pipeline_id,
1873                 params->port);
1874
1875         if (status != 0)
1876                 printf("Command failed\n");
1877 }
1878
1879 cmdline_parse_token_string_t cmd_fc_add_default_p_string =
1880         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, p_string,
1881                 "p");
1882
1883 cmdline_parse_token_num_t cmd_fc_add_default_pipeline_id =
1884         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, pipeline_id,
1885                 UINT32);
1886
1887 cmdline_parse_token_string_t cmd_fc_add_default_flow_string =
1888         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, flow_string,
1889                 "flow");
1890
1891 cmdline_parse_token_string_t cmd_fc_add_default_add_string =
1892         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result, add_string,
1893                 "add");
1894
1895 cmdline_parse_token_string_t cmd_fc_add_default_default_string =
1896         TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_result,
1897                 default_string, "default");
1898
1899 cmdline_parse_token_num_t cmd_fc_add_default_port =
1900         TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_result, port, UINT32);
1901
1902 cmdline_parse_inst_t cmd_fc_add_default = {
1903         .f = cmd_fc_add_default_parsed,
1904         .data = NULL,
1905         .help_str = "Flow add default",
1906         .tokens = {
1907                 (void *) &cmd_fc_add_default_p_string,
1908                 (void *) &cmd_fc_add_default_pipeline_id,
1909                 (void *) &cmd_fc_add_default_flow_string,
1910                 (void *) &cmd_fc_add_default_add_string,
1911                 (void *) &cmd_fc_add_default_default_string,
1912                 (void *) &cmd_fc_add_default_port,
1913                 NULL,
1914         },
1915 };
1916
1917 /*
1918  * flow del default
1919  */
1920
1921 struct cmd_fc_del_default_result {
1922         cmdline_fixed_string_t p_string;
1923         uint32_t pipeline_id;
1924         cmdline_fixed_string_t flow_string;
1925         cmdline_fixed_string_t del_string;
1926         cmdline_fixed_string_t default_string;
1927 };
1928
1929 static void
1930 cmd_fc_del_default_parsed(
1931         void *parsed_result,
1932         __rte_unused struct cmdline *cl,
1933         void *data)
1934 {
1935         struct cmd_fc_del_default_result *params = parsed_result;
1936         struct app_params *app = data;
1937         int status;
1938
1939         status = app_pipeline_fc_del_default(app, params->pipeline_id);
1940         if (status != 0)
1941                 printf("Command failed\n");
1942 }
1943
1944 cmdline_parse_token_string_t cmd_fc_del_default_p_string =
1945         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, p_string,
1946                 "p");
1947
1948 cmdline_parse_token_num_t cmd_fc_del_default_pipeline_id =
1949         TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_result, pipeline_id,
1950                 UINT32);
1951
1952 cmdline_parse_token_string_t cmd_fc_del_default_flow_string =
1953         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, flow_string,
1954                 "flow");
1955
1956 cmdline_parse_token_string_t cmd_fc_del_default_del_string =
1957         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result, del_string,
1958                 "del");
1959
1960 cmdline_parse_token_string_t cmd_fc_del_default_default_string =
1961         TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_result,
1962                 default_string, "default");
1963
1964 cmdline_parse_inst_t cmd_fc_del_default = {
1965         .f = cmd_fc_del_default_parsed,
1966         .data = NULL,
1967         .help_str = "Flow delete default",
1968         .tokens = {
1969                 (void *) &cmd_fc_del_default_p_string,
1970                 (void *) &cmd_fc_del_default_pipeline_id,
1971                 (void *) &cmd_fc_del_default_flow_string,
1972                 (void *) &cmd_fc_del_default_del_string,
1973                 (void *) &cmd_fc_del_default_default_string,
1974                 NULL,
1975         },
1976 };
1977
1978 /*
1979  * flow ls
1980  */
1981
1982 struct cmd_fc_ls_result {
1983         cmdline_fixed_string_t p_string;
1984         uint32_t pipeline_id;
1985         cmdline_fixed_string_t flow_string;
1986         cmdline_fixed_string_t ls_string;
1987 };
1988
1989 static void
1990 cmd_fc_ls_parsed(
1991         void *parsed_result,
1992         __attribute__((unused)) struct cmdline *cl,
1993         void *data)
1994 {
1995         struct cmd_fc_ls_result *params = parsed_result;
1996         struct app_params *app = data;
1997         int status;
1998
1999         status = app_pipeline_fc_ls(app, params->pipeline_id);
2000         if (status != 0)
2001                 printf("Command failed\n");
2002 }
2003
2004 cmdline_parse_token_string_t cmd_fc_ls_p_string =
2005         TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p");
2006
2007 cmdline_parse_token_num_t cmd_fc_ls_pipeline_id =
2008         TOKEN_NUM_INITIALIZER(struct cmd_fc_ls_result, pipeline_id, UINT32);
2009
2010 cmdline_parse_token_string_t cmd_fc_ls_flow_string =
2011         TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result,
2012         flow_string, "flow");
2013
2014 cmdline_parse_token_string_t cmd_fc_ls_ls_string =
2015         TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, ls_string,
2016         "ls");
2017
2018 cmdline_parse_inst_t cmd_fc_ls = {
2019         .f = cmd_fc_ls_parsed,
2020         .data = NULL,
2021         .help_str = "Flow list",
2022         .tokens = {
2023                 (void *) &cmd_fc_ls_p_string,
2024                 (void *) &cmd_fc_ls_pipeline_id,
2025                 (void *) &cmd_fc_ls_flow_string,
2026                 (void *) &cmd_fc_ls_ls_string,
2027                 NULL,
2028         },
2029 };
2030
2031 static cmdline_parse_ctx_t pipeline_cmds[] = {
2032         (cmdline_parse_inst_t *) &cmd_fc_add_qinq,
2033         (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple,
2034         (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple,
2035
2036         (cmdline_parse_inst_t *) &cmd_fc_del_qinq,
2037         (cmdline_parse_inst_t *) &cmd_fc_del_ipv4_5tuple,
2038         (cmdline_parse_inst_t *) &cmd_fc_del_ipv6_5tuple,
2039
2040         (cmdline_parse_inst_t *) &cmd_fc_add_default,
2041         (cmdline_parse_inst_t *) &cmd_fc_del_default,
2042
2043         (cmdline_parse_inst_t *) &cmd_fc_add_qinq_all,
2044         (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple_all,
2045         (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple_all,
2046
2047         (cmdline_parse_inst_t *) &cmd_fc_ls,
2048         NULL,
2049 };
2050
2051 static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = {
2052         .f_init = app_pipeline_fc_init,
2053         .f_free = app_pipeline_fc_free,
2054         .cmds = pipeline_cmds,
2055 };
2056
2057 struct pipeline_type pipeline_flow_classification = {
2058         .name = "FLOW_CLASSIFICATION",
2059         .be_ops = &pipeline_flow_classification_be_ops,
2060         .fe_ops = &pipeline_flow_classification_fe_ops,
2061 };