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
)
504 /* Find existing rule or allocate new rule */
505 entry
= app_pipeline_routing_find_route(p
, key
);
506 new_entry
= (entry
== NULL
);
508 entry
= rte_malloc(NULL
, sizeof(*entry
), RTE_CACHE_LINE_SIZE
);
514 /* Allocate and write request */
515 req
= app_msg_alloc(app
);
522 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
523 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD
;
524 memcpy(&req
->key
, key
, sizeof(*key
));
525 memcpy(&req
->data
, data
, sizeof(*data
));
527 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
534 /* Read response and write entry */
536 (rsp
->entry_ptr
== NULL
) ||
537 ((new_entry
== 0) && (rsp
->key_found
== 0)) ||
538 ((new_entry
== 1) && (rsp
->key_found
== 1))) {
539 app_msg_free(app
, rsp
);
545 memcpy(&entry
->key
, key
, sizeof(*key
));
546 memcpy(&entry
->data
, data
, sizeof(*data
));
547 entry
->entry_ptr
= rsp
->entry_ptr
;
551 TAILQ_INSERT_TAIL(&p
->routes
, entry
, node
);
555 /* Message buffer free */
556 app_msg_free(app
, rsp
);
561 app_pipeline_routing_delete_route(struct app_params
*app
,
562 uint32_t pipeline_id
,
563 struct pipeline_routing_route_key
*key
)
565 struct pipeline_routing
*p
;
567 struct pipeline_routing_route_delete_msg_req
*req
;
568 struct pipeline_routing_route_delete_msg_rsp
*rsp
;
570 struct app_pipeline_routing_route
*entry
;
572 /* Check input arguments */
577 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
582 case PIPELINE_ROUTING_ROUTE_IPV4
:
584 uint32_t depth
= key
->key
.ipv4
.depth
;
588 if ((depth
== 0) || (depth
> 32))
591 netmask
= (~0U) << (32 - depth
);
592 key
->key
.ipv4
.ip
&= netmask
;
601 entry
= app_pipeline_routing_find_route(p
, key
);
605 /* Allocate and write request */
606 req
= app_msg_alloc(app
);
610 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
611 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL
;
612 memcpy(&req
->key
, key
, sizeof(*key
));
614 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
619 if (rsp
->status
|| !rsp
->key_found
) {
620 app_msg_free(app
, rsp
);
625 TAILQ_REMOVE(&p
->routes
, entry
, node
);
630 app_msg_free(app
, rsp
);
636 app_pipeline_routing_add_default_route(struct app_params
*app
,
637 uint32_t pipeline_id
,
640 struct pipeline_routing
*p
;
642 struct pipeline_routing_route_add_default_msg_req
*req
;
643 struct pipeline_routing_route_add_default_msg_rsp
*rsp
;
645 /* Check input arguments */
649 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
653 if (port_id
>= p
->n_ports_out
)
656 /* Allocate and write request */
657 req
= app_msg_alloc(app
);
661 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
662 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT
;
663 req
->port_id
= port_id
;
665 /* Send request and wait for response */
666 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
670 /* Read response and write route */
671 if (rsp
->status
|| (rsp
->entry_ptr
== NULL
)) {
672 app_msg_free(app
, rsp
);
676 p
->default_route_port_id
= port_id
;
677 p
->default_route_entry_ptr
= rsp
->entry_ptr
;
680 p
->default_route_present
= 1;
683 app_msg_free(app
, rsp
);
689 app_pipeline_routing_delete_default_route(struct app_params
*app
,
690 uint32_t pipeline_id
)
692 struct pipeline_routing
*p
;
694 struct pipeline_routing_arp_delete_default_msg_req
*req
;
695 struct pipeline_routing_arp_delete_default_msg_rsp
*rsp
;
697 /* Check input arguments */
701 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
705 /* Allocate and write request */
706 req
= app_msg_alloc(app
);
710 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
711 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT
;
713 /* Send request and wait for response */
714 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
718 /* Read response and write route */
720 app_msg_free(app
, rsp
);
725 p
->default_route_present
= 0;
728 app_msg_free(app
, rsp
);
734 app_pipeline_routing_arp_ls(struct app_params
*app
, uint32_t pipeline_id
)
736 struct pipeline_routing
*p
;
737 struct app_pipeline_routing_arp_entry
*it
;
739 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
743 TAILQ_FOREACH(it
, &p
->arp_entries
, node
)
746 if (p
->default_arp_entry_present
)
747 printf("Default entry: port %" PRIu32
" (entry ptr = %p)\n",
748 p
->default_arp_entry_port_id
,
749 p
->default_arp_entry_ptr
);
751 printf("Default: DROP\n");
757 app_pipeline_routing_add_arp_entry(struct app_params
*app
, uint32_t pipeline_id
,
758 struct pipeline_routing_arp_key
*key
,
759 struct ether_addr
*macaddr
)
761 struct pipeline_routing
*p
;
763 struct pipeline_routing_arp_add_msg_req
*req
;
764 struct pipeline_routing_arp_add_msg_rsp
*rsp
;
766 struct app_pipeline_routing_arp_entry
*entry
;
770 /* Check input arguments */
776 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
781 case PIPELINE_ROUTING_ARP_IPV4
:
783 uint32_t port_id
= key
->key
.ipv4
.port_id
;
786 if (port_id
>= p
->n_ports_out
)
795 /* Find existing entry or allocate new */
796 entry
= app_pipeline_routing_find_arp_entry(p
, key
);
797 new_entry
= (entry
== NULL
);
799 entry
= rte_malloc(NULL
, sizeof(*entry
), RTE_CACHE_LINE_SIZE
);
805 /* Message buffer allocation */
806 req
= app_msg_alloc(app
);
813 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
814 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ARP_ADD
;
815 memcpy(&req
->key
, key
, sizeof(*key
));
816 ether_addr_copy(macaddr
, &req
->macaddr
);
818 /* Send request and wait for response */
819 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
826 /* Read response and write entry */
828 (rsp
->entry_ptr
== NULL
) ||
829 ((new_entry
== 0) && (rsp
->key_found
== 0)) ||
830 ((new_entry
== 1) && (rsp
->key_found
== 1))) {
831 app_msg_free(app
, rsp
);
837 memcpy(&entry
->key
, key
, sizeof(*key
));
838 ether_addr_copy(macaddr
, &entry
->macaddr
);
839 entry
->entry_ptr
= rsp
->entry_ptr
;
843 TAILQ_INSERT_TAIL(&p
->arp_entries
, entry
, node
);
847 /* Message buffer free */
848 app_msg_free(app
, rsp
);
853 app_pipeline_routing_delete_arp_entry(struct app_params
*app
,
854 uint32_t pipeline_id
,
855 struct pipeline_routing_arp_key
*key
)
857 struct pipeline_routing
*p
;
859 struct pipeline_routing_arp_delete_msg_req
*req
;
860 struct pipeline_routing_arp_delete_msg_rsp
*rsp
;
862 struct app_pipeline_routing_arp_entry
*entry
;
864 /* Check input arguments */
869 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
874 case PIPELINE_ROUTING_ARP_IPV4
:
876 uint32_t port_id
= key
->key
.ipv4
.port_id
;
879 if (port_id
>= p
->n_ports_out
)
889 entry
= app_pipeline_routing_find_arp_entry(p
, key
);
893 /* Allocate and write request */
894 req
= app_msg_alloc(app
);
898 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
899 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ARP_DEL
;
900 memcpy(&req
->key
, key
, sizeof(*key
));
902 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
907 if (rsp
->status
|| !rsp
->key_found
) {
908 app_msg_free(app
, rsp
);
913 TAILQ_REMOVE(&p
->arp_entries
, entry
, node
);
918 app_msg_free(app
, rsp
);
924 app_pipeline_routing_add_default_arp_entry(struct app_params
*app
,
925 uint32_t pipeline_id
,
928 struct pipeline_routing
*p
;
930 struct pipeline_routing_arp_add_default_msg_req
*req
;
931 struct pipeline_routing_arp_add_default_msg_rsp
*rsp
;
933 /* Check input arguments */
937 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
941 if (port_id
>= p
->n_ports_out
)
944 /* Allocate and write request */
945 req
= app_msg_alloc(app
);
949 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
950 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT
;
951 req
->port_id
= port_id
;
953 /* Send request and wait for response */
954 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
958 /* Read response and write entry */
959 if (rsp
->status
|| rsp
->entry_ptr
== NULL
) {
960 app_msg_free(app
, rsp
);
964 p
->default_arp_entry_port_id
= port_id
;
965 p
->default_arp_entry_ptr
= rsp
->entry_ptr
;
968 p
->default_arp_entry_present
= 1;
971 app_msg_free(app
, rsp
);
977 app_pipeline_routing_delete_default_arp_entry(struct app_params
*app
,
978 uint32_t pipeline_id
)
980 struct pipeline_routing
*p
;
982 struct pipeline_routing_arp_delete_default_msg_req
*req
;
983 struct pipeline_routing_arp_delete_default_msg_rsp
*rsp
;
985 /* Check input arguments */
989 p
= app_pipeline_data_fe(app
, pipeline_id
, &pipeline_routing
);
993 /* Allocate and write request */
994 req
= app_msg_alloc(app
);
998 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
999 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT
;
1001 /* Send request and wait for response */
1002 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
1006 /* Read response and write entry */
1008 app_msg_free(app
, rsp
);
1013 p
->default_arp_entry_present
= 0;
1016 app_msg_free(app
, rsp
);
1022 app_pipeline_routing_set_macaddr(struct app_params
*app
,
1023 uint32_t pipeline_id
)
1025 struct app_pipeline_params
*p
;
1026 struct pipeline_routing_set_macaddr_msg_req
*req
;
1027 struct pipeline_routing_set_macaddr_msg_rsp
*rsp
;
1030 /* Check input arguments */
1034 APP_PARAM_FIND_BY_ID(app
->pipeline_params
, "PIPELINE", pipeline_id
, p
);
1038 /* Allocate and write request */
1039 req
= app_msg_alloc(app
);
1043 req
->type
= PIPELINE_MSG_REQ_CUSTOM
;
1044 req
->subtype
= PIPELINE_ROUTING_MSG_REQ_SET_MACADDR
;
1046 memset(req
->macaddr
, 0, sizeof(req
->macaddr
));
1047 for (port_id
= 0; port_id
< p
->n_pktq_out
; port_id
++) {
1048 struct app_link_params
*link
;
1050 link
= app_pipeline_track_pktq_out_to_link(app
,
1054 req
->macaddr
[port_id
] = link
->mac_addr
;
1057 /* Send request and wait for response */
1058 rsp
= app_msg_send_recv(app
, pipeline_id
, req
, MSG_TIMEOUT_DEFAULT
);
1062 /* Read response and write entry */
1064 app_msg_free(app
, rsp
);
1069 app_msg_free(app
, rsp
);
1077 * route add (ARP = ON/OFF, MPLS = ON/OFF, QINQ = ON/OFF):
1078 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr>
1079 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr>
1080 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> qinq <svlan> <cvlan>
1081 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> qinq <svlan> <cvlan>
1082 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhmacaddr> mpls <mpls labels>
1083 * p <pipelineid> route add <ipaddr> <depth> port <portid> ether <nhipaddr> mpls <mpls labels>
1085 * route add default:
1086 * p <pipelineid> route add default <portid>
1089 * p <pipelineid> route del <ipaddr> <depth>
1091 * route del default:
1092 * p <pipelineid> route del default
1095 * p <pipelineid> route ls
1098 struct cmd_route_result
{
1099 cmdline_fixed_string_t p_string
;
1101 cmdline_fixed_string_t route_string
;
1102 cmdline_multi_string_t multi_string
;
1107 void *parsed_result
,
1108 __rte_unused
struct cmdline
*cl
,
1111 struct cmd_route_result
*params
= parsed_result
;
1112 struct app_params
*app
= data
;
1115 uint32_t n_tokens
= RTE_DIM(tokens
);
1118 status
= parse_tokenize_string(params
->multi_string
, tokens
, &n_tokens
);
1120 printf(CMD_MSG_TOO_MANY_ARGS
, "route");
1125 if ((n_tokens
>= 2) &&
1126 (strcmp(tokens
[0], "add") == 0) &&
1127 strcmp(tokens
[1], "default")) {
1128 struct pipeline_routing_route_key key
;
1129 struct pipeline_routing_route_data route_data
;
1130 struct in_addr ipv4
, nh_ipv4
;
1131 struct ether_addr mac_addr
;
1132 uint32_t depth
, port_id
, svlan
, cvlan
, i
;
1133 uint32_t mpls_labels
[PIPELINE_ROUTING_MPLS_LABELS_MAX
];
1134 uint32_t n_labels
= RTE_DIM(mpls_labels
);
1136 memset(&key
, 0, sizeof(key
));
1137 memset(&route_data
, 0, sizeof(route_data
));
1140 printf(CMD_MSG_NOT_ENOUGH_ARGS
, "route add");
1144 if (parse_ipv4_addr(tokens
[1], &ipv4
)) {
1145 printf(CMD_MSG_INVALID_ARG
, "ipaddr");
1149 if (parser_read_uint32(&depth
, tokens
[2])) {
1150 printf(CMD_MSG_INVALID_ARG
, "depth");
1154 if (strcmp(tokens
[3], "port")) {
1155 printf(CMD_MSG_ARG_NOT_FOUND
, "port");
1159 if (parser_read_uint32(&port_id
, tokens
[4])) {
1160 printf(CMD_MSG_INVALID_ARG
, "portid");
1164 if (strcmp(tokens
[5], "ether")) {
1165 printf(CMD_MSG_ARG_NOT_FOUND
, "ether");
1169 if (parse_mac_addr(tokens
[6], &mac_addr
)) {
1170 if (parse_ipv4_addr(tokens
[6], &nh_ipv4
)) {
1171 printf(CMD_MSG_INVALID_ARG
, "nhmacaddr or nhipaddr");
1175 route_data
.flags
|= PIPELINE_ROUTING_ROUTE_ARP
;
1179 if (strcmp(tokens
[7], "mpls") == 0) {
1180 if (n_tokens
!= 9) {
1181 printf(CMD_MSG_MISMATCH_ARGS
, "route add mpls");
1185 if (parse_mpls_labels(tokens
[8], mpls_labels
, &n_labels
)) {
1186 printf(CMD_MSG_INVALID_ARG
, "mpls labels");
1190 route_data
.flags
|= PIPELINE_ROUTING_ROUTE_MPLS
;
1191 } else if (strcmp(tokens
[7], "qinq") == 0) {
1192 if (n_tokens
!= 10) {
1193 printf(CMD_MSG_MISMATCH_ARGS
, "route add qinq");
1197 if (parser_read_uint32(&svlan
, tokens
[8])) {
1198 printf(CMD_MSG_INVALID_ARG
, "svlan");
1201 if (parser_read_uint32(&cvlan
, tokens
[9])) {
1202 printf(CMD_MSG_INVALID_ARG
, "cvlan");
1206 route_data
.flags
|= PIPELINE_ROUTING_ROUTE_QINQ
;
1208 printf(CMD_MSG_ARG_NOT_FOUND
, "mpls or qinq");
1213 switch (route_data
.flags
) {
1215 route_data
.port_id
= port_id
;
1216 route_data
.ethernet
.macaddr
= mac_addr
;
1219 case PIPELINE_ROUTING_ROUTE_ARP
:
1220 route_data
.port_id
= port_id
;
1221 route_data
.ethernet
.ip
= rte_be_to_cpu_32(nh_ipv4
.s_addr
);
1224 case PIPELINE_ROUTING_ROUTE_MPLS
:
1225 route_data
.port_id
= port_id
;
1226 route_data
.ethernet
.macaddr
= mac_addr
;
1227 for (i
= 0; i
< n_labels
; i
++)
1228 route_data
.l2
.mpls
.labels
[i
] = mpls_labels
[i
];
1229 route_data
.l2
.mpls
.n_labels
= n_labels
;
1232 case PIPELINE_ROUTING_ROUTE_MPLS
| PIPELINE_ROUTING_ROUTE_ARP
:
1233 route_data
.port_id
= port_id
;
1234 route_data
.ethernet
.ip
= rte_be_to_cpu_32(nh_ipv4
.s_addr
);
1235 for (i
= 0; i
< n_labels
; i
++)
1236 route_data
.l2
.mpls
.labels
[i
] = mpls_labels
[i
];
1237 route_data
.l2
.mpls
.n_labels
= n_labels
;
1240 case PIPELINE_ROUTING_ROUTE_QINQ
:
1241 route_data
.port_id
= port_id
;
1242 route_data
.ethernet
.macaddr
= mac_addr
;
1243 route_data
.l2
.qinq
.svlan
= svlan
;
1244 route_data
.l2
.qinq
.cvlan
= cvlan
;
1247 case PIPELINE_ROUTING_ROUTE_QINQ
| PIPELINE_ROUTING_ROUTE_ARP
:
1249 route_data
.port_id
= port_id
;
1250 route_data
.ethernet
.ip
= rte_be_to_cpu_32(nh_ipv4
.s_addr
);
1251 route_data
.l2
.qinq
.svlan
= svlan
;
1252 route_data
.l2
.qinq
.cvlan
= cvlan
;
1256 key
.type
= PIPELINE_ROUTING_ROUTE_IPV4
;
1257 key
.key
.ipv4
.ip
= rte_be_to_cpu_32(ipv4
.s_addr
);
1258 key
.key
.ipv4
.depth
= depth
;
1260 status
= app_pipeline_routing_add_route(app
,
1265 printf(CMD_MSG_FAIL
, "route add");
1270 /* route add default */
1271 if ((n_tokens
>= 2) &&
1272 (strcmp(tokens
[0], "add") == 0) &&
1273 (strcmp(tokens
[1], "default") == 0)) {
1276 if (n_tokens
!= 3) {
1277 printf(CMD_MSG_MISMATCH_ARGS
, "route add default");
1281 if (parser_read_uint32(&port_id
, tokens
[2])) {
1282 printf(CMD_MSG_INVALID_ARG
, "portid");
1286 status
= app_pipeline_routing_add_default_route(app
,
1290 printf(CMD_MSG_FAIL
, "route add default");
1293 } /* route add default */
1296 if ((n_tokens
>= 2) &&
1297 (strcmp(tokens
[0], "del") == 0) &&
1298 strcmp(tokens
[1], "default")) {
1299 struct pipeline_routing_route_key key
;
1300 struct in_addr ipv4
;
1303 memset(&key
, 0, sizeof(key
));
1305 if (n_tokens
!= 3) {
1306 printf(CMD_MSG_MISMATCH_ARGS
, "route del");
1310 if (parse_ipv4_addr(tokens
[1], &ipv4
)) {
1311 printf(CMD_MSG_INVALID_ARG
, "ipaddr");
1315 if (parser_read_uint32(&depth
, tokens
[2])) {
1316 printf(CMD_MSG_INVALID_ARG
, "depth");
1320 key
.type
= PIPELINE_ROUTING_ROUTE_IPV4
;
1321 key
.key
.ipv4
.ip
= rte_be_to_cpu_32(ipv4
.s_addr
);
1322 key
.key
.ipv4
.depth
= depth
;
1324 status
= app_pipeline_routing_delete_route(app
, params
->p
, &key
);
1326 printf(CMD_MSG_FAIL
, "route del");
1331 /* route del default */
1332 if ((n_tokens
>= 2) &&
1333 (strcmp(tokens
[0], "del") == 0) &&
1334 (strcmp(tokens
[1], "default") == 0)) {
1335 if (n_tokens
!= 2) {
1336 printf(CMD_MSG_MISMATCH_ARGS
, "route del default");
1340 status
= app_pipeline_routing_delete_default_route(app
,
1343 printf(CMD_MSG_FAIL
, "route del default");
1346 } /* route del default */
1349 if ((n_tokens
>= 1) && (strcmp(tokens
[0], "ls") == 0)) {
1350 if (n_tokens
!= 1) {
1351 printf(CMD_MSG_MISMATCH_ARGS
, "route ls");
1355 status
= app_pipeline_routing_route_ls(app
, params
->p
);
1357 printf(CMD_MSG_FAIL
, "route ls");
1362 printf(CMD_MSG_MISMATCH_ARGS
, "route");
1365 static cmdline_parse_token_string_t cmd_route_p_string
=
1366 TOKEN_STRING_INITIALIZER(struct cmd_route_result
, p_string
, "p");
1368 static cmdline_parse_token_num_t cmd_route_p
=
1369 TOKEN_NUM_INITIALIZER(struct cmd_route_result
, p
, UINT32
);
1371 static cmdline_parse_token_string_t cmd_route_route_string
=
1372 TOKEN_STRING_INITIALIZER(struct cmd_route_result
, route_string
, "route");
1374 static cmdline_parse_token_string_t cmd_route_multi_string
=
1375 TOKEN_STRING_INITIALIZER(struct cmd_route_result
, multi_string
,
1376 TOKEN_STRING_MULTI
);
1378 static cmdline_parse_inst_t cmd_route
= {
1379 .f
= cmd_route_parsed
,
1381 .help_str
= "route add / add default / del / del default / ls",
1383 (void *)&cmd_route_p_string
,
1384 (void *)&cmd_route_p
,
1385 (void *)&cmd_route_route_string
,
1386 (void *)&cmd_route_multi_string
,
1395 * p <pipelineid> arp add <portid> <ipaddr> <macaddr>
1398 * p <pipelineid> arp add default <portid>
1401 * p <pipelineid> arp del <portid> <ipaddr>
1404 * p <pipelineid> arp del default
1407 * p <pipelineid> arp ls
1410 struct cmd_arp_result
{
1411 cmdline_fixed_string_t p_string
;
1413 cmdline_fixed_string_t arp_string
;
1414 cmdline_multi_string_t multi_string
;
1419 void *parsed_result
,
1420 __rte_unused
struct cmdline
*cl
,
1423 struct cmd_arp_result
*params
= parsed_result
;
1424 struct app_params
*app
= data
;
1427 uint32_t n_tokens
= RTE_DIM(tokens
);
1430 status
= parse_tokenize_string(params
->multi_string
, tokens
, &n_tokens
);
1432 printf(CMD_MSG_TOO_MANY_ARGS
, "arp");
1437 if ((n_tokens
>= 2) &&
1438 (strcmp(tokens
[0], "add") == 0) &&
1439 strcmp(tokens
[1], "default")) {
1440 struct pipeline_routing_arp_key key
;
1441 struct in_addr ipv4
;
1442 struct ether_addr mac_addr
;
1445 memset(&key
, 0, sizeof(key
));
1447 if (n_tokens
!= 4) {
1448 printf(CMD_MSG_MISMATCH_ARGS
, "arp add");
1452 if (parser_read_uint32(&port_id
, tokens
[1])) {
1453 printf(CMD_MSG_INVALID_ARG
, "portid");
1457 if (parse_ipv4_addr(tokens
[2], &ipv4
)) {
1458 printf(CMD_MSG_INVALID_ARG
, "ipaddr");
1462 if (parse_mac_addr(tokens
[3], &mac_addr
)) {
1463 printf(CMD_MSG_INVALID_ARG
, "macaddr");
1467 key
.type
= PIPELINE_ROUTING_ARP_IPV4
;
1468 key
.key
.ipv4
.port_id
= port_id
;
1469 key
.key
.ipv4
.ip
= rte_be_to_cpu_32(ipv4
.s_addr
);
1471 status
= app_pipeline_routing_add_arp_entry(app
,
1476 printf(CMD_MSG_FAIL
, "arp add");
1481 /* arp add default */
1482 if ((n_tokens
>= 2) &&
1483 (strcmp(tokens
[0], "add") == 0) &&
1484 (strcmp(tokens
[1], "default") == 0)) {
1487 if (n_tokens
!= 3) {
1488 printf(CMD_MSG_MISMATCH_ARGS
, "arp add default");
1492 if (parser_read_uint32(&port_id
, tokens
[2])) {
1493 printf(CMD_MSG_INVALID_ARG
, "portid");
1497 status
= app_pipeline_routing_add_default_arp_entry(app
,
1501 printf(CMD_MSG_FAIL
, "arp add default");
1504 } /* arp add default */
1507 if ((n_tokens
>= 2) &&
1508 (strcmp(tokens
[0], "del") == 0) &&
1509 strcmp(tokens
[1], "default")) {
1510 struct pipeline_routing_arp_key key
;
1511 struct in_addr ipv4
;
1514 memset(&key
, 0, sizeof(key
));
1516 if (n_tokens
!= 3) {
1517 printf(CMD_MSG_MISMATCH_ARGS
, "arp del");
1521 if (parser_read_uint32(&port_id
, tokens
[1])) {
1522 printf(CMD_MSG_INVALID_ARG
, "portid");
1526 if (parse_ipv4_addr(tokens
[2], &ipv4
)) {
1527 printf(CMD_MSG_INVALID_ARG
, "ipaddr");
1531 key
.type
= PIPELINE_ROUTING_ARP_IPV4
;
1532 key
.key
.ipv4
.ip
= rte_be_to_cpu_32(ipv4
.s_addr
);
1533 key
.key
.ipv4
.port_id
= port_id
;
1535 status
= app_pipeline_routing_delete_arp_entry(app
,
1539 printf(CMD_MSG_FAIL
, "arp del");
1544 /* arp del default */
1545 if ((n_tokens
>= 2) &&
1546 (strcmp(tokens
[0], "del") == 0) &&
1547 (strcmp(tokens
[1], "default") == 0)) {
1548 if (n_tokens
!= 2) {
1549 printf(CMD_MSG_MISMATCH_ARGS
, "arp del default");
1553 status
= app_pipeline_routing_delete_default_arp_entry(app
,
1556 printf(CMD_MSG_FAIL
, "arp del default");
1559 } /* arp del default */
1562 if ((n_tokens
>= 1) && (strcmp(tokens
[0], "ls") == 0)) {
1563 if (n_tokens
!= 1) {
1564 printf(CMD_MSG_MISMATCH_ARGS
, "arp ls");
1568 status
= app_pipeline_routing_arp_ls(app
, params
->p
);
1570 printf(CMD_MSG_FAIL
, "arp ls");
1575 printf(CMD_MSG_FAIL
, "arp");
1578 static cmdline_parse_token_string_t cmd_arp_p_string
=
1579 TOKEN_STRING_INITIALIZER(struct cmd_arp_result
, p_string
, "p");
1581 static cmdline_parse_token_num_t cmd_arp_p
=
1582 TOKEN_NUM_INITIALIZER(struct cmd_arp_result
, p
, UINT32
);
1584 static cmdline_parse_token_string_t cmd_arp_arp_string
=
1585 TOKEN_STRING_INITIALIZER(struct cmd_arp_result
, arp_string
, "arp");
1587 static cmdline_parse_token_string_t cmd_arp_multi_string
=
1588 TOKEN_STRING_INITIALIZER(struct cmd_arp_result
, multi_string
,
1589 TOKEN_STRING_MULTI
);
1591 static cmdline_parse_inst_t cmd_arp
= {
1592 .f
= cmd_arp_parsed
,
1594 .help_str
= "arp add / add default / del / del default / ls",
1596 (void *)&cmd_arp_p_string
,
1598 (void *)&cmd_arp_arp_string
,
1599 (void *)&cmd_arp_multi_string
,
1604 static cmdline_parse_ctx_t pipeline_cmds
[] = {
1605 (cmdline_parse_inst_t
*)&cmd_route
,
1606 (cmdline_parse_inst_t
*)&cmd_arp
,
1610 static struct pipeline_fe_ops pipeline_routing_fe_ops
= {
1611 .f_init
= app_pipeline_routing_init
,
1612 .f_post_init
= app_pipeline_routing_post_init
,
1613 .f_free
= app_pipeline_routing_free
,
1614 .f_track
= app_pipeline_track_default
,
1615 .cmds
= pipeline_cmds
,
1618 struct pipeline_type pipeline_routing
= {
1620 .be_ops
= &pipeline_routing_be_ops
,
1621 .fe_ops
= &pipeline_routing_fe_ops
,