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.
40 #include <rte_common.h>
41 #include <rte_malloc.h>
43 #include <rte_byteorder.h>
44 #include <rte_table_lpm.h>
45 #include <rte_table_hash.h>
46 #include <rte_pipeline.h>
48 #include "pipeline_routing_be.h"
49 #include "pipeline_actions_common.h"
51 #include "hash_func.h"
53 #define MPLS_LABEL(label, exp, s, ttl) \
54 (((((uint64_t) (label)) & 0xFFFFFLLU) << 12) | \
55 ((((uint64_t) (exp)) & 0x7LLU) << 9) | \
56 ((((uint64_t) (s)) & 0x1LLU) << 8) | \
57 (((uint64_t) (ttl)) & 0xFFLU))
59 #define RTE_SCHED_PORT_HIERARCHY(subport, pipe, \
60 traffic_class, queue, color) \
61 ((((uint64_t) (queue)) & 0x3) | \
62 ((((uint64_t) (traffic_class)) & 0x3) << 2) | \
63 ((((uint64_t) (color)) & 0x3) << 4) | \
64 ((((uint64_t) (subport)) & 0xFFFF) << 16) | \
65 ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32))
68 #define MAC_SRC_DEFAULT 0x112233445566ULL
70 #ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s
71 #define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256
74 struct pipeline_routing {
76 struct pipeline_routing_params params;
77 pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
78 } __rte_cache_aligned;
84 pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg);
86 static pipeline_msg_req_handler handlers[] = {
87 [PIPELINE_MSG_REQ_PING] =
88 pipeline_msg_req_ping_handler,
89 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
90 pipeline_msg_req_stats_port_in_handler,
91 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
92 pipeline_msg_req_stats_port_out_handler,
93 [PIPELINE_MSG_REQ_STATS_TABLE] =
94 pipeline_msg_req_stats_table_handler,
95 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
96 pipeline_msg_req_port_in_enable_handler,
97 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
98 pipeline_msg_req_port_in_disable_handler,
99 [PIPELINE_MSG_REQ_CUSTOM] =
100 pipeline_routing_msg_req_custom_handler,
104 pipeline_routing_msg_req_route_add_handler(struct pipeline *p,
108 pipeline_routing_msg_req_route_del_handler(struct pipeline *p,
112 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
116 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
120 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p,
124 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p,
128 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p,
132 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p,
135 static pipeline_msg_req_handler custom_handlers[] = {
136 [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] =
137 pipeline_routing_msg_req_route_add_handler,
138 [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL] =
139 pipeline_routing_msg_req_route_del_handler,
140 [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT] =
141 pipeline_routing_msg_req_route_add_default_handler,
142 [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT] =
143 pipeline_routing_msg_req_route_del_default_handler,
144 [PIPELINE_ROUTING_MSG_REQ_ARP_ADD] =
145 pipeline_routing_msg_req_arp_add_handler,
146 [PIPELINE_ROUTING_MSG_REQ_ARP_DEL] =
147 pipeline_routing_msg_req_arp_del_handler,
148 [PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT] =
149 pipeline_routing_msg_req_arp_add_default_handler,
150 [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] =
151 pipeline_routing_msg_req_arp_del_default_handler,
157 struct routing_table_entry {
158 struct rte_pipeline_table_entry head;
160 uint32_t port_id; /* Output port ID */
161 uint32_t ip; /* Next hop IP address (only valid for remote routes) */
164 uint16_t data_offset;
165 uint16_t ether_l2_length;
167 uint16_t slab_offset[4];
174 } __attribute__((__packed__));
176 #define MACADDR_DST_WRITE(slab_ptr, slab) \
178 struct layout *dst = (struct layout *) (slab_ptr); \
179 struct layout *src = (struct layout *) &(slab); \
185 static inline __attribute__((always_inline)) void
187 struct rte_mbuf *pkt,
188 struct rte_pipeline_table_entry *table_entry,
196 struct pipeline_routing *p_rt = arg;
198 struct routing_table_entry *entry =
199 (struct routing_table_entry *) table_entry;
201 struct ipv4_hdr *ip = (struct ipv4_hdr *)
202 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.ip_hdr_offset);
204 enum rte_meter_color pkt_color = (enum rte_meter_color)
205 RTE_MBUF_METADATA_UINT32(pkt, p_rt->params.color_offset);
207 struct pipeline_routing_arp_key_ipv4 *arp_key =
208 (struct pipeline_routing_arp_key_ipv4 *)
209 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.arp_key_offset);
211 uint64_t *slab0_ptr, *slab1_ptr, *slab2_ptr, *slab3_ptr, sched;
212 uint32_t ip_da, nh_ip, port_id;
213 uint16_t total_length, data_offset, ether_l2_length;
216 total_length = rte_bswap16(ip->total_length);
217 ip_da = ip->dst_addr;
218 data_offset = entry->data_offset;
219 ether_l2_length = entry->ether_l2_length;
220 slab0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[0]);
221 slab1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[1]);
222 slab2_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[2]);
223 slab3_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[3]);
226 port_id = entry->port_id;
228 if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
233 total_length += ether_l2_length;
235 if (qinq && qinq_sched) {
236 uint32_t dscp = ip->type_of_service >> 2;
237 uint32_t svlan, cvlan, tc, tc_q;
239 if (qinq_sched == 1) {
240 uint64_t slab_qinq = rte_bswap64(entry->slab[0]);
242 svlan = (slab_qinq >> 48) & 0xFFF;
243 cvlan = (slab_qinq >> 16) & 0xFFF;
244 tc = (dscp >> 2) & 0x3;
247 uint32_t ip_src = rte_bswap32(ip->src_addr);
250 cvlan = (ip_src >> 16) & 0xFFF;
251 tc = (ip_src >> 2) & 0x3;
254 sched = RTE_SCHED_PORT_HIERARCHY(svlan,
262 pkt->data_off = data_offset;
263 pkt->data_len = total_length;
264 pkt->pkt_len = total_length;
266 if ((qinq == 0) && (mpls == 0)) {
267 *slab0_ptr = entry->slab[0];
270 MACADDR_DST_WRITE(slab1_ptr, entry->slab[1]);
274 *slab0_ptr = entry->slab[0];
275 *slab1_ptr = entry->slab[1];
278 MACADDR_DST_WRITE(slab2_ptr, entry->slab[2]);
281 pkt->hash.sched.lo = sched & 0xFFFFFFFF;
282 pkt->hash.sched.hi = sched >> 32;
287 if (mpls_color_mark) {
288 uint64_t mpls_exp = rte_bswap64(
289 (MPLS_LABEL(0, pkt_color, 0, 0) << 32) |
290 MPLS_LABEL(0, pkt_color, 0, 0));
292 *slab0_ptr = entry->slab[0] | mpls_exp;
293 *slab1_ptr = entry->slab[1] | mpls_exp;
294 *slab2_ptr = entry->slab[2];
296 *slab0_ptr = entry->slab[0];
297 *slab1_ptr = entry->slab[1];
298 *slab2_ptr = entry->slab[2];
302 MACADDR_DST_WRITE(slab3_ptr, entry->slab[3]);
306 arp_key->port_id = port_id;
311 static inline __attribute__((always_inline)) void
313 struct rte_mbuf **pkts,
314 struct rte_pipeline_table_entry **table_entries,
322 struct pipeline_routing *p_rt = arg;
324 struct routing_table_entry *entry0 =
325 (struct routing_table_entry *) table_entries[0];
326 struct routing_table_entry *entry1 =
327 (struct routing_table_entry *) table_entries[1];
328 struct routing_table_entry *entry2 =
329 (struct routing_table_entry *) table_entries[2];
330 struct routing_table_entry *entry3 =
331 (struct routing_table_entry *) table_entries[3];
333 struct ipv4_hdr *ip0 = (struct ipv4_hdr *)
334 RTE_MBUF_METADATA_UINT8_PTR(pkts[0],
335 p_rt->params.ip_hdr_offset);
336 struct ipv4_hdr *ip1 = (struct ipv4_hdr *)
337 RTE_MBUF_METADATA_UINT8_PTR(pkts[1],
338 p_rt->params.ip_hdr_offset);
339 struct ipv4_hdr *ip2 = (struct ipv4_hdr *)
340 RTE_MBUF_METADATA_UINT8_PTR(pkts[2],
341 p_rt->params.ip_hdr_offset);
342 struct ipv4_hdr *ip3 = (struct ipv4_hdr *)
343 RTE_MBUF_METADATA_UINT8_PTR(pkts[3],
344 p_rt->params.ip_hdr_offset);
346 enum rte_meter_color pkt0_color = (enum rte_meter_color)
347 RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->params.color_offset);
348 enum rte_meter_color pkt1_color = (enum rte_meter_color)
349 RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->params.color_offset);
350 enum rte_meter_color pkt2_color = (enum rte_meter_color)
351 RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->params.color_offset);
352 enum rte_meter_color pkt3_color = (enum rte_meter_color)
353 RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->params.color_offset);
355 struct pipeline_routing_arp_key_ipv4 *arp_key0 =
356 (struct pipeline_routing_arp_key_ipv4 *)
357 RTE_MBUF_METADATA_UINT8_PTR(pkts[0],
358 p_rt->params.arp_key_offset);
359 struct pipeline_routing_arp_key_ipv4 *arp_key1 =
360 (struct pipeline_routing_arp_key_ipv4 *)
361 RTE_MBUF_METADATA_UINT8_PTR(pkts[1],
362 p_rt->params.arp_key_offset);
363 struct pipeline_routing_arp_key_ipv4 *arp_key2 =
364 (struct pipeline_routing_arp_key_ipv4 *)
365 RTE_MBUF_METADATA_UINT8_PTR(pkts[2],
366 p_rt->params.arp_key_offset);
367 struct pipeline_routing_arp_key_ipv4 *arp_key3 =
368 (struct pipeline_routing_arp_key_ipv4 *)
369 RTE_MBUF_METADATA_UINT8_PTR(pkts[3],
370 p_rt->params.arp_key_offset);
372 uint64_t *slab0_ptr0, *slab1_ptr0, *slab2_ptr0, *slab3_ptr0;
373 uint64_t *slab0_ptr1, *slab1_ptr1, *slab2_ptr1, *slab3_ptr1;
374 uint64_t *slab0_ptr2, *slab1_ptr2, *slab2_ptr2, *slab3_ptr2;
375 uint64_t *slab0_ptr3, *slab1_ptr3, *slab2_ptr3, *slab3_ptr3;
376 uint64_t sched0, sched1, sched2, sched3;
378 uint32_t ip_da0, nh_ip0, port_id0;
379 uint32_t ip_da1, nh_ip1, port_id1;
380 uint32_t ip_da2, nh_ip2, port_id2;
381 uint32_t ip_da3, nh_ip3, port_id3;
383 uint16_t total_length0, data_offset0, ether_l2_length0;
384 uint16_t total_length1, data_offset1, ether_l2_length1;
385 uint16_t total_length2, data_offset2, ether_l2_length2;
386 uint16_t total_length3, data_offset3, ether_l2_length3;
389 total_length0 = rte_bswap16(ip0->total_length);
390 total_length1 = rte_bswap16(ip1->total_length);
391 total_length2 = rte_bswap16(ip2->total_length);
392 total_length3 = rte_bswap16(ip3->total_length);
394 ip_da0 = ip0->dst_addr;
395 ip_da1 = ip1->dst_addr;
396 ip_da2 = ip2->dst_addr;
397 ip_da3 = ip3->dst_addr;
399 data_offset0 = entry0->data_offset;
400 data_offset1 = entry1->data_offset;
401 data_offset2 = entry2->data_offset;
402 data_offset3 = entry3->data_offset;
404 ether_l2_length0 = entry0->ether_l2_length;
405 ether_l2_length1 = entry1->ether_l2_length;
406 ether_l2_length2 = entry2->ether_l2_length;
407 ether_l2_length3 = entry3->ether_l2_length;
409 slab0_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
410 entry0->slab_offset[0]);
411 slab1_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
412 entry0->slab_offset[1]);
413 slab2_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
414 entry0->slab_offset[2]);
415 slab3_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
416 entry0->slab_offset[3]);
418 slab0_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
419 entry1->slab_offset[0]);
420 slab1_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
421 entry1->slab_offset[1]);
422 slab2_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
423 entry1->slab_offset[2]);
424 slab3_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
425 entry1->slab_offset[3]);
427 slab0_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
428 entry2->slab_offset[0]);
429 slab1_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
430 entry2->slab_offset[1]);
431 slab2_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
432 entry2->slab_offset[2]);
433 slab3_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
434 entry2->slab_offset[3]);
436 slab0_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
437 entry3->slab_offset[0]);
438 slab1_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
439 entry3->slab_offset[1]);
440 slab2_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
441 entry3->slab_offset[2]);
442 slab3_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
443 entry3->slab_offset[3]);
446 port_id0 = entry0->port_id;
448 if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
451 port_id1 = entry1->port_id;
453 if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
456 port_id2 = entry2->port_id;
458 if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
461 port_id3 = entry3->port_id;
463 if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
468 total_length0 += ether_l2_length0;
469 total_length1 += ether_l2_length1;
470 total_length2 += ether_l2_length2;
471 total_length3 += ether_l2_length3;
473 if (qinq && qinq_sched) {
474 uint32_t dscp0 = ip0->type_of_service >> 2;
475 uint32_t dscp1 = ip1->type_of_service >> 2;
476 uint32_t dscp2 = ip2->type_of_service >> 2;
477 uint32_t dscp3 = ip3->type_of_service >> 2;
478 uint32_t svlan0, cvlan0, tc0, tc_q0;
479 uint32_t svlan1, cvlan1, tc1, tc_q1;
480 uint32_t svlan2, cvlan2, tc2, tc_q2;
481 uint32_t svlan3, cvlan3, tc3, tc_q3;
483 if (qinq_sched == 1) {
484 uint64_t slab_qinq0 = rte_bswap64(entry0->slab[0]);
485 uint64_t slab_qinq1 = rte_bswap64(entry1->slab[0]);
486 uint64_t slab_qinq2 = rte_bswap64(entry2->slab[0]);
487 uint64_t slab_qinq3 = rte_bswap64(entry3->slab[0]);
489 svlan0 = (slab_qinq0 >> 48) & 0xFFF;
490 svlan1 = (slab_qinq1 >> 48) & 0xFFF;
491 svlan2 = (slab_qinq2 >> 48) & 0xFFF;
492 svlan3 = (slab_qinq3 >> 48) & 0xFFF;
494 cvlan0 = (slab_qinq0 >> 16) & 0xFFF;
495 cvlan1 = (slab_qinq1 >> 16) & 0xFFF;
496 cvlan2 = (slab_qinq2 >> 16) & 0xFFF;
497 cvlan3 = (slab_qinq3 >> 16) & 0xFFF;
499 tc0 = (dscp0 >> 2) & 0x3;
500 tc1 = (dscp1 >> 2) & 0x3;
501 tc2 = (dscp2 >> 2) & 0x3;
502 tc3 = (dscp3 >> 2) & 0x3;
509 uint32_t ip_src0 = rte_bswap32(ip0->src_addr);
510 uint32_t ip_src1 = rte_bswap32(ip1->src_addr);
511 uint32_t ip_src2 = rte_bswap32(ip2->src_addr);
512 uint32_t ip_src3 = rte_bswap32(ip3->src_addr);
519 cvlan0 = (ip_src0 >> 16) & 0xFFF;
520 cvlan1 = (ip_src1 >> 16) & 0xFFF;
521 cvlan2 = (ip_src2 >> 16) & 0xFFF;
522 cvlan3 = (ip_src3 >> 16) & 0xFFF;
524 tc0 = (ip_src0 >> 2) & 0x3;
525 tc1 = (ip_src1 >> 2) & 0x3;
526 tc2 = (ip_src2 >> 2) & 0x3;
527 tc3 = (ip_src3 >> 2) & 0x3;
529 tc_q0 = ip_src0 & 0x3;
530 tc_q1 = ip_src1 & 0x3;
531 tc_q2 = ip_src2 & 0x3;
532 tc_q3 = ip_src3 & 0x3;
535 sched0 = RTE_SCHED_PORT_HIERARCHY(svlan0,
540 sched1 = RTE_SCHED_PORT_HIERARCHY(svlan1,
545 sched2 = RTE_SCHED_PORT_HIERARCHY(svlan2,
550 sched3 = RTE_SCHED_PORT_HIERARCHY(svlan3,
559 pkts[0]->data_off = data_offset0;
560 pkts[1]->data_off = data_offset1;
561 pkts[2]->data_off = data_offset2;
562 pkts[3]->data_off = data_offset3;
564 pkts[0]->data_len = total_length0;
565 pkts[1]->data_len = total_length1;
566 pkts[2]->data_len = total_length2;
567 pkts[3]->data_len = total_length3;
569 pkts[0]->pkt_len = total_length0;
570 pkts[1]->pkt_len = total_length1;
571 pkts[2]->pkt_len = total_length2;
572 pkts[3]->pkt_len = total_length3;
574 if ((qinq == 0) && (mpls == 0)) {
575 *slab0_ptr0 = entry0->slab[0];
576 *slab0_ptr1 = entry1->slab[0];
577 *slab0_ptr2 = entry2->slab[0];
578 *slab0_ptr3 = entry3->slab[0];
581 MACADDR_DST_WRITE(slab1_ptr0, entry0->slab[1]);
582 MACADDR_DST_WRITE(slab1_ptr1, entry1->slab[1]);
583 MACADDR_DST_WRITE(slab1_ptr2, entry2->slab[1]);
584 MACADDR_DST_WRITE(slab1_ptr3, entry3->slab[1]);
589 *slab0_ptr0 = entry0->slab[0];
590 *slab0_ptr1 = entry1->slab[0];
591 *slab0_ptr2 = entry2->slab[0];
592 *slab0_ptr3 = entry3->slab[0];
594 *slab1_ptr0 = entry0->slab[1];
595 *slab1_ptr1 = entry1->slab[1];
596 *slab1_ptr2 = entry2->slab[1];
597 *slab1_ptr3 = entry3->slab[1];
600 MACADDR_DST_WRITE(slab2_ptr0, entry0->slab[2]);
601 MACADDR_DST_WRITE(slab2_ptr1, entry1->slab[2]);
602 MACADDR_DST_WRITE(slab2_ptr2, entry2->slab[2]);
603 MACADDR_DST_WRITE(slab2_ptr3, entry3->slab[2]);
607 pkts[0]->hash.sched.lo = sched0 & 0xFFFFFFFF;
608 pkts[0]->hash.sched.hi = sched0 >> 32;
609 pkts[1]->hash.sched.lo = sched1 & 0xFFFFFFFF;
610 pkts[1]->hash.sched.hi = sched1 >> 32;
611 pkts[2]->hash.sched.lo = sched2 & 0xFFFFFFFF;
612 pkts[2]->hash.sched.hi = sched2 >> 32;
613 pkts[3]->hash.sched.lo = sched3 & 0xFFFFFFFF;
614 pkts[3]->hash.sched.hi = sched3 >> 32;
619 if (mpls_color_mark) {
620 uint64_t mpls_exp0 = rte_bswap64(
621 (MPLS_LABEL(0, pkt0_color, 0, 0) << 32) |
622 MPLS_LABEL(0, pkt0_color, 0, 0));
623 uint64_t mpls_exp1 = rte_bswap64(
624 (MPLS_LABEL(0, pkt1_color, 0, 0) << 32) |
625 MPLS_LABEL(0, pkt1_color, 0, 0));
626 uint64_t mpls_exp2 = rte_bswap64(
627 (MPLS_LABEL(0, pkt2_color, 0, 0) << 32) |
628 MPLS_LABEL(0, pkt2_color, 0, 0));
629 uint64_t mpls_exp3 = rte_bswap64(
630 (MPLS_LABEL(0, pkt3_color, 0, 0) << 32) |
631 MPLS_LABEL(0, pkt3_color, 0, 0));
633 *slab0_ptr0 = entry0->slab[0] | mpls_exp0;
634 *slab0_ptr1 = entry1->slab[0] | mpls_exp1;
635 *slab0_ptr2 = entry2->slab[0] | mpls_exp2;
636 *slab0_ptr3 = entry3->slab[0] | mpls_exp3;
638 *slab1_ptr0 = entry0->slab[1] | mpls_exp0;
639 *slab1_ptr1 = entry1->slab[1] | mpls_exp1;
640 *slab1_ptr2 = entry2->slab[1] | mpls_exp2;
641 *slab1_ptr3 = entry3->slab[1] | mpls_exp3;
643 *slab2_ptr0 = entry0->slab[2];
644 *slab2_ptr1 = entry1->slab[2];
645 *slab2_ptr2 = entry2->slab[2];
646 *slab2_ptr3 = entry3->slab[2];
648 *slab0_ptr0 = entry0->slab[0];
649 *slab0_ptr1 = entry1->slab[0];
650 *slab0_ptr2 = entry2->slab[0];
651 *slab0_ptr3 = entry3->slab[0];
653 *slab1_ptr0 = entry0->slab[1];
654 *slab1_ptr1 = entry1->slab[1];
655 *slab1_ptr2 = entry2->slab[1];
656 *slab1_ptr3 = entry3->slab[1];
658 *slab2_ptr0 = entry0->slab[2];
659 *slab2_ptr1 = entry1->slab[2];
660 *slab2_ptr2 = entry2->slab[2];
661 *slab2_ptr3 = entry3->slab[2];
665 MACADDR_DST_WRITE(slab3_ptr0, entry0->slab[3]);
666 MACADDR_DST_WRITE(slab3_ptr1, entry1->slab[3]);
667 MACADDR_DST_WRITE(slab3_ptr2, entry2->slab[3]);
668 MACADDR_DST_WRITE(slab3_ptr3, entry3->slab[3]);
673 arp_key0->port_id = port_id0;
674 arp_key1->port_id = port_id1;
675 arp_key2->port_id = port_id2;
676 arp_key3->port_id = port_id3;
678 arp_key0->ip = nh_ip0;
679 arp_key1->ip = nh_ip1;
680 arp_key2->ip = nh_ip2;
681 arp_key3->ip = nh_ip3;
685 #define PKT_WORK_ROUTING_ETHERNET(arp) \
687 pkt_work_routing_ether_arp##arp( \
688 struct rte_mbuf *pkt, \
689 struct rte_pipeline_table_entry *table_entry, \
692 pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 0, 0);\
695 #define PKT4_WORK_ROUTING_ETHERNET(arp) \
697 pkt4_work_routing_ether_arp##arp( \
698 struct rte_mbuf **pkts, \
699 struct rte_pipeline_table_entry **table_entries, \
702 pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 0, 0);\
705 #define routing_table_ah_hit_ether(arp) \
706 PKT_WORK_ROUTING_ETHERNET(arp) \
707 PKT4_WORK_ROUTING_ETHERNET(arp) \
708 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_arp##arp, \
709 pkt_work_routing_ether_arp##arp, \
710 pkt4_work_routing_ether_arp##arp)
712 routing_table_ah_hit_ether(0)
713 routing_table_ah_hit_ether(1)
715 #define PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
717 pkt_work_routing_ether_qinq_sched##sched##_arp##arp( \
718 struct rte_mbuf *pkt, \
719 struct rte_pipeline_table_entry *table_entry, \
722 pkt_work_routing(pkt, table_entry, arg, arp, 1, sched, 0, 0);\
725 #define PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
727 pkt4_work_routing_ether_qinq_sched##sched##_arp##arp( \
728 struct rte_mbuf **pkts, \
729 struct rte_pipeline_table_entry **table_entries, \
732 pkt4_work_routing(pkts, table_entries, arg, arp, 1, sched, 0, 0);\
735 #define routing_table_ah_hit_ether_qinq(sched, arp) \
736 PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
737 PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
738 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_qinq_sched##sched##_arp##arp,\
739 pkt_work_routing_ether_qinq_sched##sched##_arp##arp, \
740 pkt4_work_routing_ether_qinq_sched##sched##_arp##arp)
742 routing_table_ah_hit_ether_qinq(0, 0)
743 routing_table_ah_hit_ether_qinq(1, 0)
744 routing_table_ah_hit_ether_qinq(2, 0)
745 routing_table_ah_hit_ether_qinq(0, 1)
746 routing_table_ah_hit_ether_qinq(1, 1)
747 routing_table_ah_hit_ether_qinq(2, 1)
749 #define PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
751 pkt_work_routing_ether_mpls_color##color##_arp##arp( \
752 struct rte_mbuf *pkt, \
753 struct rte_pipeline_table_entry *table_entry, \
756 pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 1, color);\
759 #define PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
761 pkt4_work_routing_ether_mpls_color##color##_arp##arp( \
762 struct rte_mbuf **pkts, \
763 struct rte_pipeline_table_entry **table_entries, \
766 pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 1, color);\
769 #define routing_table_ah_hit_ether_mpls(color, arp) \
770 PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
771 PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
772 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_mpls_color##color##_arp##arp,\
773 pkt_work_routing_ether_mpls_color##color##_arp##arp, \
774 pkt4_work_routing_ether_mpls_color##color##_arp##arp)
776 routing_table_ah_hit_ether_mpls(0, 0)
777 routing_table_ah_hit_ether_mpls(1, 0)
778 routing_table_ah_hit_ether_mpls(0, 1)
779 routing_table_ah_hit_ether_mpls(1, 1)
781 static rte_pipeline_table_action_handler_hit
782 get_routing_table_ah_hit(struct pipeline_routing *p)
784 if (p->params.dbg_ah_disable)
787 switch (p->params.encap) {
788 case PIPELINE_ROUTING_ENCAP_ETHERNET:
789 return (p->params.n_arp_entries) ?
790 routing_table_ah_hit_ether_arp1 :
791 routing_table_ah_hit_ether_arp0;
793 case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:
794 if (p->params.n_arp_entries)
795 switch (p->params.qinq_sched) {
797 return routing_table_ah_hit_ether_qinq_sched0_arp1;
799 return routing_table_ah_hit_ether_qinq_sched1_arp1;
801 return routing_table_ah_hit_ether_qinq_sched2_arp1;
806 switch (p->params.qinq_sched) {
808 return routing_table_ah_hit_ether_qinq_sched0_arp0;
810 return routing_table_ah_hit_ether_qinq_sched1_arp0;
812 return routing_table_ah_hit_ether_qinq_sched2_arp0;
817 case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:
818 if (p->params.n_arp_entries)
819 if (p->params.mpls_color_mark)
820 return routing_table_ah_hit_ether_mpls_color1_arp1;
822 return routing_table_ah_hit_ether_mpls_color0_arp1;
824 if (p->params.mpls_color_mark)
825 return routing_table_ah_hit_ether_mpls_color1_arp0;
827 return routing_table_ah_hit_ether_mpls_color0_arp0;
837 struct arp_table_entry {
838 struct rte_pipeline_table_entry head;
847 struct rte_mbuf *pkt,
848 struct rte_pipeline_table_entry *table_entry,
849 __rte_unused void *arg)
851 struct arp_table_entry *entry = (struct arp_table_entry *) table_entry;
854 uint64_t macaddr_dst = entry->macaddr;
855 uint64_t *slab_ptr = (uint64_t *) ((char *) pkt->buf_addr +
856 (pkt->data_off - 2));
861 MACADDR_DST_WRITE(slab_ptr, macaddr_dst);
866 struct rte_mbuf **pkts,
867 struct rte_pipeline_table_entry **table_entries,
868 __rte_unused void *arg)
870 struct arp_table_entry *entry0 =
871 (struct arp_table_entry *) table_entries[0];
872 struct arp_table_entry *entry1 =
873 (struct arp_table_entry *) table_entries[1];
874 struct arp_table_entry *entry2 =
875 (struct arp_table_entry *) table_entries[2];
876 struct arp_table_entry *entry3 =
877 (struct arp_table_entry *) table_entries[3];
880 uint64_t macaddr_dst0 = entry0->macaddr;
881 uint64_t macaddr_dst1 = entry1->macaddr;
882 uint64_t macaddr_dst2 = entry2->macaddr;
883 uint64_t macaddr_dst3 = entry3->macaddr;
885 uint64_t *slab_ptr0 = (uint64_t *) ((char *) pkts[0]->buf_addr +
886 (pkts[0]->data_off - 2));
887 uint64_t *slab_ptr1 = (uint64_t *) ((char *) pkts[1]->buf_addr +
888 (pkts[1]->data_off - 2));
889 uint64_t *slab_ptr2 = (uint64_t *) ((char *) pkts[2]->buf_addr +
890 (pkts[2]->data_off - 2));
891 uint64_t *slab_ptr3 = (uint64_t *) ((char *) pkts[3]->buf_addr +
892 (pkts[3]->data_off - 2));
897 MACADDR_DST_WRITE(slab_ptr0, macaddr_dst0);
898 MACADDR_DST_WRITE(slab_ptr1, macaddr_dst1);
899 MACADDR_DST_WRITE(slab_ptr2, macaddr_dst2);
900 MACADDR_DST_WRITE(slab_ptr3, macaddr_dst3);
903 PIPELINE_TABLE_AH_HIT(arp_table_ah_hit,
907 static rte_pipeline_table_action_handler_hit
908 get_arp_table_ah_hit(struct pipeline_routing *p)
910 if (p->params.dbg_ah_disable)
913 return arp_table_ah_hit;
920 pipeline_routing_parse_args(struct pipeline_routing_params *p,
921 struct pipeline_params *params)
923 uint32_t n_routes_present = 0;
924 uint32_t encap_present = 0;
925 uint32_t qinq_sched_present = 0;
926 uint32_t mpls_color_mark_present = 0;
927 uint32_t n_arp_entries_present = 0;
928 uint32_t ip_hdr_offset_present = 0;
929 uint32_t arp_key_offset_present = 0;
930 uint32_t color_offset_present = 0;
931 uint32_t dbg_ah_disable_present = 0;
935 p->n_routes = PIPELINE_ROUTING_N_ROUTES_DEFAULT;
936 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
938 p->mpls_color_mark = 0;
939 p->n_arp_entries = 0;
940 p->dbg_ah_disable = 0;
942 for (i = 0; i < params->n_args; i++) {
943 char *arg_name = params->args_name[i];
944 char *arg_value = params->args_value[i];
947 if (strcmp(arg_name, "n_routes") == 0) {
950 PIPELINE_PARSE_ERR_DUPLICATE(
951 n_routes_present == 0, params->name,
953 n_routes_present = 1;
955 status = parser_read_uint32(&p->n_routes,
957 PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&
958 (p->n_routes != 0)), params->name,
959 arg_name, arg_value);
960 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
961 params->name, arg_name, arg_value);
967 if (strcmp(arg_name, "encap") == 0) {
968 PIPELINE_PARSE_ERR_DUPLICATE(encap_present == 0,
969 params->name, arg_name);
973 if (strcmp(arg_value, "ethernet") == 0) {
974 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
979 if (strcmp(arg_value, "ethernet_qinq") == 0) {
980 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ;
985 if (strcmp(arg_value, "ethernet_mpls") == 0) {
986 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS;
991 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
992 arg_name, arg_value);
996 if (strcmp(arg_name, "qinq_sched") == 0) {
999 PIPELINE_PARSE_ERR_DUPLICATE(
1000 qinq_sched_present == 0, params->name,
1002 qinq_sched_present = 1;
1004 status = parser_read_arg_bool(arg_value);
1005 if (status == -EINVAL) {
1006 if (strcmp(arg_value, "test") == 0) {
1011 p->qinq_sched = status;
1015 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
1016 arg_name, arg_value);
1019 /* mpls_color_mark */
1020 if (strcmp(arg_name, "mpls_color_mark") == 0) {
1023 PIPELINE_PARSE_ERR_DUPLICATE(
1024 mpls_color_mark_present == 0,
1025 params->name, arg_name);
1026 mpls_color_mark_present = 1;
1029 status = parser_read_arg_bool(arg_value);
1031 p->mpls_color_mark = status;
1035 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
1036 arg_name, arg_value);
1040 if (strcmp(arg_name, "n_arp_entries") == 0) {
1043 PIPELINE_PARSE_ERR_DUPLICATE(
1044 n_arp_entries_present == 0, params->name,
1046 n_arp_entries_present = 1;
1048 status = parser_read_uint32(&p->n_arp_entries,
1050 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1051 params->name, arg_name, arg_value);
1052 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1053 params->name, arg_name, arg_value);
1059 if (strcmp(arg_name, "ip_hdr_offset") == 0) {
1062 PIPELINE_PARSE_ERR_DUPLICATE(
1063 ip_hdr_offset_present == 0, params->name,
1065 ip_hdr_offset_present = 1;
1067 status = parser_read_uint32(&p->ip_hdr_offset,
1069 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1070 params->name, arg_name, arg_value);
1071 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1072 params->name, arg_name, arg_value);
1077 /* arp_key_offset */
1078 if (strcmp(arg_name, "arp_key_offset") == 0) {
1081 PIPELINE_PARSE_ERR_DUPLICATE(
1082 arp_key_offset_present == 0, params->name,
1084 arp_key_offset_present = 1;
1086 status = parser_read_uint32(&p->arp_key_offset,
1088 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1089 params->name, arg_name, arg_value);
1090 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1091 params->name, arg_name, arg_value);
1097 if (strcmp(arg_name, "color_offset") == 0) {
1100 PIPELINE_PARSE_ERR_DUPLICATE(
1101 color_offset_present == 0, params->name,
1103 color_offset_present = 1;
1105 status = parser_read_uint32(&p->color_offset,
1107 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1108 params->name, arg_name, arg_value);
1109 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1110 params->name, arg_name, arg_value);
1116 if (strcmp(arg_name, "dbg_ah_disable") == 0) {
1119 PIPELINE_PARSE_ERR_DUPLICATE(
1120 dbg_ah_disable_present == 0, params->name,
1122 dbg_ah_disable_present = 1;
1124 status = parser_read_arg_bool(arg_value);
1126 p->dbg_ah_disable = status;
1130 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
1131 arg_name, arg_value);
1137 PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);
1140 /* Check that mandatory arguments are present */
1141 PIPELINE_PARSE_ERR_MANDATORY(ip_hdr_offset_present, params->name,
1144 /* Check relations between arguments */
1146 case PIPELINE_ROUTING_ENCAP_ETHERNET:
1147 PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in "
1148 "section \"%s\": encap = ethernet, therefore "
1149 "qinq_sched = yes/test is not allowed",
1151 PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error "
1152 "in section \"%s\": encap = ethernet, therefore "
1153 "mpls_color_mark = yes is not allowed",
1155 PIPELINE_ARG_CHECK((!color_offset_present), "Parse error "
1156 "in section \"%s\": encap = ethernet, therefore "
1157 "color_offset is not allowed",
1161 case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:
1162 PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error "
1163 "in section \"%s\": encap = ethernet_qinq, "
1164 "therefore mpls_color_mark = yes is not allowed",
1166 PIPELINE_ARG_CHECK((!color_offset_present), "Parse error "
1167 "in section \"%s\": encap = ethernet_qinq, "
1168 "therefore color_offset is not allowed",
1172 case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:
1173 PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in "
1174 "section \"%s\": encap = ethernet_mpls, therefore "
1175 "qinq_sched = yes/test is not allowed",
1180 PIPELINE_ARG_CHECK((!(p->n_arp_entries &&
1181 (!arp_key_offset_present))), "Parse error in section "
1182 "\"%s\": n_arp_entries is set while "
1183 "arp_key_offset is not set", params->name);
1185 PIPELINE_ARG_CHECK((!((p->n_arp_entries == 0) &&
1186 arp_key_offset_present)), "Parse error in section "
1187 "\"%s\": arp_key_offset present while "
1188 "n_arp_entries is not set", params->name);
1194 pipeline_routing_init(struct pipeline_params *params,
1195 __rte_unused void *arg)
1198 struct pipeline_routing *p_rt;
1201 /* Check input arguments */
1202 if ((params == NULL) ||
1203 (params->n_ports_in == 0) ||
1204 (params->n_ports_out == 0))
1207 /* Memory allocation */
1208 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
1209 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1210 p_rt = (struct pipeline_routing *) p;
1214 strcpy(p->name, params->name);
1215 p->log_level = params->log_level;
1217 PLOG(p, HIGH, "Routing");
1219 /* Parse arguments */
1220 if (pipeline_routing_parse_args(&p_rt->params, params))
1225 struct rte_pipeline_params pipeline_params = {
1226 .name = params->name,
1227 .socket_id = params->socket_id,
1228 .offset_port_id = 0,
1231 p->p = rte_pipeline_create(&pipeline_params);
1239 p->n_ports_in = params->n_ports_in;
1240 for (i = 0; i < p->n_ports_in; i++) {
1241 struct rte_pipeline_port_in_params port_params = {
1242 .ops = pipeline_port_in_params_get_ops(
1243 ¶ms->port_in[i]),
1244 .arg_create = pipeline_port_in_params_convert(
1245 ¶ms->port_in[i]),
1248 .burst_size = params->port_in[i].burst_size,
1251 int status = rte_pipeline_port_in_create(p->p,
1256 rte_pipeline_free(p->p);
1263 p->n_ports_out = params->n_ports_out;
1264 for (i = 0; i < p->n_ports_out; i++) {
1265 struct rte_pipeline_port_out_params port_params = {
1266 .ops = pipeline_port_out_params_get_ops(
1267 ¶ms->port_out[i]),
1268 .arg_create = pipeline_port_out_params_convert(
1269 ¶ms->port_out[i]),
1274 int status = rte_pipeline_port_out_create(p->p,
1276 &p->port_out_id[i]);
1279 rte_pipeline_free(p->p);
1288 struct rte_table_lpm_params table_lpm_params = {
1290 .n_rules = p_rt->params.n_routes,
1291 .number_tbl8s = PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s,
1293 .entry_unique_size = sizeof(struct routing_table_entry),
1294 .offset = p_rt->params.ip_hdr_offset +
1295 __builtin_offsetof(struct ipv4_hdr, dst_addr),
1298 struct rte_pipeline_table_params table_params = {
1299 .ops = &rte_table_lpm_ops,
1300 .arg_create = &table_lpm_params,
1301 .f_action_hit = get_routing_table_ah_hit(p_rt),
1302 .f_action_miss = NULL,
1305 sizeof(struct routing_table_entry) -
1306 sizeof(struct rte_pipeline_table_entry),
1311 status = rte_pipeline_table_create(p->p,
1316 rte_pipeline_free(p->p);
1322 /* ARP table configuration */
1323 if (p_rt->params.n_arp_entries) {
1324 struct rte_table_hash_key8_ext_params table_arp_params = {
1325 .n_entries = p_rt->params.n_arp_entries,
1326 .n_entries_ext = p_rt->params.n_arp_entries,
1327 .f_hash = hash_default_key8,
1329 .signature_offset = 0, /* Unused */
1330 .key_offset = p_rt->params.arp_key_offset,
1333 struct rte_pipeline_table_params table_params = {
1334 .ops = &rte_table_hash_key8_ext_dosig_ops,
1335 .arg_create = &table_arp_params,
1336 .f_action_hit = get_arp_table_ah_hit(p_rt),
1337 .f_action_miss = NULL,
1339 .action_data_size = sizeof(struct arp_table_entry) -
1340 sizeof(struct rte_pipeline_table_entry),
1345 status = rte_pipeline_table_create(p->p,
1350 rte_pipeline_free(p->p);
1358 /* Connecting input ports to tables */
1359 for (i = 0; i < p->n_ports_in; i++) {
1360 int status = rte_pipeline_port_in_connect_to_table(p->p,
1365 rte_pipeline_free(p->p);
1371 /* Enable input ports */
1372 for (i = 0; i < p->n_ports_in; i++) {
1373 int status = rte_pipeline_port_in_enable(p->p,
1377 rte_pipeline_free(p->p);
1383 /* Check pipeline consistency */
1384 if (rte_pipeline_check(p->p) < 0) {
1385 rte_pipeline_free(p->p);
1390 /* Message queues */
1391 p->n_msgq = params->n_msgq;
1392 for (i = 0; i < p->n_msgq; i++)
1393 p->msgq_in[i] = params->msgq_in[i];
1394 for (i = 0; i < p->n_msgq; i++)
1395 p->msgq_out[i] = params->msgq_out[i];
1397 /* Message handlers */
1398 memcpy(p->handlers, handlers, sizeof(p->handlers));
1399 memcpy(p_rt->custom_handlers,
1401 sizeof(p_rt->custom_handlers));
1407 pipeline_routing_free(void *pipeline)
1409 struct pipeline *p = (struct pipeline *) pipeline;
1411 /* Check input arguments */
1415 /* Free resources */
1416 rte_pipeline_free(p->p);
1422 pipeline_routing_timer(void *pipeline)
1424 struct pipeline *p = (struct pipeline *) pipeline;
1426 pipeline_msg_req_handle(p);
1427 rte_pipeline_flush(p->p);
1433 pipeline_routing_msg_req_custom_handler(struct pipeline *p,
1436 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1437 struct pipeline_custom_msg_req *req = msg;
1438 pipeline_msg_req_handler f_handle;
1440 f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ?
1441 p_rt->custom_handlers[req->subtype] :
1442 pipeline_msg_req_invalid_handler;
1444 if (f_handle == NULL)
1445 f_handle = pipeline_msg_req_invalid_handler;
1447 return f_handle(p, req);
1451 pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
1453 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1454 struct pipeline_routing_route_add_msg_req *req = msg;
1455 struct pipeline_routing_route_add_msg_rsp *rsp = msg;
1457 struct rte_table_lpm_key key = {
1458 .ip = req->key.key.ipv4.ip,
1459 .depth = req->key.key.ipv4.depth,
1462 struct routing_table_entry entry_arp0 = {
1464 .action = RTE_PIPELINE_ACTION_PORT,
1465 {.port_id = p->port_out_id[req->data.port_id]},
1468 .flags = req->data.flags,
1469 .port_id = req->data.port_id,
1472 .ether_l2_length = 0,
1477 struct routing_table_entry entry_arp1 = {
1479 .action = RTE_PIPELINE_ACTION_TABLE,
1480 {.table_id = p->table_id[1]},
1483 .flags = req->data.flags,
1484 .port_id = req->data.port_id,
1485 .ip = rte_bswap32(req->data.ethernet.ip),
1487 .ether_l2_length = 0,
1492 struct rte_pipeline_table_entry *entry = (p_rt->params.n_arp_entries) ?
1493 (struct rte_pipeline_table_entry *) &entry_arp1 :
1494 (struct rte_pipeline_table_entry *) &entry_arp0;
1496 if ((req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) ||
1497 ((p_rt->params.n_arp_entries == 0) &&
1498 (req->data.flags & PIPELINE_ROUTING_ROUTE_ARP)) ||
1499 (p_rt->params.n_arp_entries &&
1500 ((req->data.flags & PIPELINE_ROUTING_ROUTE_ARP) == 0)) ||
1501 ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1502 (req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)) ||
1503 ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1504 ((req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ) == 0)) ||
1505 ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1506 (req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS)) ||
1507 ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1508 ((req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) == 0))) {
1513 /* Ether - ARP off */
1514 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
1515 (p_rt->params.n_arp_entries == 0)) {
1516 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1517 uint64_t macaddr_dst;
1518 uint64_t ethertype = ETHER_TYPE_IPv4;
1520 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1521 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1523 entry_arp0.slab[0] =
1524 rte_bswap64((macaddr_src << 16) | ethertype);
1525 entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1527 entry_arp0.slab[1] = rte_bswap64(macaddr_dst);
1528 entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1530 entry_arp0.data_offset = entry_arp0.slab_offset[1] + 2
1531 - sizeof(struct rte_mbuf);
1532 entry_arp0.ether_l2_length = 14;
1535 /* Ether - ARP on */
1536 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
1537 p_rt->params.n_arp_entries) {
1538 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1539 uint64_t ethertype = ETHER_TYPE_IPv4;
1541 entry_arp1.slab[0] = rte_bswap64((macaddr_src << 16) |
1543 entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1545 entry_arp1.data_offset = entry_arp1.slab_offset[0] - 6
1546 - sizeof(struct rte_mbuf);
1547 entry_arp1.ether_l2_length = 14;
1550 /* Ether QinQ - ARP off */
1551 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1552 (p_rt->params.n_arp_entries == 0)) {
1553 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1554 uint64_t macaddr_dst;
1555 uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
1556 uint64_t ethertype_vlan = 0x8100;
1557 uint64_t ethertype_qinq = 0x9100;
1558 uint64_t svlan = req->data.l2.qinq.svlan;
1559 uint64_t cvlan = req->data.l2.qinq.cvlan;
1561 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1562 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1564 entry_arp0.slab[0] = rte_bswap64((svlan << 48) |
1565 (ethertype_vlan << 32) |
1568 entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1570 entry_arp0.slab[1] = rte_bswap64((macaddr_src << 16) |
1572 entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1574 entry_arp0.slab[2] = rte_bswap64(macaddr_dst);
1575 entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset - 3 * 8;
1577 entry_arp0.data_offset = entry_arp0.slab_offset[2] + 2
1578 - sizeof(struct rte_mbuf);
1579 entry_arp0.ether_l2_length = 22;
1582 /* Ether QinQ - ARP on */
1583 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1584 p_rt->params.n_arp_entries) {
1585 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1586 uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
1587 uint64_t ethertype_vlan = 0x8100;
1588 uint64_t ethertype_qinq = 0x9100;
1589 uint64_t svlan = req->data.l2.qinq.svlan;
1590 uint64_t cvlan = req->data.l2.qinq.cvlan;
1592 entry_arp1.slab[0] = rte_bswap64((svlan << 48) |
1593 (ethertype_vlan << 32) |
1596 entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1598 entry_arp1.slab[1] = rte_bswap64((macaddr_src << 16) |
1600 entry_arp1.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1602 entry_arp1.data_offset = entry_arp1.slab_offset[1] - 6
1603 - sizeof(struct rte_mbuf);
1604 entry_arp1.ether_l2_length = 22;
1607 /* Ether MPLS - ARP off */
1608 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1609 (p_rt->params.n_arp_entries == 0)) {
1610 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1611 uint64_t macaddr_dst;
1612 uint64_t ethertype_mpls = 0x8847;
1614 uint64_t label0 = req->data.l2.mpls.labels[0];
1615 uint64_t label1 = req->data.l2.mpls.labels[1];
1616 uint64_t label2 = req->data.l2.mpls.labels[2];
1617 uint64_t label3 = req->data.l2.mpls.labels[3];
1618 uint32_t n_labels = req->data.l2.mpls.n_labels;
1620 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1621 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1625 entry_arp0.slab[0] = 0;
1626 entry_arp0.slab_offset[0] =
1627 p_rt->params.ip_hdr_offset - 8;
1629 entry_arp0.slab[1] = rte_bswap64(
1630 MPLS_LABEL(label0, 0, 1, 0));
1631 entry_arp0.slab_offset[1] =
1632 p_rt->params.ip_hdr_offset - 8;
1636 entry_arp0.slab[0] = 0;
1637 entry_arp0.slab_offset[0] =
1638 p_rt->params.ip_hdr_offset - 8;
1640 entry_arp0.slab[1] = rte_bswap64(
1641 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1642 MPLS_LABEL(label1, 0, 1, 0));
1643 entry_arp0.slab_offset[1] =
1644 p_rt->params.ip_hdr_offset - 8;
1648 entry_arp0.slab[0] = rte_bswap64(
1649 (MPLS_LABEL(label1, 0, 0, 0) << 32) |
1650 MPLS_LABEL(label2, 0, 1, 0));
1651 entry_arp0.slab_offset[0] =
1652 p_rt->params.ip_hdr_offset - 8;
1654 entry_arp0.slab[1] = rte_bswap64(
1655 MPLS_LABEL(label0, 0, 0, 0));
1656 entry_arp0.slab_offset[1] =
1657 p_rt->params.ip_hdr_offset - 2 * 8;
1661 entry_arp0.slab[0] = rte_bswap64(
1662 (MPLS_LABEL(label2, 0, 0, 0) << 32) |
1663 MPLS_LABEL(label3, 0, 1, 0));
1664 entry_arp0.slab_offset[0] =
1665 p_rt->params.ip_hdr_offset - 8;
1667 entry_arp0.slab[1] = rte_bswap64(
1668 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1669 MPLS_LABEL(label1, 0, 0, 0));
1670 entry_arp0.slab_offset[1] =
1671 p_rt->params.ip_hdr_offset - 2 * 8;
1679 entry_arp0.slab[2] = rte_bswap64((macaddr_src << 16) |
1681 entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset -
1684 entry_arp0.slab[3] = rte_bswap64(macaddr_dst);
1685 entry_arp0.slab_offset[3] = p_rt->params.ip_hdr_offset -
1686 (n_labels * 4 + 2 * 8);
1688 entry_arp0.data_offset = entry_arp0.slab_offset[3] + 2
1689 - sizeof(struct rte_mbuf);
1690 entry_arp0.ether_l2_length = n_labels * 4 + 14;
1693 /* Ether MPLS - ARP on */
1694 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1695 p_rt->params.n_arp_entries) {
1696 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1697 uint64_t ethertype_mpls = 0x8847;
1699 uint64_t label0 = req->data.l2.mpls.labels[0];
1700 uint64_t label1 = req->data.l2.mpls.labels[1];
1701 uint64_t label2 = req->data.l2.mpls.labels[2];
1702 uint64_t label3 = req->data.l2.mpls.labels[3];
1703 uint32_t n_labels = req->data.l2.mpls.n_labels;
1707 entry_arp1.slab[0] = 0;
1708 entry_arp1.slab_offset[0] =
1709 p_rt->params.ip_hdr_offset - 8;
1711 entry_arp1.slab[1] = rte_bswap64(
1712 MPLS_LABEL(label0, 0, 1, 0));
1713 entry_arp1.slab_offset[1] =
1714 p_rt->params.ip_hdr_offset - 8;
1718 entry_arp1.slab[0] = 0;
1719 entry_arp1.slab_offset[0] =
1720 p_rt->params.ip_hdr_offset - 8;
1722 entry_arp1.slab[1] = rte_bswap64(
1723 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1724 MPLS_LABEL(label1, 0, 1, 0));
1725 entry_arp1.slab_offset[1] =
1726 p_rt->params.ip_hdr_offset - 8;
1730 entry_arp1.slab[0] = rte_bswap64(
1731 (MPLS_LABEL(label1, 0, 0, 0) << 32) |
1732 MPLS_LABEL(label2, 0, 1, 0));
1733 entry_arp1.slab_offset[0] =
1734 p_rt->params.ip_hdr_offset - 8;
1736 entry_arp1.slab[1] = rte_bswap64(
1737 MPLS_LABEL(label0, 0, 0, 0));
1738 entry_arp1.slab_offset[1] =
1739 p_rt->params.ip_hdr_offset - 2 * 8;
1743 entry_arp1.slab[0] = rte_bswap64(
1744 (MPLS_LABEL(label2, 0, 0, 0) << 32) |
1745 MPLS_LABEL(label3, 0, 1, 0));
1746 entry_arp1.slab_offset[0] =
1747 p_rt->params.ip_hdr_offset - 8;
1749 entry_arp1.slab[1] = rte_bswap64(
1750 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1751 MPLS_LABEL(label1, 0, 0, 0));
1752 entry_arp1.slab_offset[1] =
1753 p_rt->params.ip_hdr_offset - 2 * 8;
1761 entry_arp1.slab[2] = rte_bswap64((macaddr_src << 16) |
1763 entry_arp1.slab_offset[2] = p_rt->params.ip_hdr_offset -
1766 entry_arp1.data_offset = entry_arp1.slab_offset[2] - 6
1767 - sizeof(struct rte_mbuf);
1768 entry_arp1.ether_l2_length = n_labels * 4 + 14;
1771 rsp->status = rte_pipeline_table_entry_add(p->p,
1776 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1782 pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg)
1784 struct pipeline_routing_route_delete_msg_req *req = msg;
1785 struct pipeline_routing_route_delete_msg_rsp *rsp = msg;
1787 struct rte_table_lpm_key key = {
1788 .ip = req->key.key.ipv4.ip,
1789 .depth = req->key.key.ipv4.depth,
1792 if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
1797 rsp->status = rte_pipeline_table_entry_delete(p->p,
1807 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
1810 struct pipeline_routing_route_add_default_msg_req *req = msg;
1811 struct pipeline_routing_route_add_default_msg_rsp *rsp = msg;
1813 struct routing_table_entry default_entry = {
1815 .action = RTE_PIPELINE_ACTION_PORT,
1816 {.port_id = p->port_out_id[req->port_id]},
1824 rsp->status = rte_pipeline_table_default_entry_add(p->p,
1826 (struct rte_pipeline_table_entry *) &default_entry,
1827 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1833 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
1836 struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg;
1838 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
1846 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg)
1848 struct pipeline_routing_arp_add_msg_req *req = msg;
1849 struct pipeline_routing_arp_add_msg_rsp *rsp = msg;
1851 struct pipeline_routing_arp_key_ipv4 key = {
1852 .port_id = req->key.key.ipv4.port_id,
1853 .ip = rte_bswap32(req->key.key.ipv4.ip),
1856 struct arp_table_entry entry = {
1858 .action = RTE_PIPELINE_ACTION_PORT,
1859 {.port_id = p->port_out_id[req->key.key.ipv4.port_id]},
1862 .macaddr = 0, /* set below */
1865 if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
1870 entry.macaddr = *((uint64_t *)&(req->macaddr));
1871 entry.macaddr = entry.macaddr << 16;
1873 rsp->status = rte_pipeline_table_entry_add(p->p,
1876 (struct rte_pipeline_table_entry *) &entry,
1878 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1884 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg)
1886 struct pipeline_routing_arp_delete_msg_req *req = msg;
1887 struct pipeline_routing_arp_delete_msg_rsp *rsp = msg;
1889 struct pipeline_routing_arp_key_ipv4 key = {
1890 .port_id = req->key.key.ipv4.port_id,
1891 .ip = rte_bswap32(req->key.key.ipv4.ip),
1894 if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
1899 rsp->status = rte_pipeline_table_entry_delete(p->p,
1909 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg)
1911 struct pipeline_routing_arp_add_default_msg_req *req = msg;
1912 struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg;
1914 struct arp_table_entry default_entry = {
1916 .action = RTE_PIPELINE_ACTION_PORT,
1917 {.port_id = p->port_out_id[req->port_id]},
1923 rsp->status = rte_pipeline_table_default_entry_add(p->p,
1925 (struct rte_pipeline_table_entry *) &default_entry,
1926 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1932 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
1934 struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg;
1936 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
1943 struct pipeline_be_ops pipeline_routing_be_ops = {
1944 .f_init = pipeline_routing_init,
1945 .f_free = pipeline_routing_free,
1947 .f_timer = pipeline_routing_timer,