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