examples/ip_pipeline: increase constants
[dpdk.git] / examples / ip_pipeline / pipeline / pipeline_routing.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 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 <cmdline_parse.h>
35 #include <cmdline_parse_num.h>
36 #include <cmdline_parse_string.h>
37
38 #include "app.h"
39 #include "pipeline_common_fe.h"
40 #include "pipeline_routing.h"
41 #include "parser.h"
42
43 struct app_pipeline_routing_route {
44         struct pipeline_routing_route_key key;
45         struct pipeline_routing_route_data data;
46         void *entry_ptr;
47
48         TAILQ_ENTRY(app_pipeline_routing_route) node;
49 };
50
51 struct app_pipeline_routing_arp_entry {
52         struct pipeline_routing_arp_key key;
53         struct ether_addr macaddr;
54         void *entry_ptr;
55
56         TAILQ_ENTRY(app_pipeline_routing_arp_entry) node;
57 };
58
59 struct pipeline_routing {
60         /* Parameters */
61         uint32_t n_ports_in;
62         uint32_t n_ports_out;
63
64         /* Routes */
65         TAILQ_HEAD(, app_pipeline_routing_route) routes;
66         uint32_t n_routes;
67
68         uint32_t default_route_present;
69         uint32_t default_route_port_id;
70         void *default_route_entry_ptr;
71
72         /* ARP entries */
73         TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries;
74         uint32_t n_arp_entries;
75
76         uint32_t default_arp_entry_present;
77         uint32_t default_arp_entry_port_id;
78         void *default_arp_entry_ptr;
79 };
80
81 static void *
82 pipeline_routing_init(struct pipeline_params *params,
83         __rte_unused void *arg)
84 {
85         struct pipeline_routing *p;
86         uint32_t size;
87
88         /* Check input arguments */
89         if ((params == NULL) ||
90                 (params->n_ports_in == 0) ||
91                 (params->n_ports_out == 0))
92                 return NULL;
93
94         /* Memory allocation */
95         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
96         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
97         if (p == NULL)
98                 return NULL;
99
100         /* Initialization */
101         p->n_ports_in = params->n_ports_in;
102         p->n_ports_out = params->n_ports_out;
103
104         TAILQ_INIT(&p->routes);
105         p->n_routes = 0;
106
107         TAILQ_INIT(&p->arp_entries);
108         p->n_arp_entries = 0;
109
110         return p;
111 }
112
113 static int
114 app_pipeline_routing_free(void *pipeline)
115 {
116         struct pipeline_routing *p = pipeline;
117
118         /* Check input arguments */
119         if (p == NULL)
120                 return -1;
121
122         /* Free resources */
123         while (!TAILQ_EMPTY(&p->routes)) {
124                 struct app_pipeline_routing_route *route;
125
126                 route = TAILQ_FIRST(&p->routes);
127                 TAILQ_REMOVE(&p->routes, route, node);
128                 rte_free(route);
129         }
130
131         while (!TAILQ_EMPTY(&p->arp_entries)) {
132                 struct app_pipeline_routing_arp_entry *arp_entry;
133
134                 arp_entry = TAILQ_FIRST(&p->arp_entries);
135                 TAILQ_REMOVE(&p->arp_entries, arp_entry, node);
136                 rte_free(arp_entry);
137         }
138
139         rte_free(p);
140         return 0;
141 }
142
143 static struct app_pipeline_routing_route *
144 app_pipeline_routing_find_route(struct pipeline_routing *p,
145                 const struct pipeline_routing_route_key *key)
146 {
147         struct app_pipeline_routing_route *it, *found;
148
149         found = NULL;
150         TAILQ_FOREACH(it, &p->routes, node) {
151                 if ((key->type == it->key.type) &&
152                         (key->key.ipv4.ip == it->key.key.ipv4.ip) &&
153                         (key->key.ipv4.depth == it->key.key.ipv4.depth)) {
154                         found = it;
155                         break;
156                 }
157         }
158
159         return found;
160 }
161
162 static struct app_pipeline_routing_arp_entry *
163 app_pipeline_routing_find_arp_entry(struct pipeline_routing *p,
164                 const struct pipeline_routing_arp_key *key)
165 {
166         struct app_pipeline_routing_arp_entry *it, *found;
167
168         found = NULL;
169         TAILQ_FOREACH(it, &p->arp_entries, node) {
170                 if ((key->type == it->key.type) &&
171                         (key->key.ipv4.port_id == it->key.key.ipv4.port_id) &&
172                         (key->key.ipv4.ip == it->key.key.ipv4.ip)) {
173                         found = it;
174                         break;
175                 }
176         }
177
178         return found;
179 }
180
181 static void
182 print_route(const struct app_pipeline_routing_route *route)
183 {
184         if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) {
185                 const struct pipeline_routing_route_key_ipv4 *key =
186                                 &route->key.key.ipv4;
187
188                 printf("IP Prefix = %" PRIu32 ".%" PRIu32
189                         ".%" PRIu32 ".%" PRIu32 "/%" PRIu32
190                         " => (Port = %" PRIu32,
191
192                         (key->ip >> 24) & 0xFF,
193                         (key->ip >> 16) & 0xFF,
194                         (key->ip >> 8) & 0xFF,
195                         key->ip & 0xFF,
196
197                         key->depth,
198                         route->data.port_id);
199
200                 if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
201                         printf(
202                                 ", Next Hop IP = %" PRIu32 ".%" PRIu32
203                                 ".%" PRIu32 ".%" PRIu32,
204
205                                 (route->data.ethernet.ip >> 24) & 0xFF,
206                                 (route->data.ethernet.ip >> 16) & 0xFF,
207                                 (route->data.ethernet.ip >> 8) & 0xFF,
208                                 route->data.ethernet.ip & 0xFF);
209                 else
210                         printf(
211                                 ", Next Hop HWaddress = %02" PRIx32
212                                 ":%02" PRIx32 ":%02" PRIx32
213                                 ":%02" PRIx32 ":%02" PRIx32
214                                 ":%02" PRIx32,
215
216                                 route->data.ethernet.macaddr.addr_bytes[0],
217                                 route->data.ethernet.macaddr.addr_bytes[1],
218                                 route->data.ethernet.macaddr.addr_bytes[2],
219                                 route->data.ethernet.macaddr.addr_bytes[3],
220                                 route->data.ethernet.macaddr.addr_bytes[4],
221                                 route->data.ethernet.macaddr.addr_bytes[5]);
222
223                 if (route->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)
224                         printf(", QinQ SVLAN = %" PRIu32 " CVLAN = %" PRIu32,
225                                 route->data.l2.qinq.svlan,
226                                 route->data.l2.qinq.cvlan);
227
228                 if (route->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) {
229                         uint32_t i;
230
231                         printf(", MPLS labels");
232                         for (i = 0; i < route->data.l2.mpls.n_labels; i++)
233                                 printf(" %" PRIu32,
234                                         route->data.l2.mpls.labels[i]);
235                 }
236
237                 printf(")\n");
238         }
239 }
240
241 static void
242 print_arp_entry(const struct app_pipeline_routing_arp_entry *entry)
243 {
244         printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32
245                 ".%" PRIu32 ".%" PRIu32
246                 ") => HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
247                 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
248
249                 entry->key.key.ipv4.port_id,
250                 (entry->key.key.ipv4.ip >> 24) & 0xFF,
251                 (entry->key.key.ipv4.ip >> 16) & 0xFF,
252                 (entry->key.key.ipv4.ip >> 8) & 0xFF,
253                 entry->key.key.ipv4.ip & 0xFF,
254
255                 entry->macaddr.addr_bytes[0],
256                 entry->macaddr.addr_bytes[1],
257                 entry->macaddr.addr_bytes[2],
258                 entry->macaddr.addr_bytes[3],
259                 entry->macaddr.addr_bytes[4],
260                 entry->macaddr.addr_bytes[5]);
261 }
262
263 static int
264 app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id)
265 {
266         struct pipeline_routing *p;
267         struct app_pipeline_routing_route *it;
268
269         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
270         if (p == NULL)
271                 return -EINVAL;
272
273         TAILQ_FOREACH(it, &p->routes, node)
274                 print_route(it);
275
276         if (p->default_route_present)
277                 printf("Default route: port %" PRIu32 " (entry ptr = %p)\n",
278                                 p->default_route_port_id,
279                                 p->default_route_entry_ptr);
280         else
281                 printf("Default: DROP\n");
282
283         return 0;
284 }
285
286 int
287 app_pipeline_routing_add_route(struct app_params *app,
288         uint32_t pipeline_id,
289         struct pipeline_routing_route_key *key,
290         struct pipeline_routing_route_data *data)
291 {
292         struct pipeline_routing *p;
293
294         struct pipeline_routing_route_add_msg_req *req;
295         struct pipeline_routing_route_add_msg_rsp *rsp;
296
297         struct app_pipeline_routing_route *entry;
298
299         int new_entry;
300
301         /* Check input arguments */
302         if ((app == NULL) ||
303                 (key == NULL) ||
304                 (data == NULL))
305                 return -1;
306
307         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
308         if (p == NULL)
309                 return -1;
310
311         switch (key->type) {
312         case PIPELINE_ROUTING_ROUTE_IPV4:
313         {
314                 uint32_t depth = key->key.ipv4.depth;
315                 uint32_t netmask;
316
317                 /* key */
318                 if ((depth == 0) || (depth > 32))
319                         return -1;
320
321                 netmask = (~0U) << (32 - depth);
322                 key->key.ipv4.ip &= netmask;
323
324                 /* data */
325                 if (data->port_id >= p->n_ports_out)
326                         return -1;
327         }
328         break;
329
330         default:
331                 return -1;
332         }
333
334         /* Find existing rule or allocate new rule */
335         entry = app_pipeline_routing_find_route(p, key);
336         new_entry = (entry == NULL);
337         if (entry == NULL) {
338                 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
339
340                 if (entry == NULL)
341                         return -1;
342         }
343
344         /* Allocate and write request */
345         req = app_msg_alloc(app);
346         if (req == NULL) {
347                 if (new_entry)
348                         rte_free(entry);
349                 return -1;
350         }
351
352         req->type = PIPELINE_MSG_REQ_CUSTOM;
353         req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD;
354         memcpy(&req->key, key, sizeof(*key));
355         memcpy(&req->data, data, sizeof(*data));
356
357         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
358         if (rsp == NULL) {
359                 if (new_entry)
360                         rte_free(entry);
361                 return -1;
362         }
363
364         /* Read response and write entry */
365         if (rsp->status ||
366                 (rsp->entry_ptr == NULL) ||
367                 ((new_entry == 0) && (rsp->key_found == 0)) ||
368                 ((new_entry == 1) && (rsp->key_found == 1))) {
369                 app_msg_free(app, rsp);
370                 if (new_entry)
371                         rte_free(entry);
372                 return -1;
373         }
374
375         memcpy(&entry->key, key, sizeof(*key));
376         memcpy(&entry->data, data, sizeof(*data));
377         entry->entry_ptr = rsp->entry_ptr;
378
379         /* Commit entry */
380         if (new_entry) {
381                 TAILQ_INSERT_TAIL(&p->routes, entry, node);
382                 p->n_routes++;
383         }
384
385         print_route(entry);
386
387         /* Message buffer free */
388         app_msg_free(app, rsp);
389         return 0;
390 }
391
392 int
393 app_pipeline_routing_delete_route(struct app_params *app,
394         uint32_t pipeline_id,
395         struct pipeline_routing_route_key *key)
396 {
397         struct pipeline_routing *p;
398
399         struct pipeline_routing_route_delete_msg_req *req;
400         struct pipeline_routing_route_delete_msg_rsp *rsp;
401
402         struct app_pipeline_routing_route *entry;
403
404         /* Check input arguments */
405         if ((app == NULL) ||
406                 (key == NULL))
407                 return -1;
408
409         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
410         if (p == NULL)
411                 return -1;
412
413         switch (key->type) {
414         case PIPELINE_ROUTING_ROUTE_IPV4:
415         {
416                 uint32_t depth = key->key.ipv4.depth;
417                 uint32_t netmask;
418
419                 /* key */
420                 if ((depth == 0) || (depth > 32))
421                         return -1;
422
423                 netmask = (~0U) << (32 - depth);
424                 key->key.ipv4.ip &= netmask;
425         }
426         break;
427
428         default:
429                 return -1;
430         }
431
432         /* Find rule */
433         entry = app_pipeline_routing_find_route(p, key);
434         if (entry == NULL)
435                 return 0;
436
437         /* Allocate and write request */
438         req = app_msg_alloc(app);
439         if (req == NULL)
440                 return -1;
441
442         req->type = PIPELINE_MSG_REQ_CUSTOM;
443         req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL;
444         memcpy(&req->key, key, sizeof(*key));
445
446         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
447         if (rsp == NULL)
448                 return -1;
449
450         /* Read response */
451         if (rsp->status || !rsp->key_found) {
452                 app_msg_free(app, rsp);
453                 return -1;
454         }
455
456         /* Remove route */
457         TAILQ_REMOVE(&p->routes, entry, node);
458         p->n_routes--;
459         rte_free(entry);
460
461         /* Free response */
462         app_msg_free(app, rsp);
463
464         return 0;
465 }
466
467 int
468 app_pipeline_routing_add_default_route(struct app_params *app,
469         uint32_t pipeline_id,
470         uint32_t port_id)
471 {
472         struct pipeline_routing *p;
473
474         struct pipeline_routing_route_add_default_msg_req *req;
475         struct pipeline_routing_route_add_default_msg_rsp *rsp;
476
477         /* Check input arguments */
478         if (app == NULL)
479                 return -1;
480
481         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
482         if (p == NULL)
483                 return -1;
484
485         if (port_id >= p->n_ports_out)
486                 return -1;
487
488         /* Allocate and write request */
489         req = app_msg_alloc(app);
490         if (req == NULL)
491                 return -1;
492
493         req->type = PIPELINE_MSG_REQ_CUSTOM;
494         req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT;
495         req->port_id = port_id;
496
497         /* Send request and wait for response */
498         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
499         if (rsp == NULL)
500                 return -1;
501
502         /* Read response and write route */
503         if (rsp->status || (rsp->entry_ptr == NULL)) {
504                 app_msg_free(app, rsp);
505                 return -1;
506         }
507
508         p->default_route_port_id = port_id;
509         p->default_route_entry_ptr = rsp->entry_ptr;
510
511         /* Commit route */
512         p->default_route_present = 1;
513
514         /* Free response */
515         app_msg_free(app, rsp);
516
517         return 0;
518 }
519
520 int
521 app_pipeline_routing_delete_default_route(struct app_params *app,
522         uint32_t pipeline_id)
523 {
524         struct pipeline_routing *p;
525
526         struct pipeline_routing_arp_delete_default_msg_req *req;
527         struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
528
529         /* Check input arguments */
530         if (app == NULL)
531                 return -1;
532
533         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
534         if (p == NULL)
535                 return -1;
536
537         /* Allocate and write request */
538         req = app_msg_alloc(app);
539         if (req == NULL)
540                 return -1;
541
542         req->type = PIPELINE_MSG_REQ_CUSTOM;
543         req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT;
544
545         /* Send request and wait for response */
546         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
547         if (rsp == NULL)
548                 return -1;
549
550         /* Read response and write route */
551         if (rsp->status) {
552                 app_msg_free(app, rsp);
553                 return -1;
554         }
555
556         /* Commit route */
557         p->default_route_present = 0;
558
559         /* Free response */
560         app_msg_free(app, rsp);
561
562         return 0;
563 }
564
565 static int
566 app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id)
567 {
568         struct pipeline_routing *p;
569         struct app_pipeline_routing_arp_entry *it;
570
571         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
572         if (p == NULL)
573                 return -EINVAL;
574
575         TAILQ_FOREACH(it, &p->arp_entries, node)
576                 print_arp_entry(it);
577
578         if (p->default_arp_entry_present)
579                 printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n",
580                                 p->default_arp_entry_port_id,
581                                 p->default_arp_entry_ptr);
582         else
583                 printf("Default: DROP\n");
584
585         return 0;
586 }
587
588 int
589 app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
590                 struct pipeline_routing_arp_key *key,
591                 struct ether_addr *macaddr)
592 {
593         struct pipeline_routing *p;
594
595         struct pipeline_routing_arp_add_msg_req *req;
596         struct pipeline_routing_arp_add_msg_rsp *rsp;
597
598         struct app_pipeline_routing_arp_entry *entry;
599
600         int new_entry;
601
602         /* Check input arguments */
603         if ((app == NULL) ||
604                 (key == NULL) ||
605                 (macaddr == NULL))
606                 return -1;
607
608         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
609         if (p == NULL)
610                 return -1;
611
612         switch (key->type) {
613         case PIPELINE_ROUTING_ARP_IPV4:
614         {
615                 uint32_t port_id = key->key.ipv4.port_id;
616
617                 /* key */
618                 if (port_id >= p->n_ports_out)
619                         return -1;
620         }
621         break;
622
623         default:
624                 return -1;
625         }
626
627         /* Find existing entry or allocate new */
628         entry = app_pipeline_routing_find_arp_entry(p, key);
629         new_entry = (entry == NULL);
630         if (entry == NULL) {
631                 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
632
633                 if (entry == NULL)
634                         return -1;
635         }
636
637         /* Message buffer allocation */
638         req = app_msg_alloc(app);
639         if (req == NULL) {
640                 if (new_entry)
641                         rte_free(entry);
642                 return -1;
643         }
644
645         req->type = PIPELINE_MSG_REQ_CUSTOM;
646         req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD;
647         memcpy(&req->key, key, sizeof(*key));
648         ether_addr_copy(macaddr, &req->macaddr);
649
650         /* Send request and wait for response */
651         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
652         if (rsp == NULL) {
653                 if (new_entry)
654                         rte_free(entry);
655                 return -1;
656         }
657
658         /* Read response and write entry */
659         if (rsp->status ||
660                 (rsp->entry_ptr == NULL) ||
661                 ((new_entry == 0) && (rsp->key_found == 0)) ||
662                 ((new_entry == 1) && (rsp->key_found == 1))) {
663                 app_msg_free(app, rsp);
664                 if (new_entry)
665                         rte_free(entry);
666                 return -1;
667         }
668
669         memcpy(&entry->key, key, sizeof(*key));
670         ether_addr_copy(macaddr, &entry->macaddr);
671         entry->entry_ptr = rsp->entry_ptr;
672
673         /* Commit entry */
674         if (new_entry) {
675                 TAILQ_INSERT_TAIL(&p->arp_entries, entry, node);
676                 p->n_arp_entries++;
677         }
678
679         print_arp_entry(entry);
680
681         /* Message buffer free */
682         app_msg_free(app, rsp);
683         return 0;
684 }
685
686 int
687 app_pipeline_routing_delete_arp_entry(struct app_params *app,
688         uint32_t pipeline_id,
689         struct pipeline_routing_arp_key *key)
690 {
691         struct pipeline_routing *p;
692
693         struct pipeline_routing_arp_delete_msg_req *req;
694         struct pipeline_routing_arp_delete_msg_rsp *rsp;
695
696         struct app_pipeline_routing_arp_entry *entry;
697
698         /* Check input arguments */
699         if ((app == NULL) ||
700                 (key == NULL))
701                 return -1;
702
703         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
704         if (p == NULL)
705                 return -EINVAL;
706
707         switch (key->type) {
708         case PIPELINE_ROUTING_ARP_IPV4:
709         {
710                 uint32_t port_id = key->key.ipv4.port_id;
711
712                 /* key */
713                 if (port_id >= p->n_ports_out)
714                         return -1;
715         }
716         break;
717
718         default:
719                 return -1;
720         }
721
722         /* Find rule */
723         entry = app_pipeline_routing_find_arp_entry(p, key);
724         if (entry == NULL)
725                 return 0;
726
727         /* Allocate and write request */
728         req = app_msg_alloc(app);
729         if (req == NULL)
730                 return -1;
731
732         req->type = PIPELINE_MSG_REQ_CUSTOM;
733         req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL;
734         memcpy(&req->key, key, sizeof(*key));
735
736         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
737         if (rsp == NULL)
738                 return -1;
739
740         /* Read response */
741         if (rsp->status || !rsp->key_found) {
742                 app_msg_free(app, rsp);
743                 return -1;
744         }
745
746         /* Remove entry */
747         TAILQ_REMOVE(&p->arp_entries, entry, node);
748         p->n_arp_entries--;
749         rte_free(entry);
750
751         /* Free response */
752         app_msg_free(app, rsp);
753
754         return 0;
755 }
756
757 int
758 app_pipeline_routing_add_default_arp_entry(struct app_params *app,
759                 uint32_t pipeline_id,
760                 uint32_t port_id)
761 {
762         struct pipeline_routing *p;
763
764         struct pipeline_routing_arp_add_default_msg_req *req;
765         struct pipeline_routing_arp_add_default_msg_rsp *rsp;
766
767         /* Check input arguments */
768         if (app == NULL)
769                 return -1;
770
771         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
772         if (p == NULL)
773                 return -1;
774
775         if (port_id >= p->n_ports_out)
776                 return -1;
777
778         /* Allocate and write request */
779         req = app_msg_alloc(app);
780         if (req == NULL)
781                 return -1;
782
783         req->type = PIPELINE_MSG_REQ_CUSTOM;
784         req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT;
785         req->port_id = port_id;
786
787         /* Send request and wait for response */
788         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
789         if (rsp == NULL)
790                 return -1;
791
792         /* Read response and write entry */
793         if (rsp->status || rsp->entry_ptr == NULL) {
794                 app_msg_free(app, rsp);
795                 return -1;
796         }
797
798         p->default_arp_entry_port_id = port_id;
799         p->default_arp_entry_ptr = rsp->entry_ptr;
800
801         /* Commit entry */
802         p->default_arp_entry_present = 1;
803
804         /* Free response */
805         app_msg_free(app, rsp);
806
807         return 0;
808 }
809
810 int
811 app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
812         uint32_t pipeline_id)
813 {
814         struct pipeline_routing *p;
815
816         struct pipeline_routing_arp_delete_default_msg_req *req;
817         struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
818
819         /* Check input arguments */
820         if (app == NULL)
821                 return -1;
822
823         p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
824         if (p == NULL)
825                 return -EINVAL;
826
827         /* Allocate and write request */
828         req = app_msg_alloc(app);
829         if (req == NULL)
830                 return -ENOMEM;
831
832         req->type = PIPELINE_MSG_REQ_CUSTOM;
833         req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT;
834
835         /* Send request and wait for response */
836         rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
837         if (rsp == NULL)
838                 return -ETIMEDOUT;
839
840         /* Read response and write entry */
841         if (rsp->status) {
842                 app_msg_free(app, rsp);
843                 return rsp->status;
844         }
845
846         /* Commit entry */
847         p->default_arp_entry_present = 0;
848
849         /* Free response */
850         app_msg_free(app, rsp);
851
852         return 0;
853 }
854
855 /*
856  * route
857  *
858  * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
859  *    p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
860  *    p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
861  *    p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
862  *    p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
863  *    p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
864  *    p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
865  *
866  * route add default:
867  *    p <pipelineid> route add default <portid>
868  *
869  * route del:
870  *    p <pipelineid> route del <ipaddr> <depth>
871  *
872  * route del default:
873  *    p <pipelineid> route del default
874  *
875  * route ls:
876  *    p <pipelineid> route ls
877  */
878
879 struct cmd_route_result {
880         cmdline_fixed_string_t p_string;
881         uint32_t p;
882         cmdline_fixed_string_t route_string;
883         cmdline_multi_string_t multi_string;
884 };
885
886 static void
887 cmd_route_parsed(
888         void *parsed_result,
889         __rte_unused struct cmdline *cl,
890         void *data)
891 {
892         struct cmd_route_result *params = parsed_result;
893         struct app_params *app = data;
894
895         char *tokens[16];
896         uint32_t n_tokens = RTE_DIM(tokens);
897         int status;
898
899         status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
900         if (status != 0) {
901                 printf(CMD_MSG_TOO_MANY_ARGS, "route");
902                 return;
903         }
904
905         /* route add */
906         if ((n_tokens >= 2) &&
907                 (strcmp(tokens[0], "add") == 0) &&
908                 strcmp(tokens[1], "default")) {
909                 struct pipeline_routing_route_key key;
910                 struct pipeline_routing_route_data route_data;
911                 struct in_addr ipv4, nh_ipv4;
912                 struct ether_addr mac_addr;
913                 uint32_t depth, port_id, svlan, cvlan, i;
914                 uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
915                 uint32_t n_labels = RTE_DIM(mpls_labels);
916
917                 memset(&key, 0, sizeof(key));
918                 memset(&route_data, 0, sizeof(route_data));
919
920                 if (n_tokens < 7) {
921                         printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add");
922                         return;
923                 }
924
925                 if (parse_ipv4_addr(tokens[1], &ipv4)) {
926                         printf(CMD_MSG_INVALID_ARG, "ipaddr");
927                         return;
928                 }
929
930                 if (parser_read_uint32(&depth, tokens[2])) {
931                         printf(CMD_MSG_INVALID_ARG, "depth");
932                         return;
933                 }
934
935                 if (strcmp(tokens[3], "port")) {
936                         printf(CMD_MSG_ARG_NOT_FOUND, "port");
937                         return;
938                 }
939
940                 if (parser_read_uint32(&port_id, tokens[4])) {
941                         printf(CMD_MSG_INVALID_ARG, "portid");
942                         return;
943                 }
944
945                 if (strcmp(tokens[5], "ether")) {
946                         printf(CMD_MSG_ARG_NOT_FOUND, "ether");
947                         return;
948                 }
949
950                 if (parse_mac_addr(tokens[6], &mac_addr)) {
951                         if (parse_ipv4_addr(tokens[6], &nh_ipv4)) {
952                                 printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr");
953                                 return;
954                         }
955
956                         route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP;
957                 }
958
959                 if (n_tokens > 7) {
960                         if (strcmp(tokens[7], "mpls") == 0) {
961                                 if (n_tokens != 9) {
962                                         printf(CMD_MSG_MISMATCH_ARGS, "route add mpls");
963                                         return;
964                                 }
965
966                                 if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) {
967                                         printf(CMD_MSG_INVALID_ARG, "mpls labels");
968                                         return;
969                                 }
970
971                                 route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
972                         } else if (strcmp(tokens[7], "qinq") == 0) {
973                                 if (n_tokens != 10) {
974                                         printf(CMD_MSG_MISMATCH_ARGS, "route add qinq");
975                                         return;
976                                 }
977
978                                 if (parser_read_uint32(&svlan, tokens[8])) {
979                                         printf(CMD_MSG_INVALID_ARG, "svlan");
980                                         return;
981                                 }
982                                 if (parser_read_uint32(&cvlan, tokens[9])) {
983                                         printf(CMD_MSG_INVALID_ARG, "cvlan");
984                                         return;
985                                 }
986
987                                 route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
988                         } else {
989                                 printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq");
990                                 return;
991                         }
992                 }
993
994                 switch (route_data.flags) {
995                 case 0:
996                         route_data.port_id = port_id;
997                         route_data.ethernet.macaddr = mac_addr;
998                         break;
999
1000                 case PIPELINE_ROUTING_ROUTE_ARP:
1001                         route_data.port_id = port_id;
1002                         route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1003                         break;
1004
1005                 case PIPELINE_ROUTING_ROUTE_MPLS:
1006                         route_data.port_id = port_id;
1007                         route_data.ethernet.macaddr = mac_addr;
1008                         for (i = 0; i < n_labels; i++)
1009                                 route_data.l2.mpls.labels[i] = mpls_labels[i];
1010                         route_data.l2.mpls.n_labels = n_labels;
1011                         break;
1012
1013                 case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP:
1014                         route_data.port_id = port_id;
1015                         route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1016                         for (i = 0; i < n_labels; i++)
1017                                 route_data.l2.mpls.labels[i] = mpls_labels[i];
1018                         route_data.l2.mpls.n_labels = n_labels;
1019                         break;
1020
1021                 case PIPELINE_ROUTING_ROUTE_QINQ:
1022                         route_data.port_id = port_id;
1023                         route_data.ethernet.macaddr = mac_addr;
1024                         route_data.l2.qinq.svlan = svlan;
1025                         route_data.l2.qinq.cvlan = cvlan;
1026                         break;
1027
1028                 case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP:
1029                 default:
1030                         route_data.port_id = port_id;
1031                         route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1032                         route_data.l2.qinq.svlan = svlan;
1033                         route_data.l2.qinq.cvlan = cvlan;
1034                         break;
1035                 }
1036
1037                 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1038                 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1039                 key.key.ipv4.depth = depth;
1040
1041                 status = app_pipeline_routing_add_route(app,
1042                         params->p,
1043                         &key,
1044                         &route_data);
1045                 if (status != 0)
1046                         printf(CMD_MSG_FAIL, "route add");
1047
1048                 return;
1049         } /* route add */
1050
1051         /* route add default */
1052         if ((n_tokens >= 2) &&
1053                 (strcmp(tokens[0], "add") == 0) &&
1054                 (strcmp(tokens[1], "default") == 0)) {
1055                 uint32_t port_id;
1056
1057                 if (n_tokens != 3) {
1058                         printf(CMD_MSG_MISMATCH_ARGS, "route add default");
1059                         return;
1060                 }
1061
1062                 if (parser_read_uint32(&port_id, tokens[2])) {
1063                         printf(CMD_MSG_INVALID_ARG, "portid");
1064                         return;
1065                 }
1066
1067                 status = app_pipeline_routing_add_default_route(app,
1068                         params->p,
1069                         port_id);
1070                 if (status != 0)
1071                         printf(CMD_MSG_FAIL, "route add default");
1072
1073                 return;
1074         } /* route add default */
1075
1076         /* route del*/
1077         if ((n_tokens >= 2) &&
1078                 (strcmp(tokens[0], "del") == 0) &&
1079                 strcmp(tokens[1], "default")) {
1080                 struct pipeline_routing_route_key key;
1081                 struct in_addr ipv4;
1082                 uint32_t depth;
1083
1084                 memset(&key, 0, sizeof(key));
1085
1086                 if (n_tokens != 3) {
1087                         printf(CMD_MSG_MISMATCH_ARGS, "route del");
1088                         return;
1089                 }
1090
1091                 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1092                         printf(CMD_MSG_INVALID_ARG, "ipaddr");
1093                         return;
1094                 }
1095
1096                 if (parser_read_uint32(&depth, tokens[2])) {
1097                         printf(CMD_MSG_INVALID_ARG, "depth");
1098                         return;
1099                 }
1100
1101                 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1102                 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1103                 key.key.ipv4.depth = depth;
1104
1105                 status = app_pipeline_routing_delete_route(app, params->p, &key);
1106                 if (status != 0)
1107                         printf(CMD_MSG_FAIL, "route del");
1108
1109                 return;
1110         } /* route del */
1111
1112         /* route del default */
1113         if ((n_tokens >= 2) &&
1114                 (strcmp(tokens[0], "del") == 0) &&
1115                 (strcmp(tokens[1], "default") == 0)) {
1116                 if (n_tokens != 2) {
1117                         printf(CMD_MSG_MISMATCH_ARGS, "route del default");
1118                         return;
1119                 }
1120
1121                 status = app_pipeline_routing_delete_default_route(app,
1122                         params->p);
1123                 if (status != 0)
1124                         printf(CMD_MSG_FAIL, "route del default");
1125
1126                 return;
1127         } /* route del default */
1128
1129         /* route ls */
1130         if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1131                 if (n_tokens != 1) {
1132                         printf(CMD_MSG_MISMATCH_ARGS, "route ls");
1133                         return;
1134                 }
1135
1136                 status = app_pipeline_routing_route_ls(app, params->p);
1137                 if (status != 0)
1138                         printf(CMD_MSG_FAIL, "route ls");
1139
1140                 return;
1141         } /* route ls */
1142
1143         printf(CMD_MSG_MISMATCH_ARGS, "route");
1144 }
1145
1146 static cmdline_parse_token_string_t cmd_route_p_string =
1147         TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p");
1148
1149 static cmdline_parse_token_num_t cmd_route_p =
1150         TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32);
1151
1152 static cmdline_parse_token_string_t cmd_route_route_string =
1153         TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route");
1154
1155 static cmdline_parse_token_string_t cmd_route_multi_string =
1156         TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string,
1157         TOKEN_STRING_MULTI);
1158
1159 static cmdline_parse_inst_t cmd_route = {
1160         .f = cmd_route_parsed,
1161         .data = NULL,
1162         .help_str = "route add / add default / del / del default / ls",
1163         .tokens = {
1164                 (void *)&cmd_route_p_string,
1165                 (void *)&cmd_route_p,
1166                 (void *)&cmd_route_route_string,
1167                 (void *)&cmd_route_multi_string,
1168                 NULL,
1169         },
1170 };
1171
1172 /*
1173  * arp
1174  *
1175  * arp add:
1176  *    p <pipelineid> arp add <portid> <ipaddr> <macaddr>
1177  *
1178  * arp add default:
1179  *    p <pipelineid> arp add default <portid>
1180  *
1181  * arp del:
1182  *    p <pipelineid> arp del <portid> <ipaddr>
1183  *
1184  * arp del default:
1185  *    p <pipelineid> arp del default
1186  *
1187  * arp ls:
1188  *    p <pipelineid> arp ls
1189  */
1190
1191 struct cmd_arp_result {
1192         cmdline_fixed_string_t p_string;
1193         uint32_t p;
1194         cmdline_fixed_string_t arp_string;
1195         cmdline_multi_string_t multi_string;
1196 };
1197
1198 static void
1199 cmd_arp_parsed(
1200         void *parsed_result,
1201         __rte_unused struct cmdline *cl,
1202         void *data)
1203 {
1204         struct cmd_arp_result *params = parsed_result;
1205         struct app_params *app = data;
1206
1207         char *tokens[16];
1208         uint32_t n_tokens = RTE_DIM(tokens);
1209         int status;
1210
1211         status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1212         if (status != 0) {
1213                 printf(CMD_MSG_TOO_MANY_ARGS, "arp");
1214                 return;
1215         }
1216
1217         /* arp add */
1218         if ((n_tokens >= 2) &&
1219                 (strcmp(tokens[0], "add") == 0) &&
1220                 strcmp(tokens[1], "default")) {
1221                 struct pipeline_routing_arp_key key;
1222                 struct in_addr ipv4;
1223                 struct ether_addr mac_addr;
1224                 uint32_t port_id;
1225
1226                 memset(&key, 0, sizeof(key));
1227
1228                 if (n_tokens != 4) {
1229                         printf(CMD_MSG_MISMATCH_ARGS, "arp add");
1230                         return;
1231                 }
1232
1233                 if (parser_read_uint32(&port_id, tokens[1])) {
1234                         printf(CMD_MSG_INVALID_ARG, "portid");
1235                         return;
1236                 }
1237
1238                 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1239                         printf(CMD_MSG_INVALID_ARG, "ipaddr");
1240                         return;
1241                 }
1242
1243                 if (parse_mac_addr(tokens[3], &mac_addr)) {
1244                         printf(CMD_MSG_INVALID_ARG, "macaddr");
1245                         return;
1246                 }
1247
1248                 key.type = PIPELINE_ROUTING_ARP_IPV4;
1249                 key.key.ipv4.port_id = port_id;
1250                 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1251
1252                 status = app_pipeline_routing_add_arp_entry(app,
1253                         params->p,
1254                         &key,
1255                         &mac_addr);
1256                 if (status != 0)
1257                         printf(CMD_MSG_FAIL, "arp add");
1258
1259                 return;
1260         } /* arp add */
1261
1262         /* arp add default */
1263         if ((n_tokens >= 2) &&
1264                 (strcmp(tokens[0], "add") == 0) &&
1265                 (strcmp(tokens[1], "default") == 0)) {
1266                 uint32_t port_id;
1267
1268                 if (n_tokens != 3) {
1269                         printf(CMD_MSG_MISMATCH_ARGS, "arp add default");
1270                         return;
1271                 }
1272
1273                 if (parser_read_uint32(&port_id, tokens[2])) {
1274                         printf(CMD_MSG_INVALID_ARG, "portid");
1275                         return;
1276                 }
1277
1278                 status = app_pipeline_routing_add_default_arp_entry(app,
1279                         params->p,
1280                         port_id);
1281                 if (status != 0)
1282                         printf(CMD_MSG_FAIL, "arp add default");
1283
1284                 return;
1285         } /* arp add default */
1286
1287         /* arp del*/
1288         if ((n_tokens >= 2) &&
1289                 (strcmp(tokens[0], "del") == 0) &&
1290                 strcmp(tokens[1], "default")) {
1291                 struct pipeline_routing_arp_key key;
1292                 struct in_addr ipv4;
1293                 uint32_t port_id;
1294
1295                 memset(&key, 0, sizeof(key));
1296
1297                 if (n_tokens != 3) {
1298                         printf(CMD_MSG_MISMATCH_ARGS, "arp del");
1299                         return;
1300                 }
1301
1302                 if (parser_read_uint32(&port_id, tokens[1])) {
1303                         printf(CMD_MSG_INVALID_ARG, "portid");
1304                         return;
1305                 }
1306
1307                 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1308                         printf(CMD_MSG_INVALID_ARG, "ipaddr");
1309                         return;
1310                 }
1311
1312                 key.type = PIPELINE_ROUTING_ARP_IPV4;
1313                 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1314                 key.key.ipv4.port_id = port_id;
1315
1316                 status = app_pipeline_routing_delete_arp_entry(app,
1317                         params->p,
1318                         &key);
1319                 if (status != 0)
1320                         printf(CMD_MSG_FAIL, "arp del");
1321
1322                 return;
1323         } /* arp del */
1324
1325         /* arp del default */
1326         if ((n_tokens >= 2) &&
1327                 (strcmp(tokens[0], "del") == 0) &&
1328                 (strcmp(tokens[1], "default") == 0)) {
1329                         if (n_tokens != 2) {
1330                                 printf(CMD_MSG_MISMATCH_ARGS, "arp del default");
1331                                 return;
1332                         }
1333
1334                         status = app_pipeline_routing_delete_default_arp_entry(app,
1335                                 params->p);
1336                         if (status != 0)
1337                                 printf(CMD_MSG_FAIL, "arp del default");
1338
1339                         return;
1340         } /* arp del default */
1341
1342         /* arp ls */
1343         if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1344                 if (n_tokens != 1) {
1345                         printf(CMD_MSG_MISMATCH_ARGS, "arp ls");
1346                         return;
1347                 }
1348
1349                 status = app_pipeline_routing_arp_ls(app, params->p);
1350                 if (status != 0)
1351                         printf(CMD_MSG_FAIL, "arp ls");
1352
1353                 return;
1354         } /* arp ls */
1355
1356         printf(CMD_MSG_FAIL, "arp");
1357 }
1358
1359 static cmdline_parse_token_string_t cmd_arp_p_string =
1360         TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p");
1361
1362 static cmdline_parse_token_num_t cmd_arp_p =
1363         TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32);
1364
1365 static cmdline_parse_token_string_t cmd_arp_arp_string =
1366         TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp");
1367
1368 static cmdline_parse_token_string_t cmd_arp_multi_string =
1369         TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string,
1370         TOKEN_STRING_MULTI);
1371
1372 static cmdline_parse_inst_t cmd_arp = {
1373         .f = cmd_arp_parsed,
1374         .data = NULL,
1375         .help_str = "arp add / add default / del / del default / ls",
1376         .tokens = {
1377                 (void *)&cmd_arp_p_string,
1378                 (void *)&cmd_arp_p,
1379                 (void *)&cmd_arp_arp_string,
1380                 (void *)&cmd_arp_multi_string,
1381                 NULL,
1382         },
1383 };
1384
1385 static cmdline_parse_ctx_t pipeline_cmds[] = {
1386         (cmdline_parse_inst_t *)&cmd_route,
1387         (cmdline_parse_inst_t *)&cmd_arp,
1388         NULL,
1389 };
1390
1391 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
1392         .f_init = pipeline_routing_init,
1393         .f_free = app_pipeline_routing_free,
1394         .cmds = pipeline_cmds,
1395 };
1396
1397 struct pipeline_type pipeline_routing = {
1398         .name = "ROUTING",
1399         .be_ops = &pipeline_routing_be_ops,
1400         .fe_ops = &pipeline_routing_fe_ops,
1401 };