1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
11 #include <rte_common.h>
12 #include <rte_malloc.h>
14 #include <rte_byteorder.h>
15 #include <rte_table_lpm.h>
16 #include <rte_table_hash.h>
17 #include <rte_pipeline.h>
19 #include "pipeline_routing_be.h"
20 #include "pipeline_actions_common.h"
22 #include "hash_func.h"
24 #define MPLS_LABEL(label, exp, s, ttl) \
25 (((((uint64_t) (label)) & 0xFFFFFLLU) << 12) | \
26 ((((uint64_t) (exp)) & 0x7LLU) << 9) | \
27 ((((uint64_t) (s)) & 0x1LLU) << 8) | \
28 (((uint64_t) (ttl)) & 0xFFLU))
30 #define RTE_SCHED_PORT_HIERARCHY(subport, pipe, \
31 traffic_class, queue, color) \
32 ((((uint64_t) (queue)) & 0x3) | \
33 ((((uint64_t) (traffic_class)) & 0x3) << 2) | \
34 ((((uint64_t) (color)) & 0x3) << 4) | \
35 ((((uint64_t) (subport)) & 0xFFFF) << 16) | \
36 ((((uint64_t) (pipe)) & 0xFFFFFFFF) << 32))
39 /* Network Byte Order (NBO) */
40 #define SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr, ethertype) \
41 (((uint64_t) macaddr) | (((uint64_t) rte_cpu_to_be_16(ethertype)) << 48))
43 #ifndef PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s
44 #define PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s 256
47 struct pipeline_routing {
49 struct pipeline_routing_params params;
50 pipeline_msg_req_handler custom_handlers[PIPELINE_ROUTING_MSG_REQS];
51 uint64_t macaddr[PIPELINE_MAX_PORT_OUT];
52 } __rte_cache_aligned;
58 pipeline_routing_msg_req_custom_handler(struct pipeline *p, void *msg);
60 static pipeline_msg_req_handler handlers[] = {
61 [PIPELINE_MSG_REQ_PING] =
62 pipeline_msg_req_ping_handler,
63 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
64 pipeline_msg_req_stats_port_in_handler,
65 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
66 pipeline_msg_req_stats_port_out_handler,
67 [PIPELINE_MSG_REQ_STATS_TABLE] =
68 pipeline_msg_req_stats_table_handler,
69 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
70 pipeline_msg_req_port_in_enable_handler,
71 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
72 pipeline_msg_req_port_in_disable_handler,
73 [PIPELINE_MSG_REQ_CUSTOM] =
74 pipeline_routing_msg_req_custom_handler,
78 pipeline_routing_msg_req_route_add_handler(struct pipeline *p,
82 pipeline_routing_msg_req_route_del_handler(struct pipeline *p,
86 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
90 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
94 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p,
98 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p,
102 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p,
106 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p,
110 pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p,
113 static pipeline_msg_req_handler custom_handlers[] = {
114 [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD] =
115 pipeline_routing_msg_req_route_add_handler,
116 [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL] =
117 pipeline_routing_msg_req_route_del_handler,
118 [PIPELINE_ROUTING_MSG_REQ_ROUTE_ADD_DEFAULT] =
119 pipeline_routing_msg_req_route_add_default_handler,
120 [PIPELINE_ROUTING_MSG_REQ_ROUTE_DEL_DEFAULT] =
121 pipeline_routing_msg_req_route_del_default_handler,
122 [PIPELINE_ROUTING_MSG_REQ_ARP_ADD] =
123 pipeline_routing_msg_req_arp_add_handler,
124 [PIPELINE_ROUTING_MSG_REQ_ARP_DEL] =
125 pipeline_routing_msg_req_arp_del_handler,
126 [PIPELINE_ROUTING_MSG_REQ_ARP_ADD_DEFAULT] =
127 pipeline_routing_msg_req_arp_add_default_handler,
128 [PIPELINE_ROUTING_MSG_REQ_ARP_DEL_DEFAULT] =
129 pipeline_routing_msg_req_arp_del_default_handler,
130 [PIPELINE_ROUTING_MSG_REQ_SET_MACADDR] =
131 pipeline_routing_msg_req_set_macaddr_handler,
137 struct routing_table_entry {
138 struct rte_pipeline_table_entry head;
140 uint32_t port_id; /* Output port ID */
141 uint32_t ip; /* Next hop IP address (only valid for remote routes) */
144 uint16_t data_offset;
145 uint16_t ether_l2_length;
147 uint16_t slab_offset[4];
154 } __attribute__((__packed__));
156 #define MACADDR_DST_WRITE(slab_ptr, slab) \
158 struct layout *dst = (struct layout *) (slab_ptr); \
159 struct layout *src = (struct layout *) &(slab); \
165 static __rte_always_inline void
167 struct rte_mbuf *pkt,
168 struct rte_pipeline_table_entry *table_entry,
176 struct pipeline_routing *p_rt = arg;
178 struct routing_table_entry *entry =
179 (struct routing_table_entry *) table_entry;
181 struct ipv4_hdr *ip = (struct ipv4_hdr *)
182 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.ip_hdr_offset);
184 enum rte_meter_color pkt_color = (enum rte_meter_color)
185 RTE_MBUF_METADATA_UINT32(pkt, p_rt->params.color_offset);
187 struct pipeline_routing_arp_key_ipv4 *arp_key =
188 (struct pipeline_routing_arp_key_ipv4 *)
189 RTE_MBUF_METADATA_UINT8_PTR(pkt, p_rt->params.arp_key_offset);
191 uint64_t *slab0_ptr, *slab1_ptr, *slab2_ptr, *slab3_ptr, sched;
192 uint32_t ip_da, nh_ip, port_id;
193 uint16_t total_length, data_offset, ether_l2_length;
196 total_length = rte_bswap16(ip->total_length);
197 ip_da = ip->dst_addr;
198 data_offset = entry->data_offset;
199 ether_l2_length = entry->ether_l2_length;
200 slab0_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[0]);
201 slab1_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[1]);
202 slab2_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[2]);
203 slab3_ptr = RTE_MBUF_METADATA_UINT64_PTR(pkt, entry->slab_offset[3]);
206 port_id = entry->port_id;
208 if (entry->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
213 total_length += ether_l2_length;
215 if (qinq && qinq_sched) {
216 uint32_t dscp = ip->type_of_service >> 2;
217 uint32_t svlan, cvlan, tc, tc_q;
219 if (qinq_sched == 1) {
220 uint64_t slab_qinq = rte_bswap64(entry->slab[0]);
222 svlan = (slab_qinq >> 48) & 0xFFF;
223 cvlan = (slab_qinq >> 16) & 0xFFF;
224 tc = (dscp >> 2) & 0x3;
227 uint32_t ip_src = rte_bswap32(ip->src_addr);
230 cvlan = (ip_src >> 16) & 0xFFF;
231 tc = (ip_src >> 2) & 0x3;
234 sched = RTE_SCHED_PORT_HIERARCHY(svlan,
242 pkt->data_off = data_offset;
243 pkt->data_len = total_length;
244 pkt->pkt_len = total_length;
246 if ((qinq == 0) && (mpls == 0)) {
247 *slab0_ptr = entry->slab[0];
250 MACADDR_DST_WRITE(slab1_ptr, entry->slab[1]);
254 *slab0_ptr = entry->slab[0];
255 *slab1_ptr = entry->slab[1];
258 MACADDR_DST_WRITE(slab2_ptr, entry->slab[2]);
261 pkt->hash.sched.lo = sched & 0xFFFFFFFF;
262 pkt->hash.sched.hi = sched >> 32;
267 if (mpls_color_mark) {
268 uint64_t mpls_exp = rte_bswap64(
269 (MPLS_LABEL(0, pkt_color, 0, 0) << 32) |
270 MPLS_LABEL(0, pkt_color, 0, 0));
272 *slab0_ptr = entry->slab[0] | mpls_exp;
273 *slab1_ptr = entry->slab[1] | mpls_exp;
274 *slab2_ptr = entry->slab[2];
276 *slab0_ptr = entry->slab[0];
277 *slab1_ptr = entry->slab[1];
278 *slab2_ptr = entry->slab[2];
282 MACADDR_DST_WRITE(slab3_ptr, entry->slab[3]);
286 arp_key->port_id = port_id;
291 static __rte_always_inline void
293 struct rte_mbuf **pkts,
294 struct rte_pipeline_table_entry **table_entries,
302 struct pipeline_routing *p_rt = arg;
304 struct routing_table_entry *entry0 =
305 (struct routing_table_entry *) table_entries[0];
306 struct routing_table_entry *entry1 =
307 (struct routing_table_entry *) table_entries[1];
308 struct routing_table_entry *entry2 =
309 (struct routing_table_entry *) table_entries[2];
310 struct routing_table_entry *entry3 =
311 (struct routing_table_entry *) table_entries[3];
313 struct ipv4_hdr *ip0 = (struct ipv4_hdr *)
314 RTE_MBUF_METADATA_UINT8_PTR(pkts[0],
315 p_rt->params.ip_hdr_offset);
316 struct ipv4_hdr *ip1 = (struct ipv4_hdr *)
317 RTE_MBUF_METADATA_UINT8_PTR(pkts[1],
318 p_rt->params.ip_hdr_offset);
319 struct ipv4_hdr *ip2 = (struct ipv4_hdr *)
320 RTE_MBUF_METADATA_UINT8_PTR(pkts[2],
321 p_rt->params.ip_hdr_offset);
322 struct ipv4_hdr *ip3 = (struct ipv4_hdr *)
323 RTE_MBUF_METADATA_UINT8_PTR(pkts[3],
324 p_rt->params.ip_hdr_offset);
326 enum rte_meter_color pkt0_color = (enum rte_meter_color)
327 RTE_MBUF_METADATA_UINT32(pkts[0], p_rt->params.color_offset);
328 enum rte_meter_color pkt1_color = (enum rte_meter_color)
329 RTE_MBUF_METADATA_UINT32(pkts[1], p_rt->params.color_offset);
330 enum rte_meter_color pkt2_color = (enum rte_meter_color)
331 RTE_MBUF_METADATA_UINT32(pkts[2], p_rt->params.color_offset);
332 enum rte_meter_color pkt3_color = (enum rte_meter_color)
333 RTE_MBUF_METADATA_UINT32(pkts[3], p_rt->params.color_offset);
335 struct pipeline_routing_arp_key_ipv4 *arp_key0 =
336 (struct pipeline_routing_arp_key_ipv4 *)
337 RTE_MBUF_METADATA_UINT8_PTR(pkts[0],
338 p_rt->params.arp_key_offset);
339 struct pipeline_routing_arp_key_ipv4 *arp_key1 =
340 (struct pipeline_routing_arp_key_ipv4 *)
341 RTE_MBUF_METADATA_UINT8_PTR(pkts[1],
342 p_rt->params.arp_key_offset);
343 struct pipeline_routing_arp_key_ipv4 *arp_key2 =
344 (struct pipeline_routing_arp_key_ipv4 *)
345 RTE_MBUF_METADATA_UINT8_PTR(pkts[2],
346 p_rt->params.arp_key_offset);
347 struct pipeline_routing_arp_key_ipv4 *arp_key3 =
348 (struct pipeline_routing_arp_key_ipv4 *)
349 RTE_MBUF_METADATA_UINT8_PTR(pkts[3],
350 p_rt->params.arp_key_offset);
352 uint64_t *slab0_ptr0, *slab1_ptr0, *slab2_ptr0, *slab3_ptr0;
353 uint64_t *slab0_ptr1, *slab1_ptr1, *slab2_ptr1, *slab3_ptr1;
354 uint64_t *slab0_ptr2, *slab1_ptr2, *slab2_ptr2, *slab3_ptr2;
355 uint64_t *slab0_ptr3, *slab1_ptr3, *slab2_ptr3, *slab3_ptr3;
356 uint64_t sched0, sched1, sched2, sched3;
358 uint32_t ip_da0, nh_ip0, port_id0;
359 uint32_t ip_da1, nh_ip1, port_id1;
360 uint32_t ip_da2, nh_ip2, port_id2;
361 uint32_t ip_da3, nh_ip3, port_id3;
363 uint16_t total_length0, data_offset0, ether_l2_length0;
364 uint16_t total_length1, data_offset1, ether_l2_length1;
365 uint16_t total_length2, data_offset2, ether_l2_length2;
366 uint16_t total_length3, data_offset3, ether_l2_length3;
369 total_length0 = rte_bswap16(ip0->total_length);
370 total_length1 = rte_bswap16(ip1->total_length);
371 total_length2 = rte_bswap16(ip2->total_length);
372 total_length3 = rte_bswap16(ip3->total_length);
374 ip_da0 = ip0->dst_addr;
375 ip_da1 = ip1->dst_addr;
376 ip_da2 = ip2->dst_addr;
377 ip_da3 = ip3->dst_addr;
379 data_offset0 = entry0->data_offset;
380 data_offset1 = entry1->data_offset;
381 data_offset2 = entry2->data_offset;
382 data_offset3 = entry3->data_offset;
384 ether_l2_length0 = entry0->ether_l2_length;
385 ether_l2_length1 = entry1->ether_l2_length;
386 ether_l2_length2 = entry2->ether_l2_length;
387 ether_l2_length3 = entry3->ether_l2_length;
389 slab0_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
390 entry0->slab_offset[0]);
391 slab1_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
392 entry0->slab_offset[1]);
393 slab2_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
394 entry0->slab_offset[2]);
395 slab3_ptr0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0],
396 entry0->slab_offset[3]);
398 slab0_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
399 entry1->slab_offset[0]);
400 slab1_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
401 entry1->slab_offset[1]);
402 slab2_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
403 entry1->slab_offset[2]);
404 slab3_ptr1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1],
405 entry1->slab_offset[3]);
407 slab0_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
408 entry2->slab_offset[0]);
409 slab1_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
410 entry2->slab_offset[1]);
411 slab2_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
412 entry2->slab_offset[2]);
413 slab3_ptr2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2],
414 entry2->slab_offset[3]);
416 slab0_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
417 entry3->slab_offset[0]);
418 slab1_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
419 entry3->slab_offset[1]);
420 slab2_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
421 entry3->slab_offset[2]);
422 slab3_ptr3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3],
423 entry3->slab_offset[3]);
426 port_id0 = entry0->port_id;
428 if (entry0->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
431 port_id1 = entry1->port_id;
433 if (entry1->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
436 port_id2 = entry2->port_id;
438 if (entry2->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
441 port_id3 = entry3->port_id;
443 if (entry3->flags & PIPELINE_ROUTING_ROUTE_LOCAL)
448 total_length0 += ether_l2_length0;
449 total_length1 += ether_l2_length1;
450 total_length2 += ether_l2_length2;
451 total_length3 += ether_l2_length3;
453 if (qinq && qinq_sched) {
454 uint32_t dscp0 = ip0->type_of_service >> 2;
455 uint32_t dscp1 = ip1->type_of_service >> 2;
456 uint32_t dscp2 = ip2->type_of_service >> 2;
457 uint32_t dscp3 = ip3->type_of_service >> 2;
458 uint32_t svlan0, cvlan0, tc0, tc_q0;
459 uint32_t svlan1, cvlan1, tc1, tc_q1;
460 uint32_t svlan2, cvlan2, tc2, tc_q2;
461 uint32_t svlan3, cvlan3, tc3, tc_q3;
463 if (qinq_sched == 1) {
464 uint64_t slab_qinq0 = rte_bswap64(entry0->slab[0]);
465 uint64_t slab_qinq1 = rte_bswap64(entry1->slab[0]);
466 uint64_t slab_qinq2 = rte_bswap64(entry2->slab[0]);
467 uint64_t slab_qinq3 = rte_bswap64(entry3->slab[0]);
469 svlan0 = (slab_qinq0 >> 48) & 0xFFF;
470 svlan1 = (slab_qinq1 >> 48) & 0xFFF;
471 svlan2 = (slab_qinq2 >> 48) & 0xFFF;
472 svlan3 = (slab_qinq3 >> 48) & 0xFFF;
474 cvlan0 = (slab_qinq0 >> 16) & 0xFFF;
475 cvlan1 = (slab_qinq1 >> 16) & 0xFFF;
476 cvlan2 = (slab_qinq2 >> 16) & 0xFFF;
477 cvlan3 = (slab_qinq3 >> 16) & 0xFFF;
479 tc0 = (dscp0 >> 2) & 0x3;
480 tc1 = (dscp1 >> 2) & 0x3;
481 tc2 = (dscp2 >> 2) & 0x3;
482 tc3 = (dscp3 >> 2) & 0x3;
489 uint32_t ip_src0 = rte_bswap32(ip0->src_addr);
490 uint32_t ip_src1 = rte_bswap32(ip1->src_addr);
491 uint32_t ip_src2 = rte_bswap32(ip2->src_addr);
492 uint32_t ip_src3 = rte_bswap32(ip3->src_addr);
499 cvlan0 = (ip_src0 >> 16) & 0xFFF;
500 cvlan1 = (ip_src1 >> 16) & 0xFFF;
501 cvlan2 = (ip_src2 >> 16) & 0xFFF;
502 cvlan3 = (ip_src3 >> 16) & 0xFFF;
504 tc0 = (ip_src0 >> 2) & 0x3;
505 tc1 = (ip_src1 >> 2) & 0x3;
506 tc2 = (ip_src2 >> 2) & 0x3;
507 tc3 = (ip_src3 >> 2) & 0x3;
509 tc_q0 = ip_src0 & 0x3;
510 tc_q1 = ip_src1 & 0x3;
511 tc_q2 = ip_src2 & 0x3;
512 tc_q3 = ip_src3 & 0x3;
515 sched0 = RTE_SCHED_PORT_HIERARCHY(svlan0,
520 sched1 = RTE_SCHED_PORT_HIERARCHY(svlan1,
525 sched2 = RTE_SCHED_PORT_HIERARCHY(svlan2,
530 sched3 = RTE_SCHED_PORT_HIERARCHY(svlan3,
539 pkts[0]->data_off = data_offset0;
540 pkts[1]->data_off = data_offset1;
541 pkts[2]->data_off = data_offset2;
542 pkts[3]->data_off = data_offset3;
544 pkts[0]->data_len = total_length0;
545 pkts[1]->data_len = total_length1;
546 pkts[2]->data_len = total_length2;
547 pkts[3]->data_len = total_length3;
549 pkts[0]->pkt_len = total_length0;
550 pkts[1]->pkt_len = total_length1;
551 pkts[2]->pkt_len = total_length2;
552 pkts[3]->pkt_len = total_length3;
554 if ((qinq == 0) && (mpls == 0)) {
555 *slab0_ptr0 = entry0->slab[0];
556 *slab0_ptr1 = entry1->slab[0];
557 *slab0_ptr2 = entry2->slab[0];
558 *slab0_ptr3 = entry3->slab[0];
561 MACADDR_DST_WRITE(slab1_ptr0, entry0->slab[1]);
562 MACADDR_DST_WRITE(slab1_ptr1, entry1->slab[1]);
563 MACADDR_DST_WRITE(slab1_ptr2, entry2->slab[1]);
564 MACADDR_DST_WRITE(slab1_ptr3, entry3->slab[1]);
569 *slab0_ptr0 = entry0->slab[0];
570 *slab0_ptr1 = entry1->slab[0];
571 *slab0_ptr2 = entry2->slab[0];
572 *slab0_ptr3 = entry3->slab[0];
574 *slab1_ptr0 = entry0->slab[1];
575 *slab1_ptr1 = entry1->slab[1];
576 *slab1_ptr2 = entry2->slab[1];
577 *slab1_ptr3 = entry3->slab[1];
580 MACADDR_DST_WRITE(slab2_ptr0, entry0->slab[2]);
581 MACADDR_DST_WRITE(slab2_ptr1, entry1->slab[2]);
582 MACADDR_DST_WRITE(slab2_ptr2, entry2->slab[2]);
583 MACADDR_DST_WRITE(slab2_ptr3, entry3->slab[2]);
587 pkts[0]->hash.sched.lo = sched0 & 0xFFFFFFFF;
588 pkts[0]->hash.sched.hi = sched0 >> 32;
589 pkts[1]->hash.sched.lo = sched1 & 0xFFFFFFFF;
590 pkts[1]->hash.sched.hi = sched1 >> 32;
591 pkts[2]->hash.sched.lo = sched2 & 0xFFFFFFFF;
592 pkts[2]->hash.sched.hi = sched2 >> 32;
593 pkts[3]->hash.sched.lo = sched3 & 0xFFFFFFFF;
594 pkts[3]->hash.sched.hi = sched3 >> 32;
599 if (mpls_color_mark) {
600 uint64_t mpls_exp0 = rte_bswap64(
601 (MPLS_LABEL(0, pkt0_color, 0, 0) << 32) |
602 MPLS_LABEL(0, pkt0_color, 0, 0));
603 uint64_t mpls_exp1 = rte_bswap64(
604 (MPLS_LABEL(0, pkt1_color, 0, 0) << 32) |
605 MPLS_LABEL(0, pkt1_color, 0, 0));
606 uint64_t mpls_exp2 = rte_bswap64(
607 (MPLS_LABEL(0, pkt2_color, 0, 0) << 32) |
608 MPLS_LABEL(0, pkt2_color, 0, 0));
609 uint64_t mpls_exp3 = rte_bswap64(
610 (MPLS_LABEL(0, pkt3_color, 0, 0) << 32) |
611 MPLS_LABEL(0, pkt3_color, 0, 0));
613 *slab0_ptr0 = entry0->slab[0] | mpls_exp0;
614 *slab0_ptr1 = entry1->slab[0] | mpls_exp1;
615 *slab0_ptr2 = entry2->slab[0] | mpls_exp2;
616 *slab0_ptr3 = entry3->slab[0] | mpls_exp3;
618 *slab1_ptr0 = entry0->slab[1] | mpls_exp0;
619 *slab1_ptr1 = entry1->slab[1] | mpls_exp1;
620 *slab1_ptr2 = entry2->slab[1] | mpls_exp2;
621 *slab1_ptr3 = entry3->slab[1] | mpls_exp3;
623 *slab2_ptr0 = entry0->slab[2];
624 *slab2_ptr1 = entry1->slab[2];
625 *slab2_ptr2 = entry2->slab[2];
626 *slab2_ptr3 = entry3->slab[2];
628 *slab0_ptr0 = entry0->slab[0];
629 *slab0_ptr1 = entry1->slab[0];
630 *slab0_ptr2 = entry2->slab[0];
631 *slab0_ptr3 = entry3->slab[0];
633 *slab1_ptr0 = entry0->slab[1];
634 *slab1_ptr1 = entry1->slab[1];
635 *slab1_ptr2 = entry2->slab[1];
636 *slab1_ptr3 = entry3->slab[1];
638 *slab2_ptr0 = entry0->slab[2];
639 *slab2_ptr1 = entry1->slab[2];
640 *slab2_ptr2 = entry2->slab[2];
641 *slab2_ptr3 = entry3->slab[2];
645 MACADDR_DST_WRITE(slab3_ptr0, entry0->slab[3]);
646 MACADDR_DST_WRITE(slab3_ptr1, entry1->slab[3]);
647 MACADDR_DST_WRITE(slab3_ptr2, entry2->slab[3]);
648 MACADDR_DST_WRITE(slab3_ptr3, entry3->slab[3]);
653 arp_key0->port_id = port_id0;
654 arp_key1->port_id = port_id1;
655 arp_key2->port_id = port_id2;
656 arp_key3->port_id = port_id3;
658 arp_key0->ip = nh_ip0;
659 arp_key1->ip = nh_ip1;
660 arp_key2->ip = nh_ip2;
661 arp_key3->ip = nh_ip3;
665 #define PKT_WORK_ROUTING_ETHERNET(arp) \
667 pkt_work_routing_ether_arp##arp( \
668 struct rte_mbuf *pkt, \
669 struct rte_pipeline_table_entry *table_entry, \
672 pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 0, 0);\
675 #define PKT4_WORK_ROUTING_ETHERNET(arp) \
677 pkt4_work_routing_ether_arp##arp( \
678 struct rte_mbuf **pkts, \
679 struct rte_pipeline_table_entry **table_entries, \
682 pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 0, 0);\
685 #define routing_table_ah_hit_ether(arp) \
686 PKT_WORK_ROUTING_ETHERNET(arp) \
687 PKT4_WORK_ROUTING_ETHERNET(arp) \
688 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_arp##arp, \
689 pkt_work_routing_ether_arp##arp, \
690 pkt4_work_routing_ether_arp##arp)
692 routing_table_ah_hit_ether(0)
693 routing_table_ah_hit_ether(1)
695 #define PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
697 pkt_work_routing_ether_qinq_sched##sched##_arp##arp( \
698 struct rte_mbuf *pkt, \
699 struct rte_pipeline_table_entry *table_entry, \
702 pkt_work_routing(pkt, table_entry, arg, arp, 1, sched, 0, 0);\
705 #define PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
707 pkt4_work_routing_ether_qinq_sched##sched##_arp##arp( \
708 struct rte_mbuf **pkts, \
709 struct rte_pipeline_table_entry **table_entries, \
712 pkt4_work_routing(pkts, table_entries, arg, arp, 1, sched, 0, 0);\
715 #define routing_table_ah_hit_ether_qinq(sched, arp) \
716 PKT_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
717 PKT4_WORK_ROUTING_ETHERNET_QINQ(sched, arp) \
718 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_qinq_sched##sched##_arp##arp,\
719 pkt_work_routing_ether_qinq_sched##sched##_arp##arp, \
720 pkt4_work_routing_ether_qinq_sched##sched##_arp##arp)
722 routing_table_ah_hit_ether_qinq(0, 0)
723 routing_table_ah_hit_ether_qinq(1, 0)
724 routing_table_ah_hit_ether_qinq(2, 0)
725 routing_table_ah_hit_ether_qinq(0, 1)
726 routing_table_ah_hit_ether_qinq(1, 1)
727 routing_table_ah_hit_ether_qinq(2, 1)
729 #define PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
731 pkt_work_routing_ether_mpls_color##color##_arp##arp( \
732 struct rte_mbuf *pkt, \
733 struct rte_pipeline_table_entry *table_entry, \
736 pkt_work_routing(pkt, table_entry, arg, arp, 0, 0, 1, color);\
739 #define PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
741 pkt4_work_routing_ether_mpls_color##color##_arp##arp( \
742 struct rte_mbuf **pkts, \
743 struct rte_pipeline_table_entry **table_entries, \
746 pkt4_work_routing(pkts, table_entries, arg, arp, 0, 0, 1, color);\
749 #define routing_table_ah_hit_ether_mpls(color, arp) \
750 PKT_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
751 PKT4_WORK_ROUTING_ETHERNET_MPLS(color, arp) \
752 PIPELINE_TABLE_AH_HIT(routing_table_ah_hit_ether_mpls_color##color##_arp##arp,\
753 pkt_work_routing_ether_mpls_color##color##_arp##arp, \
754 pkt4_work_routing_ether_mpls_color##color##_arp##arp)
756 routing_table_ah_hit_ether_mpls(0, 0)
757 routing_table_ah_hit_ether_mpls(1, 0)
758 routing_table_ah_hit_ether_mpls(0, 1)
759 routing_table_ah_hit_ether_mpls(1, 1)
761 static rte_pipeline_table_action_handler_hit
762 get_routing_table_ah_hit(struct pipeline_routing *p)
764 if (p->params.dbg_ah_disable)
767 switch (p->params.encap) {
768 case PIPELINE_ROUTING_ENCAP_ETHERNET:
769 return (p->params.n_arp_entries) ?
770 routing_table_ah_hit_ether_arp1 :
771 routing_table_ah_hit_ether_arp0;
773 case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:
774 if (p->params.n_arp_entries)
775 switch (p->params.qinq_sched) {
777 return routing_table_ah_hit_ether_qinq_sched0_arp1;
779 return routing_table_ah_hit_ether_qinq_sched1_arp1;
781 return routing_table_ah_hit_ether_qinq_sched2_arp1;
786 switch (p->params.qinq_sched) {
788 return routing_table_ah_hit_ether_qinq_sched0_arp0;
790 return routing_table_ah_hit_ether_qinq_sched1_arp0;
792 return routing_table_ah_hit_ether_qinq_sched2_arp0;
797 case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:
798 if (p->params.n_arp_entries)
799 if (p->params.mpls_color_mark)
800 return routing_table_ah_hit_ether_mpls_color1_arp1;
802 return routing_table_ah_hit_ether_mpls_color0_arp1;
804 if (p->params.mpls_color_mark)
805 return routing_table_ah_hit_ether_mpls_color1_arp0;
807 return routing_table_ah_hit_ether_mpls_color0_arp0;
817 struct arp_table_entry {
818 struct rte_pipeline_table_entry head;
827 struct rte_mbuf *pkt,
828 struct rte_pipeline_table_entry *table_entry,
829 __rte_unused void *arg)
831 struct arp_table_entry *entry = (struct arp_table_entry *) table_entry;
834 uint64_t macaddr_dst = entry->macaddr;
835 uint64_t *slab_ptr = (uint64_t *) ((char *) pkt->buf_addr +
836 (pkt->data_off - 2));
841 MACADDR_DST_WRITE(slab_ptr, macaddr_dst);
846 struct rte_mbuf **pkts,
847 struct rte_pipeline_table_entry **table_entries,
848 __rte_unused void *arg)
850 struct arp_table_entry *entry0 =
851 (struct arp_table_entry *) table_entries[0];
852 struct arp_table_entry *entry1 =
853 (struct arp_table_entry *) table_entries[1];
854 struct arp_table_entry *entry2 =
855 (struct arp_table_entry *) table_entries[2];
856 struct arp_table_entry *entry3 =
857 (struct arp_table_entry *) table_entries[3];
860 uint64_t macaddr_dst0 = entry0->macaddr;
861 uint64_t macaddr_dst1 = entry1->macaddr;
862 uint64_t macaddr_dst2 = entry2->macaddr;
863 uint64_t macaddr_dst3 = entry3->macaddr;
865 uint64_t *slab_ptr0 = (uint64_t *) ((char *) pkts[0]->buf_addr +
866 (pkts[0]->data_off - 2));
867 uint64_t *slab_ptr1 = (uint64_t *) ((char *) pkts[1]->buf_addr +
868 (pkts[1]->data_off - 2));
869 uint64_t *slab_ptr2 = (uint64_t *) ((char *) pkts[2]->buf_addr +
870 (pkts[2]->data_off - 2));
871 uint64_t *slab_ptr3 = (uint64_t *) ((char *) pkts[3]->buf_addr +
872 (pkts[3]->data_off - 2));
877 MACADDR_DST_WRITE(slab_ptr0, macaddr_dst0);
878 MACADDR_DST_WRITE(slab_ptr1, macaddr_dst1);
879 MACADDR_DST_WRITE(slab_ptr2, macaddr_dst2);
880 MACADDR_DST_WRITE(slab_ptr3, macaddr_dst3);
883 PIPELINE_TABLE_AH_HIT(arp_table_ah_hit,
887 static rte_pipeline_table_action_handler_hit
888 get_arp_table_ah_hit(struct pipeline_routing *p)
890 if (p->params.dbg_ah_disable)
893 return arp_table_ah_hit;
900 pipeline_routing_parse_args(struct pipeline_routing_params *p,
901 struct pipeline_params *params)
903 uint32_t n_routes_present = 0;
904 uint32_t port_local_dest_present = 0;
905 uint32_t encap_present = 0;
906 uint32_t qinq_sched_present = 0;
907 uint32_t mpls_color_mark_present = 0;
908 uint32_t n_arp_entries_present = 0;
909 uint32_t ip_hdr_offset_present = 0;
910 uint32_t arp_key_offset_present = 0;
911 uint32_t color_offset_present = 0;
912 uint32_t dbg_ah_disable_present = 0;
916 p->n_routes = PIPELINE_ROUTING_N_ROUTES_DEFAULT;
917 p->port_local_dest = params->n_ports_out - 1;
918 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
920 p->mpls_color_mark = 0;
921 p->n_arp_entries = 0;
922 p->dbg_ah_disable = 0;
924 for (i = 0; i < params->n_args; i++) {
925 char *arg_name = params->args_name[i];
926 char *arg_value = params->args_value[i];
929 if (strcmp(arg_name, "n_routes") == 0) {
932 PIPELINE_PARSE_ERR_DUPLICATE(
933 n_routes_present == 0, params->name,
935 n_routes_present = 1;
937 status = parser_read_uint32(&p->n_routes,
939 PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&
940 (p->n_routes != 0)), params->name,
941 arg_name, arg_value);
942 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
943 params->name, arg_name, arg_value);
947 /* port_local_dest */
948 if (strcmp(arg_name, "port_local_dest") == 0) {
951 PIPELINE_PARSE_ERR_DUPLICATE(
952 port_local_dest_present == 0, params->name,
954 port_local_dest_present = 1;
956 status = parser_read_uint32(&p->port_local_dest,
958 PIPELINE_PARSE_ERR_INV_VAL(((status == 0) &&
959 (p->port_local_dest < params->n_ports_out)),
960 params->name, arg_name, arg_value);
966 if (strcmp(arg_name, "encap") == 0) {
967 PIPELINE_PARSE_ERR_DUPLICATE(encap_present == 0,
968 params->name, arg_name);
972 if (strcmp(arg_value, "ethernet") == 0) {
973 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET;
978 if (strcmp(arg_value, "ethernet_qinq") == 0) {
979 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ;
984 if (strcmp(arg_value, "ethernet_mpls") == 0) {
985 p->encap = PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS;
990 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
991 arg_name, arg_value);
995 if (strcmp(arg_name, "qinq_sched") == 0) {
998 PIPELINE_PARSE_ERR_DUPLICATE(
999 qinq_sched_present == 0, params->name,
1001 qinq_sched_present = 1;
1003 status = parser_read_arg_bool(arg_value);
1004 if (status == -EINVAL) {
1005 if (strcmp(arg_value, "test") == 0) {
1010 p->qinq_sched = status;
1014 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
1015 arg_name, arg_value);
1018 /* mpls_color_mark */
1019 if (strcmp(arg_name, "mpls_color_mark") == 0) {
1022 PIPELINE_PARSE_ERR_DUPLICATE(
1023 mpls_color_mark_present == 0,
1024 params->name, arg_name);
1025 mpls_color_mark_present = 1;
1028 status = parser_read_arg_bool(arg_value);
1030 p->mpls_color_mark = status;
1034 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
1035 arg_name, arg_value);
1039 if (strcmp(arg_name, "n_arp_entries") == 0) {
1042 PIPELINE_PARSE_ERR_DUPLICATE(
1043 n_arp_entries_present == 0, params->name,
1045 n_arp_entries_present = 1;
1047 status = parser_read_uint32(&p->n_arp_entries,
1049 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1050 params->name, arg_name, arg_value);
1051 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1052 params->name, arg_name, arg_value);
1058 if (strcmp(arg_name, "ip_hdr_offset") == 0) {
1061 PIPELINE_PARSE_ERR_DUPLICATE(
1062 ip_hdr_offset_present == 0, params->name,
1064 ip_hdr_offset_present = 1;
1066 status = parser_read_uint32(&p->ip_hdr_offset,
1068 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1069 params->name, arg_name, arg_value);
1070 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1071 params->name, arg_name, arg_value);
1076 /* arp_key_offset */
1077 if (strcmp(arg_name, "arp_key_offset") == 0) {
1080 PIPELINE_PARSE_ERR_DUPLICATE(
1081 arp_key_offset_present == 0, params->name,
1083 arp_key_offset_present = 1;
1085 status = parser_read_uint32(&p->arp_key_offset,
1087 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1088 params->name, arg_name, arg_value);
1089 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1090 params->name, arg_name, arg_value);
1096 if (strcmp(arg_name, "color_offset") == 0) {
1099 PIPELINE_PARSE_ERR_DUPLICATE(
1100 color_offset_present == 0, params->name,
1102 color_offset_present = 1;
1104 status = parser_read_uint32(&p->color_offset,
1106 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
1107 params->name, arg_name, arg_value);
1108 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
1109 params->name, arg_name, arg_value);
1115 if (strcmp(arg_name, "dbg_ah_disable") == 0) {
1118 PIPELINE_PARSE_ERR_DUPLICATE(
1119 dbg_ah_disable_present == 0, params->name,
1121 dbg_ah_disable_present = 1;
1123 status = parser_read_arg_bool(arg_value);
1125 p->dbg_ah_disable = status;
1129 PIPELINE_PARSE_ERR_INV_VAL(0, params->name,
1130 arg_name, arg_value);
1136 PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);
1139 /* Check that mandatory arguments are present */
1140 PIPELINE_PARSE_ERR_MANDATORY(ip_hdr_offset_present, params->name,
1143 /* Check relations between arguments */
1145 case PIPELINE_ROUTING_ENCAP_ETHERNET:
1146 PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in "
1147 "section \"%s\": encap = ethernet, therefore "
1148 "qinq_sched = yes/test is not allowed",
1150 PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error "
1151 "in section \"%s\": encap = ethernet, therefore "
1152 "mpls_color_mark = yes is not allowed",
1154 PIPELINE_ARG_CHECK((!color_offset_present), "Parse error "
1155 "in section \"%s\": encap = ethernet, therefore "
1156 "color_offset is not allowed",
1160 case PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ:
1161 PIPELINE_ARG_CHECK((!p->mpls_color_mark), "Parse error "
1162 "in section \"%s\": encap = ethernet_qinq, "
1163 "therefore mpls_color_mark = yes is not allowed",
1165 PIPELINE_ARG_CHECK((!color_offset_present), "Parse error "
1166 "in section \"%s\": encap = ethernet_qinq, "
1167 "therefore color_offset is not allowed",
1171 case PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS:
1172 PIPELINE_ARG_CHECK((!p->qinq_sched), "Parse error in "
1173 "section \"%s\": encap = ethernet_mpls, therefore "
1174 "qinq_sched = yes/test is not allowed",
1179 PIPELINE_ARG_CHECK((!(p->n_arp_entries &&
1180 (!arp_key_offset_present))), "Parse error in section "
1181 "\"%s\": n_arp_entries is set while "
1182 "arp_key_offset is not set", params->name);
1184 PIPELINE_ARG_CHECK((!((p->n_arp_entries == 0) &&
1185 arp_key_offset_present)), "Parse error in section "
1186 "\"%s\": arp_key_offset present while "
1187 "n_arp_entries is not set", params->name);
1193 pipeline_routing_init(struct pipeline_params *params,
1194 __rte_unused void *arg)
1197 struct pipeline_routing *p_rt;
1200 /* Check input arguments */
1201 if ((params == NULL) ||
1202 (params->n_ports_in == 0) ||
1203 (params->n_ports_out == 0))
1206 /* Memory allocation */
1207 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_routing));
1208 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1209 p_rt = (struct pipeline_routing *) p;
1213 strcpy(p->name, params->name);
1214 p->log_level = params->log_level;
1216 PLOG(p, HIGH, "Routing");
1218 /* Parse arguments */
1219 if (pipeline_routing_parse_args(&p_rt->params, params))
1224 struct rte_pipeline_params pipeline_params = {
1225 .name = params->name,
1226 .socket_id = params->socket_id,
1227 .offset_port_id = 0,
1230 p->p = rte_pipeline_create(&pipeline_params);
1238 p->n_ports_in = params->n_ports_in;
1239 for (i = 0; i < p->n_ports_in; i++) {
1240 struct rte_pipeline_port_in_params port_params = {
1241 .ops = pipeline_port_in_params_get_ops(
1242 ¶ms->port_in[i]),
1243 .arg_create = pipeline_port_in_params_convert(
1244 ¶ms->port_in[i]),
1247 .burst_size = params->port_in[i].burst_size,
1250 int status = rte_pipeline_port_in_create(p->p,
1255 rte_pipeline_free(p->p);
1262 p->n_ports_out = params->n_ports_out;
1263 for (i = 0; i < p->n_ports_out; i++) {
1264 struct rte_pipeline_port_out_params port_params = {
1265 .ops = pipeline_port_out_params_get_ops(
1266 ¶ms->port_out[i]),
1267 .arg_create = pipeline_port_out_params_convert(
1268 ¶ms->port_out[i]),
1273 int status = rte_pipeline_port_out_create(p->p,
1275 &p->port_out_id[i]);
1278 rte_pipeline_free(p->p);
1287 struct rte_table_lpm_params table_lpm_params = {
1289 .n_rules = p_rt->params.n_routes,
1290 .number_tbl8s = PIPELINE_ROUTING_LPM_TABLE_NUMBER_TABLE8s,
1292 .entry_unique_size = sizeof(struct routing_table_entry),
1293 .offset = p_rt->params.ip_hdr_offset +
1294 __builtin_offsetof(struct ipv4_hdr, dst_addr),
1297 struct rte_pipeline_table_params table_params = {
1298 .ops = &rte_table_lpm_ops,
1299 .arg_create = &table_lpm_params,
1300 .f_action_hit = get_routing_table_ah_hit(p_rt),
1301 .f_action_miss = NULL,
1304 sizeof(struct routing_table_entry) -
1305 sizeof(struct rte_pipeline_table_entry),
1310 status = rte_pipeline_table_create(p->p,
1315 rte_pipeline_free(p->p);
1321 /* ARP table configuration */
1322 if (p_rt->params.n_arp_entries) {
1323 struct rte_table_hash_params table_arp_params = {
1326 .key_offset = p_rt->params.arp_key_offset,
1328 .n_keys = p_rt->params.n_arp_entries,
1330 rte_align32pow2(p_rt->params.n_arp_entries / 4),
1331 .f_hash = hash_default_key8,
1335 struct rte_pipeline_table_params table_params = {
1336 .ops = &rte_table_hash_key8_ext_ops,
1337 .arg_create = &table_arp_params,
1338 .f_action_hit = get_arp_table_ah_hit(p_rt),
1339 .f_action_miss = NULL,
1341 .action_data_size = sizeof(struct arp_table_entry) -
1342 sizeof(struct rte_pipeline_table_entry),
1347 status = rte_pipeline_table_create(p->p,
1352 rte_pipeline_free(p->p);
1360 /* Connecting input ports to tables */
1361 for (i = 0; i < p->n_ports_in; i++) {
1362 int status = rte_pipeline_port_in_connect_to_table(p->p,
1367 rte_pipeline_free(p->p);
1373 /* Enable input ports */
1374 for (i = 0; i < p->n_ports_in; i++) {
1375 int status = rte_pipeline_port_in_enable(p->p,
1379 rte_pipeline_free(p->p);
1385 /* Check pipeline consistency */
1386 if (rte_pipeline_check(p->p) < 0) {
1387 rte_pipeline_free(p->p);
1392 /* Message queues */
1393 p->n_msgq = params->n_msgq;
1394 for (i = 0; i < p->n_msgq; i++)
1395 p->msgq_in[i] = params->msgq_in[i];
1396 for (i = 0; i < p->n_msgq; i++)
1397 p->msgq_out[i] = params->msgq_out[i];
1399 /* Message handlers */
1400 memcpy(p->handlers, handlers, sizeof(p->handlers));
1401 memcpy(p_rt->custom_handlers,
1403 sizeof(p_rt->custom_handlers));
1409 pipeline_routing_free(void *pipeline)
1411 struct pipeline *p = (struct pipeline *) pipeline;
1413 /* Check input arguments */
1417 /* Free resources */
1418 rte_pipeline_free(p->p);
1424 pipeline_routing_timer(void *pipeline)
1426 struct pipeline *p = (struct pipeline *) pipeline;
1428 pipeline_msg_req_handle(p);
1429 rte_pipeline_flush(p->p);
1435 pipeline_routing_msg_req_custom_handler(struct pipeline *p,
1438 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1439 struct pipeline_custom_msg_req *req = msg;
1440 pipeline_msg_req_handler f_handle;
1442 f_handle = (req->subtype < PIPELINE_ROUTING_MSG_REQS) ?
1443 p_rt->custom_handlers[req->subtype] :
1444 pipeline_msg_req_invalid_handler;
1446 if (f_handle == NULL)
1447 f_handle = pipeline_msg_req_invalid_handler;
1449 return f_handle(p, req);
1453 pipeline_routing_msg_req_route_add_handler(struct pipeline *p, void *msg)
1455 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1456 struct pipeline_routing_route_add_msg_req *req = msg;
1457 struct pipeline_routing_route_add_msg_rsp *rsp = msg;
1459 struct rte_table_lpm_key key = {
1460 .ip = req->key.key.ipv4.ip,
1461 .depth = req->key.key.ipv4.depth,
1464 struct routing_table_entry entry_arp0 = {
1466 .action = RTE_PIPELINE_ACTION_PORT,
1467 {.port_id = p->port_out_id[req->data.port_id]},
1470 .flags = req->data.flags,
1471 .port_id = req->data.port_id,
1474 .ether_l2_length = 0,
1479 struct routing_table_entry entry_arp1 = {
1481 .action = RTE_PIPELINE_ACTION_TABLE,
1482 {.table_id = p->table_id[1]},
1485 .flags = req->data.flags,
1486 .port_id = req->data.port_id,
1487 .ip = rte_bswap32(req->data.ethernet.ip),
1489 .ether_l2_length = 0,
1494 struct rte_pipeline_table_entry *entry = (p_rt->params.n_arp_entries) ?
1495 (struct rte_pipeline_table_entry *) &entry_arp1 :
1496 (struct rte_pipeline_table_entry *) &entry_arp0;
1498 if ((req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) ||
1499 ((p_rt->params.n_arp_entries == 0) &&
1500 (req->data.flags & PIPELINE_ROUTING_ROUTE_ARP)) ||
1501 (p_rt->params.n_arp_entries &&
1502 ((req->data.flags & PIPELINE_ROUTING_ROUTE_ARP) == 0)) ||
1503 ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1504 (req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ)) ||
1505 ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1506 ((req->data.flags & PIPELINE_ROUTING_ROUTE_QINQ) == 0)) ||
1507 ((p_rt->params.encap != PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1508 (req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS)) ||
1509 ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1510 ((req->data.flags & PIPELINE_ROUTING_ROUTE_MPLS) == 0))) {
1515 /* Ether - ARP off */
1516 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
1517 (p_rt->params.n_arp_entries == 0)) {
1518 uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
1519 uint64_t macaddr_dst;
1520 uint64_t ethertype = ETHER_TYPE_IPv4;
1522 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1523 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1525 entry_arp0.slab[0] =
1526 SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype);
1527 entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1529 entry_arp0.slab[1] = rte_bswap64(macaddr_dst);
1530 entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1532 entry_arp0.data_offset = entry_arp0.slab_offset[1] + 2
1533 - sizeof(struct rte_mbuf);
1534 entry_arp0.ether_l2_length = 14;
1537 /* Ether - ARP on */
1538 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET) &&
1539 p_rt->params.n_arp_entries) {
1540 uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
1541 uint64_t ethertype = ETHER_TYPE_IPv4;
1543 entry_arp1.slab[0] =
1544 SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype);
1545 entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1547 entry_arp1.data_offset = entry_arp1.slab_offset[0] - 6
1548 - sizeof(struct rte_mbuf);
1549 entry_arp1.ether_l2_length = 14;
1552 /* Ether QinQ - ARP off */
1553 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1554 (p_rt->params.n_arp_entries == 0)) {
1555 uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
1556 uint64_t macaddr_dst;
1557 uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
1558 uint64_t ethertype_vlan = 0x8100;
1559 uint64_t ethertype_qinq = 0x9100;
1560 uint64_t svlan = req->data.l2.qinq.svlan;
1561 uint64_t cvlan = req->data.l2.qinq.cvlan;
1563 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1564 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1566 entry_arp0.slab[0] = rte_bswap64((svlan << 48) |
1567 (ethertype_vlan << 32) |
1570 entry_arp0.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1572 entry_arp0.slab[1] =
1573 SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq);
1574 entry_arp0.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1576 entry_arp0.slab[2] = rte_bswap64(macaddr_dst);
1577 entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset - 3 * 8;
1579 entry_arp0.data_offset = entry_arp0.slab_offset[2] + 2
1580 - sizeof(struct rte_mbuf);
1581 entry_arp0.ether_l2_length = 22;
1584 /* Ether QinQ - ARP on */
1585 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_QINQ) &&
1586 p_rt->params.n_arp_entries) {
1587 uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
1588 uint64_t ethertype_ipv4 = ETHER_TYPE_IPv4;
1589 uint64_t ethertype_vlan = 0x8100;
1590 uint64_t ethertype_qinq = 0x9100;
1591 uint64_t svlan = req->data.l2.qinq.svlan;
1592 uint64_t cvlan = req->data.l2.qinq.cvlan;
1594 entry_arp1.slab[0] = rte_bswap64((svlan << 48) |
1595 (ethertype_vlan << 32) |
1598 entry_arp1.slab_offset[0] = p_rt->params.ip_hdr_offset - 8;
1600 entry_arp1.slab[1] =
1601 SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_qinq);
1602 entry_arp1.slab_offset[1] = p_rt->params.ip_hdr_offset - 2 * 8;
1604 entry_arp1.data_offset = entry_arp1.slab_offset[1] - 6
1605 - sizeof(struct rte_mbuf);
1606 entry_arp1.ether_l2_length = 22;
1609 /* Ether MPLS - ARP off */
1610 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1611 (p_rt->params.n_arp_entries == 0)) {
1612 uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
1613 uint64_t macaddr_dst;
1614 uint64_t ethertype_mpls = 0x8847;
1616 uint64_t label0 = req->data.l2.mpls.labels[0];
1617 uint64_t label1 = req->data.l2.mpls.labels[1];
1618 uint64_t label2 = req->data.l2.mpls.labels[2];
1619 uint64_t label3 = req->data.l2.mpls.labels[3];
1620 uint32_t n_labels = req->data.l2.mpls.n_labels;
1622 macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
1623 macaddr_dst = rte_bswap64(macaddr_dst << 16);
1627 entry_arp0.slab[0] = 0;
1628 entry_arp0.slab_offset[0] =
1629 p_rt->params.ip_hdr_offset - 8;
1631 entry_arp0.slab[1] = rte_bswap64(
1632 MPLS_LABEL(label0, 0, 1, 0));
1633 entry_arp0.slab_offset[1] =
1634 p_rt->params.ip_hdr_offset - 8;
1638 entry_arp0.slab[0] = 0;
1639 entry_arp0.slab_offset[0] =
1640 p_rt->params.ip_hdr_offset - 8;
1642 entry_arp0.slab[1] = rte_bswap64(
1643 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1644 MPLS_LABEL(label1, 0, 1, 0));
1645 entry_arp0.slab_offset[1] =
1646 p_rt->params.ip_hdr_offset - 8;
1650 entry_arp0.slab[0] = rte_bswap64(
1651 (MPLS_LABEL(label1, 0, 0, 0) << 32) |
1652 MPLS_LABEL(label2, 0, 1, 0));
1653 entry_arp0.slab_offset[0] =
1654 p_rt->params.ip_hdr_offset - 8;
1656 entry_arp0.slab[1] = rte_bswap64(
1657 MPLS_LABEL(label0, 0, 0, 0));
1658 entry_arp0.slab_offset[1] =
1659 p_rt->params.ip_hdr_offset - 2 * 8;
1663 entry_arp0.slab[0] = rte_bswap64(
1664 (MPLS_LABEL(label2, 0, 0, 0) << 32) |
1665 MPLS_LABEL(label3, 0, 1, 0));
1666 entry_arp0.slab_offset[0] =
1667 p_rt->params.ip_hdr_offset - 8;
1669 entry_arp0.slab[1] = rte_bswap64(
1670 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1671 MPLS_LABEL(label1, 0, 0, 0));
1672 entry_arp0.slab_offset[1] =
1673 p_rt->params.ip_hdr_offset - 2 * 8;
1681 entry_arp0.slab[2] =
1682 SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls);
1683 entry_arp0.slab_offset[2] = p_rt->params.ip_hdr_offset -
1686 entry_arp0.slab[3] = rte_bswap64(macaddr_dst);
1687 entry_arp0.slab_offset[3] = p_rt->params.ip_hdr_offset -
1688 (n_labels * 4 + 2 * 8);
1690 entry_arp0.data_offset = entry_arp0.slab_offset[3] + 2
1691 - sizeof(struct rte_mbuf);
1692 entry_arp0.ether_l2_length = n_labels * 4 + 14;
1695 /* Ether MPLS - ARP on */
1696 if ((p_rt->params.encap == PIPELINE_ROUTING_ENCAP_ETHERNET_MPLS) &&
1697 p_rt->params.n_arp_entries) {
1698 uint64_t macaddr_src = p_rt->macaddr[req->data.port_id];
1699 uint64_t ethertype_mpls = 0x8847;
1701 uint64_t label0 = req->data.l2.mpls.labels[0];
1702 uint64_t label1 = req->data.l2.mpls.labels[1];
1703 uint64_t label2 = req->data.l2.mpls.labels[2];
1704 uint64_t label3 = req->data.l2.mpls.labels[3];
1705 uint32_t n_labels = req->data.l2.mpls.n_labels;
1709 entry_arp1.slab[0] = 0;
1710 entry_arp1.slab_offset[0] =
1711 p_rt->params.ip_hdr_offset - 8;
1713 entry_arp1.slab[1] = rte_bswap64(
1714 MPLS_LABEL(label0, 0, 1, 0));
1715 entry_arp1.slab_offset[1] =
1716 p_rt->params.ip_hdr_offset - 8;
1720 entry_arp1.slab[0] = 0;
1721 entry_arp1.slab_offset[0] =
1722 p_rt->params.ip_hdr_offset - 8;
1724 entry_arp1.slab[1] = rte_bswap64(
1725 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1726 MPLS_LABEL(label1, 0, 1, 0));
1727 entry_arp1.slab_offset[1] =
1728 p_rt->params.ip_hdr_offset - 8;
1732 entry_arp1.slab[0] = rte_bswap64(
1733 (MPLS_LABEL(label1, 0, 0, 0) << 32) |
1734 MPLS_LABEL(label2, 0, 1, 0));
1735 entry_arp1.slab_offset[0] =
1736 p_rt->params.ip_hdr_offset - 8;
1738 entry_arp1.slab[1] = rte_bswap64(
1739 MPLS_LABEL(label0, 0, 0, 0));
1740 entry_arp1.slab_offset[1] =
1741 p_rt->params.ip_hdr_offset - 2 * 8;
1745 entry_arp1.slab[0] = rte_bswap64(
1746 (MPLS_LABEL(label2, 0, 0, 0) << 32) |
1747 MPLS_LABEL(label3, 0, 1, 0));
1748 entry_arp1.slab_offset[0] =
1749 p_rt->params.ip_hdr_offset - 8;
1751 entry_arp1.slab[1] = rte_bswap64(
1752 (MPLS_LABEL(label0, 0, 0, 0) << 32) |
1753 MPLS_LABEL(label1, 0, 0, 0));
1754 entry_arp1.slab_offset[1] =
1755 p_rt->params.ip_hdr_offset - 2 * 8;
1763 entry_arp1.slab[2] =
1764 SLAB_NBO_MACADDRSRC_ETHERTYPE(macaddr_src, ethertype_mpls);
1765 entry_arp1.slab_offset[2] = p_rt->params.ip_hdr_offset -
1768 entry_arp1.data_offset = entry_arp1.slab_offset[2] - 6
1769 - sizeof(struct rte_mbuf);
1770 entry_arp1.ether_l2_length = n_labels * 4 + 14;
1773 rsp->status = rte_pipeline_table_entry_add(p->p,
1778 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1784 pipeline_routing_msg_req_route_del_handler(struct pipeline *p, void *msg)
1786 struct pipeline_routing_route_delete_msg_req *req = msg;
1787 struct pipeline_routing_route_delete_msg_rsp *rsp = msg;
1789 struct rte_table_lpm_key key = {
1790 .ip = req->key.key.ipv4.ip,
1791 .depth = req->key.key.ipv4.depth,
1794 if (req->key.type != PIPELINE_ROUTING_ROUTE_IPV4) {
1799 rsp->status = rte_pipeline_table_entry_delete(p->p,
1809 pipeline_routing_msg_req_route_add_default_handler(struct pipeline *p,
1812 struct pipeline_routing_route_add_default_msg_req *req = msg;
1813 struct pipeline_routing_route_add_default_msg_rsp *rsp = msg;
1815 struct routing_table_entry default_entry = {
1817 .action = RTE_PIPELINE_ACTION_PORT,
1818 {.port_id = p->port_out_id[req->port_id]},
1826 rsp->status = rte_pipeline_table_default_entry_add(p->p,
1828 (struct rte_pipeline_table_entry *) &default_entry,
1829 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1835 pipeline_routing_msg_req_route_del_default_handler(struct pipeline *p,
1838 struct pipeline_routing_route_delete_default_msg_rsp *rsp = msg;
1840 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
1848 pipeline_routing_msg_req_arp_add_handler(struct pipeline *p, void *msg)
1850 struct pipeline_routing_arp_add_msg_req *req = msg;
1851 struct pipeline_routing_arp_add_msg_rsp *rsp = msg;
1853 struct pipeline_routing_arp_key_ipv4 key = {
1854 .port_id = req->key.key.ipv4.port_id,
1855 .ip = rte_bswap32(req->key.key.ipv4.ip),
1858 struct arp_table_entry entry = {
1860 .action = RTE_PIPELINE_ACTION_PORT,
1861 {.port_id = p->port_out_id[req->key.key.ipv4.port_id]},
1864 .macaddr = 0, /* set below */
1867 if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
1872 entry.macaddr = *((uint64_t *)&(req->macaddr));
1873 entry.macaddr = entry.macaddr << 16;
1875 rsp->status = rte_pipeline_table_entry_add(p->p,
1878 (struct rte_pipeline_table_entry *) &entry,
1880 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1886 pipeline_routing_msg_req_arp_del_handler(struct pipeline *p, void *msg)
1888 struct pipeline_routing_arp_delete_msg_req *req = msg;
1889 struct pipeline_routing_arp_delete_msg_rsp *rsp = msg;
1891 struct pipeline_routing_arp_key_ipv4 key = {
1892 .port_id = req->key.key.ipv4.port_id,
1893 .ip = rte_bswap32(req->key.key.ipv4.ip),
1896 if (req->key.type != PIPELINE_ROUTING_ARP_IPV4) {
1901 rsp->status = rte_pipeline_table_entry_delete(p->p,
1911 pipeline_routing_msg_req_arp_add_default_handler(struct pipeline *p, void *msg)
1913 struct pipeline_routing_arp_add_default_msg_req *req = msg;
1914 struct pipeline_routing_arp_add_default_msg_rsp *rsp = msg;
1916 struct arp_table_entry default_entry = {
1918 .action = RTE_PIPELINE_ACTION_PORT,
1919 {.port_id = p->port_out_id[req->port_id]},
1925 rsp->status = rte_pipeline_table_default_entry_add(p->p,
1927 (struct rte_pipeline_table_entry *) &default_entry,
1928 (struct rte_pipeline_table_entry **) &rsp->entry_ptr);
1934 pipeline_routing_msg_req_arp_del_default_handler(struct pipeline *p, void *msg)
1936 struct pipeline_routing_arp_delete_default_msg_rsp *rsp = msg;
1938 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
1946 pipeline_routing_msg_req_set_macaddr_handler(struct pipeline *p, void *msg)
1948 struct pipeline_routing *p_rt = (struct pipeline_routing *) p;
1949 struct pipeline_routing_set_macaddr_msg_req *req = msg;
1950 struct pipeline_routing_set_macaddr_msg_rsp *rsp = msg;
1953 for (port_id = 0; port_id < p->n_ports_out; port_id++)
1954 p_rt->macaddr[port_id] = req->macaddr[port_id];
1961 struct pipeline_be_ops pipeline_routing_be_ops = {
1962 .f_init = pipeline_routing_init,
1963 .f_free = pipeline_routing_free,
1965 .f_timer = pipeline_routing_timer,