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