2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
23 #include <rte_common.h>
24 #include <rte_malloc.h>
27 #include <rte_byteorder.h>
28 #include <rte_table_lpm.h>
29 #include <rte_table_hash.h>
30 #include <rte_jhash.h>
31 #include <rte_thash.h>
32 #include <rte_cycles.h>
33 #include <rte_ethdev.h>
34 #include <rte_prefetch.h>
35 #include <rte_table_array.h>
36 #include "pipeline_loadb_be.h"
37 #include "pipeline_actions_common.h"
38 #include "hash_func.h"
39 #include "pipeline_arpicmp_be.h"
40 #include "vnf_common.h"
43 #define BYTES_TO_BITS 8
44 #define ROTATE_15_BITS 15
46 #define MAX_VNF_THREADS 16
51 uint8_t total_vnf_threads;
52 uint32_t phyport_offset;
54 struct pipeline_loadb {
56 pipeline_msg_req_handler custom_handlers[PIPELINE_LOADB_MSG_REQS];
58 uint8_t n_vnf_threads;
60 uint32_t outport_offset;
61 uint64_t receivedLBPktCount;
62 uint64_t droppedLBPktCount;
63 uint8_t links_map[PIPELINE_MAX_PORT_IN];
64 uint8_t outport_id[PIPELINE_MAX_PORT_IN];
68 } __rte_cache_aligned;
70 uint8_t default_rss_key[] = {
71 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
72 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
73 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
74 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
75 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a,
78 static void *pipeline_loadb_msg_req_custom_handler(struct pipeline *p,
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_loadb_msg_req_custom_handler,
99 static void *pipeline_loadb_msg_req_entry_dbg_handler(struct pipeline *,
102 static pipeline_msg_req_handler custom_handlers[] = {
103 [PIPELINE_LOADB_MSG_REQ_ENTRY_DBG] =
104 pipeline_loadb_msg_req_entry_dbg_handler,
110 struct loadb_table_entry {
111 struct rte_pipeline_table_entry head;
112 } __rte_cache_aligned;
114 void *pipeline_loadb_msg_req_custom_handler(struct pipeline *p, void *msg)
116 struct pipeline_loadb *p_lb = (struct pipeline_loadb *)p;
117 struct pipeline_custom_msg_req *req = msg;
118 pipeline_msg_req_handler f_handle;
120 f_handle = (req->subtype < PIPELINE_LOADB_MSG_REQS) ?
121 p_lb->custom_handlers[req->subtype] :
122 pipeline_msg_req_invalid_handler;
124 if (f_handle == NULL)
125 f_handle = pipeline_msg_req_invalid_handler;
127 return f_handle(p, req);
130 uint32_t lb_pkt_print_count;
132 uint8_t calculate_lb_thread_prv(struct rte_mbuf *pkt, void *arg)
134 uint32_t hash_key[2], hash_ipv4;
135 uint32_t temp1, temp2, temp3;
137 struct pipeline_loadb_in_port_h_arg *ap = arg;
138 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *) ap->p;
139 uint8_t nthreads = p_loadb->n_vnf_threads;
140 union rte_thash_tuple tuple;
147 struct lb_pkt *lb_pkt = (struct lb_pkt *)
148 RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
150 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6) {
151 src_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.src_addr;
152 dst_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.dst_addr;
153 src_port = &lb_pkt->ipv6_port.src_port;
154 dst_port = &lb_pkt->ipv6_port.dst_port;
155 protocol = &lb_pkt->ipv6_port.ipv6.proto;
157 src_addr = &lb_pkt->ipv4_port.ipv4.src_addr;
158 dst_addr = &lb_pkt->ipv4_port.ipv4.dst_addr;
159 src_port = &lb_pkt->ipv4_port.src_port;
160 dst_port = &lb_pkt->ipv4_port.dst_port;
161 protocol = &lb_pkt->ipv4_port.ipv4.next_proto_id;
164 switch (p_loadb->n_lb_tuples) {
169 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6)
170 temp1 = rte_bswap32(dst_addr[3]) ^ *dst_port;
172 temp1 = *dst_addr ^ *dst_port;
174 temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^
175 (temp1 >> 8) ^ temp1;
177 temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
179 /* To select the thread */
180 thread = temp3 % nthreads;
181 /* To select the Q */
182 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
183 (thread + 1) - p_loadb->p.n_ports_in);
189 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6)
190 hash_key[0] = rte_bswap32(dst_addr[3]);
192 hash_key[0] = rte_bswap32(*dst_addr);
195 hash_ipv4 = rte_jhash(&hash_key[0], 4, 0);
197 /* To select the thread */
198 thread = (hash_ipv4 % nthreads);
200 /* To select the Q */
201 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
202 (thread + 1) - p_loadb->p.n_ports_in);
205 printf("thread: %u hash: %x hash_key: %x\n",
206 thread, hash_ipv4, hash_key[0]);
212 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
214 hash_key[0] = rte_bswap32(dst_addr[3]);
215 hash_key[1] = *dst_port << 16;
217 hash_key[0] = rte_bswap32(*dst_addr);
218 hash_key[1] = *dst_port << 16;
221 hash_ipv4 = rte_jhash(&hash_key[0], 6, 0);
223 /* To select the thread */
224 thread = (hash_ipv4 % nthreads);
226 /* To select the Q */
227 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
228 (thread + 1) - p_loadb->p.n_ports_in);
230 if (LOADB_DEBUG > 3) {
231 printf("public_addr: %x public_port: %x\n",
232 hash_key[0], *dst_port);
233 printf("thread: %u hash: %x hash_key0: %x "
234 "hash_key1: %x\n", thread, hash_ipv4,
235 hash_key[0], hash_key[1]);
240 printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
245 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
247 tuple.v4.src_addr = rte_bswap32(src_addr[3]);
248 tuple.v4.dst_addr = rte_bswap32(dst_addr[3]);
249 tuple.v4.sport = *src_port;
250 tuple.v4.dport = *dst_port;
252 tuple.v4.src_addr = rte_bswap32(*src_addr);
253 tuple.v4.dst_addr = rte_bswap32(*dst_addr);
254 tuple.v4.sport = *src_port;
255 tuple.v4.dport = *dst_port;
258 hash_ipv4 = rte_softrss((uint32_t *)&tuple,
263 /* To select the thread */
264 thread = (hash_ipv4 % nthreads);
266 /* To select the Q */
267 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
268 (thread + 1) - p_loadb->p.n_ports_in);
270 if (LOADB_DEBUG > 3) {
271 printf("src_addr: %x dst_addr: %x src_port: %x "
272 "dst_port: %x\n", tuple.v4.src_addr, tuple.v4.dst_addr,
273 tuple.v4.sport, tuple.v4.dport);
274 printf("thread: %u hash: %x\n", thread, hash_ipv4);
281 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
283 /* point to last 32 bits of IPv6 addresses*/
289 temp1 = *src_addr ^ *dst_addr ^ *src_port ^
290 *dst_port ^ *protocol;
292 temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^ (temp1 >> 8) ^ temp1;
293 temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
297 /* To select the thread */
298 thread = (temp3 % nthreads);
300 /* To select the Q */
301 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
302 (thread + 1) - p_loadb->p.n_ports_in);
304 if (LOADB_DEBUG > 3) {
305 printf("thread: %u temp1: %x temp2: %x temp3: %x\n",
306 thread, temp1, temp2, temp3);
307 printf("src_addr: %x dst_addr: %x src_port: %x "
308 "dst_port: %x protocol: %x\n", *src_addr, *dst_addr,
309 *src_port, *dst_port, *protocol);
314 printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
320 uint8_t calculate_lb_thread_pub(struct rte_mbuf *pkt, void *arg)
322 uint32_t hash_key[2], hash_ipv4;
323 uint32_t temp1, temp2, temp3;
325 struct pipeline_loadb_in_port_h_arg *ap = arg;
326 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *) ap->p;
327 uint8_t nthreads = p_loadb->n_vnf_threads;
328 union rte_thash_tuple tuple;
335 struct lb_pkt *lb_pkt = (struct lb_pkt *)
336 RTE_MBUF_METADATA_UINT8_PTR(pkt,
339 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) == ETHER_TYPE_IPv6) {
340 src_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.src_addr;
341 dst_addr = (uint32_t *)&lb_pkt->ipv6_port.ipv6.dst_addr;
342 src_port = &lb_pkt->ipv6_port.src_port;
343 dst_port = &lb_pkt->ipv6_port.dst_port;
344 protocol = &lb_pkt->ipv6_port.ipv6.proto;
346 src_addr = &lb_pkt->ipv4_port.ipv4.src_addr;
347 dst_addr = &lb_pkt->ipv4_port.ipv4.dst_addr;
348 src_port = &lb_pkt->ipv4_port.src_port;
349 dst_port = &lb_pkt->ipv4_port.dst_port;
350 protocol = &lb_pkt->ipv4_port.ipv4.next_proto_id;
353 switch (p_loadb->n_lb_tuples) {
358 temp1 = *src_addr ^ *src_port;
359 temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^
360 (temp1 >> 8) ^ temp1;
361 temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
363 /* To select the thread */
364 thread = temp3 % nthreads;
365 /* To select the Q */
366 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
367 (thread + 1) - p_loadb->p.n_ports_in);
374 hash_key[0] = rte_bswap32(*src_addr);
377 hash_ipv4 = rte_jhash(&hash_key[0], 4, 0);
379 /* To select the thread */
380 thread = hash_ipv4 % nthreads;
381 /* To select the Q */
382 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
383 (thread + 1) - p_loadb->p.n_ports_in);
386 printf("thread: %u hash: %x hash_key: %x\n",
387 thread, hash_ipv4, hash_key[0]);
393 hash_key[0] = rte_bswap32(*src_addr);
394 hash_key[1] = *src_port << 16;
397 hash_ipv4 = rte_jhash(&hash_key[0], 6, 0);
399 /* To select the thread */
400 thread = hash_ipv4 % nthreads;
401 /* To select the Q */
402 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
403 (thread + 1) - p_loadb->p.n_ports_in);
405 if (LOADB_DEBUG > 3) {
406 printf("thread: %u hash: %x hash_key0: %x "
407 "hash_key1: %x\n", thread, hash_ipv4,
408 hash_key[0], hash_key[1]);
409 printf("public_addr: %x public_port: %x\n",
410 hash_key[0], *src_port);
415 printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
420 tuple.v4.src_addr = rte_bswap32(*src_addr);
421 tuple.v4.dst_addr = rte_bswap32(*dst_addr);
422 tuple.v4.sport = *src_port;
423 tuple.v4.dport = *dst_port;
426 hash_ipv4 = rte_softrss((uint32_t *)&tuple,
427 RTE_THASH_V4_L4_LEN, default_rss_key);
430 /* To select the thread */
431 thread = hash_ipv4 % nthreads;
432 /* To select the Q */
433 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
434 (thread + 1) - p_loadb->p.n_ports_in);
436 if (LOADB_DEBUG > 3) {
437 printf("src_addr: %x dst_addr: %x src_port: %x "
438 "dst_port: %x\n", tuple.v4.src_addr,
439 tuple.v4.dst_addr, tuple.v4.sport, tuple.v4.dport);
441 printf("thread: %u hash: %x\n", thread, hash_ipv4);
447 if (rte_be_to_cpu_16(lb_pkt->eth.ether_type) ==
449 /* point to last 32 bits of IPv6 addresses*/
455 temp1 = *src_addr ^ *dst_addr ^ *src_port ^
456 *dst_port ^ *protocol;
457 temp2 = (temp1 >> 24) ^ (temp1 >> 16) ^
458 (temp1 >> 8) ^ temp1;
459 temp3 = (temp2 >> 4) ^ (temp2 & 0xf);
461 /* To select the thread */
462 thread = temp3 % nthreads;
463 /* To select the Q */
464 thread = ap->in_port_id + (p_loadb->p.n_ports_in *
465 (thread + 1) - p_loadb->p.n_ports_in);
467 if (LOADB_DEBUG > 3) {
468 printf("src_addr: %x dst_addr: %x src_port: %x "
469 "dst_port: %x protocol: %x\n", *src_addr, *dst_addr,
470 *src_port, *dst_port, *protocol);
472 printf("thread: %u temp1: %x temp2: %x temp3: %x\n",
473 thread, temp1, temp2, temp3);
479 printf("Invalid n_lb_tuples: %d\n", p_loadb->n_lb_tuples);
486 pkt_work_loadb_key_prv(
487 struct rte_mbuf *pkt,
488 __rte_unused uint32_t pkt_num,
491 struct pipeline_loadb_in_port_h_arg *ap = arg;
492 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
493 uint32_t outport_offset = p_loadb->outport_offset;
495 struct lb_pkt *lb_pkt = (struct lb_pkt *)
496 RTE_MBUF_METADATA_UINT8_PTR(pkt,
498 uint32_t *out_port = RTE_MBUF_METADATA_UINT32_PTR(pkt,
501 #ifdef MY_LOADB_DBG_PRINT
502 if (LOADB_DEBUG == 3)
503 printf("Start pkt_work_loadb_key\n");
506 if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
508 lb_pkt_print_count++;
509 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
510 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
511 rte_be_to_cpu_16(lb_pkt->eth.ether_type),
512 lb_pkt->ipv4_port.ipv4.next_proto_id, ETH_TYPE_ARP,
513 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
517 *out_port = calculate_lb_thread_prv(pkt, arg);
519 p_loadb->receivedLBPktCount++;
521 #ifdef MY_LOADB_DBG_PRINT
522 if (LOADB_DEBUG == 3)
523 printf("End pkt_work_loadb_key\n");
528 pkt_work_loadb_key_pub(
529 struct rte_mbuf *pkt,
530 __rte_unused uint32_t pkt_num,
533 struct pipeline_loadb_in_port_h_arg *ap = arg;
534 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
535 uint32_t outport_offset = p_loadb->outport_offset;
537 struct lb_pkt *lb_pkt = (struct lb_pkt *)
538 RTE_MBUF_METADATA_UINT8_PTR(pkt,
540 uint32_t *out_port = RTE_MBUF_METADATA_UINT32_PTR(pkt,
543 #ifdef MY_LOADB_DBG_PRINT
544 if (LOADB_DEBUG == 3)
545 printf("Start pkt_work_loadb_key\n");
548 if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
550 lb_pkt_print_count++;
551 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
552 "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
553 rte_be_to_cpu_16(lb_pkt->eth.ether_type),
554 lb_pkt->ipv4_port.ipv4.next_proto_id, ETH_TYPE_ARP,
555 ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
559 *out_port = calculate_lb_thread_pub(pkt, arg);
561 p_loadb->receivedLBPktCount++;
562 #ifdef MY_LOADB_DBG_PRINT
563 if (LOADB_DEBUG == 3)
564 printf("End pkt_work_loadb_key\n");
569 pkt4_work_loadb_key_prv(
570 struct rte_mbuf **pkt,
571 __rte_unused uint32_t pkt_num,
574 struct pipeline_loadb_in_port_h_arg *ap = arg;
575 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
576 uint32_t outport_offset = p_loadb->outport_offset;
578 uint32_t *out_port0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
580 uint32_t *out_port1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
582 uint32_t *out_port2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
584 uint32_t *out_port3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
587 struct lb_pkt *lb_pkt0 = (struct lb_pkt *)
588 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
590 struct lb_pkt *lb_pkt1 = (struct lb_pkt *)
591 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
593 struct lb_pkt *lb_pkt2 = (struct lb_pkt *)
594 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
596 struct lb_pkt *lb_pkt3 = (struct lb_pkt *)
597 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
600 #ifdef MY_LOADB_DBG_PRINT
601 if (LOADB_DEBUG == 3)
602 printf("Start pkt4_work_loadb_key\n");
605 if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
607 lb_pkt_print_count++;
609 printf("\nEth Typ %x, Prot %x\n",
610 rte_be_to_cpu_16(lb_pkt0->eth.ether_type),
611 lb_pkt0->ipv4_port.ipv4.next_proto_id);
614 lb_pkt_print_count++;
616 printf("\nEth Typ %x, Prot %x\n",
617 rte_be_to_cpu_16(lb_pkt1->eth.ether_type),
618 lb_pkt1->ipv4_port.ipv4.next_proto_id);
621 lb_pkt_print_count++;
623 printf("\nEth Typ %x, Prot %x\n",
624 rte_be_to_cpu_16(lb_pkt2->eth.ether_type),
625 lb_pkt2->ipv4_port.ipv4.next_proto_id);
628 lb_pkt_print_count++;
630 printf("\nEth Typ %x, Prot %x\n",
631 rte_be_to_cpu_16(lb_pkt3->eth.ether_type),
632 lb_pkt3->ipv4_port.ipv4.next_proto_id);
634 *out_port0 = calculate_lb_thread_prv(pkt[0], arg);
635 *out_port1 = calculate_lb_thread_prv(pkt[1], arg);
636 *out_port2 = calculate_lb_thread_prv(pkt[2], arg);
637 *out_port3 = calculate_lb_thread_prv(pkt[3], arg);
639 p_loadb->receivedLBPktCount += 4;
641 #ifdef MY_LOADB_DBG_PRINT
642 if (LOADB_DEBUG == 3)
643 printf("End pkt4_work_loadb_key\n");
649 pkt4_work_loadb_key_pub(
650 struct rte_mbuf **pkt,
651 __rte_unused uint32_t pkt_num,
654 struct pipeline_loadb_in_port_h_arg *ap = arg;
655 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)ap->p;
656 uint32_t outport_offset = p_loadb->outport_offset;
658 uint32_t *out_port0 = RTE_MBUF_METADATA_UINT32_PTR(pkt[0],
660 uint32_t *out_port1 = RTE_MBUF_METADATA_UINT32_PTR(pkt[1],
662 uint32_t *out_port2 = RTE_MBUF_METADATA_UINT32_PTR(pkt[2],
664 uint32_t *out_port3 = RTE_MBUF_METADATA_UINT32_PTR(pkt[3],
667 struct lb_pkt *lb_pkt0 = (struct lb_pkt *)
668 RTE_MBUF_METADATA_UINT8_PTR(pkt[0],
670 struct lb_pkt *lb_pkt1 = (struct lb_pkt *)
671 RTE_MBUF_METADATA_UINT8_PTR(pkt[1],
673 struct lb_pkt *lb_pkt2 = (struct lb_pkt *)
674 RTE_MBUF_METADATA_UINT8_PTR(pkt[2],
676 struct lb_pkt *lb_pkt3 = (struct lb_pkt *)
677 RTE_MBUF_METADATA_UINT8_PTR(pkt[3],
680 #ifdef MY_LOADB_DBG_PRINT
681 if (LOADB_DEBUG == 3)
682 printf("Start pkt4_work_loadb_key\n");
685 if ((LOADB_DEBUG > 2) && (lb_pkt_print_count < 10)) {
687 lb_pkt_print_count++;
689 printf("\nEth Typ %x, Prot %x\n",
690 rte_be_to_cpu_16(lb_pkt0->eth.ether_type),
691 lb_pkt0->ipv4_port.ipv4.next_proto_id);
694 lb_pkt_print_count++;
696 printf("\nEth Typ %x, Prot %x\n",
697 rte_be_to_cpu_16(lb_pkt1->eth.ether_type),
698 lb_pkt1->ipv4_port.ipv4.next_proto_id);
701 lb_pkt_print_count++;
703 printf("\nEth Typ %x, Prot %x\n",
704 rte_be_to_cpu_16(lb_pkt2->eth.ether_type),
705 lb_pkt2->ipv4_port.ipv4.next_proto_id);
708 lb_pkt_print_count++;
710 printf("\nEth Typ %x, Prot %x\n",
711 rte_be_to_cpu_16(lb_pkt3->eth.ether_type),
712 lb_pkt3->ipv4_port.ipv4.next_proto_id);
714 *out_port0 = calculate_lb_thread_prv(pkt[0], arg);
715 *out_port1 = calculate_lb_thread_pub(pkt[1], arg);
716 *out_port2 = calculate_lb_thread_pub(pkt[2], arg);
717 *out_port3 = calculate_lb_thread_pub(pkt[3], arg);
719 p_loadb->receivedLBPktCount += 4;
720 #ifdef MY_LOADB_DBG_PRINT
721 if (LOADB_DEBUG == 3)
722 printf("End pkt4_work_loadb_key\n");
727 PIPELINE_LOADB_KEY_PORT_IN_AH(port_in_ah_loadb_key_prv,
728 pkt_work_loadb_key_prv,
729 pkt4_work_loadb_key_prv);
731 PIPELINE_LOADB_KEY_PORT_IN_AH(port_in_ah_loadb_key_pub,
732 pkt_work_loadb_key_pub,
733 pkt4_work_loadb_key_pub);
736 pipeline_loadb_parse_args(struct pipeline_loadb *p,
737 struct pipeline_params *params)
739 uint32_t outport_offset_present = 0;
740 uint32_t n_vnf_threads_present = 0;
741 uint32_t pktq_in_prv_present = 0;
742 uint32_t prv_que_handler_present = 0;
743 uint32_t prv_to_pub_map_present = 0;
744 uint8_t n_prv_in_port = 0;
747 /* Default number of tuples */
751 printf("LOADB pipeline_loadb_parse_args params->n_args: %d\n",
754 for (i = 0; i < params->n_args; i++) {
755 char *arg_name = params->args_name[i];
756 char *arg_value = params->args_value[i];
759 printf("LOADB args[%d]: %s %d, %s\n", i, arg_name,
760 atoi(arg_value), arg_value);
762 /* outport_offset = 128 + 8 */
763 if (strcmp(arg_name, "outport_offset") == 0) {
764 if (outport_offset_present)
766 outport_offset_present = 1;
768 p->outport_offset = atoi(arg_value);
769 if (p->outport_offset <= 0) {
770 printf("Outport_offset is invalid\n");
773 printf("outport_offset: 0x%x\n", p->outport_offset);
776 /* n_vnf_threads = 4 */
777 if (strcmp(arg_name, "n_vnf_threads") == 0) {
778 if (n_vnf_threads_present)
780 n_vnf_threads_present = 1;
782 p->n_vnf_threads = atoi(arg_value);
784 total_vnf_threads += p->n_vnf_threads;
786 if ((p->n_vnf_threads <= 0)
787 || (total_vnf_threads > MAX_VNF_THREADS)) {
788 printf("n_vnf_threads : MIN->0 MAX->16\n");
791 printf("n_vnf_threads : 0x%x\n", p->n_vnf_threads);
792 printf("total_vnf_threads: 0x%x\n", total_vnf_threads);
797 if (strcmp(arg_name, "pktq_in_prv") == 0) {
798 if (pktq_in_prv_present) {
799 printf("Duplicate pktq_in_prv ... "
800 "parse failed..\n\n");
803 pktq_in_prv_present = 1;
805 int rxport = 0, j = 0;
806 char phy_port_num[8];
807 char *token = strtok(arg_value, "RXQ");
810 while ((j < 7) && (token[j] != '.')) {
811 phy_port_num[j] = token[j];
814 phy_port_num[j] = '\0';
815 rxport = atoi(phy_port_num);
816 printf("token: %s, phy_port_str: %s, "
818 token, phy_port_num, rxport);
819 prv_in_port_a[n_prv_in_port++] = rxport;
822 if(rxport < PIPELINE_MAX_PORT_IN)
823 in_port_dir_a[rxport] = 1;
825 token = strtok(NULL, "RXQ");
828 if (n_prv_in_port == 0) {
829 printf("VNF common parse error - "
830 "no prv RX phy port\n");
836 /* pktq_in_prv_handler */
838 if (strcmp(arg_name, "prv_que_handler") == 0) {
840 if (prv_que_handler_present) {
841 printf("Duplicate pktq_in_prv ..\n\n");
844 prv_que_handler_present = 1;
849 /* get the first token */
850 token = strtok(arg_value, "(");
851 token = strtok(token, ")");
852 token = strtok(token, ",");
853 printf("***** prv_que_handler *****\n");
855 printf("string is :%s\n", token);
858 //printf("string is null\n");
859 printf("string is :%s\n", token);
861 /* walk through other tokens */
862 while (token != NULL) {
863 printf(" %s\n", token);
864 rxport = atoi(token);
865 prv_que_port_index[n_prv_in_port++] = rxport;
867 if(rxport < PIPELINE_MAX_PORT_IN)
868 in_port_egress_prv[rxport] = 1;
871 token = strtok(NULL, ",");
874 if (n_prv_in_port == 0) {
875 printf("VNF common parse err - no prv RX phy port\n");
882 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
883 if (prv_to_pub_map_present) {
884 printf("Duplicated prv_to_pub_map ... "
885 "parse failed ...\n");
888 prv_to_pub_map_present = 1;
890 int rxport = 0, txport = 0, j = 0, k = 0;
891 char rx_phy_port_num[5];
892 char tx_phy_port_num[5];
893 char *token = strtok(arg_value, "(");
896 while ((j < 4) && (token[j] != ',')) {
897 rx_phy_port_num[j] = token[j];
900 rx_phy_port_num[j] = '\0';
901 rxport = atoi(rx_phy_port_num);
905 while ((k < 4) && (token[j+k] != ')')) {
906 tx_phy_port_num[k] = token[j+k];
909 tx_phy_port_num[k] = '\0';
910 txport = atoi(tx_phy_port_num);
912 printf("token: %s,rx_phy_port_str: %s, phy_port_num "
913 "%d, tx_phy_port_str: %s, tx_phy_port_num %d\n",
914 token, rx_phy_port_num, rxport,
915 tx_phy_port_num, txport);
916 if(rxport < PIPELINE_MAX_PORT_IN)
917 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
918 (txport >= PIPELINE_MAX_PORT_IN) ||
919 (in_port_dir_a[rxport] != 1)) {
920 printf("CG-NAPT parse error - "
921 "incorrect prv-pub translation. Rx %d, "
922 "Tx %d, Rx Dir %d\n", rxport, txport,
923 in_port_dir_a[rxport]);
928 if (rxport < PIPELINE_MAX_PORT_IN)
929 prv_to_pub_map[rxport] = txport;
932 if(txport < PIPELINE_MAX_PORT_IN)
933 pub_to_prv_map[txport] = rxport;
934 token = strtok(NULL, "(");
939 /* Set number of tuples if available in config file */
940 if (strcmp(arg_name, "n_lb_tuples") == 0) {
941 p->n_lb_tuples = atoi(arg_value);
942 printf("n_lb_tuples: 0x%x\n", p->n_lb_tuples);
946 if (strcmp(arg_name, "loadb_debug") == 0) {
947 LOADB_DEBUG = atoi(arg_value);
951 /* any other Unknown argument return -1 */
954 /* Check that mandatory arguments are present */
955 if ((n_vnf_threads_present == 0) || (outport_offset_present == 0))
962 int check_loadb_thread(
963 struct app_params *app,
964 struct pipeline_params *params,
965 int32_t n_vnf_threads)
968 int pipeline_num = 0;
970 int dont_care = sscanf(params->name, "PIPELINE%d", &pipeline_num);
973 /* changed from pipeline_num+1 to +2 */
974 for (i = pipeline_num + 2; i < app->n_pipelines; i++) {
975 struct app_pipeline_params *p = &app->pipeline_params[i];
976 if (!strncmp(p->type, "LOADB", strlen(p->type)))
980 if (n_vnf_threads != count)
986 static void *pipeline_loadb_init(
987 struct pipeline_params *params,
988 __rte_unused void *arg)
989 /* arg is app parameter (struct app_params *app) */
990 /*save it for use in port in handler */
993 struct pipeline_loadb *p_loadb;
994 uint32_t size, i, in_ports_arg_size;
996 /* Check input arguments */
997 if ((params == NULL) ||
998 (params->n_ports_in == 0) || (params->n_ports_out == 0))
1001 /* Memory allocation */
1002 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_loadb));
1003 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1004 p_loadb = (struct pipeline_loadb *)p;
1008 strcpy(p->name, params->name);
1009 p->log_level = params->log_level;
1011 PLOG(p, HIGH, "LOADB");
1013 p_loadb->n_vnf_threads = 0;
1014 p_loadb->outport_offset = 0;
1015 p_loadb->receivedLBPktCount = 0;
1016 p_loadb->droppedLBPktCount = 0;
1017 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
1018 p_loadb->links_map[i] = 0xff;
1020 p_loadb->pipeline_num = 0xff;
1021 p_loadb->n_prv_Q = 0;
1022 p_loadb->n_pub_Q = 0;
1024 /* Parse arguments */
1026 if (pipeline_loadb_parse_args(p_loadb, params))
1031 struct rte_pipeline_params pipeline_params = {
1033 .socket_id = params->socket_id,
1034 .offset_port_id = 0,
1037 p->p = rte_pipeline_create(&pipeline_params);
1043 printf("Loadb p->p %p, socket %d\n", p->p,
1044 pipeline_params.socket_id);
1047 /* Memory allocation for in_port_h_arg */
1049 RTE_CACHE_LINE_ROUNDUP((sizeof(struct pipeline_loadb_in_port_h_arg))
1050 * (params->n_ports_in));
1051 struct pipeline_loadb_in_port_h_arg *ap =
1052 (struct pipeline_loadb_in_port_h_arg *)
1055 RTE_CACHE_LINE_SIZE);
1059 printf("ap pointer %p\n", ap);
1062 p->n_ports_in = params->n_ports_in;
1063 for (i = 0; i < p->n_ports_in; i++) {
1064 /* passing our loadb pipeline in call back arg */
1065 (ap[i]).p = p_loadb;
1066 (ap[i]).in_port_id = i;
1068 struct rte_pipeline_port_in_params port_params = {
1070 pipeline_port_in_params_get_ops(¶ms->port_in
1073 pipeline_port_in_params_convert(¶ms->port_in
1075 /* Public in-port handler */
1078 .burst_size = params->port_in[i].burst_size,
1081 /* Private in-port handler */
1082 if (is_port_index_privte(i)) {/* Multiport changes*/
1083 printf("LOADB %d port is Prv\n", i);
1084 port_params.f_action = port_in_ah_loadb_key_prv;
1086 printf("LOADB %d port is Pub\n", i);
1087 port_params.f_action = port_in_ah_loadb_key_pub;
1090 int status = rte_pipeline_port_in_create(p->p,
1095 rte_pipeline_free(p->p);
1102 p_loadb->n_pub_Q = p_loadb->p.n_ports_in - p_loadb->n_prv_Q;
1103 printf("LOADB : n_prv_Q - %d n_pub_Q - %d\n",
1104 p_loadb->n_prv_Q, p_loadb->n_pub_Q);
1106 for (i = 0; i < p->n_ports_in; i++) {
1107 printf("is_port_index_privte(%d): %d\n", i,
1108 is_port_index_privte(i));
1109 printf("is_phy_port_privte(%d): %d\n", i,
1110 is_phy_port_privte(i));
1111 printf("action handler of %d:%p\n", i,
1112 p_loadb->p.p->ports_in[i].f_action);
1116 p->n_ports_out = params->n_ports_out;
1117 for (i = 0; i < p->n_ports_out; i++) {
1118 struct rte_pipeline_port_out_params port_params = {
1120 pipeline_port_out_params_get_ops(¶ms->port_out
1123 pipeline_port_out_params_convert(¶ms->port_out
1129 int status = rte_pipeline_port_out_create(p->p,
1131 &p->port_out_id[i]);
1134 rte_pipeline_free(p->p);
1139 printf("Outport p->port_out_id[%d] %p\n", i,
1140 &p->port_out_id[i]);
1143 int pipeline_num = 0;
1144 int dont_care = sscanf(params->name, "PIPELINE%d", &pipeline_num);
1145 if (dont_care != 1) {
1146 printf("Unable to read pipeline number\n");
1149 p_loadb->pipeline_num = pipeline_num;
1151 set_outport_id(pipeline_num, p, lb_outport_id);
1152 set_phy_outport_map(pipeline_num, p_loadb->links_map);
1154 set_port_to_loadb_map(pipeline_num);
1156 register_loadb_to_arp(pipeline_num, p, app);
1158 register_pipeline_Qs(p_loadb->pipeline_num, p);
1159 set_link_map(p_loadb->pipeline_num, p, p_loadb->links_map);
1160 //set_outport_id(p_loadb->pipeline_num, p, p_loadb->outport_id);
1166 struct rte_table_array_params table_array_params = {
1167 .n_entries = MAX_VNF_THREADS,
1168 .offset = p_loadb->outport_offset,
1170 struct rte_pipeline_table_params table_params = {
1171 .ops = &rte_table_array_ops,
1172 .arg_create = &table_array_params,
1173 .f_action_hit = NULL,
1174 .f_action_miss = NULL,
1176 .action_data_size = 0,
1181 status = rte_pipeline_table_create(p->p,
1186 rte_pipeline_free(p->p);
1192 /* Connecting input ports to tables */
1193 for (i = 0; i < p->n_ports_in; i++) {
1194 int status = rte_pipeline_port_in_connect_to_table(
1200 rte_pipeline_free(p->p);
1206 /* Enable input ports */
1207 for (i = 0; i < p->n_ports_in; i++) {
1208 int status = rte_pipeline_port_in_enable(p->p,
1212 rte_pipeline_free(p->p);
1218 /* Initialize table entries */
1220 for (i = 0; i < MAX_VNF_THREADS; i++) {
1221 struct rte_table_array_key key = {
1224 struct loadb_table_entry entry;
1225 entry.head.action = RTE_PIPELINE_ACTION_PORT;
1227 if (i < p->n_ports_out) {
1228 entry.head.port_id = p->port_out_id[i];
1229 printf("\ni %d, p->port_out_id[%d] %d", i, i,
1232 /* First CGNAPT thread */
1233 entry.head.port_id = p->port_out_id[0];
1234 entry.head.action = RTE_PIPELINE_ACTION_DROP;
1237 struct rte_pipeline_table_entry *entry_ptr;
1238 int key_found, status;
1239 status = rte_pipeline_table_entry_add(
1243 (struct rte_pipeline_table_entry *)
1248 rte_pipeline_free(p->p);
1254 /* Add default entry to tables */
1256 struct rte_pipeline_table_entry default_entry = {
1257 .action = RTE_PIPELINE_ACTION_PORT,
1258 /* LB by default forward to 1st cgnat thread */
1259 .port_id = p->port_out_id[0],
1262 struct rte_pipeline_table_entry *default_entry_ptr;
1264 int status = rte_pipeline_table_default_entry_add(
1268 &default_entry_ptr);
1271 rte_pipeline_free(p->p);
1278 /* Check pipeline consistency */
1279 if (rte_pipeline_check(p->p) < 0) {
1280 rte_pipeline_free(p->p);
1285 /* Message queues */
1286 p->n_msgq = params->n_msgq;
1287 for (i = 0; i < p->n_msgq; i++)
1288 p->msgq_in[i] = params->msgq_in[i];
1289 for (i = 0; i < p->n_msgq; i++)
1290 p->msgq_out[i] = params->msgq_out[i];
1292 /* Message handlers */
1293 memcpy(p->handlers, handlers, sizeof(p->handlers));
1294 memcpy(p_loadb->custom_handlers,
1295 custom_handlers, sizeof(p_loadb->custom_handlers));
1300 static int pipeline_loadb_free(void *pipeline)
1302 struct pipeline *p = (struct pipeline *)pipeline;
1304 /* Check input arguments */
1308 /* Free resources */
1309 rte_pipeline_free(p->p);
1315 pipeline_loadb_track(void *pipeline,
1316 __rte_unused uint32_t port_in, uint32_t *port_out)
1318 struct pipeline *p = (struct pipeline *)pipeline;
1320 /* Check input arguments */
1321 if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
1324 if (p->n_ports_in == 1) {
1332 static int pipeline_loadb_timer(void *pipeline)
1334 struct pipeline *p = (struct pipeline *)pipeline;
1336 pipeline_msg_req_handle(p);
1337 rte_pipeline_flush(p->p);
1342 void *pipeline_loadb_msg_req_entry_dbg_handler(struct pipeline *p, void *msg)
1344 struct pipeline_loadb_entry_dbg_msg_rsp *rsp = msg;
1346 struct pipeline_loadb *p_loadb = (struct pipeline_loadb *)p;
1350 printf("LoadB debug handler called with args %x %x, offset %d\n",
1351 Msg[LOADB_DBG_CMD_OFST], Msg[LOADB_DBG_CMD_OFST + 1],
1352 LOADB_DBG_CMD_OFST);
1354 if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_STATS_SHOW) {
1355 printf("\nLoadB Packet Stats: Received %" PRIu64 "\n",
1356 p_loadb->receivedLBPktCount);
1359 if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_STATS_CLEAR) {
1360 printf("\nLoadB Packet Stats: Received %" PRIu64 "\n",
1361 p_loadb->receivedLBPktCount);
1362 p_loadb->receivedLBPktCount = 0;
1366 if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_DBG_LEVEL) {
1367 LOADB_DEBUG = Msg[LOADB_DBG_CMD_OFST + 1];
1368 printf("LOADB Debug level set to %d\n", LOADB_DEBUG);
1369 lb_pkt_print_count = 0;
1372 if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_DBG_SHOW) {
1373 printf("\nLoadB DBG Level: %u\n", LOADB_DEBUG);
1376 if (Msg[LOADB_DBG_CMD_OFST] == LOADB_DBG_CMD_IF_STATS) {
1380 for (i = 0; i < p->n_ports_in; i++) {
1381 struct rte_eth_stats stats;
1382 rte_eth_stats_get(p_loadb->links_map[i], &stats);
1383 if (is_phy_port_privte(i))
1384 printf("Private Port Stats %d\n", i);
1386 printf("Public Port Stats %d\n", i);
1387 printf("\n\tipackets : %" PRIu64 "\n\topackets : %"
1388 PRIu64 "\n\tierrors : %" PRIu64
1389 "\n\toerrors : %" PRIu64 "\n\trx_nombuf: %"
1390 PRIu64 "\n", stats.ipackets, stats.opackets,
1391 stats.ierrors, stats.oerrors, stats.rx_nombuf);
1392 if (is_phy_port_privte(i))
1393 printf("Private Q: ");
1395 printf("Public Q: ");
1396 for (j = 0; j < RTE_ETHDEV_QUEUE_STAT_CNTRS; j++)
1397 printf(" %" PRIu64 ", %" PRIu64 "|",
1398 stats.q_ipackets[j],
1399 stats.q_opackets[j]);
1411 struct pipeline_be_ops pipeline_loadb_be_ops = {
1412 .f_init = pipeline_loadb_init,
1413 .f_free = pipeline_loadb_free,
1415 .f_timer = pipeline_loadb_timer,
1416 .f_track = pipeline_loadb_track,