]> git.proxmox.com Git - ceph.git/blob - ceph/src/dpdk/examples/ip_pipeline/pipeline/pipeline_routing.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / dpdk / 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 };