1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
5 #include <cmdline_parse.h>
6 #include <cmdline_parse_num.h>
7 #include <cmdline_parse_string.h>
10 #include "pipeline_common_fe.h"
11 #include "pipeline_routing.h"
14 struct app_pipeline_routing_route {
15 struct pipeline_routing_route_key key;
16 struct pipeline_routing_route_data data;
19 TAILQ_ENTRY(app_pipeline_routing_route) node;
22 struct app_pipeline_routing_arp_entry {
23 struct pipeline_routing_arp_key key;
24 struct ether_addr macaddr;
27 TAILQ_ENTRY(app_pipeline_routing_arp_entry) node;
30 struct pipeline_routing {
32 struct app_params *app;
36 struct pipeline_routing_params rp;
39 uint32_t link_id[PIPELINE_MAX_PORT_OUT];
42 TAILQ_HEAD(, app_pipeline_routing_route) routes;
45 uint32_t default_route_present;
46 uint32_t default_route_port_id;
47 void *default_route_entry_ptr;
50 TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries;
51 uint32_t n_arp_entries;
53 uint32_t default_arp_entry_present;
54 uint32_t default_arp_entry_port_id;
55 void *default_arp_entry_ptr;
59 app_pipeline_routing_find_link(struct pipeline_routing *p,
65 for (i = 0; i < p->n_ports_out; i++)
66 if (p->link_id[i] == link_id) {
75 app_pipeline_routing_link_op(__rte_unused struct app_params *app,
80 struct pipeline_routing_route_key key0, key1;
81 struct pipeline_routing *p = arg;
82 struct app_link_params *lp;
83 uint32_t port_id, netmask;
89 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp);
93 status = app_pipeline_routing_find_link(p,
99 netmask = (~0U) << (32 - lp->depth);
101 /* Local network (directly attached network) */
102 key0.type = PIPELINE_ROUTING_ROUTE_IPV4;
103 key0.key.ipv4.ip = lp->ip & netmask;
104 key0.key.ipv4.depth = lp->depth;
106 /* Local termination */
107 key1.type = PIPELINE_ROUTING_ROUTE_IPV4;
108 key1.key.ipv4.ip = lp->ip;
109 key1.key.ipv4.depth = 32;
112 struct pipeline_routing_route_data data0, data1;
114 /* Local network (directly attached network) */
115 memset(&data0, 0, sizeof(data0));
116 data0.flags = PIPELINE_ROUTING_ROUTE_LOCAL |
117 PIPELINE_ROUTING_ROUTE_ARP;
118 if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ)
119 data0.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
120 if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) {
121 data0.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
122 data0.l2.mpls.n_labels = 1;
124 data0.port_id = port_id;
126 if (p->rp.n_arp_entries)
127 app_pipeline_routing_add_route(app,
132 /* Local termination */
133 memset(&data1, 0, sizeof(data1));
134 data1.flags = PIPELINE_ROUTING_ROUTE_LOCAL |
135 PIPELINE_ROUTING_ROUTE_ARP;
136 if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ)
137 data1.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
138 if (p->rp.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) {
139 data1.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
140 data1.l2.mpls.n_labels = 1;
142 data1.port_id = p->rp.port_local_dest;
144 app_pipeline_routing_add_route(app,
149 /* Local network (directly attached network) */
150 if (p->rp.n_arp_entries)
151 app_pipeline_routing_delete_route(app,
155 /* Local termination */
156 app_pipeline_routing_delete_route(app,
163 app_pipeline_routing_set_link_op(
164 struct app_params *app,
165 struct pipeline_routing *p)
169 for (port_id = 0; port_id < p->n_ports_out; port_id++) {
170 struct app_link_params *link;
174 link = app_pipeline_track_pktq_out_to_link(app,
180 link_id = link - app->link_params;
181 p->link_id[port_id] = link_id;
183 status = app_link_set_op(app,
186 app_pipeline_routing_link_op,
196 app_pipeline_routing_init(struct pipeline_params *params,
199 struct app_params *app = (struct app_params *) arg;
200 struct pipeline_routing *p;
201 uint32_t pipeline_id, size;
204 /* Check input arguments */
205 if ((params == NULL) ||
206 (params->n_ports_in == 0) ||
207 (params->n_ports_out == 0))
210 APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id);
212 /* Memory allocation */
213 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
214 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
220 p->pipeline_id = pipeline_id;
221 p->n_ports_in = params->n_ports_in;
222 p->n_ports_out = params->n_ports_out;
224 status = pipeline_routing_parse_args(&p->rp, params);
229 TAILQ_INIT(&p->routes);
232 TAILQ_INIT(&p->arp_entries);
233 p->n_arp_entries = 0;
235 app_pipeline_routing_set_link_op(app, p);
241 app_pipeline_routing_post_init(void *pipeline)
243 struct pipeline_routing *p = pipeline;
245 /* Check input arguments */
249 return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id);
253 app_pipeline_routing_free(void *pipeline)
255 struct pipeline_routing *p = pipeline;
257 /* Check input arguments */
262 while (!TAILQ_EMPTY(&p->routes)) {
263 struct app_pipeline_routing_route *route;
265 route = TAILQ_FIRST(&p->routes);
266 TAILQ_REMOVE(&p->routes, route, node);
270 while (!TAILQ_EMPTY(&p->arp_entries)) {
271 struct app_pipeline_routing_arp_entry *arp_entry;
273 arp_entry = TAILQ_FIRST(&p->arp_entries);
274 TAILQ_REMOVE(&p->arp_entries, arp_entry, node);
282 static struct app_pipeline_routing_route *
283 app_pipeline_routing_find_route(struct pipeline_routing *p,
284 const struct pipeline_routing_route_key *key)
286 struct app_pipeline_routing_route *it, *found;
289 TAILQ_FOREACH(it, &p->routes, node) {
290 if ((key->type == it->key.type) &&
291 (key->key.ipv4.ip == it->key.key.ipv4.ip) &&
292 (key->key.ipv4.depth == it->key.key.ipv4.depth)) {
301 static struct app_pipeline_routing_arp_entry *
302 app_pipeline_routing_find_arp_entry(struct pipeline_routing *p,
303 const struct pipeline_routing_arp_key *key)
305 struct app_pipeline_routing_arp_entry *it, *found;
308 TAILQ_FOREACH(it, &p->arp_entries, node) {
309 if ((key->type == it->key.type) &&
310 (key->key.ipv4.port_id == it->key.key.ipv4.port_id) &&
311 (key->key.ipv4.ip == it->key.key.ipv4.ip)) {
321 print_route(const struct app_pipeline_routing_route *route)
323 if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) {
324 const struct pipeline_routing_route_key_ipv4 *key =
325 &route->key.key.ipv4;
327 printf("IP Prefix = %" PRIu32 ".%" PRIu32
328 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32
329 " => (Port = %" PRIu32,
331 (key->ip >> 24) & 0xFF,
332 (key->ip >> 16) & 0xFF,
333 (key->ip >> 8) & 0xFF,
337 route->data.port_id);
339 if (route->data.flags & PIPELINE_ROUTING_ROUTE_LOCAL)
341 else if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
343 ", Next Hop IP = %" PRIu32 ".%" PRIu32
344 ".%" PRIu32 ".%" PRIu32,
346 (route->data.ethernet.ip >> 24) & 0xFF,
347 (route->data.ethernet.ip >> 16) & 0xFF,
348 (route->data.ethernet.ip >> 8) & 0xFF,
349 route->data.ethernet.ip & 0xFF);
352 ", Next Hop HWaddress = %02" PRIx32
353 ":%02" PRIx32 ":%02" PRIx32
354 ":%02" PRIx32 ":%02" PRIx32
357 route->data.ethernet.macaddr.addr_bytes[0],
358 route->data.ethernet.macaddr.addr_bytes[1],
359 route->data.ethernet.macaddr.addr_bytes[2],
360 route->data.ethernet.macaddr.addr_bytes[3],
361 route->data.ethernet.macaddr.addr_bytes[4],
362 route->data.ethernet.macaddr.addr_bytes[5]);
364 if (route->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)
365 printf(", QinQ SVLAN = %" PRIu32 " CVLAN = %" PRIu32,
366 route->data.l2.qinq.svlan,
367 route->data.l2.qinq.cvlan);
369 if (route->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) {
372 printf(", MPLS labels");
373 for (i = 0; i < route->data.l2.mpls.n_labels; i++)
375 route->data.l2.mpls.labels[i]);
383 print_arp_entry(const struct app_pipeline_routing_arp_entry *entry)
385 printf("(Port = %" PRIu32 ", IP = %" PRIu32 ".%" PRIu32
386 ".%" PRIu32 ".%" PRIu32
387 ") => HWaddress = %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32
388 ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\n",
390 entry->key.key.ipv4.port_id,
391 (entry->key.key.ipv4.ip >> 24) & 0xFF,
392 (entry->key.key.ipv4.ip >> 16) & 0xFF,
393 (entry->key.key.ipv4.ip >> 8) & 0xFF,
394 entry->key.key.ipv4.ip & 0xFF,
396 entry->macaddr.addr_bytes[0],
397 entry->macaddr.addr_bytes[1],
398 entry->macaddr.addr_bytes[2],
399 entry->macaddr.addr_bytes[3],
400 entry->macaddr.addr_bytes[4],
401 entry->macaddr.addr_bytes[5]);
405 app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id)
407 struct pipeline_routing *p;
408 struct app_pipeline_routing_route *it;
410 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
414 TAILQ_FOREACH(it, &p->routes, node)
417 if (p->default_route_present)
418 printf("Default route: port %" PRIu32 " (entry ptr = %p)\n",
419 p->default_route_port_id,
420 p->default_route_entry_ptr);
422 printf("Default: DROP\n");
428 app_pipeline_routing_add_route(struct app_params *app,
429 uint32_t pipeline_id,
430 struct pipeline_routing_route_key *key,
431 struct pipeline_routing_route_data *data)
433 struct pipeline_routing *p;
435 struct pipeline_routing_route_add_msg_req *req;
436 struct pipeline_routing_route_add_msg_rsp *rsp;
438 struct app_pipeline_routing_route *entry;
442 /* Check input arguments */
448 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
453 case PIPELINE_ROUTING_ROUTE_IPV4:
455 uint32_t depth = key->key.ipv4.depth;
459 if ((depth == 0) || (depth > 32))
462 netmask = (~0U) << (32 - depth);
463 key->key.ipv4.ip &= netmask;
466 if (data->port_id >= p->n_ports_out)
469 /* Valid range of VLAN tags 12 bits */
470 if (data->flags & PIPELINE_ROUTING_ROUTE_QINQ)
471 if ((data->l2.qinq.svlan & 0xF000) ||
472 (data->l2.qinq.cvlan & 0xF000))
475 /* Max number of MPLS labels supported */
476 if (data->flags & PIPELINE_ROUTING_ROUTE_MPLS) {
479 if (data->l2.mpls.n_labels >
480 PIPELINE_ROUTING_MPLS_LABELS_MAX)
483 /* Max MPLS label value 20 bits */
484 for (i = 0; i < data->l2.mpls.n_labels; i++)
485 if (data->l2.mpls.labels[i] & 0xFFF00000)
495 /* Find existing rule or allocate new rule */
496 entry = app_pipeline_routing_find_route(p, key);
497 new_entry = (entry == NULL);
499 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
505 /* Allocate and write request */
506 req = app_msg_alloc(app);
513 req->type = PIPELINE_MSG_REQ_CUSTOM;
514 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD;
515 memcpy(&req->key, key, sizeof(*key));
516 memcpy(&req->data, data, sizeof(*data));
518 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
525 /* Read response and write entry */
527 (rsp->entry_ptr == NULL) ||
528 ((new_entry == 0) && (rsp->key_found == 0)) ||
529 ((new_entry == 1) && (rsp->key_found == 1))) {
530 app_msg_free(app, rsp);
536 memcpy(&entry->key, key, sizeof(*key));
537 memcpy(&entry->data, data, sizeof(*data));
538 entry->entry_ptr = rsp->entry_ptr;
542 TAILQ_INSERT_TAIL(&p->routes, entry, node);
546 /* Message buffer free */
547 app_msg_free(app, rsp);
552 app_pipeline_routing_delete_route(struct app_params *app,
553 uint32_t pipeline_id,
554 struct pipeline_routing_route_key *key)
556 struct pipeline_routing *p;
558 struct pipeline_routing_route_delete_msg_req *req;
559 struct pipeline_routing_route_delete_msg_rsp *rsp;
561 struct app_pipeline_routing_route *entry;
563 /* Check input arguments */
568 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
573 case PIPELINE_ROUTING_ROUTE_IPV4:
575 uint32_t depth = key->key.ipv4.depth;
579 if ((depth == 0) || (depth > 32))
582 netmask = (~0U) << (32 - depth);
583 key->key.ipv4.ip &= netmask;
592 entry = app_pipeline_routing_find_route(p, key);
596 /* Allocate and write request */
597 req = app_msg_alloc(app);
601 req->type = PIPELINE_MSG_REQ_CUSTOM;
602 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL;
603 memcpy(&req->key, key, sizeof(*key));
605 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
610 if (rsp->status || !rsp->key_found) {
611 app_msg_free(app, rsp);
616 TAILQ_REMOVE(&p->routes, entry, node);
621 app_msg_free(app, rsp);
627 app_pipeline_routing_add_default_route(struct app_params *app,
628 uint32_t pipeline_id,
631 struct pipeline_routing *p;
633 struct pipeline_routing_route_add_default_msg_req *req;
634 struct pipeline_routing_route_add_default_msg_rsp *rsp;
636 /* Check input arguments */
640 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
644 if (port_id >= p->n_ports_out)
647 /* Allocate and write request */
648 req = app_msg_alloc(app);
652 req->type = PIPELINE_MSG_REQ_CUSTOM;
653 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT;
654 req->port_id = port_id;
656 /* Send request and wait for response */
657 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
661 /* Read response and write route */
662 if (rsp->status || (rsp->entry_ptr == NULL)) {
663 app_msg_free(app, rsp);
667 p->default_route_port_id = port_id;
668 p->default_route_entry_ptr = rsp->entry_ptr;
671 p->default_route_present = 1;
674 app_msg_free(app, rsp);
680 app_pipeline_routing_delete_default_route(struct app_params *app,
681 uint32_t pipeline_id)
683 struct pipeline_routing *p;
685 struct pipeline_routing_arp_delete_default_msg_req *req;
686 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
688 /* Check input arguments */
692 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
696 /* Allocate and write request */
697 req = app_msg_alloc(app);
701 req->type = PIPELINE_MSG_REQ_CUSTOM;
702 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT;
704 /* Send request and wait for response */
705 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
709 /* Read response and write route */
711 app_msg_free(app, rsp);
716 p->default_route_present = 0;
719 app_msg_free(app, rsp);
725 app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id)
727 struct pipeline_routing *p;
728 struct app_pipeline_routing_arp_entry *it;
730 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
734 TAILQ_FOREACH(it, &p->arp_entries, node)
737 if (p->default_arp_entry_present)
738 printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n",
739 p->default_arp_entry_port_id,
740 p->default_arp_entry_ptr);
742 printf("Default: DROP\n");
748 app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
749 struct pipeline_routing_arp_key *key,
750 struct ether_addr *macaddr)
752 struct pipeline_routing *p;
754 struct pipeline_routing_arp_add_msg_req *req;
755 struct pipeline_routing_arp_add_msg_rsp *rsp;
757 struct app_pipeline_routing_arp_entry *entry;
761 /* Check input arguments */
767 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
772 case PIPELINE_ROUTING_ARP_IPV4:
774 uint32_t port_id = key->key.ipv4.port_id;
777 if (port_id >= p->n_ports_out)
786 /* Find existing entry or allocate new */
787 entry = app_pipeline_routing_find_arp_entry(p, key);
788 new_entry = (entry == NULL);
790 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
796 /* Message buffer allocation */
797 req = app_msg_alloc(app);
804 req->type = PIPELINE_MSG_REQ_CUSTOM;
805 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD;
806 memcpy(&req->key, key, sizeof(*key));
807 ether_addr_copy(macaddr, &req->macaddr);
809 /* Send request and wait for response */
810 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
817 /* Read response and write entry */
819 (rsp->entry_ptr == NULL) ||
820 ((new_entry == 0) && (rsp->key_found == 0)) ||
821 ((new_entry == 1) && (rsp->key_found == 1))) {
822 app_msg_free(app, rsp);
828 memcpy(&entry->key, key, sizeof(*key));
829 ether_addr_copy(macaddr, &entry->macaddr);
830 entry->entry_ptr = rsp->entry_ptr;
834 TAILQ_INSERT_TAIL(&p->arp_entries, entry, node);
838 /* Message buffer free */
839 app_msg_free(app, rsp);
844 app_pipeline_routing_delete_arp_entry(struct app_params *app,
845 uint32_t pipeline_id,
846 struct pipeline_routing_arp_key *key)
848 struct pipeline_routing *p;
850 struct pipeline_routing_arp_delete_msg_req *req;
851 struct pipeline_routing_arp_delete_msg_rsp *rsp;
853 struct app_pipeline_routing_arp_entry *entry;
855 /* Check input arguments */
860 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
865 case PIPELINE_ROUTING_ARP_IPV4:
867 uint32_t port_id = key->key.ipv4.port_id;
870 if (port_id >= p->n_ports_out)
880 entry = app_pipeline_routing_find_arp_entry(p, key);
884 /* Allocate and write request */
885 req = app_msg_alloc(app);
889 req->type = PIPELINE_MSG_REQ_CUSTOM;
890 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL;
891 memcpy(&req->key, key, sizeof(*key));
893 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
898 if (rsp->status || !rsp->key_found) {
899 app_msg_free(app, rsp);
904 TAILQ_REMOVE(&p->arp_entries, entry, node);
909 app_msg_free(app, rsp);
915 app_pipeline_routing_add_default_arp_entry(struct app_params *app,
916 uint32_t pipeline_id,
919 struct pipeline_routing *p;
921 struct pipeline_routing_arp_add_default_msg_req *req;
922 struct pipeline_routing_arp_add_default_msg_rsp *rsp;
924 /* Check input arguments */
928 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
932 if (port_id >= p->n_ports_out)
935 /* Allocate and write request */
936 req = app_msg_alloc(app);
940 req->type = PIPELINE_MSG_REQ_CUSTOM;
941 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT;
942 req->port_id = port_id;
944 /* Send request and wait for response */
945 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
949 /* Read response and write entry */
950 if (rsp->status || rsp->entry_ptr == NULL) {
951 app_msg_free(app, rsp);
955 p->default_arp_entry_port_id = port_id;
956 p->default_arp_entry_ptr = rsp->entry_ptr;
959 p->default_arp_entry_present = 1;
962 app_msg_free(app, rsp);
968 app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
969 uint32_t pipeline_id)
971 struct pipeline_routing *p;
973 struct pipeline_routing_arp_delete_default_msg_req *req;
974 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
976 /* Check input arguments */
980 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
984 /* Allocate and write request */
985 req = app_msg_alloc(app);
989 req->type = PIPELINE_MSG_REQ_CUSTOM;
990 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT;
992 /* Send request and wait for response */
993 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
997 /* Read response and write entry */
999 app_msg_free(app, rsp);
1004 p->default_arp_entry_present = 0;
1007 app_msg_free(app, rsp);
1013 app_pipeline_routing_set_macaddr(struct app_params *app,
1014 uint32_t pipeline_id)
1016 struct app_pipeline_params *p;
1017 struct pipeline_routing_set_macaddr_msg_req *req;
1018 struct pipeline_routing_set_macaddr_msg_rsp *rsp;
1021 /* Check input arguments */
1025 APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
1029 /* Allocate and write request */
1030 req = app_msg_alloc(app);
1034 req->type = PIPELINE_MSG_REQ_CUSTOM;
1035 req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR;
1037 memset(req->macaddr, 0, sizeof(req->macaddr));
1038 for (port_id = 0; port_id < p->n_pktq_out; port_id++) {
1039 struct app_link_params *link;
1041 link = app_pipeline_track_pktq_out_to_link(app,
1045 req->macaddr[port_id] = link->mac_addr;
1048 /* Send request and wait for response */
1049 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
1053 /* Read response and write entry */
1055 app_msg_free(app, rsp);
1060 app_msg_free(app, rsp);
1068 * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
1069 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
1070 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
1071 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
1072 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
1073 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
1074 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
1076 * route add default:
1077 * p <pipelineid> route add default <portid>
1080 * p <pipelineid> route del <ipaddr> <depth>
1082 * route del default:
1083 * p <pipelineid> route del default
1086 * p <pipelineid> route ls
1089 struct cmd_route_result {
1090 cmdline_fixed_string_t p_string;
1092 cmdline_fixed_string_t route_string;
1093 cmdline_multi_string_t multi_string;
1098 void *parsed_result,
1099 __rte_unused struct cmdline *cl,
1102 struct cmd_route_result *params = parsed_result;
1103 struct app_params *app = data;
1106 uint32_t n_tokens = RTE_DIM(tokens);
1109 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1111 printf(CMD_MSG_TOO_MANY_ARGS, "route");
1116 if ((n_tokens >= 2) &&
1117 (strcmp(tokens[0], "add") == 0) &&
1118 strcmp(tokens[1], "default")) {
1119 struct pipeline_routing_route_key key;
1120 struct pipeline_routing_route_data route_data;
1121 struct in_addr ipv4, nh_ipv4;
1122 struct ether_addr mac_addr;
1123 uint32_t depth, port_id, svlan, cvlan, i;
1124 uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
1125 uint32_t n_labels = RTE_DIM(mpls_labels);
1127 memset(&key, 0, sizeof(key));
1128 memset(&route_data, 0, sizeof(route_data));
1131 printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add");
1135 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1136 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1140 if (parser_read_uint32(&depth, tokens[2])) {
1141 printf(CMD_MSG_INVALID_ARG, "depth");
1145 if (strcmp(tokens[3], "port")) {
1146 printf(CMD_MSG_ARG_NOT_FOUND, "port");
1150 if (parser_read_uint32(&port_id, tokens[4])) {
1151 printf(CMD_MSG_INVALID_ARG, "portid");
1155 if (strcmp(tokens[5], "ether")) {
1156 printf(CMD_MSG_ARG_NOT_FOUND, "ether");
1160 if (parse_mac_addr(tokens[6], &mac_addr)) {
1161 if (parse_ipv4_addr(tokens[6], &nh_ipv4)) {
1162 printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr");
1166 route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP;
1170 if (strcmp(tokens[7], "mpls") == 0) {
1171 if (n_tokens != 9) {
1172 printf(CMD_MSG_MISMATCH_ARGS, "route add mpls");
1176 if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) {
1177 printf(CMD_MSG_INVALID_ARG, "mpls labels");
1181 route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
1182 } else if (strcmp(tokens[7], "qinq") == 0) {
1183 if (n_tokens != 10) {
1184 printf(CMD_MSG_MISMATCH_ARGS, "route add qinq");
1188 if (parser_read_uint32(&svlan, tokens[8])) {
1189 printf(CMD_MSG_INVALID_ARG, "svlan");
1192 if (parser_read_uint32(&cvlan, tokens[9])) {
1193 printf(CMD_MSG_INVALID_ARG, "cvlan");
1197 route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
1199 printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq");
1204 switch (route_data.flags) {
1206 route_data.port_id = port_id;
1207 route_data.ethernet.macaddr = mac_addr;
1210 case PIPELINE_ROUTING_ROUTE_ARP:
1211 route_data.port_id = port_id;
1212 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1215 case PIPELINE_ROUTING_ROUTE_MPLS:
1216 route_data.port_id = port_id;
1217 route_data.ethernet.macaddr = mac_addr;
1218 for (i = 0; i < n_labels; i++)
1219 route_data.l2.mpls.labels[i] = mpls_labels[i];
1220 route_data.l2.mpls.n_labels = n_labels;
1223 case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP:
1224 route_data.port_id = port_id;
1225 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1226 for (i = 0; i < n_labels; i++)
1227 route_data.l2.mpls.labels[i] = mpls_labels[i];
1228 route_data.l2.mpls.n_labels = n_labels;
1231 case PIPELINE_ROUTING_ROUTE_QINQ:
1232 route_data.port_id = port_id;
1233 route_data.ethernet.macaddr = mac_addr;
1234 route_data.l2.qinq.svlan = svlan;
1235 route_data.l2.qinq.cvlan = cvlan;
1238 case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP:
1240 route_data.port_id = port_id;
1241 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1242 route_data.l2.qinq.svlan = svlan;
1243 route_data.l2.qinq.cvlan = cvlan;
1247 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1248 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1249 key.key.ipv4.depth = depth;
1251 status = app_pipeline_routing_add_route(app,
1256 printf(CMD_MSG_FAIL, "route add");
1261 /* route add default */
1262 if ((n_tokens >= 2) &&
1263 (strcmp(tokens[0], "add") == 0) &&
1264 (strcmp(tokens[1], "default") == 0)) {
1267 if (n_tokens != 3) {
1268 printf(CMD_MSG_MISMATCH_ARGS, "route add default");
1272 if (parser_read_uint32(&port_id, tokens[2])) {
1273 printf(CMD_MSG_INVALID_ARG, "portid");
1277 status = app_pipeline_routing_add_default_route(app,
1281 printf(CMD_MSG_FAIL, "route add default");
1284 } /* route add default */
1287 if ((n_tokens >= 2) &&
1288 (strcmp(tokens[0], "del") == 0) &&
1289 strcmp(tokens[1], "default")) {
1290 struct pipeline_routing_route_key key;
1291 struct in_addr ipv4;
1294 memset(&key, 0, sizeof(key));
1296 if (n_tokens != 3) {
1297 printf(CMD_MSG_MISMATCH_ARGS, "route del");
1301 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1302 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1306 if (parser_read_uint32(&depth, tokens[2])) {
1307 printf(CMD_MSG_INVALID_ARG, "depth");
1311 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1312 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1313 key.key.ipv4.depth = depth;
1315 status = app_pipeline_routing_delete_route(app, params->p, &key);
1317 printf(CMD_MSG_FAIL, "route del");
1322 /* route del default */
1323 if ((n_tokens >= 2) &&
1324 (strcmp(tokens[0], "del") == 0) &&
1325 (strcmp(tokens[1], "default") == 0)) {
1326 if (n_tokens != 2) {
1327 printf(CMD_MSG_MISMATCH_ARGS, "route del default");
1331 status = app_pipeline_routing_delete_default_route(app,
1334 printf(CMD_MSG_FAIL, "route del default");
1337 } /* route del default */
1340 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1341 if (n_tokens != 1) {
1342 printf(CMD_MSG_MISMATCH_ARGS, "route ls");
1346 status = app_pipeline_routing_route_ls(app, params->p);
1348 printf(CMD_MSG_FAIL, "route ls");
1353 printf(CMD_MSG_MISMATCH_ARGS, "route");
1356 static cmdline_parse_token_string_t cmd_route_p_string =
1357 TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p");
1359 static cmdline_parse_token_num_t cmd_route_p =
1360 TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32);
1362 static cmdline_parse_token_string_t cmd_route_route_string =
1363 TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route");
1365 static cmdline_parse_token_string_t cmd_route_multi_string =
1366 TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string,
1367 TOKEN_STRING_MULTI);
1369 static cmdline_parse_inst_t cmd_route = {
1370 .f = cmd_route_parsed,
1372 .help_str = "route add / add default / del / del default / ls",
1374 (void *)&cmd_route_p_string,
1375 (void *)&cmd_route_p,
1376 (void *)&cmd_route_route_string,
1377 (void *)&cmd_route_multi_string,
1386 * p <pipelineid> arp add <portid> <ipaddr> <macaddr>
1389 * p <pipelineid> arp add default <portid>
1392 * p <pipelineid> arp del <portid> <ipaddr>
1395 * p <pipelineid> arp del default
1398 * p <pipelineid> arp ls
1401 struct cmd_arp_result {
1402 cmdline_fixed_string_t p_string;
1404 cmdline_fixed_string_t arp_string;
1405 cmdline_multi_string_t multi_string;
1410 void *parsed_result,
1411 __rte_unused struct cmdline *cl,
1414 struct cmd_arp_result *params = parsed_result;
1415 struct app_params *app = data;
1418 uint32_t n_tokens = RTE_DIM(tokens);
1421 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1423 printf(CMD_MSG_TOO_MANY_ARGS, "arp");
1428 if ((n_tokens >= 2) &&
1429 (strcmp(tokens[0], "add") == 0) &&
1430 strcmp(tokens[1], "default")) {
1431 struct pipeline_routing_arp_key key;
1432 struct in_addr ipv4;
1433 struct ether_addr mac_addr;
1436 memset(&key, 0, sizeof(key));
1438 if (n_tokens != 4) {
1439 printf(CMD_MSG_MISMATCH_ARGS, "arp add");
1443 if (parser_read_uint32(&port_id, tokens[1])) {
1444 printf(CMD_MSG_INVALID_ARG, "portid");
1448 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1449 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1453 if (parse_mac_addr(tokens[3], &mac_addr)) {
1454 printf(CMD_MSG_INVALID_ARG, "macaddr");
1458 key.type = PIPELINE_ROUTING_ARP_IPV4;
1459 key.key.ipv4.port_id = port_id;
1460 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1462 status = app_pipeline_routing_add_arp_entry(app,
1467 printf(CMD_MSG_FAIL, "arp add");
1472 /* arp add default */
1473 if ((n_tokens >= 2) &&
1474 (strcmp(tokens[0], "add") == 0) &&
1475 (strcmp(tokens[1], "default") == 0)) {
1478 if (n_tokens != 3) {
1479 printf(CMD_MSG_MISMATCH_ARGS, "arp add default");
1483 if (parser_read_uint32(&port_id, tokens[2])) {
1484 printf(CMD_MSG_INVALID_ARG, "portid");
1488 status = app_pipeline_routing_add_default_arp_entry(app,
1492 printf(CMD_MSG_FAIL, "arp add default");
1495 } /* arp add default */
1498 if ((n_tokens >= 2) &&
1499 (strcmp(tokens[0], "del") == 0) &&
1500 strcmp(tokens[1], "default")) {
1501 struct pipeline_routing_arp_key key;
1502 struct in_addr ipv4;
1505 memset(&key, 0, sizeof(key));
1507 if (n_tokens != 3) {
1508 printf(CMD_MSG_MISMATCH_ARGS, "arp del");
1512 if (parser_read_uint32(&port_id, tokens[1])) {
1513 printf(CMD_MSG_INVALID_ARG, "portid");
1517 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1518 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1522 key.type = PIPELINE_ROUTING_ARP_IPV4;
1523 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1524 key.key.ipv4.port_id = port_id;
1526 status = app_pipeline_routing_delete_arp_entry(app,
1530 printf(CMD_MSG_FAIL, "arp del");
1535 /* arp del default */
1536 if ((n_tokens >= 2) &&
1537 (strcmp(tokens[0], "del") == 0) &&
1538 (strcmp(tokens[1], "default") == 0)) {
1539 if (n_tokens != 2) {
1540 printf(CMD_MSG_MISMATCH_ARGS, "arp del default");
1544 status = app_pipeline_routing_delete_default_arp_entry(app,
1547 printf(CMD_MSG_FAIL, "arp del default");
1550 } /* arp del default */
1553 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1554 if (n_tokens != 1) {
1555 printf(CMD_MSG_MISMATCH_ARGS, "arp ls");
1559 status = app_pipeline_routing_arp_ls(app, params->p);
1561 printf(CMD_MSG_FAIL, "arp ls");
1566 printf(CMD_MSG_FAIL, "arp");
1569 static cmdline_parse_token_string_t cmd_arp_p_string =
1570 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p");
1572 static cmdline_parse_token_num_t cmd_arp_p =
1573 TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32);
1575 static cmdline_parse_token_string_t cmd_arp_arp_string =
1576 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp");
1578 static cmdline_parse_token_string_t cmd_arp_multi_string =
1579 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string,
1580 TOKEN_STRING_MULTI);
1582 static cmdline_parse_inst_t cmd_arp = {
1583 .f = cmd_arp_parsed,
1585 .help_str = "arp add / add default / del / del default / ls",
1587 (void *)&cmd_arp_p_string,
1589 (void *)&cmd_arp_arp_string,
1590 (void *)&cmd_arp_multi_string,
1595 static cmdline_parse_ctx_t pipeline_cmds[] = {
1596 (cmdline_parse_inst_t *)&cmd_route,
1597 (cmdline_parse_inst_t *)&cmd_arp,
1601 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
1602 .f_init = app_pipeline_routing_init,
1603 .f_post_init = app_pipeline_routing_post_init,
1604 .f_free = app_pipeline_routing_free,
1605 .f_track = app_pipeline_track_default,
1606 .cmds = pipeline_cmds,
1609 struct pipeline_type pipeline_routing = {
1611 .be_ops = &pipeline_routing_be_ops,
1612 .fe_ops = &pipeline_routing_fe_ops,