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