4 * Copyright(c) 2010-2015 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"
50 #include "hash_func.h"
52 #define MPLS_LABEL(label, exp, s, ttl) \
53 (((((uint64_t) (label)) & 0xFFFFFLLU) << 12) | \
54 ((((uint64_t) (exp)) & 0x7LLU) << 9) | \
55 ((((uint64_t) (s)) & 0x1LLU) << 8) | \
56 (((uint64_t) (ttl)) & 0xFFLU))
58 #define RTE_SCHED_PORT_HIERARCHY(subport, pipe, \
59 traffic_class, queue, color) \
60 ((((uint64_t) (queue)) & 0x3) | \
61 ((((uint64_t) (traffic_class)) & 0x3) << 2) | \
62 ((((uint64_t) (color)) & 0x3) << 4) | \
63 ((((uint64_t) (subport)) & 0xFFFF) << 16) | \
64 ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32))
67 #define MAC_SRC_DEFAULT 0x112233445566
69 struct pipeline_routing {
71 struct pipeline_routing_params params;
72 pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
73 } __rte_cache_aligned;
79 pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg);
81 static pipeline_msg_req_handler handlers[] = {
82 [PIPELINE_MSG_REQ_PING] =
83 pipeline_msg_req_ping_handler,
84 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
85 pipeline_msg_req_stats_port_in_handler,
86 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
87 pipeline_msg_req_stats_port_out_handler,
88 [PIPELINE_MSG_REQ_STATS_TABLE] =
89 pipeline_msg_req_stats_table_handler,
90 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
91 pipeline_msg_req_port_in_enable_handler,
92 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
93 pipeline_msg_req_port_in_disable_handler,
94 [PIPELINE_MSG_REQ_CUSTOM] =
95 pipeline_routing_msg_req_custom_handler,
99 pipeline_routing_msg_req_route_add_handler(struct pipeline *p,
103 pipeline_routing_msg_req_route_del_handler(struct pipeline *p,
107 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
111 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
115 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p,
119 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p,
123 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p,
127 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p,
130 static pipeline_msg_req_handler custom_handlers[] = {
131 [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] =
132 pipeline_routing_msg_req_route_add_handler,
133 [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL] =
134 pipeline_routing_msg_req_route_del_handler,
135 [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT] =
136 pipeline_routing_msg_req_route_add_default_handler,
137 [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT] =
138 pipeline_routing_msg_req_route_del_default_handler,
139 [PIPELINE_ROUTING_MSG_REQ_ARP_ADD] =
140 pipeline_routing_msg_req_arp_add_handler,
141 [PIPELINE_ROUTING_MSG_REQ_ARP_DEL] =
142 pipeline_routing_msg_req_arp_del_handler,
143 [PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT] =
144 pipeline_routing_msg_req_arp_add_default_handler,
145 [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] =
146 pipeline_routing_msg_req_arp_del_default_handler,
152 struct routing_table_entry {
153 struct rte_pipeline_table_entry head;
155 uint32_t port_id; /* Output port ID */
156 uint32_t ip; /* Next hop IP address (only valid for remote routes) */
159 uint16_t data_offset;
160 uint16_t ether_l2_length;
162 uint16_t slab_offset[4];
169 } __attribute__((__packed__));
171 #define MACADDR_DST_WRITE(slab_ptr, slab) \
173 struct layout *dst = (struct layout *) (slab_ptr); \
174 struct layout *src = (struct layout *) &(slab); \
180 static inline __attribute__((always_inline)) void
182 struct rte_mbuf *pkt,
183 struct rte_pipeline_table_entry *table_entry,
191 struct pipeline_routing *p_rt = arg;
193 struct routing_table_entry *entry =
194 (struct routing_table_entry *) table_entry;
196 struct ipv4_hdr *ip = (struct ipv4_hdr *)
197 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.ip_hdr_offset);
199 enum rte_meter_color pkt_color = (enum rte_meter_color)
200 RTE_MBUF_METADATA_UINT32(pkt, p_rt->params.color_offset);
202 struct pipeline_routing_arp_key_ipv4 *arp_key =
203 (struct pipeline_routing_arp_key_ipv4 *)
204 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.arp_key_offset);
206 uint64_t *slab0_ptr, *slab1_ptr, *slab2_ptr, *slab3_ptr, sched;
207 uint32_t ip_da, nh_ip, port_id;
208 uint16_t total_length, data_offset, ether_l2_length;
211 total_length = rte_bswap16(ip->total_length);
212 ip_da = ip->dst_addr;
213 data_offset = entry->data_offset;
214 ether_l2_length = entry->ether_l2_length;
215 slab0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[0]);
216 slab1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[1]);
217 slab2_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[2]);
218 slab3_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[3]);
221 port_id = entry->port_id;
223 if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
228 total_length += ether_l2_length;
230 if (qinq && qinq_sched) {
231 uint32_t dscp = ip->type_of_service >> 2;
232 uint32_t svlan, cvlan, tc, tc_q;
234 if (qinq_sched == 1) {
235 uint64_t slab_qinq = rte_bswap64(entry->slab[0]);
237 svlan = (slab_qinq >> 48) & 0xFFF;
238 cvlan = (slab_qinq >> 16) & 0xFFF;
239 tc = (dscp >> 2) & 0x3;
242 uint32_t ip_src = rte_bswap32(ip->src_addr);
245 cvlan = (ip_src >> 16) & 0xFFF;
246 tc = (ip_src >> 2) & 0x3;
249 sched = RTE_SCHED_PORT_HIERARCHY(svlan,
257 pkt->data_off = data_offset;
258 pkt->data_len = total_length;
259 pkt->pkt_len = total_length;
261 if ((qinq == 0) && (mpls == 0)) {
262 *slab0_ptr = entry->slab[0];
265 MACADDR_DST_WRITE(slab1_ptr, entry->slab[1]);
269 *slab0_ptr = entry->slab[0];
270 *slab1_ptr = entry->slab[1];
273 MACADDR_DST_WRITE(slab2_ptr, entry->slab[2]);
276 pkt->hash.sched.lo = sched & 0xFFFFFFFF;
277 pkt->hash.sched.hi = sched >> 32;
282 if (mpls_color_mark) {
283 uint64_t mpls_exp = rte_bswap64(
284 (MPLS_LABEL(0, pkt_color, 0, 0) << 32) |
285 MPLS_LABEL(0, pkt_color, 0, 0));
287 *slab0_ptr = entry->slab[0] | mpls_exp;
288 *slab1_ptr = entry->slab[1] | mpls_exp;
289 *slab2_ptr = entry->slab[2];
291 *slab0_ptr = entry->slab[0];
292 *slab1_ptr = entry->slab[1];
293 *slab2_ptr = entry->slab[2];
297 MACADDR_DST_WRITE(slab3_ptr, entry->slab[3]);
301 arp_key->port_id = port_id;
306 static inline __attribute__((always_inline)) void
308 struct rte_mbuf **pkts,
309 struct rte_pipeline_table_entry **table_entries,
317 struct pipeline_routing *p_rt = arg;
319 struct routing_table_entry *entry0 =
320 (struct routing_table_entry *) table_entries[0];
321 struct routing_table_entry *entry1 =
322 (struct routing_table_entry *) table_entries[1];
323 struct routing_table_entry *entry2 =
324 (struct routing_table_entry *) table_entries[2];
325 struct routing_table_entry *entry3 =
326 (struct routing_table_entry *) table_entries[3];
328 struct ipv4_hdr *ip0 = (struct ipv4_hdr *)
329 RTE_MBUF_METADATA_UINT8_PTR(pkts[0],
330 p_rt->params.ip_hdr_offset);
331 struct ipv4_hdr *ip1 = (struct ipv4_hdr *)
332 RTE_MBUF_METADATA_UINT8_PTR(pkts[1],
333 p_rt->params.ip_hdr_offset);
334 struct ipv4_hdr *ip2 = (struct ipv4_hdr *)
335 RTE_MBUF_METADATA_UINT8_PTR(pkts[2],
336 p_rt->params.ip_hdr_offset);
337 struct ipv4_hdr *ip3 = (struct ipv4_hdr *)
338 RTE_MBUF_METADATA_UINT8_PTR(pkts[3],
339 p_rt->params.ip_hdr_offset);
341 enum rte_meter_color pkt0_color = (enum rte_meter_color)
342 RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->params.color_offset);
343 enum rte_meter_color pkt1_color = (enum rte_meter_color)
344 RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->params.color_offset);
345 enum rte_meter_color pkt2_color = (enum rte_meter_color)
346 RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->params.color_offset);
347 enum rte_meter_color pkt3_color = (enum rte_meter_color)
348 RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->params.color_offset);
350 struct pipeline_routing_arp_key_ipv4 *arp_key0 =
351 (struct pipeline_routing_arp_key_ipv4 *)
352 RTE_MBUF_METADATA_UINT8_PTR(pkts[0],
353 p_rt->params.arp_key_offset);
354 struct pipeline_routing_arp_key_ipv4 *arp_key1 =
355 (struct pipeline_routing_arp_key_ipv4 *)
356 RTE_MBUF_METADATA_UINT8_PTR(pkts[1],
357 p_rt->params.arp_key_offset);
358 struct pipeline_routing_arp_key_ipv4 *arp_key2 =
359 (struct pipeline_routing_arp_key_ipv4 *)
360 RTE_MBUF_METADATA_UINT8_PTR(pkts[2],
361 p_rt->params.arp_key_offset);
362 struct pipeline_routing_arp_key_ipv4 *arp_key3 =
363 (struct pipeline_routing_arp_key_ipv4 *)
364 RTE_MBUF_METADATA_UINT8_PTR(pkts[3],
365 p_rt->params.arp_key_offset);
367 uint64_t *slab0_ptr0, *slab1_ptr0, *slab2_ptr0, *slab3_ptr0;
368 uint64_t *slab0_ptr1, *slab1_ptr1, *slab2_ptr1, *slab3_ptr1;
369 uint64_t *slab0_ptr2, *slab1_ptr2, *slab2_ptr2, *slab3_ptr2;
370 uint64_t *slab0_ptr3, *slab1_ptr3, *slab2_ptr3, *slab3_ptr3;
371 uint64_t sched0, sched1, sched2, sched3;
373 uint32_t ip_da0, nh_ip0, port_id0;
374 uint32_t ip_da1, nh_ip1, port_id1;
375 uint32_t ip_da2, nh_ip2, port_id2;
376 uint32_t ip_da3, nh_ip3, port_id3;
378 uint16_t total_length0, data_offset0, ether_l2_length0;
379 uint16_t total_length1, data_offset1, ether_l2_length1;
380 uint16_t total_length2, data_offset2, ether_l2_length2;
381 uint16_t total_length3, data_offset3, ether_l2_length3;
384 total_length0 = rte_bswap16(ip0->total_length);
385 total_length1 = rte_bswap16(ip1->total_length);
386 total_length2 = rte_bswap16(ip2->total_length);
387 total_length3 = rte_bswap16(ip3->total_length);
389 ip_da0 = ip0->dst_addr;
390 ip_da1 = ip1->dst_addr;
391 ip_da2 = ip2->dst_addr;
392 ip_da3 = ip3->dst_addr;
394 data_offset0 = entry0->data_offset;
395 data_offset1 = entry1->data_offset;
396 data_offset2 = entry2->data_offset;
397 data_offset3 = entry3->data_offset;
399 ether_l2_length0 = entry0->ether_l2_length;
400 ether_l2_length1 = entry1->ether_l2_length;
401 ether_l2_length2 = entry2->ether_l2_length;
402 ether_l2_length3 = entry3->ether_l2_length;
404 slab0_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
405 entry0->slab_offset[0]);
406 slab1_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
407 entry0->slab_offset[1]);
408 slab2_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
409 entry0->slab_offset[2]);
410 slab3_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
411 entry0->slab_offset[3]);
413 slab0_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
414 entry1->slab_offset[0]);
415 slab1_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
416 entry1->slab_offset[1]);
417 slab2_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
418 entry1->slab_offset[2]);
419 slab3_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
420 entry1->slab_offset[3]);
422 slab0_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
423 entry2->slab_offset[0]);
424 slab1_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
425 entry2->slab_offset[1]);
426 slab2_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
427 entry2->slab_offset[2]);
428 slab3_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
429 entry2->slab_offset[3]);
431 slab0_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
432 entry3->slab_offset[0]);
433 slab1_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
434 entry3->slab_offset[1]);
435 slab2_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
436 entry3->slab_offset[2]);
437 slab3_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
438 entry3->slab_offset[3]);
441 port_id0 = entry0->port_id;
443 if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
446 port_id1 = entry1->port_id;
448 if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
451 port_id2 = entry2->port_id;
453 if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
456 port_id3 = entry3->port_id;
458 if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
463 total_length0 += ether_l2_length0;
464 total_length1 += ether_l2_length1;
465 total_length2 += ether_l2_length2;
466 total_length3 += ether_l2_length3;
468 if (qinq && qinq_sched) {
469 uint32_t dscp0 = ip0->type_of_service >> 2;
470 uint32_t dscp1 = ip1->type_of_service >> 2;
471 uint32_t dscp2 = ip2->type_of_service >> 2;
472 uint32_t dscp3 = ip3->type_of_service >> 2;
473 uint32_t svlan0, cvlan0, tc0, tc_q0;
474 uint32_t svlan1, cvlan1, tc1, tc_q1;
475 uint32_t svlan2, cvlan2, tc2, tc_q2;
476 uint32_t svlan3, cvlan3, tc3, tc_q3;
478 if (qinq_sched == 1) {
479 uint64_t slab_qinq0 = rte_bswap64(entry0->slab[0]);
480 uint64_t slab_qinq1 = rte_bswap64(entry1->slab[0]);
481 uint64_t slab_qinq2 = rte_bswap64(entry2->slab[0]);
482 uint64_t slab_qinq3 = rte_bswap64(entry3->slab[0]);
484 svlan0 = (slab_qinq0 >> 48) & 0xFFF;
485 svlan1 = (slab_qinq1 >> 48) & 0xFFF;
486 svlan2 = (slab_qinq2 >> 48) & 0xFFF;
487 svlan3 = (slab_qinq3 >> 48) & 0xFFF;
489 cvlan0 = (slab_qinq0 >> 16) & 0xFFF;
490 cvlan1 = (slab_qinq1 >> 16) & 0xFFF;
491 cvlan2 = (slab_qinq2 >> 16) & 0xFFF;
492 cvlan3 = (slab_qinq3 >> 16) & 0xFFF;
494 tc0 = (dscp0 >> 2) & 0x3;
495 tc1 = (dscp1 >> 2) & 0x3;
496 tc2 = (dscp2 >> 2) & 0x3;
497 tc3 = (dscp3 >> 2) & 0x3;
504 uint32_t ip_src0 = rte_bswap32(ip0->src_addr);
505 uint32_t ip_src1 = rte_bswap32(ip1->src_addr);
506 uint32_t ip_src2 = rte_bswap32(ip2->src_addr);
507 uint32_t ip_src3 = rte_bswap32(ip3->src_addr);
514 cvlan0 = (ip_src0 >> 16) & 0xFFF;
515 cvlan1 = (ip_src1 >> 16) & 0xFFF;
516 cvlan2 = (ip_src2 >> 16) & 0xFFF;
517 cvlan3 = (ip_src3 >> 16) & 0xFFF;
519 tc0 = (ip_src0 >> 2) & 0x3;
520 tc1 = (ip_src1 >> 2) & 0x3;
521 tc2 = (ip_src2 >> 2) & 0x3;
522 tc3 = (ip_src3 >> 2) & 0x3;
524 tc_q0 = ip_src0 & 0x3;
525 tc_q1 = ip_src1 & 0x3;
526 tc_q2 = ip_src2 & 0x3;
527 tc_q3 = ip_src3 & 0x3;
530 sched0 = RTE_SCHED_PORT_HIERARCHY(svlan0,
535 sched1 = RTE_SCHED_PORT_HIERARCHY(svlan1,
540 sched2 = RTE_SCHED_PORT_HIERARCHY(svlan2,
545 sched3 = RTE_SCHED_PORT_HIERARCHY(svlan3,
554 pkts[0]->data_off = data_offset0;
555 pkts[1]->data_off = data_offset1;
556 pkts[2]->data_off = data_offset2;
557 pkts[3]->data_off = data_offset3;
559 pkts[0]->data_len = total_length0;
560 pkts[1]->data_len = total_length1;
561 pkts[2]->data_len = total_length2;
562 pkts[3]->data_len = total_length3;
564 pkts[0]->pkt_len = total_length0;
565 pkts[1]->pkt_len = total_length1;
566 pkts[2]->pkt_len = total_length2;
567 pkts[3]->pkt_len = total_length3;
569 if ((qinq == 0) && (mpls == 0)) {
570 *slab0_ptr0 = entry0->slab[0];
571 *slab0_ptr1 = entry1->slab[0];
572 *slab0_ptr2 = entry2->slab[0];
573 *slab0_ptr3 = entry3->slab[0];
576 MACADDR_DST_WRITE(slab1_ptr0, entry0->slab[1]);
577 MACADDR_DST_WRITE(slab1_ptr1, entry1->slab[1]);
578 MACADDR_DST_WRITE(slab1_ptr2, entry2->slab[1]);
579 MACADDR_DST_WRITE(slab1_ptr3, entry3->slab[1]);
584 *slab0_ptr0 = entry0->slab[0];
585 *slab0_ptr1 = entry1->slab[0];
586 *slab0_ptr2 = entry2->slab[0];
587 *slab0_ptr3 = entry3->slab[0];
589 *slab1_ptr0 = entry0->slab[1];
590 *slab1_ptr1 = entry1->slab[1];
591 *slab1_ptr2 = entry2->slab[1];
592 *slab1_ptr3 = entry3->slab[1];
595 MACADDR_DST_WRITE(slab2_ptr0, entry0->slab[2]);
596 MACADDR_DST_WRITE(slab2_ptr1, entry1->slab[2]);
597 MACADDR_DST_WRITE(slab2_ptr2, entry2->slab[2]);
598 MACADDR_DST_WRITE(slab2_ptr3, entry3->slab[2]);
602 pkts[0]->hash.sched.lo = sched0 & 0xFFFFFFFF;
603 pkts[0]->hash.sched.hi = sched0 >> 32;
604 pkts[1]->hash.sched.lo = sched1 & 0xFFFFFFFF;
605 pkts[1]->hash.sched.hi = sched1 >> 32;
606 pkts[2]->hash.sched.lo = sched2 & 0xFFFFFFFF;
607 pkts[2]->hash.sched.hi = sched2 >> 32;
608 pkts[3]->hash.sched.lo = sched3 & 0xFFFFFFFF;
609 pkts[3]->hash.sched.hi = sched3 >> 32;
614 if (mpls_color_mark) {
615 uint64_t mpls_exp0 = rte_bswap64(
616 (MPLS_LABEL(0, pkt0_color, 0, 0) << 32) |
617 MPLS_LABEL(0, pkt0_color, 0, 0));
618 uint64_t mpls_exp1 = rte_bswap64(
619 (MPLS_LABEL(0, pkt1_color, 0, 0) << 32) |
620 MPLS_LABEL(0, pkt1_color, 0, 0));
621 uint64_t mpls_exp2 = rte_bswap64(
622 (MPLS_LABEL(0, pkt2_color, 0, 0) << 32) |
623 MPLS_LABEL(0, pkt2_color, 0, 0));
624 uint64_t mpls_exp3 = rte_bswap64(
625 (MPLS_LABEL(0, pkt3_color, 0, 0) << 32) |
626 MPLS_LABEL(0, pkt3_color, 0, 0));
628 *slab0_ptr0 = entry0->slab[0] | mpls_exp0;
629 *slab0_ptr1 = entry1->slab[0] | mpls_exp1;
630 *slab0_ptr2 = entry2->slab[0] | mpls_exp2;
631 *slab0_ptr3 = entry3->slab[0] | mpls_exp3;
633 *slab1_ptr0 = entry0->slab[1] | mpls_exp0;
634 *slab1_ptr1 = entry1->slab[1] | mpls_exp1;
635 *slab1_ptr2 = entry2->slab[1] | mpls_exp2;
636 *slab1_ptr3 = entry3->slab[1] | mpls_exp3;
638 *slab2_ptr0 = entry0->slab[2];
639 *slab2_ptr1 = entry1->slab[2];
640 *slab2_ptr2 = entry2->slab[2];
641 *slab2_ptr3 = entry3->slab[2];
643 *slab0_ptr0 = entry0->slab[0];
644 *slab0_ptr1 = entry1->slab[0];
645 *slab0_ptr2 = entry2->slab[0];
646 *slab0_ptr3 = entry3->slab[0];
648 *slab1_ptr0 = entry0->slab[1];
649 *slab1_ptr1 = entry1->slab[1];
650 *slab1_ptr2 = entry2->slab[1];
651 *slab1_ptr3 = entry3->slab[1];
653 *slab2_ptr0 = entry0->slab[2];
654 *slab2_ptr1 = entry1->slab[2];
655 *slab2_ptr2 = entry2->slab[2];
656 *slab2_ptr3 = entry3->slab[2];
660 MACADDR_DST_WRITE(slab3_ptr0, entry0->slab[3]);
661 MACADDR_DST_WRITE(slab3_ptr1, entry1->slab[3]);
662 MACADDR_DST_WRITE(slab3_ptr2, entry2->slab[3]);
663 MACADDR_DST_WRITE(slab3_ptr3, entry3->slab[3]);
668 arp_key0->port_id = port_id0;
669 arp_key1->port_id = port_id1;
670 arp_key2->port_id = port_id2;
671 arp_key3->port_id = port_id3;
673 arp_key0->ip = nh_ip0;
674 arp_key1->ip = nh_ip1;
675 arp_key2->ip = nh_ip2;
676 arp_key3->ip = nh_ip3;
680 #define PKT_WORK_ROUTING_ETHERNET(arp) \
682 pkt_work_routing_ether_arp##arp( \
683 struct rte_mbuf *pkt, \
684 struct rte_pipeline_table_entry *table_entry, \
687 pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 0, 0);\
690 #define PKT4_WORK_ROUTING_ETHERNET(arp) \
692 pkt4_work_routing_ether_arp##arp( \
693 struct rte_mbuf **pkts, \
694 struct rte_pipeline_table_entry **table_entries, \
697 pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 0, 0);\
700 #define routing_table_ah_hit_ether(arp) \
701 PKT_WORK_ROUTING_ETHERNET(arp) \
702 PKT4_WORK_ROUTING_ETHERNET(arp) \
703 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_arp##arp, \
704 pkt_work_routing_ether_arp##arp, \
705 pkt4_work_routing_ether_arp##arp)
707 routing_table_ah_hit_ether(0)
708 routing_table_ah_hit_ether(1)
710 #define PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
712 pkt_work_routing_ether_qinq_sched##sched##_arp##arp( \
713 struct rte_mbuf *pkt, \
714 struct rte_pipeline_table_entry *table_entry, \
717 pkt_work_routing(pkt, table_entry, arg, arp, 1, sched, 0, 0);\
720 #define PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
722 pkt4_work_routing_ether_qinq_sched##sched##_arp##arp( \
723 struct rte_mbuf **pkts, \
724 struct rte_pipeline_table_entry **table_entries, \
727 pkt4_work_routing(pkts, table_entries, arg, arp, 1, sched, 0, 0);\
730 #define routing_table_ah_hit_ether_qinq(sched, arp) \
731 PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
732 PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
733 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_qinq_sched##sched##_arp##arp,\
734 pkt_work_routing_ether_qinq_sched##sched##_arp##arp, \
735 pkt4_work_routing_ether_qinq_sched##sched##_arp##arp)
737 routing_table_ah_hit_ether_qinq(0, 0)
738 routing_table_ah_hit_ether_qinq(1, 0)
739 routing_table_ah_hit_ether_qinq(2, 0)
740 routing_table_ah_hit_ether_qinq(0, 1)
741 routing_table_ah_hit_ether_qinq(1, 1)
742 routing_table_ah_hit_ether_qinq(2, 1)
744 #define PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
746 pkt_work_routing_ether_mpls_color##color##_arp##arp( \
747 struct rte_mbuf *pkt, \
748 struct rte_pipeline_table_entry *table_entry, \
751 pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 1, color);\
754 #define PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
756 pkt4_work_routing_ether_mpls_color##color##_arp##arp( \
757 struct rte_mbuf **pkts, \
758 struct rte_pipeline_table_entry **table_entries, \
761 pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 1, color);\
764 #define routing_table_ah_hit_ether_mpls(color, arp) \
765 PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
766 PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
767 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_mpls_color##color##_arp##arp,\
768 pkt_work_routing_ether_mpls_color##color##_arp##arp, \
769 pkt4_work_routing_ether_mpls_color##color##_arp##arp)
771 routing_table_ah_hit_ether_mpls(0, 0)
772 routing_table_ah_hit_ether_mpls(1, 0)
773 routing_table_ah_hit_ether_mpls(0, 1)
774 routing_table_ah_hit_ether_mpls(1, 1)
776 static rte_pipeline_table_action_handler_hit
777 get_routing_table_ah_hit(struct pipeline_routing *p)
779 if (p->params.dbg_ah_disable)
782 switch (p->params.encap) {
783 case PIPELINE_ROUTING_ENCAP_ETHERNET:
784 return (p->params.n_arp_entries) ?
785 routing_table_ah_hit_ether_arp1 :
786 routing_table_ah_hit_ether_arp0;
788 case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:
789 if (p->params.n_arp_entries)
790 switch (p->params.qinq_sched) {
792 return routing_table_ah_hit_ether_qinq_sched0_arp1;
794 return routing_table_ah_hit_ether_qinq_sched1_arp1;
796 return routing_table_ah_hit_ether_qinq_sched2_arp1;
801 switch (p->params.qinq_sched) {
803 return routing_table_ah_hit_ether_qinq_sched0_arp0;
805 return routing_table_ah_hit_ether_qinq_sched1_arp0;
807 return routing_table_ah_hit_ether_qinq_sched2_arp0;
812 case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:
813 if (p->params.n_arp_entries)
814 if (p->params.mpls_color_mark)
815 return routing_table_ah_hit_ether_mpls_color1_arp1;
817 return routing_table_ah_hit_ether_mpls_color0_arp1;
819 if (p->params.mpls_color_mark)
820 return routing_table_ah_hit_ether_mpls_color1_arp0;
822 return routing_table_ah_hit_ether_mpls_color0_arp0;
832 struct arp_table_entry {
833 struct rte_pipeline_table_entry head;
842 struct rte_mbuf *pkt,
843 struct rte_pipeline_table_entry *table_entry,
844 __rte_unused void *arg)
846 struct arp_table_entry *entry = (struct arp_table_entry *) table_entry;
849 uint64_t macaddr_dst = entry->macaddr;
850 uint64_t *slab_ptr = (uint64_t *) ((char *) pkt->buf_addr +
851 (pkt->data_off - 2));
856 MACADDR_DST_WRITE(slab_ptr, macaddr_dst);
861 struct rte_mbuf **pkts,
862 struct rte_pipeline_table_entry **table_entries,
863 __rte_unused void *arg)
865 struct arp_table_entry *entry0 =
866 (struct arp_table_entry *) table_entries[0];
867 struct arp_table_entry *entry1 =
868 (struct arp_table_entry *) table_entries[1];
869 struct arp_table_entry *entry2 =
870 (struct arp_table_entry *) table_entries[2];
871 struct arp_table_entry *entry3 =
872 (struct arp_table_entry *) table_entries[3];
875 uint64_t macaddr_dst0 = entry0->macaddr;
876 uint64_t macaddr_dst1 = entry1->macaddr;
877 uint64_t macaddr_dst2 = entry2->macaddr;
878 uint64_t macaddr_dst3 = entry3->macaddr;
880 uint64_t *slab_ptr0 = (uint64_t *) ((char *) pkts[0]->buf_addr +
881 (pkts[0]->data_off - 2));
882 uint64_t *slab_ptr1 = (uint64_t *) ((char *) pkts[1]->buf_addr +
883 (pkts[1]->data_off - 2));
884 uint64_t *slab_ptr2 = (uint64_t *) ((char *) pkts[2]->buf_addr +
885 (pkts[2]->data_off - 2));
886 uint64_t *slab_ptr3 = (uint64_t *) ((char *) pkts[3]->buf_addr +
887 (pkts[3]->data_off - 2));
892 MACADDR_DST_WRITE(slab_ptr0, macaddr_dst0);
893 MACADDR_DST_WRITE(slab_ptr1, macaddr_dst1);
894 MACADDR_DST_WRITE(slab_ptr2, macaddr_dst2);
895 MACADDR_DST_WRITE(slab_ptr3, macaddr_dst3);
898 PIPELINE_TABLE_AH_HIT(arp_table_ah_hit,
902 static rte_pipeline_table_action_handler_hit
903 get_arp_table_ah_hit(struct pipeline_routing *p)
905 if (p->params.dbg_ah_disable)
908 return arp_table_ah_hit;
915 pipeline_routing_parse_args(struct pipeline_routing_params *p,
916 struct pipeline_params *params)
918 uint32_t n_routes_present = 0;
919 uint32_t encap_present = 0;
920 uint32_t qinq_sched_present = 0;
921 uint32_t mpls_color_mark_present = 0;
922 uint32_t n_arp_entries_present = 0;
923 uint32_t ip_hdr_offset_present = 0;
924 uint32_t arp_key_offset_present = 0;
925 uint32_t color_offset_present = 0;
926 uint32_t dbg_ah_disable_present = 0;
930 p->n_routes = PIPELINE_ROUTING_N_ROUTES_DEFAULT;
931 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
933 p->mpls_color_mark = 0;
934 p->n_arp_entries = 0;
935 p->dbg_ah_disable = 0;
937 for (i = 0; i < params->n_args; i++) {
938 char *arg_name = params->args_name[i];
939 char *arg_value = params->args_value[i];
942 if (strcmp(arg_name, "n_routes") == 0) {
943 if (n_routes_present)
945 n_routes_present = 1;
947 p->n_routes = atoi(arg_value);
948 if (p->n_routes == 0)
955 if (strcmp(arg_name, "encap") == 0) {
961 if (strcmp(arg_value, "ethernet") == 0) {
962 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
967 if (strcmp(arg_value, "ethernet_qinq") == 0) {
968 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ;
973 if (strcmp(arg_value, "ethernet_mpls") == 0) {
974 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS;
983 if (strcmp(arg_name, "qinq_sched") == 0) {
984 if (qinq_sched_present)
987 qinq_sched_present = 1;
989 if (strcmp(arg_value, "no") == 0)
991 else if (strcmp(arg_value, "yes") == 0)
993 else if (strcmp(arg_value, "test") == 0)
1001 /* mpls_color_mark */
1002 if (strcmp(arg_name, "mpls_color_mark") == 0) {
1003 if (mpls_color_mark_present)
1006 mpls_color_mark_present = 1;
1008 if (strcmp(arg_value, "no") == 0)
1009 p->mpls_color_mark = 0;
1010 else if (strcmp(arg_value, "yes") == 0)
1011 p->mpls_color_mark = 1;
1019 if (strcmp(arg_name, "n_arp_entries") == 0) {
1020 if (n_arp_entries_present)
1022 n_arp_entries_present = 1;
1024 p->n_arp_entries = atoi(arg_value);
1030 if (strcmp(arg_name, "ip_hdr_offset") == 0) {
1031 if (ip_hdr_offset_present)
1033 ip_hdr_offset_present = 1;
1035 p->ip_hdr_offset = atoi(arg_value);
1040 /* arp_key_offset */
1041 if (strcmp(arg_name, "arp_key_offset") == 0) {
1042 if (arp_key_offset_present)
1044 arp_key_offset_present = 1;
1046 p->arp_key_offset = atoi(arg_value);
1052 if (strcmp(arg_name, "color_offset") == 0) {
1053 if (color_offset_present)
1055 color_offset_present = 1;
1057 p->color_offset = atoi(arg_value);
1063 if (strcmp(arg_name, "dbg_ah_disable") == 0) {
1064 if (dbg_ah_disable_present)
1066 dbg_ah_disable_present = 1;
1068 if (strcmp(arg_value, "no") == 0)
1069 p->dbg_ah_disable = 0;
1070 else if (strcmp(arg_value, "yes") == 0)
1071 p->dbg_ah_disable = 1;
1082 /* Check that mandatory arguments are present */
1083 if (ip_hdr_offset_present == 0)
1086 /* Check relations between arguments */
1088 case PIPELINE_ROUTING_ENCAP_ETHERNET:
1089 if (p->qinq_sched ||
1090 p->mpls_color_mark ||
1091 color_offset_present)
1095 case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:
1096 if (p->mpls_color_mark ||
1097 color_offset_present)
1101 case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:
1110 if ((p->n_arp_entries && (arp_key_offset_present == 0)) ||
1111 ((p->n_arp_entries == 0) && arp_key_offset_present))
1118 pipeline_routing_init(struct pipeline_params *params,
1119 __rte_unused void *arg)
1122 struct pipeline_routing *p_rt;
1125 /* Check input arguments */
1126 if ((params == NULL) ||
1127 (params->n_ports_in == 0) ||
1128 (params->n_ports_out == 0))
1131 /* Memory allocation */
1132 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
1133 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1134 p_rt = (struct pipeline_routing *) p;
1138 strcpy(p->name, params->name);
1139 p->log_level = params->log_level;
1141 PLOG(p, HIGH, "Routing");
1143 /* Parse arguments */
1144 if (pipeline_routing_parse_args(&p_rt->params, params))
1149 struct rte_pipeline_params pipeline_params = {
1150 .name = params->name,
1151 .socket_id = params->socket_id,
1152 .offset_port_id = 0,
1155 p->p = rte_pipeline_create(&pipeline_params);
1163 p->n_ports_in = params->n_ports_in;
1164 for (i = 0; i < p->n_ports_in; i++) {
1165 struct rte_pipeline_port_in_params port_params = {
1166 .ops = pipeline_port_in_params_get_ops(
1167 ¶ms->port_in[i]),
1168 .arg_create = pipeline_port_in_params_convert(
1169 ¶ms->port_in[i]),
1172 .burst_size = params->port_in[i].burst_size,
1175 int status = rte_pipeline_port_in_create(p->p,
1180 rte_pipeline_free(p->p);
1187 p->n_ports_out = params->n_ports_out;
1188 for (i = 0; i < p->n_ports_out; i++) {
1189 struct rte_pipeline_port_out_params port_params = {
1190 .ops = pipeline_port_out_params_get_ops(
1191 ¶ms->port_out[i]),
1192 .arg_create = pipeline_port_out_params_convert(
1193 ¶ms->port_out[i]),
1195 .f_action_bulk = NULL,
1199 int status = rte_pipeline_port_out_create(p->p,
1201 &p->port_out_id[i]);
1204 rte_pipeline_free(p->p);
1213 struct rte_table_lpm_params table_lpm_params = {
1215 .n_rules = p_rt->params.n_routes,
1216 .entry_unique_size = sizeof(struct routing_table_entry),
1217 .offset = p_rt->params.ip_hdr_offset +
1218 __builtin_offsetof(struct ipv4_hdr, dst_addr),
1221 struct rte_pipeline_table_params table_params = {
1222 .ops = &rte_table_lpm_ops,
1223 .arg_create = &table_lpm_params,
1224 .f_action_hit = get_routing_table_ah_hit(p_rt),
1225 .f_action_miss = NULL,
1228 sizeof(struct routing_table_entry) -
1229 sizeof(struct rte_pipeline_table_entry),
1234 status = rte_pipeline_table_create(p->p,
1239 rte_pipeline_free(p->p);
1245 /* ARP table configuration */
1246 if (p_rt->params.n_arp_entries) {
1247 struct rte_table_hash_key8_ext_params table_arp_params = {
1248 .n_entries = p_rt->params.n_arp_entries,
1249 .n_entries_ext = p_rt->params.n_arp_entries,
1250 .f_hash = hash_default_key8,
1252 .signature_offset = 0, /* Unused */
1253 .key_offset = p_rt->params.arp_key_offset,
1256 struct rte_pipeline_table_params table_params = {
1257 .ops = &rte_table_hash_key8_ext_dosig_ops,
1258 .arg_create = &table_arp_params,
1259 .f_action_hit = get_arp_table_ah_hit(p_rt),
1260 .f_action_miss = NULL,
1262 .action_data_size = sizeof(struct arp_table_entry) -
1263 sizeof(struct rte_pipeline_table_entry),
1268 status = rte_pipeline_table_create(p->p,
1273 rte_pipeline_free(p->p);
1281 /* Connecting input ports to tables */
1282 for (i = 0; i < p->n_ports_in; i++) {
1283 int status = rte_pipeline_port_in_connect_to_table(p->p,
1288 rte_pipeline_free(p->p);
1294 /* Enable input ports */
1295 for (i = 0; i < p->n_ports_in; i++) {
1296 int status = rte_pipeline_port_in_enable(p->p,
1300 rte_pipeline_free(p->p);
1306 /* Check pipeline consistency */
1307 if (rte_pipeline_check(p->p) < 0) {
1308 rte_pipeline_free(p->p);
1313 /* Message queues */
1314 p->n_msgq = params->n_msgq;
1315 for (i = 0; i < p->n_msgq; i++)
1316 p->msgq_in[i] = params->msgq_in[i];
1317 for (i = 0; i < p->n_msgq; i++)
1318 p->msgq_out[i] = params->msgq_out[i];
1320 /* Message handlers */
1321 memcpy(p->handlers, handlers, sizeof(p->handlers));
1322 memcpy(p_rt->custom_handlers,
1324 sizeof(p_rt->custom_handlers));
1330 pipeline_routing_free(void *pipeline)
1332 struct pipeline *p = (struct pipeline *) pipeline;
1334 /* Check input arguments */
1338 /* Free resources */
1339 rte_pipeline_free(p->p);
1345 pipeline_routing_track(void *pipeline,
1346 __rte_unused uint32_t port_in,
1349 struct pipeline *p = (struct pipeline *) pipeline;
1351 /* Check input arguments */
1353 (port_in >= p->n_ports_in) ||
1357 if (p->n_ports_in == 1) {
1366 pipeline_routing_timer(void *pipeline)
1368 struct pipeline *p = (struct pipeline *) pipeline;
1370 pipeline_msg_req_handle(p);
1371 rte_pipeline_flush(p->p);
1377 pipeline_routing_msg_req_custom_handler(struct pipeline *p,
1380 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1381 struct pipeline_custom_msg_req *req = msg;
1382 pipeline_msg_req_handler f_handle;
1384 f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ?
1385 p_rt->custom_handlers[req->subtype] :
1386 pipeline_msg_req_invalid_handler;
1388 if (f_handle == NULL)
1389 f_handle = pipeline_msg_req_invalid_handler;
1391 return f_handle(p, req);
1395 pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
1397 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1398 struct pipeline_routing_route_add_msg_req *req = msg;
1399 struct pipeline_routing_route_add_msg_rsp *rsp = msg;
1401 struct rte_table_lpm_key key = {
1402 .ip = req->key.key.ipv4.ip,
1403 .depth = req->key.key.ipv4.depth,
1406 struct routing_table_entry entry_arp0 = {
1408 .action = RTE_PIPELINE_ACTION_PORT,
1409 {.port_id = p->port_out_id[req->data.port_id]},
1412 .flags = req->data.flags,
1413 .port_id = req->data.port_id,
1416 .ether_l2_length = 0,
1421 struct routing_table_entry entry_arp1 = {
1423 .action = RTE_PIPELINE_ACTION_TABLE,
1424 {.table_id = p->table_id[1]},
1427 .flags = req->data.flags,
1428 .port_id = req->data.port_id,
1429 .ip = rte_bswap32(req->data.ethernet.ip),
1431 .ether_l2_length = 0,
1436 struct rte_pipeline_table_entry *entry = (p_rt->params.n_arp_entries) ?
1437 (struct rte_pipeline_table_entry *) &entry_arp1 :
1438 (struct rte_pipeline_table_entry *) &entry_arp0;
1440 if ((req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) ||
1441 ((p_rt->params.n_arp_entries == 0) &&
1442 (req->data.flags & PIPELINE_ROUTING_ROUTE_ARP)) ||
1443 (p_rt->params.n_arp_entries &&
1444 ((req->data.flags & PIPELINE_ROUTING_ROUTE_ARP) == 0)) ||
1445 ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1446 (req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)) ||
1447 ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1448 ((req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ) == 0)) ||
1449 ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1450 (req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS)) ||
1451 ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1452 ((req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) == 0))) {
1457 /* Ether - ARP off */
1458 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
1459 (p_rt->params.n_arp_entries == 0)) {
1460 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1461 uint64_t macaddr_dst;
1462 uint64_t ethertype = ETHER_TYPE_IPv4;
1464 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1465 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1467 entry_arp0.slab[0] =
1468 rte_bswap64((macaddr_src << 16) | ethertype);
1469 entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1471 entry_arp0.slab[1] = rte_bswap64(macaddr_dst);
1472 entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1474 entry_arp0.data_offset = entry_arp0.slab_offset[1] + 2
1475 - sizeof(struct rte_mbuf);
1476 entry_arp0.ether_l2_length = 14;
1479 /* Ether - ARP on */
1480 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
1481 p_rt->params.n_arp_entries) {
1482 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1483 uint64_t ethertype = ETHER_TYPE_IPv4;
1485 entry_arp1.slab[0] = rte_bswap64((macaddr_src << 16) |
1487 entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1489 entry_arp1.data_offset = entry_arp1.slab_offset[0] - 6
1490 - sizeof(struct rte_mbuf);
1491 entry_arp1.ether_l2_length = 14;
1494 /* Ether QinQ - ARP off */
1495 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1496 (p_rt->params.n_arp_entries == 0)) {
1497 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1498 uint64_t macaddr_dst;
1499 uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
1500 uint64_t ethertype_vlan = 0x8100;
1501 uint64_t ethertype_qinq = 0x9100;
1502 uint64_t svlan = req->data.l2.qinq.svlan;
1503 uint64_t cvlan = req->data.l2.qinq.cvlan;
1505 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1506 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1508 entry_arp0.slab[0] = rte_bswap64((svlan << 48) |
1509 (ethertype_vlan << 32) |
1512 entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1514 entry_arp0.slab[1] = rte_bswap64((macaddr_src << 16) |
1516 entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1518 entry_arp0.slab[2] = rte_bswap64(macaddr_dst);
1519 entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset - 3 * 8;
1521 entry_arp0.data_offset = entry_arp0.slab_offset[2] + 2
1522 - sizeof(struct rte_mbuf);
1523 entry_arp0.ether_l2_length = 22;
1526 /* Ether QinQ - ARP on */
1527 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1528 p_rt->params.n_arp_entries) {
1529 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1530 uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
1531 uint64_t ethertype_vlan = 0x8100;
1532 uint64_t ethertype_qinq = 0x9100;
1533 uint64_t svlan = req->data.l2.qinq.svlan;
1534 uint64_t cvlan = req->data.l2.qinq.cvlan;
1536 entry_arp1.slab[0] = rte_bswap64((svlan << 48) |
1537 (ethertype_vlan << 32) |
1540 entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1542 entry_arp1.slab[1] = rte_bswap64((macaddr_src << 16) |
1544 entry_arp1.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1546 entry_arp1.data_offset = entry_arp1.slab_offset[1] - 6
1547 - sizeof(struct rte_mbuf);
1548 entry_arp1.ether_l2_length = 22;
1551 /* Ether MPLS - ARP off */
1552 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1553 (p_rt->params.n_arp_entries == 0)) {
1554 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1555 uint64_t macaddr_dst;
1556 uint64_t ethertype_mpls = 0x8847;
1558 uint64_t label0 = req->data.l2.mpls.labels[0];
1559 uint64_t label1 = req->data.l2.mpls.labels[1];
1560 uint64_t label2 = req->data.l2.mpls.labels[2];
1561 uint64_t label3 = req->data.l2.mpls.labels[3];
1562 uint32_t n_labels = req->data.l2.mpls.n_labels;
1564 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1565 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1569 entry_arp0.slab[0] = 0;
1570 entry_arp0.slab_offset[0] =
1571 p_rt->params.ip_hdr_offset - 8;
1573 entry_arp0.slab[1] = rte_bswap64(
1574 MPLS_LABEL(label0, 0, 1, 0));
1575 entry_arp0.slab_offset[1] =
1576 p_rt->params.ip_hdr_offset - 8;
1580 entry_arp0.slab[0] = 0;
1581 entry_arp0.slab_offset[0] =
1582 p_rt->params.ip_hdr_offset - 8;
1584 entry_arp0.slab[1] = rte_bswap64(
1585 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1586 MPLS_LABEL(label1, 0, 1, 0));
1587 entry_arp0.slab_offset[1] =
1588 p_rt->params.ip_hdr_offset - 8;
1592 entry_arp0.slab[0] = rte_bswap64(
1593 (MPLS_LABEL(label1, 0, 0, 0) << 32) |
1594 MPLS_LABEL(label2, 0, 1, 0));
1595 entry_arp0.slab_offset[0] =
1596 p_rt->params.ip_hdr_offset - 8;
1598 entry_arp0.slab[1] = rte_bswap64(
1599 MPLS_LABEL(label0, 0, 0, 0));
1600 entry_arp0.slab_offset[1] =
1601 p_rt->params.ip_hdr_offset - 2 * 8;
1605 entry_arp0.slab[0] = rte_bswap64(
1606 (MPLS_LABEL(label2, 0, 0, 0) << 32) |
1607 MPLS_LABEL(label3, 0, 1, 0));
1608 entry_arp0.slab_offset[0] =
1609 p_rt->params.ip_hdr_offset - 8;
1611 entry_arp0.slab[1] = rte_bswap64(
1612 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1613 MPLS_LABEL(label1, 0, 0, 0));
1614 entry_arp0.slab_offset[1] =
1615 p_rt->params.ip_hdr_offset - 2 * 8;
1623 entry_arp0.slab[2] = rte_bswap64((macaddr_src << 16) |
1625 entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset -
1628 entry_arp0.slab[3] = rte_bswap64(macaddr_dst);
1629 entry_arp0.slab_offset[3] = p_rt->params.ip_hdr_offset -
1630 (n_labels * 4 + 2 * 8);
1632 entry_arp0.data_offset = entry_arp0.slab_offset[3] + 2
1633 - sizeof(struct rte_mbuf);
1634 entry_arp0.ether_l2_length = n_labels * 4 + 14;
1637 /* Ether MPLS - ARP on */
1638 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1639 p_rt->params.n_arp_entries) {
1640 uint64_t macaddr_src = MAC_SRC_DEFAULT;
1641 uint64_t ethertype_mpls = 0x8847;
1643 uint64_t label0 = req->data.l2.mpls.labels[0];
1644 uint64_t label1 = req->data.l2.mpls.labels[1];
1645 uint64_t label2 = req->data.l2.mpls.labels[2];
1646 uint64_t label3 = req->data.l2.mpls.labels[3];
1647 uint32_t n_labels = req->data.l2.mpls.n_labels;
1651 entry_arp1.slab[0] = 0;
1652 entry_arp1.slab_offset[0] =
1653 p_rt->params.ip_hdr_offset - 8;
1655 entry_arp1.slab[1] = rte_bswap64(
1656 MPLS_LABEL(label0, 0, 1, 0));
1657 entry_arp1.slab_offset[1] =
1658 p_rt->params.ip_hdr_offset - 8;
1662 entry_arp1.slab[0] = 0;
1663 entry_arp1.slab_offset[0] =
1664 p_rt->params.ip_hdr_offset - 8;
1666 entry_arp1.slab[1] = rte_bswap64(
1667 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1668 MPLS_LABEL(label1, 0, 1, 0));
1669 entry_arp1.slab_offset[1] =
1670 p_rt->params.ip_hdr_offset - 8;
1674 entry_arp1.slab[0] = rte_bswap64(
1675 (MPLS_LABEL(label1, 0, 0, 0) << 32) |
1676 MPLS_LABEL(label2, 0, 1, 0));
1677 entry_arp1.slab_offset[0] =
1678 p_rt->params.ip_hdr_offset - 8;
1680 entry_arp1.slab[1] = rte_bswap64(
1681 MPLS_LABEL(label0, 0, 0, 0));
1682 entry_arp1.slab_offset[1] =
1683 p_rt->params.ip_hdr_offset - 2 * 8;
1687 entry_arp1.slab[0] = rte_bswap64(
1688 (MPLS_LABEL(label2, 0, 0, 0) << 32) |
1689 MPLS_LABEL(label3, 0, 1, 0));
1690 entry_arp1.slab_offset[0] =
1691 p_rt->params.ip_hdr_offset - 8;
1693 entry_arp1.slab[1] = rte_bswap64(
1694 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1695 MPLS_LABEL(label1, 0, 0, 0));
1696 entry_arp1.slab_offset[1] =
1697 p_rt->params.ip_hdr_offset - 2 * 8;
1705 entry_arp1.slab[2] = rte_bswap64((macaddr_src << 16) |
1707 entry_arp1.slab_offset[2] = p_rt->params.ip_hdr_offset -
1710 entry_arp1.data_offset = entry_arp1.slab_offset[2] - 6
1711 - sizeof(struct rte_mbuf);
1712 entry_arp1.ether_l2_length = n_labels * 4 + 14;
1715 rsp->status = rte_pipeline_table_entry_add(p->p,
1720 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1726 pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg)
1728 struct pipeline_routing_route_delete_msg_req *req = msg;
1729 struct pipeline_routing_route_delete_msg_rsp *rsp = msg;
1731 struct rte_table_lpm_key key = {
1732 .ip = req->key.key.ipv4.ip,
1733 .depth = req->key.key.ipv4.depth,
1736 if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
1741 rsp->status = rte_pipeline_table_entry_delete(p->p,
1751 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
1754 struct pipeline_routing_route_add_default_msg_req *req = msg;
1755 struct pipeline_routing_route_add_default_msg_rsp *rsp = msg;
1757 struct routing_table_entry default_entry = {
1759 .action = RTE_PIPELINE_ACTION_PORT,
1760 {.port_id = p->port_out_id[req->port_id]},
1768 rsp->status = rte_pipeline_table_default_entry_add(p->p,
1770 (struct rte_pipeline_table_entry *) &default_entry,
1771 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1777 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
1780 struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg;
1782 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
1790 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg)
1792 struct pipeline_routing_arp_add_msg_req *req = msg;
1793 struct pipeline_routing_arp_add_msg_rsp *rsp = msg;
1795 struct pipeline_routing_arp_key_ipv4 key = {
1796 .port_id = req->key.key.ipv4.port_id,
1797 .ip = rte_bswap32(req->key.key.ipv4.ip),
1800 struct arp_table_entry entry = {
1802 .action = RTE_PIPELINE_ACTION_PORT,
1803 {.port_id = p->port_out_id[req->key.key.ipv4.port_id]},
1806 .macaddr = 0, /* set below */
1809 if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
1814 entry.macaddr = *((uint64_t *)&(req->macaddr));
1815 entry.macaddr = entry.macaddr << 16;
1817 rsp->status = rte_pipeline_table_entry_add(p->p,
1820 (struct rte_pipeline_table_entry *) &entry,
1822 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1828 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg)
1830 struct pipeline_routing_arp_delete_msg_req *req = msg;
1831 struct pipeline_routing_arp_delete_msg_rsp *rsp = msg;
1833 struct pipeline_routing_arp_key_ipv4 key = {
1834 .port_id = req->key.key.ipv4.port_id,
1835 .ip = rte_bswap32(req->key.key.ipv4.ip),
1838 if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
1843 rsp->status = rte_pipeline_table_entry_delete(p->p,
1853 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg)
1855 struct pipeline_routing_arp_add_default_msg_req *req = msg;
1856 struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg;
1858 struct arp_table_entry default_entry = {
1860 .action = RTE_PIPELINE_ACTION_PORT,
1861 {.port_id = p->port_out_id[req->port_id]},
1867 rsp->status = rte_pipeline_table_default_entry_add(p->p,
1869 (struct rte_pipeline_table_entry *) &default_entry,
1870 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1876 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
1878 struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg;
1880 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
1887 struct pipeline_be_ops pipeline_routing_be_ops = {
1888 .f_init = pipeline_routing_init,
1889 .f_free = pipeline_routing_free,
1891 .f_timer = pipeline_routing_timer,
1892 .f_track = pipeline_routing_track,