4 * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include <cmdline_parse.h>
35 #include <cmdline_parse_num.h>
36 #include <cmdline_parse_string.h>
39 #include "pipeline_common_fe.h"
40 #include "pipeline_routing.h"
43 struct app_pipeline_routing_route {
44 struct pipeline_routing_route_key key;
45 struct pipeline_routing_route_data data;
48 TAILQ_ENTRY(app_pipeline_routing_route) node;
51 struct app_pipeline_routing_arp_entry {
52 struct pipeline_routing_arp_key key;
53 struct ether_addr macaddr;
56 TAILQ_ENTRY(app_pipeline_routing_arp_entry) node;
59 struct pipeline_routing {
65 TAILQ_HEAD(, app_pipeline_routing_route) routes;
68 uint32_t default_route_present;
69 uint32_t default_route_port_id;
70 void *default_route_entry_ptr;
73 TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries;
74 uint32_t n_arp_entries;
76 uint32_t default_arp_entry_present;
77 uint32_t default_arp_entry_port_id;
78 void *default_arp_entry_ptr;
82 pipeline_routing_init(struct pipeline_params *params,
83 __rte_unused void *arg)
85 struct pipeline_routing *p;
88 /* Check input arguments */
89 if ((params == NULL) ||
90 (params->n_ports_in == 0) ||
91 (params->n_ports_out == 0))
94 /* Memory allocation */
95 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
96 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
101 p->n_ports_in = params->n_ports_in;
102 p->n_ports_out = params->n_ports_out;
104 TAILQ_INIT(&p->routes);
107 TAILQ_INIT(&p->arp_entries);
108 p->n_arp_entries = 0;
114 app_pipeline_routing_free(void *pipeline)
116 struct pipeline_routing *p = pipeline;
118 /* Check input arguments */
123 while (!TAILQ_EMPTY(&p->routes)) {
124 struct app_pipeline_routing_route *route;
126 route = TAILQ_FIRST(&p->routes);
127 TAILQ_REMOVE(&p->routes, route, node);
131 while (!TAILQ_EMPTY(&p->arp_entries)) {
132 struct app_pipeline_routing_arp_entry *arp_entry;
134 arp_entry = TAILQ_FIRST(&p->arp_entries);
135 TAILQ_REMOVE(&p->arp_entries, arp_entry, node);
143 static struct app_pipeline_routing_route *
144 app_pipeline_routing_find_route(struct pipeline_routing *p,
145 const struct pipeline_routing_route_key *key)
147 struct app_pipeline_routing_route *it, *found;
150 TAILQ_FOREACH(it, &p->routes, node) {
151 if ((key->type == it->key.type) &&
152 (key->key.ipv4.ip == it->key.key.ipv4.ip) &&
153 (key->key.ipv4.depth == it->key.key.ipv4.depth)) {
162 static struct app_pipeline_routing_arp_entry *
163 app_pipeline_routing_find_arp_entry(struct pipeline_routing *p,
164 const struct pipeline_routing_arp_key *key)
166 struct app_pipeline_routing_arp_entry *it, *found;
169 TAILQ_FOREACH(it, &p->arp_entries, node) {
170 if ((key->type == it->key.type) &&
171 (key->key.ipv4.port_id == it->key.key.ipv4.port_id) &&
172 (key->key.ipv4.ip == it->key.key.ipv4.ip)) {
182 print_route(const struct app_pipeline_routing_route *route)
184 if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) {
185 const struct pipeline_routing_route_key_ipv4 *key =
186 &route->key.key.ipv4;
188 printf("IP Prefix = %" PRIu32 ".%" PRIu32
189 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32
190 " => (Port = %" PRIu32,
192 (key->ip >> 24) & 0xFF,
193 (key->ip >> 16) & 0xFF,
194 (key->ip >> 8) & 0xFF,
198 route->data.port_id);
200 if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
202 ", Next Hop IP = %" PRIu32 ".%" PRIu32
203 ".%" PRIu32 ".%" PRIu32,
205 (route->data.ethernet.ip >> 24) & 0xFF,
206 (route->data.ethernet.ip >> 16) & 0xFF,
207 (route->data.ethernet.ip >> 8) & 0xFF,
208 route->data.ethernet.ip & 0xFF);
211 ", Next Hop HWaddress = %02" PRIx32
212 ":%02" PRIx32 ":%02" PRIx32
213 ":%02" PRIx32 ":%02" PRIx32
216 route->data.ethernet.macaddr.addr_bytes[0],
217 route->data.ethernet.macaddr.addr_bytes[1],
218 route->data.ethernet.macaddr.addr_bytes[2],
219 route->data.ethernet.macaddr.addr_bytes[3],
220 route->data.ethernet.macaddr.addr_bytes[4],
221 route->data.ethernet.macaddr.addr_bytes[5]);
223 if (route->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)
224 printf(", QinQ SVLAN = %" PRIu32 " CVLAN = %" PRIu32,
225 route->data.l2.qinq.svlan,
226 route->data.l2.qinq.cvlan);
228 if (route->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) {
231 printf(", MPLS labels");
232 for (i = 0; i < route->data.l2.mpls.n_labels; i++)
234 route->data.l2.mpls.labels[i]);
242 print_arp_entry(const struct app_pipeline_routing_arp_entry *entry)
244 printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32
245 ".%" PRIu32 ".%" PRIu32
246 ") => HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
247 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
249 entry->key.key.ipv4.port_id,
250 (entry->key.key.ipv4.ip >> 24) & 0xFF,
251 (entry->key.key.ipv4.ip >> 16) & 0xFF,
252 (entry->key.key.ipv4.ip >> 8) & 0xFF,
253 entry->key.key.ipv4.ip & 0xFF,
255 entry->macaddr.addr_bytes[0],
256 entry->macaddr.addr_bytes[1],
257 entry->macaddr.addr_bytes[2],
258 entry->macaddr.addr_bytes[3],
259 entry->macaddr.addr_bytes[4],
260 entry->macaddr.addr_bytes[5]);
264 app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id)
266 struct pipeline_routing *p;
267 struct app_pipeline_routing_route *it;
269 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
273 TAILQ_FOREACH(it, &p->routes, node)
276 if (p->default_route_present)
277 printf("Default route: port %" PRIu32 " (entry ptr = %p)\n",
278 p->default_route_port_id,
279 p->default_route_entry_ptr);
281 printf("Default: DROP\n");
287 app_pipeline_routing_add_route(struct app_params *app,
288 uint32_t pipeline_id,
289 struct pipeline_routing_route_key *key,
290 struct pipeline_routing_route_data *data)
292 struct pipeline_routing *p;
294 struct pipeline_routing_route_add_msg_req *req;
295 struct pipeline_routing_route_add_msg_rsp *rsp;
297 struct app_pipeline_routing_route *entry;
301 /* Check input arguments */
307 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
312 case PIPELINE_ROUTING_ROUTE_IPV4:
314 uint32_t depth = key->key.ipv4.depth;
318 if ((depth == 0) || (depth > 32))
321 netmask = (~0U) << (32 - depth);
322 key->key.ipv4.ip &= netmask;
325 if (data->port_id >= p->n_ports_out)
334 /* Find existing rule or allocate new rule */
335 entry = app_pipeline_routing_find_route(p, key);
336 new_entry = (entry == NULL);
338 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
344 /* Allocate and write request */
345 req = app_msg_alloc(app);
352 req->type = PIPELINE_MSG_REQ_CUSTOM;
353 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD;
354 memcpy(&req->key, key, sizeof(*key));
355 memcpy(&req->data, data, sizeof(*data));
357 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
364 /* Read response and write entry */
366 (rsp->entry_ptr == NULL) ||
367 ((new_entry == 0) && (rsp->key_found == 0)) ||
368 ((new_entry == 1) && (rsp->key_found == 1))) {
369 app_msg_free(app, rsp);
375 memcpy(&entry->key, key, sizeof(*key));
376 memcpy(&entry->data, data, sizeof(*data));
377 entry->entry_ptr = rsp->entry_ptr;
381 TAILQ_INSERT_TAIL(&p->routes, entry, node);
385 /* Message buffer free */
386 app_msg_free(app, rsp);
391 app_pipeline_routing_delete_route(struct app_params *app,
392 uint32_t pipeline_id,
393 struct pipeline_routing_route_key *key)
395 struct pipeline_routing *p;
397 struct pipeline_routing_route_delete_msg_req *req;
398 struct pipeline_routing_route_delete_msg_rsp *rsp;
400 struct app_pipeline_routing_route *entry;
402 /* Check input arguments */
407 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
412 case PIPELINE_ROUTING_ROUTE_IPV4:
414 uint32_t depth = key->key.ipv4.depth;
418 if ((depth == 0) || (depth > 32))
421 netmask = (~0U) << (32 - depth);
422 key->key.ipv4.ip &= netmask;
431 entry = app_pipeline_routing_find_route(p, key);
435 /* Allocate and write request */
436 req = app_msg_alloc(app);
440 req->type = PIPELINE_MSG_REQ_CUSTOM;
441 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL;
442 memcpy(&req->key, key, sizeof(*key));
444 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
449 if (rsp->status || !rsp->key_found) {
450 app_msg_free(app, rsp);
455 TAILQ_REMOVE(&p->routes, entry, node);
460 app_msg_free(app, rsp);
466 app_pipeline_routing_add_default_route(struct app_params *app,
467 uint32_t pipeline_id,
470 struct pipeline_routing *p;
472 struct pipeline_routing_route_add_default_msg_req *req;
473 struct pipeline_routing_route_add_default_msg_rsp *rsp;
475 /* Check input arguments */
479 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
483 if (port_id >= p->n_ports_out)
486 /* Allocate and write request */
487 req = app_msg_alloc(app);
491 req->type = PIPELINE_MSG_REQ_CUSTOM;
492 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT;
493 req->port_id = port_id;
495 /* Send request and wait for response */
496 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
500 /* Read response and write route */
501 if (rsp->status || (rsp->entry_ptr == NULL)) {
502 app_msg_free(app, rsp);
506 p->default_route_port_id = port_id;
507 p->default_route_entry_ptr = rsp->entry_ptr;
510 p->default_route_present = 1;
513 app_msg_free(app, rsp);
519 app_pipeline_routing_delete_default_route(struct app_params *app,
520 uint32_t pipeline_id)
522 struct pipeline_routing *p;
524 struct pipeline_routing_arp_delete_default_msg_req *req;
525 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
527 /* Check input arguments */
531 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
535 /* Allocate and write request */
536 req = app_msg_alloc(app);
540 req->type = PIPELINE_MSG_REQ_CUSTOM;
541 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT;
543 /* Send request and wait for response */
544 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
548 /* Read response and write route */
550 app_msg_free(app, rsp);
555 p->default_route_present = 0;
558 app_msg_free(app, rsp);
564 app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id)
566 struct pipeline_routing *p;
567 struct app_pipeline_routing_arp_entry *it;
569 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
573 TAILQ_FOREACH(it, &p->arp_entries, node)
576 if (p->default_arp_entry_present)
577 printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n",
578 p->default_arp_entry_port_id,
579 p->default_arp_entry_ptr);
581 printf("Default: DROP\n");
587 app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
588 struct pipeline_routing_arp_key *key,
589 struct ether_addr *macaddr)
591 struct pipeline_routing *p;
593 struct pipeline_routing_arp_add_msg_req *req;
594 struct pipeline_routing_arp_add_msg_rsp *rsp;
596 struct app_pipeline_routing_arp_entry *entry;
600 /* Check input arguments */
606 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
611 case PIPELINE_ROUTING_ARP_IPV4:
613 uint32_t port_id = key->key.ipv4.port_id;
616 if (port_id >= p->n_ports_out)
625 /* Find existing entry or allocate new */
626 entry = app_pipeline_routing_find_arp_entry(p, key);
627 new_entry = (entry == NULL);
629 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
635 /* Message buffer allocation */
636 req = app_msg_alloc(app);
643 req->type = PIPELINE_MSG_REQ_CUSTOM;
644 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD;
645 memcpy(&req->key, key, sizeof(*key));
646 ether_addr_copy(macaddr, &req->macaddr);
648 /* Send request and wait for response */
649 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
656 /* Read response and write entry */
658 (rsp->entry_ptr == NULL) ||
659 ((new_entry == 0) && (rsp->key_found == 0)) ||
660 ((new_entry == 1) && (rsp->key_found == 1))) {
661 app_msg_free(app, rsp);
667 memcpy(&entry->key, key, sizeof(*key));
668 ether_addr_copy(macaddr, &entry->macaddr);
669 entry->entry_ptr = rsp->entry_ptr;
673 TAILQ_INSERT_TAIL(&p->arp_entries, entry, node);
677 /* Message buffer free */
678 app_msg_free(app, rsp);
683 app_pipeline_routing_delete_arp_entry(struct app_params *app,
684 uint32_t pipeline_id,
685 struct pipeline_routing_arp_key *key)
687 struct pipeline_routing *p;
689 struct pipeline_routing_arp_delete_msg_req *req;
690 struct pipeline_routing_arp_delete_msg_rsp *rsp;
692 struct app_pipeline_routing_arp_entry *entry;
694 /* Check input arguments */
699 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
704 case PIPELINE_ROUTING_ARP_IPV4:
706 uint32_t port_id = key->key.ipv4.port_id;
709 if (port_id >= p->n_ports_out)
719 entry = app_pipeline_routing_find_arp_entry(p, key);
723 /* Allocate and write request */
724 req = app_msg_alloc(app);
728 req->type = PIPELINE_MSG_REQ_CUSTOM;
729 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL;
730 memcpy(&req->key, key, sizeof(*key));
732 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
737 if (rsp->status || !rsp->key_found) {
738 app_msg_free(app, rsp);
743 TAILQ_REMOVE(&p->arp_entries, entry, node);
748 app_msg_free(app, rsp);
754 app_pipeline_routing_add_default_arp_entry(struct app_params *app,
755 uint32_t pipeline_id,
758 struct pipeline_routing *p;
760 struct pipeline_routing_arp_add_default_msg_req *req;
761 struct pipeline_routing_arp_add_default_msg_rsp *rsp;
763 /* Check input arguments */
767 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
771 if (port_id >= p->n_ports_out)
774 /* Allocate and write request */
775 req = app_msg_alloc(app);
779 req->type = PIPELINE_MSG_REQ_CUSTOM;
780 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT;
781 req->port_id = port_id;
783 /* Send request and wait for response */
784 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
788 /* Read response and write entry */
789 if (rsp->status || rsp->entry_ptr == NULL) {
790 app_msg_free(app, rsp);
794 p->default_arp_entry_port_id = port_id;
795 p->default_arp_entry_ptr = rsp->entry_ptr;
798 p->default_arp_entry_present = 1;
801 app_msg_free(app, rsp);
807 app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
808 uint32_t pipeline_id)
810 struct pipeline_routing *p;
812 struct pipeline_routing_arp_delete_default_msg_req *req;
813 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
815 /* Check input arguments */
819 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
823 /* Allocate and write request */
824 req = app_msg_alloc(app);
828 req->type = PIPELINE_MSG_REQ_CUSTOM;
829 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT;
831 /* Send request and wait for response */
832 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
836 /* Read response and write entry */
838 app_msg_free(app, rsp);
843 p->default_arp_entry_present = 0;
846 app_msg_free(app, rsp);
854 * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
855 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
856 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
857 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
858 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
859 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
860 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
863 * p <pipelineid> route add default <portid>
866 * p <pipelineid> route del <ipaddr> <depth>
869 * p <pipelineid> route del default
872 * p <pipelineid> route ls
875 struct cmd_route_result {
876 cmdline_fixed_string_t p_string;
878 cmdline_fixed_string_t route_string;
879 cmdline_multi_string_t multi_string;
885 __rte_unused struct cmdline *cl,
888 struct cmd_route_result *params = parsed_result;
889 struct app_params *app = data;
892 uint32_t n_tokens = RTE_DIM(tokens);
895 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
897 printf(CMD_MSG_TOO_MANY_ARGS, "route");
902 if ((n_tokens >= 2) &&
903 (strcmp(tokens[0], "add") == 0) &&
904 strcmp(tokens[1], "default")) {
905 struct pipeline_routing_route_key key;
906 struct pipeline_routing_route_data route_data;
907 struct in_addr ipv4, nh_ipv4;
908 struct ether_addr mac_addr;
909 uint32_t depth, port_id, svlan, cvlan, i;
910 uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
911 uint32_t n_labels = RTE_DIM(mpls_labels);
913 memset(&key, 0, sizeof(key));
914 memset(&route_data, 0, sizeof(route_data));
917 printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add");
921 if (parse_ipv4_addr(tokens[1], &ipv4)) {
922 printf(CMD_MSG_INVALID_ARG, "ipaddr");
926 if (parser_read_uint32(&depth, tokens[2])) {
927 printf(CMD_MSG_INVALID_ARG, "depth");
931 if (strcmp(tokens[3], "port")) {
932 printf(CMD_MSG_ARG_NOT_FOUND, "port");
936 if (parser_read_uint32(&port_id, tokens[4])) {
937 printf(CMD_MSG_INVALID_ARG, "portid");
941 if (strcmp(tokens[5], "ether")) {
942 printf(CMD_MSG_ARG_NOT_FOUND, "ether");
946 if (parse_mac_addr(tokens[6], &mac_addr)) {
947 if (parse_ipv4_addr(tokens[6], &nh_ipv4)) {
948 printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr");
952 route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP;
956 if (strcmp(tokens[7], "mpls") == 0) {
958 printf(CMD_MSG_MISMATCH_ARGS, "route add mpls");
962 if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) {
963 printf(CMD_MSG_INVALID_ARG, "mpls labels");
967 route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
968 } else if (strcmp(tokens[7], "qinq") == 0) {
969 if (n_tokens != 10) {
970 printf(CMD_MSG_MISMATCH_ARGS, "route add qinq");
974 if (parser_read_uint32(&svlan, tokens[8])) {
975 printf(CMD_MSG_INVALID_ARG, "svlan");
978 if (parser_read_uint32(&cvlan, tokens[9])) {
979 printf(CMD_MSG_INVALID_ARG, "cvlan");
983 route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
985 printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq");
990 switch (route_data.flags) {
992 route_data.port_id = port_id;
993 route_data.ethernet.macaddr = mac_addr;
996 case PIPELINE_ROUTING_ROUTE_ARP:
997 route_data.port_id = port_id;
998 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1001 case PIPELINE_ROUTING_ROUTE_MPLS:
1002 route_data.port_id = port_id;
1003 route_data.ethernet.macaddr = mac_addr;
1004 for (i = 0; i < n_labels; i++)
1005 route_data.l2.mpls.labels[i] = mpls_labels[i];
1006 route_data.l2.mpls.n_labels = n_labels;
1009 case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP:
1010 route_data.port_id = port_id;
1011 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1012 for (i = 0; i < n_labels; i++)
1013 route_data.l2.mpls.labels[i] = mpls_labels[i];
1014 route_data.l2.mpls.n_labels = n_labels;
1017 case PIPELINE_ROUTING_ROUTE_QINQ:
1018 route_data.port_id = port_id;
1019 route_data.ethernet.macaddr = mac_addr;
1020 route_data.l2.qinq.svlan = svlan;
1021 route_data.l2.qinq.cvlan = cvlan;
1024 case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP:
1026 route_data.port_id = port_id;
1027 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1028 route_data.l2.qinq.svlan = svlan;
1029 route_data.l2.qinq.cvlan = cvlan;
1033 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1034 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1035 key.key.ipv4.depth = depth;
1037 status = app_pipeline_routing_add_route(app,
1042 printf(CMD_MSG_FAIL, "route add");
1047 /* route add default */
1048 if ((n_tokens >= 2) &&
1049 (strcmp(tokens[0], "add") == 0) &&
1050 (strcmp(tokens[1], "default") == 0)) {
1053 if (n_tokens != 3) {
1054 printf(CMD_MSG_MISMATCH_ARGS, "route add default");
1058 if (parser_read_uint32(&port_id, tokens[2])) {
1059 printf(CMD_MSG_INVALID_ARG, "portid");
1063 status = app_pipeline_routing_add_default_route(app,
1067 printf(CMD_MSG_FAIL, "route add default");
1070 } /* route add default */
1073 if ((n_tokens >= 2) &&
1074 (strcmp(tokens[0], "del") == 0) &&
1075 strcmp(tokens[1], "default")) {
1076 struct pipeline_routing_route_key key;
1077 struct in_addr ipv4;
1080 memset(&key, 0, sizeof(key));
1082 if (n_tokens != 3) {
1083 printf(CMD_MSG_MISMATCH_ARGS, "route del");
1087 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1088 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1092 if (parser_read_uint32(&depth, tokens[2])) {
1093 printf(CMD_MSG_INVALID_ARG, "depth");
1097 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1098 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1099 key.key.ipv4.depth = depth;
1101 status = app_pipeline_routing_delete_route(app, params->p, &key);
1103 printf(CMD_MSG_FAIL, "route del");
1108 /* route del default */
1109 if ((n_tokens >= 2) &&
1110 (strcmp(tokens[0], "del") == 0) &&
1111 (strcmp(tokens[1], "default") == 0)) {
1112 if (n_tokens != 2) {
1113 printf(CMD_MSG_MISMATCH_ARGS, "route del default");
1117 status = app_pipeline_routing_delete_default_route(app,
1120 printf(CMD_MSG_FAIL, "route del default");
1123 } /* route del default */
1126 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1127 if (n_tokens != 1) {
1128 printf(CMD_MSG_MISMATCH_ARGS, "route ls");
1132 status = app_pipeline_routing_route_ls(app, params->p);
1134 printf(CMD_MSG_FAIL, "route ls");
1139 printf(CMD_MSG_MISMATCH_ARGS, "route");
1142 static cmdline_parse_token_string_t cmd_route_p_string =
1143 TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p");
1145 static cmdline_parse_token_num_t cmd_route_p =
1146 TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32);
1148 static cmdline_parse_token_string_t cmd_route_route_string =
1149 TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route");
1151 static cmdline_parse_token_string_t cmd_route_multi_string =
1152 TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string,
1153 TOKEN_STRING_MULTI);
1155 static cmdline_parse_inst_t cmd_route = {
1156 .f = cmd_route_parsed,
1158 .help_str = "route add / add default / del / del default / ls",
1160 (void *)&cmd_route_p_string,
1161 (void *)&cmd_route_p,
1162 (void *)&cmd_route_route_string,
1163 (void *)&cmd_route_multi_string,
1172 * p <pipelineid> arp add <portid> <ipaddr> <macaddr>
1175 * p <pipelineid> arp add default <portid>
1178 * p <pipelineid> arp del <portid> <ipaddr>
1181 * p <pipelineid> arp del default
1184 * p <pipelineid> arp ls
1187 struct cmd_arp_result {
1188 cmdline_fixed_string_t p_string;
1190 cmdline_fixed_string_t arp_string;
1191 cmdline_multi_string_t multi_string;
1196 void *parsed_result,
1197 __rte_unused struct cmdline *cl,
1200 struct cmd_arp_result *params = parsed_result;
1201 struct app_params *app = data;
1204 uint32_t n_tokens = RTE_DIM(tokens);
1207 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1209 printf(CMD_MSG_TOO_MANY_ARGS, "arp");
1214 if ((n_tokens >= 2) &&
1215 (strcmp(tokens[0], "add") == 0) &&
1216 strcmp(tokens[1], "default")) {
1217 struct pipeline_routing_arp_key key;
1218 struct in_addr ipv4;
1219 struct ether_addr mac_addr;
1222 memset(&key, 0, sizeof(key));
1224 if (n_tokens != 4) {
1225 printf(CMD_MSG_MISMATCH_ARGS, "arp add");
1229 if (parser_read_uint32(&port_id, tokens[1])) {
1230 printf(CMD_MSG_INVALID_ARG, "portid");
1234 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1235 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1239 if (parse_mac_addr(tokens[3], &mac_addr)) {
1240 printf(CMD_MSG_INVALID_ARG, "macaddr");
1244 key.type = PIPELINE_ROUTING_ARP_IPV4;
1245 key.key.ipv4.port_id = port_id;
1246 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1248 status = app_pipeline_routing_add_arp_entry(app,
1253 printf(CMD_MSG_FAIL, "arp add");
1258 /* arp add default */
1259 if ((n_tokens >= 2) &&
1260 (strcmp(tokens[0], "add") == 0) &&
1261 (strcmp(tokens[1], "default") == 0)) {
1264 if (n_tokens != 3) {
1265 printf(CMD_MSG_MISMATCH_ARGS, "arp add default");
1269 if (parser_read_uint32(&port_id, tokens[2])) {
1270 printf(CMD_MSG_INVALID_ARG, "portid");
1274 status = app_pipeline_routing_add_default_arp_entry(app,
1278 printf(CMD_MSG_FAIL, "arp add default");
1281 } /* arp add default */
1284 if ((n_tokens >= 2) &&
1285 (strcmp(tokens[0], "del") == 0) &&
1286 strcmp(tokens[1], "default")) {
1287 struct pipeline_routing_arp_key key;
1288 struct in_addr ipv4;
1291 memset(&key, 0, sizeof(key));
1293 if (n_tokens != 3) {
1294 printf(CMD_MSG_MISMATCH_ARGS, "arp del");
1298 if (parser_read_uint32(&port_id, tokens[1])) {
1299 printf(CMD_MSG_INVALID_ARG, "portid");
1303 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1304 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1308 key.type = PIPELINE_ROUTING_ARP_IPV4;
1309 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1310 key.key.ipv4.port_id = port_id;
1312 status = app_pipeline_routing_delete_arp_entry(app,
1316 printf(CMD_MSG_FAIL, "arp del");
1321 /* arp del default */
1322 if ((n_tokens >= 2) &&
1323 (strcmp(tokens[0], "del") == 0) &&
1324 (strcmp(tokens[1], "default") == 0)) {
1325 if (n_tokens != 2) {
1326 printf(CMD_MSG_MISMATCH_ARGS, "arp del default");
1330 status = app_pipeline_routing_delete_default_arp_entry(app,
1333 printf(CMD_MSG_FAIL, "arp del default");
1336 } /* arp del default */
1339 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1340 if (n_tokens != 1) {
1341 printf(CMD_MSG_MISMATCH_ARGS, "arp ls");
1345 status = app_pipeline_routing_arp_ls(app, params->p);
1347 printf(CMD_MSG_FAIL, "arp ls");
1352 printf(CMD_MSG_FAIL, "arp");
1355 static cmdline_parse_token_string_t cmd_arp_p_string =
1356 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p");
1358 static cmdline_parse_token_num_t cmd_arp_p =
1359 TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32);
1361 static cmdline_parse_token_string_t cmd_arp_arp_string =
1362 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp");
1364 static cmdline_parse_token_string_t cmd_arp_multi_string =
1365 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string,
1366 TOKEN_STRING_MULTI);
1368 static cmdline_parse_inst_t cmd_arp = {
1369 .f = cmd_arp_parsed,
1371 .help_str = "arp add / add default / del / del default / ls",
1373 (void *)&cmd_arp_p_string,
1375 (void *)&cmd_arp_arp_string,
1376 (void *)&cmd_arp_multi_string,
1381 static cmdline_parse_ctx_t pipeline_cmds[] = {
1382 (cmdline_parse_inst_t *)&cmd_route,
1383 (cmdline_parse_inst_t *)&cmd_arp,
1387 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
1388 .f_init = pipeline_routing_init,
1389 .f_post_init = NULL,
1390 .f_free = app_pipeline_routing_free,
1391 .f_track = app_pipeline_track_default,
1392 .cmds = pipeline_cmds,
1395 struct pipeline_type pipeline_routing = {
1397 .be_ops = &pipeline_routing_be_ops,
1398 .fe_ops = &pipeline_routing_fe_ops,