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 uint32_t link_id[PIPELINE_MAX_PORT_OUT];
71 TAILQ_HEAD(, app_pipeline_routing_route) routes;
74 uint32_t default_route_present;
75 uint32_t default_route_port_id;
76 void *default_route_entry_ptr;
79 TAILQ_HEAD(, app_pipeline_routing_arp_entry) arp_entries;
80 uint32_t n_arp_entries;
82 uint32_t default_arp_entry_present;
83 uint32_t default_arp_entry_port_id;
84 void *default_arp_entry_ptr;
88 app_pipeline_routing_find_link(struct pipeline_routing *p,
94 for (i = 0; i < p->n_ports_out; i++)
95 if (p->link_id[i] == link_id) {
104 app_pipeline_routing_link_op(__rte_unused struct app_params *app,
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;
118 APP_PARAM_FIND_BY_ID(app->link_params, "LINK", link_id, lp);
122 status = app_pipeline_routing_find_link(p,
128 netmask = (~0U) << (32 - lp->depth);
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;
135 /* Local termination */
136 key1.type = PIPELINE_ROUTING_ROUTE_IPV4;
137 key1.key.ipv4.ip = lp->ip;
138 key1.key.ipv4.depth = 32;
141 struct pipeline_routing_route_data data0, data1;
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;
153 data0.port_id = port_id;
155 if (p->rp.n_arp_entries)
156 app_pipeline_routing_add_route(app,
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;
171 data1.port_id = p->rp.port_local_dest;
173 app_pipeline_routing_add_route(app,
178 /* Local network (directly attached network) */
179 if (p->rp.n_arp_entries)
180 app_pipeline_routing_delete_route(app,
184 /* Local termination */
185 app_pipeline_routing_delete_route(app,
192 app_pipeline_routing_set_link_op(
193 struct app_params *app,
194 struct pipeline_routing *p)
198 for (port_id = 0; port_id < p->n_ports_out; port_id++) {
199 struct app_link_params *link;
203 link = app_pipeline_track_pktq_out_to_link(app,
209 link_id = link - app->link_params;
210 p->link_id[port_id] = link_id;
212 status = app_link_set_op(app,
215 app_pipeline_routing_link_op,
225 app_pipeline_routing_init(struct pipeline_params *params,
228 struct app_params *app = (struct app_params *) arg;
229 struct pipeline_routing *p;
230 uint32_t pipeline_id, size;
233 /* Check input arguments */
234 if ((params == NULL) ||
235 (params->n_ports_in == 0) ||
236 (params->n_ports_out == 0))
239 APP_PARAM_GET_ID(params, "PIPELINE", pipeline_id);
241 /* Memory allocation */
242 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
243 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
249 p->pipeline_id = pipeline_id;
250 p->n_ports_in = params->n_ports_in;
251 p->n_ports_out = params->n_ports_out;
253 status = pipeline_routing_parse_args(&p->rp, params);
258 TAILQ_INIT(&p->routes);
261 TAILQ_INIT(&p->arp_entries);
262 p->n_arp_entries = 0;
264 app_pipeline_routing_set_link_op(app, p);
270 app_pipeline_routing_post_init(void *pipeline)
272 struct pipeline_routing *p = pipeline;
274 /* Check input arguments */
278 return app_pipeline_routing_set_macaddr(p->app, p->pipeline_id);
282 app_pipeline_routing_free(void *pipeline)
284 struct pipeline_routing *p = pipeline;
286 /* Check input arguments */
291 while (!TAILQ_EMPTY(&p->routes)) {
292 struct app_pipeline_routing_route *route;
294 route = TAILQ_FIRST(&p->routes);
295 TAILQ_REMOVE(&p->routes, route, node);
299 while (!TAILQ_EMPTY(&p->arp_entries)) {
300 struct app_pipeline_routing_arp_entry *arp_entry;
302 arp_entry = TAILQ_FIRST(&p->arp_entries);
303 TAILQ_REMOVE(&p->arp_entries, arp_entry, node);
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)
315 struct app_pipeline_routing_route *it, *found;
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)) {
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)
334 struct app_pipeline_routing_arp_entry *it, *found;
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)) {
350 print_route(const struct app_pipeline_routing_route *route)
352 if (route->key.type == PIPELINE_ROUTING_ROUTE_IPV4) {
353 const struct pipeline_routing_route_key_ipv4 *key =
354 &route->key.key.ipv4;
356 printf("IP Prefix = %" PRIu32 ".%" PRIu32
357 ".%" PRIu32 ".%" PRIu32 "/%" PRIu32
358 " => (Port = %" PRIu32,
360 (key->ip >> 24) & 0xFF,
361 (key->ip >> 16) & 0xFF,
362 (key->ip >> 8) & 0xFF,
366 route->data.port_id);
368 if (route->data.flags & PIPELINE_ROUTING_ROUTE_LOCAL)
370 else if (route->data.flags & PIPELINE_ROUTING_ROUTE_ARP)
372 ", Next Hop IP = %" PRIu32 ".%" PRIu32
373 ".%" PRIu32 ".%" PRIu32,
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);
381 ", Next Hop HWaddress = %02" PRIx32
382 ":%02" PRIx32 ":%02" PRIx32
383 ":%02" PRIx32 ":%02" PRIx32
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]);
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);
398 if (route->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) {
401 printf(", MPLS labels");
402 for (i = 0; i < route->data.l2.mpls.n_labels; i++)
404 route->data.l2.mpls.labels[i]);
412 print_arp_entry(const struct app_pipeline_routing_arp_entry *entry)
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",
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,
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]);
434 app_pipeline_routing_route_ls(struct app_params *app, uint32_t pipeline_id)
436 struct pipeline_routing *p;
437 struct app_pipeline_routing_route *it;
439 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
443 TAILQ_FOREACH(it, &p->routes, node)
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);
451 printf("Default: DROP\n");
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)
462 struct pipeline_routing *p;
464 struct pipeline_routing_route_add_msg_req *req;
465 struct pipeline_routing_route_add_msg_rsp *rsp;
467 struct app_pipeline_routing_route *entry;
471 /* Check input arguments */
477 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
482 case PIPELINE_ROUTING_ROUTE_IPV4:
484 uint32_t depth = key->key.ipv4.depth;
488 if ((depth == 0) || (depth > 32))
491 netmask = (~0U) << (32 - depth);
492 key->key.ipv4.ip &= netmask;
495 if (data->port_id >= p->n_ports_out)
498 /* Valid range of VLAN tags 12 bits */
499 if (data->flags & PIPELINE_ROUTING_ROUTE_QINQ)
500 if ((data->l2.qinq.svlan & 0xF000) ||
501 (data->l2.qinq.cvlan & 0xF000))
504 /* Max number of MPLS labels supported */
505 if (data->flags & PIPELINE_ROUTING_ROUTE_MPLS) {
508 if (data->l2.mpls.n_labels >
509 PIPELINE_ROUTING_MPLS_LABELS_MAX)
512 /* Max MPLS label value 20 bits */
513 for (i = 0; i < data->l2.mpls.n_labels; i++)
514 if (data->l2.mpls.labels[i] & 0xFFF00000)
524 /* Find existing rule or allocate new rule */
525 entry = app_pipeline_routing_find_route(p, key);
526 new_entry = (entry == NULL);
528 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
534 /* Allocate and write request */
535 req = app_msg_alloc(app);
542 req->type = PIPELINE_MSG_REQ_CUSTOM;
543 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD;
544 memcpy(&req->key, key, sizeof(*key));
545 memcpy(&req->data, data, sizeof(*data));
547 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
554 /* Read response and write entry */
556 (rsp->entry_ptr == NULL) ||
557 ((new_entry == 0) && (rsp->key_found == 0)) ||
558 ((new_entry == 1) && (rsp->key_found == 1))) {
559 app_msg_free(app, rsp);
565 memcpy(&entry->key, key, sizeof(*key));
566 memcpy(&entry->data, data, sizeof(*data));
567 entry->entry_ptr = rsp->entry_ptr;
571 TAILQ_INSERT_TAIL(&p->routes, entry, node);
575 /* Message buffer free */
576 app_msg_free(app, rsp);
581 app_pipeline_routing_delete_route(struct app_params *app,
582 uint32_t pipeline_id,
583 struct pipeline_routing_route_key *key)
585 struct pipeline_routing *p;
587 struct pipeline_routing_route_delete_msg_req *req;
588 struct pipeline_routing_route_delete_msg_rsp *rsp;
590 struct app_pipeline_routing_route *entry;
592 /* Check input arguments */
597 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
602 case PIPELINE_ROUTING_ROUTE_IPV4:
604 uint32_t depth = key->key.ipv4.depth;
608 if ((depth == 0) || (depth > 32))
611 netmask = (~0U) << (32 - depth);
612 key->key.ipv4.ip &= netmask;
621 entry = app_pipeline_routing_find_route(p, key);
625 /* Allocate and write request */
626 req = app_msg_alloc(app);
630 req->type = PIPELINE_MSG_REQ_CUSTOM;
631 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL;
632 memcpy(&req->key, key, sizeof(*key));
634 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
639 if (rsp->status || !rsp->key_found) {
640 app_msg_free(app, rsp);
645 TAILQ_REMOVE(&p->routes, entry, node);
650 app_msg_free(app, rsp);
656 app_pipeline_routing_add_default_route(struct app_params *app,
657 uint32_t pipeline_id,
660 struct pipeline_routing *p;
662 struct pipeline_routing_route_add_default_msg_req *req;
663 struct pipeline_routing_route_add_default_msg_rsp *rsp;
665 /* Check input arguments */
669 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
673 if (port_id >= p->n_ports_out)
676 /* Allocate and write request */
677 req = app_msg_alloc(app);
681 req->type = PIPELINE_MSG_REQ_CUSTOM;
682 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT;
683 req->port_id = port_id;
685 /* Send request and wait for response */
686 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
690 /* Read response and write route */
691 if (rsp->status || (rsp->entry_ptr == NULL)) {
692 app_msg_free(app, rsp);
696 p->default_route_port_id = port_id;
697 p->default_route_entry_ptr = rsp->entry_ptr;
700 p->default_route_present = 1;
703 app_msg_free(app, rsp);
709 app_pipeline_routing_delete_default_route(struct app_params *app,
710 uint32_t pipeline_id)
712 struct pipeline_routing *p;
714 struct pipeline_routing_arp_delete_default_msg_req *req;
715 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
717 /* Check input arguments */
721 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
725 /* Allocate and write request */
726 req = app_msg_alloc(app);
730 req->type = PIPELINE_MSG_REQ_CUSTOM;
731 req->subtype = PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT;
733 /* Send request and wait for response */
734 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
738 /* Read response and write route */
740 app_msg_free(app, rsp);
745 p->default_route_present = 0;
748 app_msg_free(app, rsp);
754 app_pipeline_routing_arp_ls(struct app_params *app, uint32_t pipeline_id)
756 struct pipeline_routing *p;
757 struct app_pipeline_routing_arp_entry *it;
759 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
763 TAILQ_FOREACH(it, &p->arp_entries, node)
766 if (p->default_arp_entry_present)
767 printf("Default entry: port %" PRIu32 " (entry ptr = %p)\n",
768 p->default_arp_entry_port_id,
769 p->default_arp_entry_ptr);
771 printf("Default: DROP\n");
777 app_pipeline_routing_add_arp_entry(struct app_params *app, uint32_t pipeline_id,
778 struct pipeline_routing_arp_key *key,
779 struct ether_addr *macaddr)
781 struct pipeline_routing *p;
783 struct pipeline_routing_arp_add_msg_req *req;
784 struct pipeline_routing_arp_add_msg_rsp *rsp;
786 struct app_pipeline_routing_arp_entry *entry;
790 /* Check input arguments */
796 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
801 case PIPELINE_ROUTING_ARP_IPV4:
803 uint32_t port_id = key->key.ipv4.port_id;
806 if (port_id >= p->n_ports_out)
815 /* Find existing entry or allocate new */
816 entry = app_pipeline_routing_find_arp_entry(p, key);
817 new_entry = (entry == NULL);
819 entry = rte_malloc(NULL, sizeof(*entry), RTE_CACHE_LINE_SIZE);
825 /* Message buffer allocation */
826 req = app_msg_alloc(app);
833 req->type = PIPELINE_MSG_REQ_CUSTOM;
834 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD;
835 memcpy(&req->key, key, sizeof(*key));
836 ether_addr_copy(macaddr, &req->macaddr);
838 /* Send request and wait for response */
839 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
846 /* Read response and write entry */
848 (rsp->entry_ptr == NULL) ||
849 ((new_entry == 0) && (rsp->key_found == 0)) ||
850 ((new_entry == 1) && (rsp->key_found == 1))) {
851 app_msg_free(app, rsp);
857 memcpy(&entry->key, key, sizeof(*key));
858 ether_addr_copy(macaddr, &entry->macaddr);
859 entry->entry_ptr = rsp->entry_ptr;
863 TAILQ_INSERT_TAIL(&p->arp_entries, entry, node);
867 /* Message buffer free */
868 app_msg_free(app, rsp);
873 app_pipeline_routing_delete_arp_entry(struct app_params *app,
874 uint32_t pipeline_id,
875 struct pipeline_routing_arp_key *key)
877 struct pipeline_routing *p;
879 struct pipeline_routing_arp_delete_msg_req *req;
880 struct pipeline_routing_arp_delete_msg_rsp *rsp;
882 struct app_pipeline_routing_arp_entry *entry;
884 /* Check input arguments */
889 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
894 case PIPELINE_ROUTING_ARP_IPV4:
896 uint32_t port_id = key->key.ipv4.port_id;
899 if (port_id >= p->n_ports_out)
909 entry = app_pipeline_routing_find_arp_entry(p, key);
913 /* Allocate and write request */
914 req = app_msg_alloc(app);
918 req->type = PIPELINE_MSG_REQ_CUSTOM;
919 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL;
920 memcpy(&req->key, key, sizeof(*key));
922 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
927 if (rsp->status || !rsp->key_found) {
928 app_msg_free(app, rsp);
933 TAILQ_REMOVE(&p->arp_entries, entry, node);
938 app_msg_free(app, rsp);
944 app_pipeline_routing_add_default_arp_entry(struct app_params *app,
945 uint32_t pipeline_id,
948 struct pipeline_routing *p;
950 struct pipeline_routing_arp_add_default_msg_req *req;
951 struct pipeline_routing_arp_add_default_msg_rsp *rsp;
953 /* Check input arguments */
957 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
961 if (port_id >= p->n_ports_out)
964 /* Allocate and write request */
965 req = app_msg_alloc(app);
969 req->type = PIPELINE_MSG_REQ_CUSTOM;
970 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT;
971 req->port_id = port_id;
973 /* Send request and wait for response */
974 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
978 /* Read response and write entry */
979 if (rsp->status || rsp->entry_ptr == NULL) {
980 app_msg_free(app, rsp);
984 p->default_arp_entry_port_id = port_id;
985 p->default_arp_entry_ptr = rsp->entry_ptr;
988 p->default_arp_entry_present = 1;
991 app_msg_free(app, rsp);
997 app_pipeline_routing_delete_default_arp_entry(struct app_params *app,
998 uint32_t pipeline_id)
1000 struct pipeline_routing *p;
1002 struct pipeline_routing_arp_delete_default_msg_req *req;
1003 struct pipeline_routing_arp_delete_default_msg_rsp *rsp;
1005 /* Check input arguments */
1009 p = app_pipeline_data_fe(app, pipeline_id, &pipeline_routing);
1013 /* Allocate and write request */
1014 req = app_msg_alloc(app);
1018 req->type = PIPELINE_MSG_REQ_CUSTOM;
1019 req->subtype = PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT;
1021 /* Send request and wait for response */
1022 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
1026 /* Read response and write entry */
1028 app_msg_free(app, rsp);
1033 p->default_arp_entry_present = 0;
1036 app_msg_free(app, rsp);
1042 app_pipeline_routing_set_macaddr(struct app_params *app,
1043 uint32_t pipeline_id)
1045 struct app_pipeline_params *p;
1046 struct pipeline_routing_set_macaddr_msg_req *req;
1047 struct pipeline_routing_set_macaddr_msg_rsp *rsp;
1050 /* Check input arguments */
1054 APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, p);
1058 /* Allocate and write request */
1059 req = app_msg_alloc(app);
1063 req->type = PIPELINE_MSG_REQ_CUSTOM;
1064 req->subtype = PIPELINE_ROUTING_MSG_REQ_SET_MACADDR;
1066 memset(req->macaddr, 0, sizeof(req->macaddr));
1067 for (port_id = 0; port_id < p->n_pktq_out; port_id++) {
1068 struct app_link_params *link;
1070 link = app_pipeline_track_pktq_out_to_link(app,
1074 req->macaddr[port_id] = link->mac_addr;
1077 /* Send request and wait for response */
1078 rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT);
1082 /* Read response and write entry */
1084 app_msg_free(app, rsp);
1089 app_msg_free(app, rsp);
1097 * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
1098 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
1099 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
1100 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
1101 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
1102 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
1103 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
1105 * route add default:
1106 * p <pipelineid> route add default <portid>
1109 * p <pipelineid> route del <ipaddr> <depth>
1111 * route del default:
1112 * p <pipelineid> route del default
1115 * p <pipelineid> route ls
1118 struct cmd_route_result {
1119 cmdline_fixed_string_t p_string;
1121 cmdline_fixed_string_t route_string;
1122 cmdline_multi_string_t multi_string;
1127 void *parsed_result,
1128 __rte_unused struct cmdline *cl,
1131 struct cmd_route_result *params = parsed_result;
1132 struct app_params *app = data;
1135 uint32_t n_tokens = RTE_DIM(tokens);
1138 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1140 printf(CMD_MSG_TOO_MANY_ARGS, "route");
1145 if ((n_tokens >= 2) &&
1146 (strcmp(tokens[0], "add") == 0) &&
1147 strcmp(tokens[1], "default")) {
1148 struct pipeline_routing_route_key key;
1149 struct pipeline_routing_route_data route_data;
1150 struct in_addr ipv4, nh_ipv4;
1151 struct ether_addr mac_addr;
1152 uint32_t depth, port_id, svlan, cvlan, i;
1153 uint32_t mpls_labels[PIPELINE_ROUTING_MPLS_LABELS_MAX];
1154 uint32_t n_labels = RTE_DIM(mpls_labels);
1156 memset(&key, 0, sizeof(key));
1157 memset(&route_data, 0, sizeof(route_data));
1160 printf(CMD_MSG_NOT_ENOUGH_ARGS, "route add");
1164 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1165 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1169 if (parser_read_uint32(&depth, tokens[2])) {
1170 printf(CMD_MSG_INVALID_ARG, "depth");
1174 if (strcmp(tokens[3], "port")) {
1175 printf(CMD_MSG_ARG_NOT_FOUND, "port");
1179 if (parser_read_uint32(&port_id, tokens[4])) {
1180 printf(CMD_MSG_INVALID_ARG, "portid");
1184 if (strcmp(tokens[5], "ether")) {
1185 printf(CMD_MSG_ARG_NOT_FOUND, "ether");
1189 if (parse_mac_addr(tokens[6], &mac_addr)) {
1190 if (parse_ipv4_addr(tokens[6], &nh_ipv4)) {
1191 printf(CMD_MSG_INVALID_ARG, "nhmacaddr or nhipaddr");
1195 route_data.flags |= PIPELINE_ROUTING_ROUTE_ARP;
1199 if (strcmp(tokens[7], "mpls") == 0) {
1200 if (n_tokens != 9) {
1201 printf(CMD_MSG_MISMATCH_ARGS, "route add mpls");
1205 if (parse_mpls_labels(tokens[8], mpls_labels, &n_labels)) {
1206 printf(CMD_MSG_INVALID_ARG, "mpls labels");
1210 route_data.flags |= PIPELINE_ROUTING_ROUTE_MPLS;
1211 } else if (strcmp(tokens[7], "qinq") == 0) {
1212 if (n_tokens != 10) {
1213 printf(CMD_MSG_MISMATCH_ARGS, "route add qinq");
1217 if (parser_read_uint32(&svlan, tokens[8])) {
1218 printf(CMD_MSG_INVALID_ARG, "svlan");
1221 if (parser_read_uint32(&cvlan, tokens[9])) {
1222 printf(CMD_MSG_INVALID_ARG, "cvlan");
1226 route_data.flags |= PIPELINE_ROUTING_ROUTE_QINQ;
1228 printf(CMD_MSG_ARG_NOT_FOUND, "mpls or qinq");
1233 switch (route_data.flags) {
1235 route_data.port_id = port_id;
1236 route_data.ethernet.macaddr = mac_addr;
1239 case 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);
1244 case PIPELINE_ROUTING_ROUTE_MPLS:
1245 route_data.port_id = port_id;
1246 route_data.ethernet.macaddr = mac_addr;
1247 for (i = 0; i < n_labels; i++)
1248 route_data.l2.mpls.labels[i] = mpls_labels[i];
1249 route_data.l2.mpls.n_labels = n_labels;
1252 case PIPELINE_ROUTING_ROUTE_MPLS | PIPELINE_ROUTING_ROUTE_ARP:
1253 route_data.port_id = port_id;
1254 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1255 for (i = 0; i < n_labels; i++)
1256 route_data.l2.mpls.labels[i] = mpls_labels[i];
1257 route_data.l2.mpls.n_labels = n_labels;
1260 case PIPELINE_ROUTING_ROUTE_QINQ:
1261 route_data.port_id = port_id;
1262 route_data.ethernet.macaddr = mac_addr;
1263 route_data.l2.qinq.svlan = svlan;
1264 route_data.l2.qinq.cvlan = cvlan;
1267 case PIPELINE_ROUTING_ROUTE_QINQ | PIPELINE_ROUTING_ROUTE_ARP:
1269 route_data.port_id = port_id;
1270 route_data.ethernet.ip = rte_be_to_cpu_32(nh_ipv4.s_addr);
1271 route_data.l2.qinq.svlan = svlan;
1272 route_data.l2.qinq.cvlan = cvlan;
1276 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1277 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1278 key.key.ipv4.depth = depth;
1280 status = app_pipeline_routing_add_route(app,
1285 printf(CMD_MSG_FAIL, "route add");
1290 /* route add default */
1291 if ((n_tokens >= 2) &&
1292 (strcmp(tokens[0], "add") == 0) &&
1293 (strcmp(tokens[1], "default") == 0)) {
1296 if (n_tokens != 3) {
1297 printf(CMD_MSG_MISMATCH_ARGS, "route add default");
1301 if (parser_read_uint32(&port_id, tokens[2])) {
1302 printf(CMD_MSG_INVALID_ARG, "portid");
1306 status = app_pipeline_routing_add_default_route(app,
1310 printf(CMD_MSG_FAIL, "route add default");
1313 } /* route add default */
1316 if ((n_tokens >= 2) &&
1317 (strcmp(tokens[0], "del") == 0) &&
1318 strcmp(tokens[1], "default")) {
1319 struct pipeline_routing_route_key key;
1320 struct in_addr ipv4;
1323 memset(&key, 0, sizeof(key));
1325 if (n_tokens != 3) {
1326 printf(CMD_MSG_MISMATCH_ARGS, "route del");
1330 if (parse_ipv4_addr(tokens[1], &ipv4)) {
1331 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1335 if (parser_read_uint32(&depth, tokens[2])) {
1336 printf(CMD_MSG_INVALID_ARG, "depth");
1340 key.type = PIPELINE_ROUTING_ROUTE_IPV4;
1341 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1342 key.key.ipv4.depth = depth;
1344 status = app_pipeline_routing_delete_route(app, params->p, &key);
1346 printf(CMD_MSG_FAIL, "route del");
1351 /* route del default */
1352 if ((n_tokens >= 2) &&
1353 (strcmp(tokens[0], "del") == 0) &&
1354 (strcmp(tokens[1], "default") == 0)) {
1355 if (n_tokens != 2) {
1356 printf(CMD_MSG_MISMATCH_ARGS, "route del default");
1360 status = app_pipeline_routing_delete_default_route(app,
1363 printf(CMD_MSG_FAIL, "route del default");
1366 } /* route del default */
1369 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1370 if (n_tokens != 1) {
1371 printf(CMD_MSG_MISMATCH_ARGS, "route ls");
1375 status = app_pipeline_routing_route_ls(app, params->p);
1377 printf(CMD_MSG_FAIL, "route ls");
1382 printf(CMD_MSG_MISMATCH_ARGS, "route");
1385 static cmdline_parse_token_string_t cmd_route_p_string =
1386 TOKEN_STRING_INITIALIZER(struct cmd_route_result, p_string, "p");
1388 static cmdline_parse_token_num_t cmd_route_p =
1389 TOKEN_NUM_INITIALIZER(struct cmd_route_result, p, UINT32);
1391 static cmdline_parse_token_string_t cmd_route_route_string =
1392 TOKEN_STRING_INITIALIZER(struct cmd_route_result, route_string, "route");
1394 static cmdline_parse_token_string_t cmd_route_multi_string =
1395 TOKEN_STRING_INITIALIZER(struct cmd_route_result, multi_string,
1396 TOKEN_STRING_MULTI);
1398 static cmdline_parse_inst_t cmd_route = {
1399 .f = cmd_route_parsed,
1401 .help_str = "route add / add default / del / del default / ls",
1403 (void *)&cmd_route_p_string,
1404 (void *)&cmd_route_p,
1405 (void *)&cmd_route_route_string,
1406 (void *)&cmd_route_multi_string,
1415 * p <pipelineid> arp add <portid> <ipaddr> <macaddr>
1418 * p <pipelineid> arp add default <portid>
1421 * p <pipelineid> arp del <portid> <ipaddr>
1424 * p <pipelineid> arp del default
1427 * p <pipelineid> arp ls
1430 struct cmd_arp_result {
1431 cmdline_fixed_string_t p_string;
1433 cmdline_fixed_string_t arp_string;
1434 cmdline_multi_string_t multi_string;
1439 void *parsed_result,
1440 __rte_unused struct cmdline *cl,
1443 struct cmd_arp_result *params = parsed_result;
1444 struct app_params *app = data;
1447 uint32_t n_tokens = RTE_DIM(tokens);
1450 status = parse_tokenize_string(params->multi_string, tokens, &n_tokens);
1452 printf(CMD_MSG_TOO_MANY_ARGS, "arp");
1457 if ((n_tokens >= 2) &&
1458 (strcmp(tokens[0], "add") == 0) &&
1459 strcmp(tokens[1], "default")) {
1460 struct pipeline_routing_arp_key key;
1461 struct in_addr ipv4;
1462 struct ether_addr mac_addr;
1465 memset(&key, 0, sizeof(key));
1467 if (n_tokens != 4) {
1468 printf(CMD_MSG_MISMATCH_ARGS, "arp add");
1472 if (parser_read_uint32(&port_id, tokens[1])) {
1473 printf(CMD_MSG_INVALID_ARG, "portid");
1477 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1478 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1482 if (parse_mac_addr(tokens[3], &mac_addr)) {
1483 printf(CMD_MSG_INVALID_ARG, "macaddr");
1487 key.type = PIPELINE_ROUTING_ARP_IPV4;
1488 key.key.ipv4.port_id = port_id;
1489 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1491 status = app_pipeline_routing_add_arp_entry(app,
1496 printf(CMD_MSG_FAIL, "arp add");
1501 /* arp add default */
1502 if ((n_tokens >= 2) &&
1503 (strcmp(tokens[0], "add") == 0) &&
1504 (strcmp(tokens[1], "default") == 0)) {
1507 if (n_tokens != 3) {
1508 printf(CMD_MSG_MISMATCH_ARGS, "arp add default");
1512 if (parser_read_uint32(&port_id, tokens[2])) {
1513 printf(CMD_MSG_INVALID_ARG, "portid");
1517 status = app_pipeline_routing_add_default_arp_entry(app,
1521 printf(CMD_MSG_FAIL, "arp add default");
1524 } /* arp add default */
1527 if ((n_tokens >= 2) &&
1528 (strcmp(tokens[0], "del") == 0) &&
1529 strcmp(tokens[1], "default")) {
1530 struct pipeline_routing_arp_key key;
1531 struct in_addr ipv4;
1534 memset(&key, 0, sizeof(key));
1536 if (n_tokens != 3) {
1537 printf(CMD_MSG_MISMATCH_ARGS, "arp del");
1541 if (parser_read_uint32(&port_id, tokens[1])) {
1542 printf(CMD_MSG_INVALID_ARG, "portid");
1546 if (parse_ipv4_addr(tokens[2], &ipv4)) {
1547 printf(CMD_MSG_INVALID_ARG, "ipaddr");
1551 key.type = PIPELINE_ROUTING_ARP_IPV4;
1552 key.key.ipv4.ip = rte_be_to_cpu_32(ipv4.s_addr);
1553 key.key.ipv4.port_id = port_id;
1555 status = app_pipeline_routing_delete_arp_entry(app,
1559 printf(CMD_MSG_FAIL, "arp del");
1564 /* arp del default */
1565 if ((n_tokens >= 2) &&
1566 (strcmp(tokens[0], "del") == 0) &&
1567 (strcmp(tokens[1], "default") == 0)) {
1568 if (n_tokens != 2) {
1569 printf(CMD_MSG_MISMATCH_ARGS, "arp del default");
1573 status = app_pipeline_routing_delete_default_arp_entry(app,
1576 printf(CMD_MSG_FAIL, "arp del default");
1579 } /* arp del default */
1582 if ((n_tokens >= 1) && (strcmp(tokens[0], "ls") == 0)) {
1583 if (n_tokens != 1) {
1584 printf(CMD_MSG_MISMATCH_ARGS, "arp ls");
1588 status = app_pipeline_routing_arp_ls(app, params->p);
1590 printf(CMD_MSG_FAIL, "arp ls");
1595 printf(CMD_MSG_FAIL, "arp");
1598 static cmdline_parse_token_string_t cmd_arp_p_string =
1599 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, p_string, "p");
1601 static cmdline_parse_token_num_t cmd_arp_p =
1602 TOKEN_NUM_INITIALIZER(struct cmd_arp_result, p, UINT32);
1604 static cmdline_parse_token_string_t cmd_arp_arp_string =
1605 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, arp_string, "arp");
1607 static cmdline_parse_token_string_t cmd_arp_multi_string =
1608 TOKEN_STRING_INITIALIZER(struct cmd_arp_result, multi_string,
1609 TOKEN_STRING_MULTI);
1611 static cmdline_parse_inst_t cmd_arp = {
1612 .f = cmd_arp_parsed,
1614 .help_str = "arp add / add default / del / del default / ls",
1616 (void *)&cmd_arp_p_string,
1618 (void *)&cmd_arp_arp_string,
1619 (void *)&cmd_arp_multi_string,
1624 static cmdline_parse_ctx_t pipeline_cmds[] = {
1625 (cmdline_parse_inst_t *)&cmd_route,
1626 (cmdline_parse_inst_t *)&cmd_arp,
1630 static struct pipeline_fe_ops pipeline_routing_fe_ops = {
1631 .f_init = app_pipeline_routing_init,
1632 .f_post_init = app_pipeline_routing_post_init,
1633 .f_free = app_pipeline_routing_free,
1634 .f_track = app_pipeline_track_default,
1635 .cmds = pipeline_cmds,
1638 struct pipeline_type pipeline_routing = {
1640 .be_ops = &pipeline_routing_be_ops,
1641 .fe_ops = &pipeline_routing_fe_ops,