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 {
61 struct app_params *app;
65 struct pipeline_routing_params rp;
68 TAILQ_HEAD(, app_pipeline_routing_route) routes;
71 uint32_t default_route_present;
72 uint32_t default_route_port_id;
73 void *default_route_entry_ptr;
76 TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries;
77 uint32_t n_arp_entries;
79 uint32_t default_arp_entry_present;
80 uint32_t default_arp_entry_port_id;
81 void *default_arp_entry_ptr;
85 app_pipeline_routing_init(struct pipeline_params *params,
88 struct app_params *app = (struct app_params *) arg;
89 struct pipeline_routing *p;
90 uint32_t pipeline_id, size;
93 /* Check input arguments */
94 if ((params == NULL) ||
95 (params->n_ports_in == 0) ||
96 (params->n_ports_out == 0))
99 APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id);
101 /* Memory allocation */
102 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
103 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
109 p->pipeline_id = pipeline_id;
110 p->n_ports_in = params->n_ports_in;
111 p->n_ports_out = params->n_ports_out;
113 status = pipeline_routing_parse_args(&p->rp, params);
118 TAILQ_INIT(&p->routes);
121 TAILQ_INIT(&p->arp_entries);
122 p->n_arp_entries = 0;
128 app_pipeline_routing_post_init(void *pipeline)
130 struct pipeline_routing *p = pipeline;
132 /* Check input arguments */
136 return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id);
140 app_pipeline_routing_free(void *pipeline)
142 struct pipeline_routing *p = pipeline;
144 /* Check input arguments */
149 while (!TAILQ_EMPTY(&p->routes)) {
150 struct app_pipeline_routing_route *route;
152 route = TAILQ_FIRST(&p->routes);
153 TAILQ_REMOVE(&p->routes, route, node);
157 while (!TAILQ_EMPTY(&p->arp_entries)) {
158 struct app_pipeline_routing_arp_entry *arp_entry;
160 arp_entry = TAILQ_FIRST(&p->arp_entries);
161 TAILQ_REMOVE(&p->arp_entries, arp_entry, node);
169 static struct app_pipeline_routing_route *
170 app_pipeline_routing_find_route(struct pipeline_routing *p,
171 const struct pipeline_routing_route_key *key)
173 struct app_pipeline_routing_route *it, *found;
176 TAILQ_FOREACH(it, &p->routes, node) {
177 if ((key->type == it->key.type) &&
178 (key->key.ipv4.ip == it->key.key.ipv4.ip) &&
179 (key->key.ipv4.depth == it->key.key.ipv4.depth)) {
188 static struct app_pipeline_routing_arp_entry *
189 app_pipeline_routing_find_arp_entry(struct pipeline_routing *p,
190 const struct pipeline_routing_arp_key *key)
192 struct app_pipeline_routing_arp_entry *it, *found;
195 TAILQ_FOREACH(it, &p->arp_entries, node) {
196 if ((key->type == it->key.type) &&
197 (key->key.ipv4.port_id == it->key.key.ipv4.port_id) &&
198 (key->key.ipv4.ip == it->key.key.ipv4.ip)) {
208 print_route(const struct app_pipeline_routing_route *route)
210 if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) {
211 const struct pipeline_routing_route_key_ipv4 *key =
212 &route->key.key.ipv4;
214 printf("IP Prefix = %" PRIu32 ".%" PRIu32
215 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32
216 " => (Port = %" PRIu32,
218 (key->ip >> 24) & 0xFF,
219 (key->ip >> 16) & 0xFF,
220 (key->ip >> 8) & 0xFF,
224 route->data.port_id);
226 if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
228 ", Next Hop IP = %" PRIu32 ".%" PRIu32
229 ".%" PRIu32 ".%" PRIu32,
231 (route->data.ethernet.ip >> 24) & 0xFF,
232 (route->data.ethernet.ip >> 16) & 0xFF,
233 (route->data.ethernet.ip >> 8) & 0xFF,
234 route->data.ethernet.ip & 0xFF);
237 ", Next Hop HWaddress = %02" PRIx32
238 ":%02" PRIx32 ":%02" PRIx32
239 ":%02" PRIx32 ":%02" PRIx32
242 route->data.ethernet.macaddr.addr_bytes[0],
243 route->data.ethernet.macaddr.addr_bytes[1],
244 route->data.ethernet.macaddr.addr_bytes[2],
245 route->data.ethernet.macaddr.addr_bytes[3],
246 route->data.ethernet.macaddr.addr_bytes[4],
247 route->data.ethernet.macaddr.addr_bytes[5]);
249 if (route->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)
250 printf(", QinQ SVLAN = %" PRIu32 " CVLAN = %" PRIu32,
251 route->data.l2.qinq.svlan,
252 route->data.l2.qinq.cvlan);
254 if (route->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) {
257 printf(", MPLS labels");
258 for (i = 0; i < route->data.l2.mpls.n_labels; i++)
260 route->data.l2.mpls.labels[i]);
268 print_arp_entry(const struct app_pipeline_routing_arp_entry *entry)
270 printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32
271 ".%" PRIu32 ".%" PRIu32
272 ") => HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
273 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
275 entry->key.key.ipv4.port_id,
276 (entry->key.key.ipv4.ip >> 24) & 0xFF,
277 (entry->key.key.ipv4.ip >> 16) & 0xFF,
278 (entry->key.key.ipv4.ip >> 8) & 0xFF,
279 entry->key.key.ipv4.ip & 0xFF,
281 entry->macaddr.addr_bytes[0],
282 entry->macaddr.addr_bytes[1],
283 entry->macaddr.addr_bytes[2],
284 entry->macaddr.addr_bytes[3],
285 entry->macaddr.addr_bytes[4],
286 entry->macaddr.addr_bytes[5]);
290 app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id)
292 struct pipeline_routing *p;
293 struct app_pipeline_routing_route *it;
295 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
299 TAILQ_FOREACH(it, &p->routes, node)
302 if (p->default_route_present)
303 printf("Default route: port %" PRIu32 " (entry ptr = %p)\n",
304 p->default_route_port_id,
305 p->default_route_entry_ptr);
307 printf("Default: DROP\n");
313 app_pipeline_routing_add_route(struct app_params *app,
314 uint32_t pipeline_id,
315 struct pipeline_routing_route_key *key,
316 struct pipeline_routing_route_data *data)
318 struct pipeline_routing *p;
320 struct pipeline_routing_route_add_msg_req *req;
321 struct pipeline_routing_route_add_msg_rsp *rsp;
323 struct app_pipeline_routing_route *entry;
327 /* Check input arguments */
333 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
338 case PIPELINE_ROUTING_ROUTE_IPV4:
340 uint32_t depth = key->key.ipv4.depth;
344 if ((depth == 0) || (depth > 32))
347 netmask = (~0U) << (32 - depth);
348 key->key.ipv4.ip &= netmask;
351 if (data->port_id >= p->n_ports_out)
360 /* Find existing rule or allocate new rule */
361 entry = app_pipeline_routing_find_route(p, key);
362 new_entry = (entry == NULL);
364 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
370 /* Allocate and write request */
371 req = app_msg_alloc(app);
378 req->type = PIPELINE_MSG_REQ_CUSTOM;
379 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD;
380 memcpy(&req->key, key, sizeof(*key));
381 memcpy(&req->data, data, sizeof(*data));
383 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
390 /* Read response and write entry */
392 (rsp->entry_ptr == NULL) ||
393 ((new_entry == 0) && (rsp->key_found == 0)) ||
394 ((new_entry == 1) && (rsp->key_found == 1))) {
395 app_msg_free(app, rsp);
401 memcpy(&entry->key, key, sizeof(*key));
402 memcpy(&entry->data, data, sizeof(*data));
403 entry->entry_ptr = rsp->entry_ptr;
407 TAILQ_INSERT_TAIL(&p->routes, entry, node);
411 /* Message buffer free */
412 app_msg_free(app, rsp);
417 app_pipeline_routing_delete_route(struct app_params *app,
418 uint32_t pipeline_id,
419 struct pipeline_routing_route_key *key)
421 struct pipeline_routing *p;
423 struct pipeline_routing_route_delete_msg_req *req;
424 struct pipeline_routing_route_delete_msg_rsp *rsp;
426 struct app_pipeline_routing_route *entry;
428 /* Check input arguments */
433 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
438 case PIPELINE_ROUTING_ROUTE_IPV4:
440 uint32_t depth = key->key.ipv4.depth;
444 if ((depth == 0) || (depth > 32))
447 netmask = (~0U) << (32 - depth);
448 key->key.ipv4.ip &= netmask;
457 entry = app_pipeline_routing_find_route(p, key);
461 /* Allocate and write request */
462 req = app_msg_alloc(app);
466 req->type = PIPELINE_MSG_REQ_CUSTOM;
467 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL;
468 memcpy(&req->key, key, sizeof(*key));
470 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
475 if (rsp->status || !rsp->key_found) {
476 app_msg_free(app, rsp);
481 TAILQ_REMOVE(&p->routes, entry, node);
486 app_msg_free(app, rsp);
492 app_pipeline_routing_add_default_route(struct app_params *app,
493 uint32_t pipeline_id,
496 struct pipeline_routing *p;
498 struct pipeline_routing_route_add_default_msg_req *req;
499 struct pipeline_routing_route_add_default_msg_rsp *rsp;
501 /* Check input arguments */
505 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
509 if (port_id >= p->n_ports_out)
512 /* Allocate and write request */
513 req = app_msg_alloc(app);
517 req->type = PIPELINE_MSG_REQ_CUSTOM;
518 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT;
519 req->port_id = port_id;
521 /* Send request and wait for response */
522 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
526 /* Read response and write route */
527 if (rsp->status || (rsp->entry_ptr == NULL)) {
528 app_msg_free(app, rsp);
532 p->default_route_port_id = port_id;
533 p->default_route_entry_ptr = rsp->entry_ptr;
536 p->default_route_present = 1;
539 app_msg_free(app, rsp);
545 app_pipeline_routing_delete_default_route(struct app_params *app,
546 uint32_t pipeline_id)
548 struct pipeline_routing *p;
550 struct pipeline_routing_arp_delete_default_msg_req *req;
551 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
553 /* Check input arguments */
557 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
561 /* Allocate and write request */
562 req = app_msg_alloc(app);
566 req->type = PIPELINE_MSG_REQ_CUSTOM;
567 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT;
569 /* Send request and wait for response */
570 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
574 /* Read response and write route */
576 app_msg_free(app, rsp);
581 p->default_route_present = 0;
584 app_msg_free(app, rsp);
590 app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id)
592 struct pipeline_routing *p;
593 struct app_pipeline_routing_arp_entry *it;
595 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
599 TAILQ_FOREACH(it, &p->arp_entries, node)
602 if (p->default_arp_entry_present)
603 printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n",
604 p->default_arp_entry_port_id,
605 p->default_arp_entry_ptr);
607 printf("Default: DROP\n");
613 app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
614 struct pipeline_routing_arp_key *key,
615 struct ether_addr *macaddr)
617 struct pipeline_routing *p;
619 struct pipeline_routing_arp_add_msg_req *req;
620 struct pipeline_routing_arp_add_msg_rsp *rsp;
622 struct app_pipeline_routing_arp_entry *entry;
626 /* Check input arguments */
632 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
637 case PIPELINE_ROUTING_ARP_IPV4:
639 uint32_t port_id = key->key.ipv4.port_id;
642 if (port_id >= p->n_ports_out)
651 /* Find existing entry or allocate new */
652 entry = app_pipeline_routing_find_arp_entry(p, key);
653 new_entry = (entry == NULL);
655 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
661 /* Message buffer allocation */
662 req = app_msg_alloc(app);
669 req->type = PIPELINE_MSG_REQ_CUSTOM;
670 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD;
671 memcpy(&req->key, key, sizeof(*key));
672 ether_addr_copy(macaddr, &req->macaddr);
674 /* Send request and wait for response */
675 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
682 /* Read response and write entry */
684 (rsp->entry_ptr == NULL) ||
685 ((new_entry == 0) && (rsp->key_found == 0)) ||
686 ((new_entry == 1) && (rsp->key_found == 1))) {
687 app_msg_free(app, rsp);
693 memcpy(&entry->key, key, sizeof(*key));
694 ether_addr_copy(macaddr, &entry->macaddr);
695 entry->entry_ptr = rsp->entry_ptr;
699 TAILQ_INSERT_TAIL(&p->arp_entries, entry, node);
703 /* Message buffer free */
704 app_msg_free(app, rsp);
709 app_pipeline_routing_delete_arp_entry(struct app_params *app,
710 uint32_t pipeline_id,
711 struct pipeline_routing_arp_key *key)
713 struct pipeline_routing *p;
715 struct pipeline_routing_arp_delete_msg_req *req;
716 struct pipeline_routing_arp_delete_msg_rsp *rsp;
718 struct app_pipeline_routing_arp_entry *entry;
720 /* Check input arguments */
725 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
730 case PIPELINE_ROUTING_ARP_IPV4:
732 uint32_t port_id = key->key.ipv4.port_id;
735 if (port_id >= p->n_ports_out)
745 entry = app_pipeline_routing_find_arp_entry(p, key);
749 /* Allocate and write request */
750 req = app_msg_alloc(app);
754 req->type = PIPELINE_MSG_REQ_CUSTOM;
755 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL;
756 memcpy(&req->key, key, sizeof(*key));
758 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
763 if (rsp->status || !rsp->key_found) {
764 app_msg_free(app, rsp);
769 TAILQ_REMOVE(&p->arp_entries, entry, node);
774 app_msg_free(app, rsp);
780 app_pipeline_routing_add_default_arp_entry(struct app_params *app,
781 uint32_t pipeline_id,
784 struct pipeline_routing *p;
786 struct pipeline_routing_arp_add_default_msg_req *req;
787 struct pipeline_routing_arp_add_default_msg_rsp *rsp;
789 /* Check input arguments */
793 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
797 if (port_id >= p->n_ports_out)
800 /* Allocate and write request */
801 req = app_msg_alloc(app);
805 req->type = PIPELINE_MSG_REQ_CUSTOM;
806 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT;
807 req->port_id = port_id;
809 /* Send request and wait for response */
810 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
814 /* Read response and write entry */
815 if (rsp->status || rsp->entry_ptr == NULL) {
816 app_msg_free(app, rsp);
820 p->default_arp_entry_port_id = port_id;
821 p->default_arp_entry_ptr = rsp->entry_ptr;
824 p->default_arp_entry_present = 1;
827 app_msg_free(app, rsp);
833 app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
834 uint32_t pipeline_id)
836 struct pipeline_routing *p;
838 struct pipeline_routing_arp_delete_default_msg_req *req;
839 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
841 /* Check input arguments */
845 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
849 /* Allocate and write request */
850 req = app_msg_alloc(app);
854 req->type = PIPELINE_MSG_REQ_CUSTOM;
855 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT;
857 /* Send request and wait for response */
858 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
862 /* Read response and write entry */
864 app_msg_free(app, rsp);
869 p->default_arp_entry_present = 0;
872 app_msg_free(app, rsp);
878 app_pipeline_routing_set_macaddr(struct app_params *app,
879 uint32_t pipeline_id)
881 struct app_pipeline_params *p;
882 struct pipeline_routing_set_macaddr_msg_req *req;
883 struct pipeline_routing_set_macaddr_msg_rsp *rsp;
886 /* Check input arguments */
890 APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
894 /* Allocate and write request */
895 req = app_msg_alloc(app);
899 req->type = PIPELINE_MSG_REQ_CUSTOM;
900 req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR;
902 memset(req->macaddr, 0, sizeof(req->macaddr));
903 for (port_id = 0; port_id < p->n_pktq_out; port_id++) {
904 struct app_link_params *link;
906 link = app_pipeline_track_pktq_out_to_link(app,
910 req->macaddr[port_id] = link->mac_addr;
913 /* Send request and wait for response */
914 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
918 /* Read response and write entry */
920 app_msg_free(app, rsp);
925 app_msg_free(app, rsp);
933 * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
934 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
935 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
936 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
937 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
938 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
939 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
942 * p <pipelineid> route add default <portid>
945 * p <pipelineid> route del <ipaddr> <depth>
948 * p <pipelineid> route del default
951 * p <pipelineid> route ls
954 struct cmd_route_result {
955 cmdline_fixed_string_t p_string;
957 cmdline_fixed_string_t route_string;
958 cmdline_multi_string_t multi_string;
964 __rte_unused struct cmdline *cl,
967 struct cmd_route_result *params = parsed_result;
968 struct app_params *app = data;
971 uint32_t n_tokens = RTE_DIM(tokens);
974 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
976 printf(CMD_MSG_TOO_MANY_ARGS, "route");
981 if ((n_tokens >= 2) &&
982 (strcmp(tokens[0], "add") == 0) &&
983 strcmp(tokens[1], "default")) {
984 struct pipeline_routing_route_key key;
985 struct pipeline_routing_route_data route_data;
986 struct in_addr ipv4, nh_ipv4;
987 struct ether_addr mac_addr;
988 uint32_t depth, port_id, svlan, cvlan, i;
989 uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
990 uint32_t n_labels = RTE_DIM(mpls_labels);
992 memset(&key, 0, sizeof(key));
993 memset(&route_data, 0, sizeof(route_data));
996 printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add");
1000 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1001 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1005 if (parser_read_uint32(&depth, tokens[2])) {
1006 printf(CMD_MSG_INVALID_ARG, "depth");
1010 if (strcmp(tokens[3], "port")) {
1011 printf(CMD_MSG_ARG_NOT_FOUND, "port");
1015 if (parser_read_uint32(&port_id, tokens[4])) {
1016 printf(CMD_MSG_INVALID_ARG, "portid");
1020 if (strcmp(tokens[5], "ether")) {
1021 printf(CMD_MSG_ARG_NOT_FOUND, "ether");
1025 if (parse_mac_addr(tokens[6], &mac_addr)) {
1026 if (parse_ipv4_addr(tokens[6], &nh_ipv4)) {
1027 printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr");
1031 route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP;
1035 if (strcmp(tokens[7], "mpls") == 0) {
1036 if (n_tokens != 9) {
1037 printf(CMD_MSG_MISMATCH_ARGS, "route add mpls");
1041 if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) {
1042 printf(CMD_MSG_INVALID_ARG, "mpls labels");
1046 route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
1047 } else if (strcmp(tokens[7], "qinq") == 0) {
1048 if (n_tokens != 10) {
1049 printf(CMD_MSG_MISMATCH_ARGS, "route add qinq");
1053 if (parser_read_uint32(&svlan, tokens[8])) {
1054 printf(CMD_MSG_INVALID_ARG, "svlan");
1057 if (parser_read_uint32(&cvlan, tokens[9])) {
1058 printf(CMD_MSG_INVALID_ARG, "cvlan");
1062 route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
1064 printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq");
1069 switch (route_data.flags) {
1071 route_data.port_id = port_id;
1072 route_data.ethernet.macaddr = mac_addr;
1075 case PIPELINE_ROUTING_ROUTE_ARP:
1076 route_data.port_id = port_id;
1077 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1080 case PIPELINE_ROUTING_ROUTE_MPLS:
1081 route_data.port_id = port_id;
1082 route_data.ethernet.macaddr = mac_addr;
1083 for (i = 0; i < n_labels; i++)
1084 route_data.l2.mpls.labels[i] = mpls_labels[i];
1085 route_data.l2.mpls.n_labels = n_labels;
1088 case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP:
1089 route_data.port_id = port_id;
1090 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1091 for (i = 0; i < n_labels; i++)
1092 route_data.l2.mpls.labels[i] = mpls_labels[i];
1093 route_data.l2.mpls.n_labels = n_labels;
1096 case PIPELINE_ROUTING_ROUTE_QINQ:
1097 route_data.port_id = port_id;
1098 route_data.ethernet.macaddr = mac_addr;
1099 route_data.l2.qinq.svlan = svlan;
1100 route_data.l2.qinq.cvlan = cvlan;
1103 case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP:
1105 route_data.port_id = port_id;
1106 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1107 route_data.l2.qinq.svlan = svlan;
1108 route_data.l2.qinq.cvlan = cvlan;
1112 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1113 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1114 key.key.ipv4.depth = depth;
1116 status = app_pipeline_routing_add_route(app,
1121 printf(CMD_MSG_FAIL, "route add");
1126 /* route add default */
1127 if ((n_tokens >= 2) &&
1128 (strcmp(tokens[0], "add") == 0) &&
1129 (strcmp(tokens[1], "default") == 0)) {
1132 if (n_tokens != 3) {
1133 printf(CMD_MSG_MISMATCH_ARGS, "route add default");
1137 if (parser_read_uint32(&port_id, tokens[2])) {
1138 printf(CMD_MSG_INVALID_ARG, "portid");
1142 status = app_pipeline_routing_add_default_route(app,
1146 printf(CMD_MSG_FAIL, "route add default");
1149 } /* route add default */
1152 if ((n_tokens >= 2) &&
1153 (strcmp(tokens[0], "del") == 0) &&
1154 strcmp(tokens[1], "default")) {
1155 struct pipeline_routing_route_key key;
1156 struct in_addr ipv4;
1159 memset(&key, 0, sizeof(key));
1161 if (n_tokens != 3) {
1162 printf(CMD_MSG_MISMATCH_ARGS, "route del");
1166 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1167 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1171 if (parser_read_uint32(&depth, tokens[2])) {
1172 printf(CMD_MSG_INVALID_ARG, "depth");
1176 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1177 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1178 key.key.ipv4.depth = depth;
1180 status = app_pipeline_routing_delete_route(app, params->p, &key);
1182 printf(CMD_MSG_FAIL, "route del");
1187 /* route del default */
1188 if ((n_tokens >= 2) &&
1189 (strcmp(tokens[0], "del") == 0) &&
1190 (strcmp(tokens[1], "default") == 0)) {
1191 if (n_tokens != 2) {
1192 printf(CMD_MSG_MISMATCH_ARGS, "route del default");
1196 status = app_pipeline_routing_delete_default_route(app,
1199 printf(CMD_MSG_FAIL, "route del default");
1202 } /* route del default */
1205 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1206 if (n_tokens != 1) {
1207 printf(CMD_MSG_MISMATCH_ARGS, "route ls");
1211 status = app_pipeline_routing_route_ls(app, params->p);
1213 printf(CMD_MSG_FAIL, "route ls");
1218 printf(CMD_MSG_MISMATCH_ARGS, "route");
1221 static cmdline_parse_token_string_t cmd_route_p_string =
1222 TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p");
1224 static cmdline_parse_token_num_t cmd_route_p =
1225 TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32);
1227 static cmdline_parse_token_string_t cmd_route_route_string =
1228 TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route");
1230 static cmdline_parse_token_string_t cmd_route_multi_string =
1231 TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string,
1232 TOKEN_STRING_MULTI);
1234 static cmdline_parse_inst_t cmd_route = {
1235 .f = cmd_route_parsed,
1237 .help_str = "route add / add default / del / del default / ls",
1239 (void *)&cmd_route_p_string,
1240 (void *)&cmd_route_p,
1241 (void *)&cmd_route_route_string,
1242 (void *)&cmd_route_multi_string,
1251 * p <pipelineid> arp add <portid> <ipaddr> <macaddr>
1254 * p <pipelineid> arp add default <portid>
1257 * p <pipelineid> arp del <portid> <ipaddr>
1260 * p <pipelineid> arp del default
1263 * p <pipelineid> arp ls
1266 struct cmd_arp_result {
1267 cmdline_fixed_string_t p_string;
1269 cmdline_fixed_string_t arp_string;
1270 cmdline_multi_string_t multi_string;
1275 void *parsed_result,
1276 __rte_unused struct cmdline *cl,
1279 struct cmd_arp_result *params = parsed_result;
1280 struct app_params *app = data;
1283 uint32_t n_tokens = RTE_DIM(tokens);
1286 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1288 printf(CMD_MSG_TOO_MANY_ARGS, "arp");
1293 if ((n_tokens >= 2) &&
1294 (strcmp(tokens[0], "add") == 0) &&
1295 strcmp(tokens[1], "default")) {
1296 struct pipeline_routing_arp_key key;
1297 struct in_addr ipv4;
1298 struct ether_addr mac_addr;
1301 memset(&key, 0, sizeof(key));
1303 if (n_tokens != 4) {
1304 printf(CMD_MSG_MISMATCH_ARGS, "arp add");
1308 if (parser_read_uint32(&port_id, tokens[1])) {
1309 printf(CMD_MSG_INVALID_ARG, "portid");
1313 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1314 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1318 if (parse_mac_addr(tokens[3], &mac_addr)) {
1319 printf(CMD_MSG_INVALID_ARG, "macaddr");
1323 key.type = PIPELINE_ROUTING_ARP_IPV4;
1324 key.key.ipv4.port_id = port_id;
1325 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1327 status = app_pipeline_routing_add_arp_entry(app,
1332 printf(CMD_MSG_FAIL, "arp add");
1337 /* arp add default */
1338 if ((n_tokens >= 2) &&
1339 (strcmp(tokens[0], "add") == 0) &&
1340 (strcmp(tokens[1], "default") == 0)) {
1343 if (n_tokens != 3) {
1344 printf(CMD_MSG_MISMATCH_ARGS, "arp add default");
1348 if (parser_read_uint32(&port_id, tokens[2])) {
1349 printf(CMD_MSG_INVALID_ARG, "portid");
1353 status = app_pipeline_routing_add_default_arp_entry(app,
1357 printf(CMD_MSG_FAIL, "arp add default");
1360 } /* arp add default */
1363 if ((n_tokens >= 2) &&
1364 (strcmp(tokens[0], "del") == 0) &&
1365 strcmp(tokens[1], "default")) {
1366 struct pipeline_routing_arp_key key;
1367 struct in_addr ipv4;
1370 memset(&key, 0, sizeof(key));
1372 if (n_tokens != 3) {
1373 printf(CMD_MSG_MISMATCH_ARGS, "arp del");
1377 if (parser_read_uint32(&port_id, tokens[1])) {
1378 printf(CMD_MSG_INVALID_ARG, "portid");
1382 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1383 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1387 key.type = PIPELINE_ROUTING_ARP_IPV4;
1388 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1389 key.key.ipv4.port_id = port_id;
1391 status = app_pipeline_routing_delete_arp_entry(app,
1395 printf(CMD_MSG_FAIL, "arp del");
1400 /* arp del default */
1401 if ((n_tokens >= 2) &&
1402 (strcmp(tokens[0], "del") == 0) &&
1403 (strcmp(tokens[1], "default") == 0)) {
1404 if (n_tokens != 2) {
1405 printf(CMD_MSG_MISMATCH_ARGS, "arp del default");
1409 status = app_pipeline_routing_delete_default_arp_entry(app,
1412 printf(CMD_MSG_FAIL, "arp del default");
1415 } /* arp del default */
1418 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1419 if (n_tokens != 1) {
1420 printf(CMD_MSG_MISMATCH_ARGS, "arp ls");
1424 status = app_pipeline_routing_arp_ls(app, params->p);
1426 printf(CMD_MSG_FAIL, "arp ls");
1431 printf(CMD_MSG_FAIL, "arp");
1434 static cmdline_parse_token_string_t cmd_arp_p_string =
1435 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p");
1437 static cmdline_parse_token_num_t cmd_arp_p =
1438 TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32);
1440 static cmdline_parse_token_string_t cmd_arp_arp_string =
1441 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp");
1443 static cmdline_parse_token_string_t cmd_arp_multi_string =
1444 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string,
1445 TOKEN_STRING_MULTI);
1447 static cmdline_parse_inst_t cmd_arp = {
1448 .f = cmd_arp_parsed,
1450 .help_str = "arp add / add default / del / del default / ls",
1452 (void *)&cmd_arp_p_string,
1454 (void *)&cmd_arp_arp_string,
1455 (void *)&cmd_arp_multi_string,
1460 static cmdline_parse_ctx_t pipeline_cmds[] = {
1461 (cmdline_parse_inst_t *)&cmd_route,
1462 (cmdline_parse_inst_t *)&cmd_arp,
1466 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
1467 .f_init = app_pipeline_routing_init,
1468 .f_post_init = app_pipeline_routing_post_init,
1469 .f_free = app_pipeline_routing_free,
1470 .f_track = app_pipeline_track_default,
1471 .cmds = pipeline_cmds,
1474 struct pipeline_type pipeline_routing = {
1476 .be_ops = &pipeline_routing_be_ops,
1477 .fe_ops = &pipeline_routing_fe_ops,