[l2l3 stack] implements new arp state machine & arp buffering
[samplevnf.git] / common / VIL / pipeline_txrx / pipeline_txrx_be.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 */
16
17 #include <string.h>
18
19 #include <rte_common.h>
20 #include <rte_malloc.h>
21 #include <rte_byteorder.h>
22 #include <rte_table_stub.h>
23 #include <rte_table_hash.h>
24 #include <rte_pipeline.h>
25
26 #include "pipeline_txrx_be.h"
27 #include "pipeline_actions_common.h"
28 #include "parser.h"
29 #include "hash_func.h"
30 #include "pipeline_arpicmp_be.h"
31 #include "vnf_common.h"
32 #include "app.h"
33 #ifndef VNF_ACL
34 #include "lib_icmpv6.h"
35 #endif
36
37 uint8_t TXRX_DEBUG;
38 int pkt_burst_cnt;
39
40
41 struct pipeline_txrx {
42         struct pipeline p;
43         pipeline_msg_req_handler
44                 custom_handlers[PIPELINE_TXRX_MSG_REQS];
45         uint64_t receivedPktCount;
46         uint64_t droppedPktCount;
47         uint8_t links_map[PIPELINE_MAX_PORT_IN];
48         uint8_t outport_id[PIPELINE_MAX_PORT_IN];
49         uint8_t pipeline_num;
50         uint8_t txrx_type;
51 } __rte_cache_aligned;
52
53 enum{
54 TYPE_TXTX,
55 TYPE_RXRX,
56 };
57 static void *pipeline_txrx_msg_req_custom_handler(struct pipeline *p,
58                                                         void *msg);
59 static pipeline_msg_req_handler handlers[] = {
60         [PIPELINE_MSG_REQ_PING] =
61                 pipeline_msg_req_ping_handler,
62         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
63                 pipeline_msg_req_stats_port_in_handler,
64         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
65                 pipeline_msg_req_stats_port_out_handler,
66         [PIPELINE_MSG_REQ_STATS_TABLE] =
67                 pipeline_msg_req_stats_table_handler,
68         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
69                 pipeline_msg_req_port_in_enable_handler,
70         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
71                 pipeline_msg_req_port_in_disable_handler,
72         [PIPELINE_MSG_REQ_CUSTOM] =
73                 pipeline_txrx_msg_req_custom_handler,
74
75 };
76
77 static void *pipeline_txrx_msg_req_entry_dbg_handler(struct pipeline *p,
78                                                                  void *msg);
79 static void *pipeline_txrx_msg_req_entry_dbg_handler(
80         __rte_unused struct pipeline *p,
81         __rte_unused void *msg)
82 {
83         /*have to handle dbg commands*/
84         return NULL;
85 }
86
87 static __rte_unused pipeline_msg_req_handler custom_handlers[] = {
88         [PIPELINE_TXRX_MSG_REQ_ENTRY_DBG] =
89                         pipeline_txrx_msg_req_entry_dbg_handler,
90 };
91
92 /**
93  * Function for pipeline custom handlers
94  *
95  * @param pipeline
96  *  A void pointer to pipeline
97  * @param msg
98  *  void pointer for incoming data
99  *
100  * @return
101  *  void pointer of response
102  */
103 void *pipeline_txrx_msg_req_custom_handler(struct pipeline *p, void *msg)
104 {
105         struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)p;
106         struct pipeline_custom_msg_req *req = msg;
107         pipeline_msg_req_handler f_handle;
108
109         f_handle = (req->subtype < PIPELINE_TXRX_MSG_REQS) ?
110                         p_txrx->custom_handlers[req->subtype] :
111                         pipeline_msg_req_invalid_handler;
112
113         if (f_handle == NULL)
114                 f_handle = pipeline_msg_req_invalid_handler;
115
116         return f_handle(p, req);
117 }
118
119 /* Not needed as no arguments are needed for TxRX
120  * ARP arguments are handled in ARP module
121  */
122 int
123 pipeline_txrx_parse_args(struct pipeline_txrx *p,
124                          struct pipeline_params *params);
125 int
126 pipeline_txrx_parse_args(struct pipeline_txrx *p,
127                          struct pipeline_params *params)
128 {
129         uint32_t i;
130         uint8_t txrx_type_present = 0;
131
132         if (TXRX_DEBUG > 2)
133                 printf("TXRX pipeline_txrx_parse_args params->n_args: %d\n",
134                         params->n_args);
135
136         for (i = 0; i < params->n_args; i++) {
137                 char *arg_name = params->args_name[i];
138                 char *arg_value = params->args_value[i];
139
140                 if (TXRX_DEBUG > 2)
141                         printf("TXRX args[%d]: %s %d, %s\n", i, arg_name,
142                                 atoi(arg_value), arg_value);
143
144                  /* txrx_type = val */
145                 if (strcmp(arg_name, "pipeline_txrx_type") == 0) {
146                         if (txrx_type_present)
147                                 return -1;
148                          txrx_type_present = 1;
149
150
151                         if (strcmp(arg_value, "TXTX") == 0) {
152                                 p->txrx_type = TYPE_TXTX;
153                                 printf("pipeline_txrx_type is TXTX\n");
154                         }
155                         if (strcmp(arg_value, "RXRX") == 0) {
156                                 p->txrx_type = TYPE_RXRX;
157                                 printf("pipeline_txrx_type is RXRX\n");
158                         }
159                         continue;
160                 }
161         }
162
163         if (!txrx_type_present) {
164                 printf("TXRX type not specified\n");
165                 return -1;
166         }
167
168         return 0;
169
170 }
171
172 uint32_t txrx_pkt_print_count;
173 static inline void
174 pkt_work_txrx(struct rte_mbuf *pkt, uint32_t pkt_num, void *arg)
175 {
176
177         struct pipeline_txrx_in_port_h_arg *ap = arg;
178         struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)ap->p;
179         uint8_t solicited_node_multicast_addr[16] =
180                                         {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
181
182         p_txrx->receivedPktCount++;
183
184         if (p_txrx->txrx_type == TYPE_TXTX)
185                 return;
186
187         uint8_t in_port_id = pkt->port;
188         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
189
190         uint32_t pkt_mask = 1 << pkt_num;
191         /* ARP outport number */
192         uint32_t out_port = p_txrx->p.n_ports_out - 1;
193
194         uint16_t *eth_proto =
195                         RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
196
197         uint8_t *protocol;
198         uint32_t prot_offset =
199                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
200
201         #ifdef IPV6
202         struct ipv6_hdr *ipv6_h;
203         ipv6_h = rte_pktmbuf_mtod_offset (pkt, struct ipv6_hdr *, sizeof(struct ether_hdr));
204         uint32_t prot_offset_ipv6 =
205                          MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
206
207         if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6)
208                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset_ipv6);
209         else
210                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
211         #else
212         protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
213         #endif
214
215
216         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
217                 print_pkt1(pkt);
218                 txrx_pkt_print_count++;
219                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
220                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
221                                  rte_be_to_cpu_16(*eth_proto), *protocol, ETH_TYPE_ARP,
222                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
223         }
224         /* Classifier for ICMP pass-through*/
225         struct app_link_params *link;
226
227         link = &myApp->link_params[in_port_id];
228
229         /* header room + eth hdr size + src_aadr offset in ip header */
230         uint32_t dst_addr_offset =
231                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
232         uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
233
234         if (TXRX_DEBUG > 2)
235                 if (rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV4)
236                         printf ("%s: linkIp: %x, dst_addr: %x\n", __FUNCTION__, link->ip, *dst_addr);
237
238         #if 1
239         switch (rte_be_to_cpu_16(*eth_proto)) {
240         case ETH_TYPE_ARP:
241                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
242                         out_port, pkt);
243                 rte_pipeline_ah_packet_hijack(p_txrx->p.p, pkt_mask);
244         break;
245
246         case ETH_TYPE_IPV4:
247                 if ((*protocol == IP_PROTOCOL_ICMP)  &&
248                         (link->ip == rte_be_to_cpu_32(*dst_addr))) {
249                         if (is_phy_port_privte(pkt->port)) {
250                                 rte_pipeline_port_out_packet_insert(
251                                         p_txrx->p.p,
252                                         out_port, pkt);
253                                 rte_pipeline_ah_packet_drop(
254                                         p_txrx->p.p,
255                                         pkt_mask);
256                         }
257                 }
258
259         break;
260
261         #ifdef IPV6
262         case ETH_TYPE_IPV6:
263                 if (*protocol == ICMPV6_PROTOCOL_ID) {
264                         if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
265                         || !memcmp(ipv6_h->dst_addr, solicited_node_multicast_addr, 13)) {
266                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
267                                         out_port, pkt);
268                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
269                         } else {
270                                 printf("Dropping the IPv6 pkt\n");
271                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
272                         }
273                 }
274         break;
275         #endif
276
277         default: /* Not valid pkt */
278                 printf("Dropping the pkt\n");
279                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
280
281         }
282         #endif
283
284 }
285
286 static inline void
287 pkt4_work_txrx(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
288 {
289         struct pipeline_txrx_in_port_h_arg *ap = arg;
290         struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)ap->p;
291         uint8_t solicited_node_multicast_addr[16] =
292                                         {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293                 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
294
295         if (p_txrx->txrx_type == TYPE_TXTX)
296                 return;
297
298         uint16_t in_port_id = (*pkt)->port;
299         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
300
301
302         uint32_t pkt_mask0 = 1 << pkt_num;
303         uint32_t pkt_mask1 = 1 << (pkt_num + 1);
304         uint32_t pkt_mask2 = 1 << (pkt_num + 2);
305         uint32_t pkt_mask3 = 1 << (pkt_num + 3);
306
307         /* ARP outport number */
308         uint32_t out_port = p_txrx->p.n_ports_out - 1;
309
310         uint16_t *eth_proto0 =
311                         RTE_MBUF_METADATA_UINT16_PTR(pkt[0], eth_proto_offset);
312         uint16_t *eth_proto1 =
313                         RTE_MBUF_METADATA_UINT16_PTR(pkt[1], eth_proto_offset);
314         uint16_t *eth_proto2 =
315                         RTE_MBUF_METADATA_UINT16_PTR(pkt[2], eth_proto_offset);
316         uint16_t *eth_proto3 =
317                         RTE_MBUF_METADATA_UINT16_PTR(pkt[3], eth_proto_offset);
318
319         uint8_t *protocol0, *protocol1, *protocol2, *protocol3;
320         uint32_t prot_offset =
321                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
322
323         #ifdef IPV6
324         struct ipv6_hdr *ipv6_h0, *ipv6_h1, *ipv6_h2, *ipv6_h3;
325         ipv6_h0 = rte_pktmbuf_mtod_offset (pkt[0], struct ipv6_hdr *, sizeof(struct ether_hdr));
326         uint32_t prot_offset_ipv6 =
327                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
328
329 /* --0-- */
330         if (rte_be_to_cpu_16(*eth_proto0) == ETHER_TYPE_IPv6)
331                 protocol0 =
332                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset_ipv6);
333         else
334                 protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
335
336 /* --1-- */
337         ipv6_h1 = rte_pktmbuf_mtod_offset (pkt[1], struct ipv6_hdr *, sizeof(struct ether_hdr));
338         if (rte_be_to_cpu_16(*eth_proto1) == ETHER_TYPE_IPv6)
339                 protocol1 =
340                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset_ipv6);
341         else
342                 protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
343
344 /* --2-- */
345         ipv6_h2 = rte_pktmbuf_mtod_offset (pkt[2], struct ipv6_hdr *, sizeof(struct ether_hdr));
346         if (rte_be_to_cpu_16(*eth_proto2) == ETHER_TYPE_IPv6)
347                 protocol2 =
348                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset_ipv6);
349         else
350                 protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
351
352 /* --3-- */
353         ipv6_h3 = rte_pktmbuf_mtod_offset (pkt[3], struct ipv6_hdr *, sizeof(struct ether_hdr));
354         if (rte_be_to_cpu_16(*eth_proto3) == ETHER_TYPE_IPv6)
355                 protocol3 =
356                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset_ipv6);
357         else
358                 protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
359         #else
360         protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
361         protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
362         protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
363         protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
364         #endif
365
366         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
367                 print_pkt1(pkt[0]);
368                 txrx_pkt_print_count++;
369                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
370                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
371                                  rte_be_to_cpu_16(*eth_proto0), *protocol0, ETH_TYPE_ARP,
372                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
373         }
374
375         struct app_link_params *link;
376
377         link = &myApp->link_params[in_port_id];
378
379         /* header room + eth hdr size + src_aadr offset in ip header */
380         uint32_t dst_addr_offset0 =
381                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
382         uint32_t *dst_addr0 =
383                         RTE_MBUF_METADATA_UINT32_PTR(pkt[0], dst_addr_offset0);
384
385         if (TXRX_DEBUG > 2)
386                 if (rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
387                         printf ("%s: linkIp: %x, dst_addr0: %x\n", __FUNCTION__, link->ip, *dst_addr0);
388
389         #if 1
390         switch (rte_be_to_cpu_16(*eth_proto0)) {
391         case ETH_TYPE_ARP:
392                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
393                         out_port, pkt[0]);
394                 rte_pipeline_ah_packet_hijack(p_txrx->p.p, pkt_mask0);
395         break;
396
397         case ETH_TYPE_IPV4:
398                 if ((*protocol0 == IP_PROTOCOL_ICMP)  &&
399                         (link->ip == rte_be_to_cpu_32(*dst_addr0))) {
400                         if (is_phy_port_privte(pkt[0]->port)) {
401                                 rte_pipeline_port_out_packet_insert(
402                                         p_txrx->p.p, out_port, pkt[0]);
403                                 rte_pipeline_ah_packet_drop(
404                                         p_txrx->p.p, pkt_mask0);
405                         }
406                 }
407
408         break;
409
410         #ifdef IPV6
411         case ETH_TYPE_IPV6:
412                 if (*protocol0 == ICMPV6_PROTOCOL_ID) {
413                         if (!memcmp(ipv6_h0->dst_addr, link->ipv6, 16)
414                                 || !memcmp(ipv6_h0->dst_addr, solicited_node_multicast_addr, 13)) {
415                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
416                                         out_port, pkt[0]);
417                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
418
419                         } else {
420                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
421                         }
422                 }
423         break;
424         #endif
425
426         default: /* Not valid pkt */
427                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
428
429         }
430         #endif
431
432         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
433                 print_pkt1(pkt[1]);
434                 txrx_pkt_print_count++;
435                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
436                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
437                                  rte_be_to_cpu_16(*eth_proto1), *protocol1, ETH_TYPE_ARP,
438                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
439         }
440
441         /* header room + eth hdr size + src_aadr offset in ip header */
442         uint32_t dst_addr_offset1 =
443                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
444         uint32_t *dst_addr1 =
445                         RTE_MBUF_METADATA_UINT32_PTR(pkt[1], dst_addr_offset1);
446
447         if (TXRX_DEBUG > 2)
448                 if (rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
449                         printf ("%s: linkIp: %x, dst_addr1: %x\n", __FUNCTION__, link->ip, *dst_addr1);
450
451         switch (rte_be_to_cpu_16(*eth_proto1)) {
452         case ETH_TYPE_ARP:
453                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
454                         out_port, pkt[1]);
455                 rte_pipeline_ah_packet_hijack(p_txrx->p.p, pkt_mask1);
456         break;
457
458         case ETH_TYPE_IPV4:
459                 if ((*protocol1 == IP_PROTOCOL_ICMP)  &&
460                         (link->ip == rte_be_to_cpu_32(*dst_addr1))) {
461                         if (is_phy_port_privte(pkt[1]->port)) {
462                                 rte_pipeline_port_out_packet_insert(
463                                         p_txrx->p.p,
464                                         out_port, pkt[1]);
465                                 rte_pipeline_ah_packet_drop(
466                                         p_txrx->p.p,
467                                         pkt_mask1);
468                         }
469                 }
470
471         break;
472
473         #ifdef IPV6
474         case ETH_TYPE_IPV6:
475                 if (*protocol1 == ICMPV6_PROTOCOL_ID) {
476                         #ifndef VNF_ACL
477                         if (!memcmp(ipv6_h1->dst_addr, link->ipv6, 16)
478                                 || !memcmp(ipv6_h1->dst_addr, solicited_node_multicast_addr, 13)) {
479                         #endif
480                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
481                                         out_port, pkt[1]);
482                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
483                         #ifndef VNF_ACL
484                         } else {
485                                 printf("Dropping the IPv6 pkt\n");
486                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
487                         }
488                         #endif
489                 }
490         break;
491         #endif
492
493         default: /* Not valid pkt */
494                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
495
496         }
497
498         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
499                 print_pkt1(pkt[2]);
500                 txrx_pkt_print_count++;
501                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
502                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
503                                  rte_be_to_cpu_16(*eth_proto2), *protocol2, ETH_TYPE_ARP,
504                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
505         }
506
507         /* header room + eth hdr size + src_aadr offset in ip header */
508         uint32_t dst_addr_offset2 =
509                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
510         uint32_t *dst_addr2 =
511                         RTE_MBUF_METADATA_UINT32_PTR(pkt[2], dst_addr_offset2);
512
513         if (TXRX_DEBUG > 2)
514                 if (rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
515                         printf ("%s: linkIp: %x, dst_addr2: %x\n", __FUNCTION__, link->ip, *dst_addr2);
516
517         switch (rte_be_to_cpu_16(*eth_proto2)) {
518         case ETH_TYPE_ARP:
519                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
520                         out_port, pkt[2]);
521                 rte_pipeline_ah_packet_hijack(p_txrx->p.p, pkt_mask2);
522         break;
523
524         case ETH_TYPE_IPV4:
525                 if ((*protocol2 == IP_PROTOCOL_ICMP)  &&
526                         (link->ip == rte_be_to_cpu_32(*dst_addr2))) {
527                         if (is_phy_port_privte(pkt[2]->port)) {
528                                 rte_pipeline_port_out_packet_insert(
529                                         p_txrx->p.p,
530                                         out_port, pkt[2]);
531                                 rte_pipeline_ah_packet_drop(
532                                         p_txrx->p.p,
533                                         pkt_mask2);
534                         }
535                 }
536
537         break;
538
539         #ifdef IPV6
540         case ETH_TYPE_IPV6:
541                 if (*protocol2 == ICMPV6_PROTOCOL_ID) {
542                         #ifndef VNF_ACL
543                         if (!memcmp(ipv6_h2->dst_addr, link->ipv6, 16)
544                                 || !memcmp(ipv6_h2->dst_addr, solicited_node_multicast_addr, 13)) {
545                         #endif
546                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
547                                         out_port, pkt[2]);
548                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
549                         #ifndef VNF_ACL
550                         } else {
551                                 printf("Dropping the IPv6 pkt\n");
552                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
553                         }
554                         #endif
555                 }
556         break;
557         #endif
558
559         default: /* Not valid pkt */
560                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
561
562         }
563
564         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
565                 print_pkt1(pkt[3]);
566                 txrx_pkt_print_count++;
567                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
568                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
569                                  rte_be_to_cpu_16(*eth_proto3), *protocol3, ETH_TYPE_ARP,
570                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
571         }
572
573         /* header room + eth hdr size + src_aadr offset in ip header */
574         uint32_t dst_addr_offset3 =
575                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
576         uint32_t *dst_addr3 =
577                         RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset3);
578
579         if (TXRX_DEBUG > 2)
580                 if (rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
581                         printf ("%s: linkIp: %x, dst_addr3: %x\n", __FUNCTION__, link->ip, *dst_addr3);
582
583         switch (rte_be_to_cpu_16(*eth_proto3)) {
584         case ETH_TYPE_ARP:
585                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
586                         out_port, pkt[3]);
587                 rte_pipeline_ah_packet_hijack(p_txrx->p.p, pkt_mask3);
588         break;
589
590         case ETH_TYPE_IPV4:
591                 if ((*protocol3 == IP_PROTOCOL_ICMP)  &&
592                         (link->ip == rte_be_to_cpu_32(*dst_addr3))) {
593                         if (is_phy_port_privte(pkt[3]->port)) {
594                                 rte_pipeline_port_out_packet_insert(
595                                         p_txrx->p.p,
596                                         out_port, pkt[3]);
597                                 rte_pipeline_ah_packet_drop(
598                                         p_txrx->p.p,
599                                         pkt_mask3);
600                         }
601                 }
602
603         break;
604
605         #ifdef IPV6
606         case ETH_TYPE_IPV6:
607                 if (*protocol3 == ICMPV6_PROTOCOL_ID) {
608                         #ifndef VNF_ACL
609                         if (!memcmp(ipv6_h3->dst_addr, link->ipv6, 16)
610                                 || !memcmp(ipv6_h3->dst_addr, solicited_node_multicast_addr, 13)) {
611                         #endif
612                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
613                                         out_port, pkt[3]);
614                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
615                         #ifndef VNF_ACL
616                         } else {
617                                 printf("Dropping the IPv6 pkt\n");
618                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
619                         }
620                         #endif
621                 }
622         break;
623         #endif
624
625         default: /* Not valid pkt */
626                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
627
628         }
629
630         p_txrx->receivedPktCount += 4;
631
632 }
633
634 PIPELINE_TXRX_KEY_PORT_IN_AH(port_in_ah_txrx, pkt_work_txrx, pkt4_work_txrx);
635
636 static void *pipeline_txrx_init(struct pipeline_params *params,
637                                 __rte_unused void *arg)
638 {
639         struct pipeline *p;
640         struct pipeline_txrx *p_pt;
641         uint32_t size, i, in_ports_arg_size;
642
643         printf("Start pipeline_txrx_init\n");
644
645         /* Check input arguments */
646         if ((params == NULL) ||
647                         (params->n_ports_in == 0) ||
648                         (params->n_ports_out == 0))
649                 return NULL;
650
651         /* Memory allocation */
652         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_txrx));
653         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
654         p_pt = (struct pipeline_txrx *)p;
655         if (p == NULL)
656                 return NULL;
657
658         PLOG(p, HIGH, "TXRX");
659         strcpy(p->name, params->name);
660         p->log_level = params->log_level;
661
662         p_pt->receivedPktCount = 0;
663         p_pt->droppedPktCount = 0;
664         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++)
665                 p_pt->links_map[i] = 0xff;
666
667         p_pt->pipeline_num = 0;
668         printf("txrx initialization of variables done\n");
669
670         /* Parse arguments */
671         if (pipeline_txrx_parse_args(p_pt, params))
672                 return NULL;
673
674         /* Pipeline */
675         {
676                 struct rte_pipeline_params pipeline_params = {
677                         .name = "TXRX",
678                         .socket_id = params->socket_id,
679                         .offset_port_id = 0,
680                 };
681
682                 p->p = rte_pipeline_create(&pipeline_params);
683                 if (p->p == NULL) {
684                         rte_free(p);
685                         return NULL;
686                 }
687         }
688
689         p->n_ports_in = params->n_ports_in;
690         p->n_ports_out = params->n_ports_out;
691         p->n_tables = p->n_ports_in;
692
693         /* Memory allocation for in_port_h_arg */
694         in_ports_arg_size =
695                 RTE_CACHE_LINE_ROUNDUP((sizeof
696                                         (struct pipeline_txrx_in_port_h_arg)) *
697                                 (params->n_ports_in));
698         struct pipeline_txrx_in_port_h_arg *ap =
699                 (struct pipeline_txrx_in_port_h_arg *)rte_zmalloc(NULL,
700                                 in_ports_arg_size,
701                                 RTE_CACHE_LINE_SIZE);
702         if (ap == NULL)
703                 return NULL;
704         /*Input ports */
705         for (i = 0; i < p->n_ports_in; i++) {
706                 /* passing our txrx pipeline in call back arg */
707                 (ap[i]).p = p_pt;
708                 (ap[i]).in_port_id = i;
709                 struct rte_pipeline_port_in_params port_params = {
710                         .ops =
711                                         pipeline_port_in_params_get_ops(&params->
712                                                                         port_in[i]),
713                         .arg_create =
714                                         pipeline_port_in_params_convert(&params->
715                                                                         port_in[i]),
716                         .f_action = NULL,
717                         .arg_ah = &(ap[i]),
718                         .burst_size = params->port_in[i].burst_size,
719                 };
720
721                         port_params.f_action = port_in_ah_txrx;
722
723                 int status = rte_pipeline_port_in_create(p->p,
724                                                          &port_params,
725                                                          &p->port_in_id[i]);
726
727                 if (status) {
728                         rte_pipeline_free(p->p);
729                         rte_free(p);
730                         return NULL;
731                 }
732         }
733
734         /* Output ports */
735         for (i = 0; i < p->n_ports_out; i++) {
736                 struct rte_pipeline_port_out_params port_params = {
737                         .ops =
738                                         pipeline_port_out_params_get_ops(&params->
739                                                                          port_out[i]),
740                         .arg_create =
741                                         pipeline_port_out_params_convert(&params->
742                                                                          port_out[i]),
743                         .f_action = NULL,
744                         .arg_ah = NULL,
745                 };
746
747                 int status = rte_pipeline_port_out_create(p->p,
748                                                                 &port_params,
749                                                                 &p->port_out_id[i]);
750
751                 if (status) {
752                         rte_pipeline_free(p->p);
753                         rte_free(p);
754                         return NULL;
755                 }
756         }
757
758         int pipeline_num = 0;
759         int status = sscanf(params->name, "PIPELINE%d", &pipeline_num);
760         if (status < 0) {
761                 printf("Unable to read pipeline number\n");
762                 return NULL;
763         }
764         p_pt->pipeline_num = (uint8_t) pipeline_num;
765
766         register_pipeline_Qs(p_pt->pipeline_num, p);
767         set_link_map(p_pt->pipeline_num, p, p_pt->links_map);
768         set_outport_id(p_pt->pipeline_num, p, p_pt->outport_id);
769
770         /* Tables */
771         for (i = 0; i < p->n_ports_in; i++) {
772                 struct rte_pipeline_table_params table_params = {
773                         .ops = &rte_table_stub_ops,
774                         .arg_create = NULL,
775                         .f_action_hit = NULL,
776                         .f_action_miss = NULL,
777                         .arg_ah = NULL,
778                         .action_data_size = 0,
779                 };
780
781                 int status = rte_pipeline_table_create(p->p,
782                                                                          &table_params,
783                                                                          &p->table_id[i]);
784
785                 if (status) {
786                         rte_pipeline_free(p->p);
787                         rte_free(p);
788                         return NULL;
789                 }
790         }
791
792         /* Connecting input ports to tables */
793         for (i = 0; i < p->n_ports_in; i++) {
794                 int status = rte_pipeline_port_in_connect_to_table(p->p,
795                                                                          p->
796                                                                          port_in_id
797                                                                          [i],
798                                                                          p->
799                                                                          table_id[i]);
800
801                 if (status) {
802                         rte_pipeline_free(p->p);
803                         rte_free(p);
804                         return NULL;
805                 }
806         }
807
808         /* Add entries to tables */
809         for (i = 0; i < p->n_ports_in; i++) {
810                 struct rte_pipeline_table_entry default_entry = {
811                         .action = RTE_PIPELINE_ACTION_PORT,
812                         .port_id = p->port_out_id[i],
813                 };
814
815                 struct rte_pipeline_table_entry *default_entry_ptr;
816
817                 int status = rte_pipeline_table_default_entry_add(
818                                 p->p,
819                                 p->
820                                 table_id[i],
821                                 &default_entry,
822                                 &default_entry_ptr);
823
824                 if (status) {
825                         rte_pipeline_free(p->p);
826                         rte_free(p);
827                         return NULL;
828                 }
829         }
830
831         /* Enable input ports */
832         for (i = 0; i < p->n_ports_in; i++) {
833                 int status = rte_pipeline_port_in_enable(p->p,
834                                                          p->port_in_id[i]);
835
836                 if (status) {
837                         rte_pipeline_free(p->p);
838                         rte_free(p);
839                         return NULL;
840                 }
841         }
842
843         /* Check pipeline consistency */
844         if (rte_pipeline_check(p->p) < 0) {
845                 rte_pipeline_free(p->p);
846                 rte_free(p);
847                 return NULL;
848         }
849
850         /* Message queues */
851         p->n_msgq = params->n_msgq;
852         for (i = 0; i < p->n_msgq; i++)
853                 p->msgq_in[i] = params->msgq_in[i];
854         for (i = 0; i < p->n_msgq; i++)
855                 p->msgq_out[i] = params->msgq_out[i];
856
857         /* Message handlers */
858         memcpy(p->handlers, handlers, sizeof(p->handlers));
859
860         return p;
861 }
862
863 static int pipeline_txrx_free(void *pipeline)
864 {
865         struct pipeline *p = (struct pipeline *)pipeline;
866
867         /* Check input arguments */
868         if (p == NULL)
869                 return -1;
870
871         /* Free resources */
872         rte_pipeline_free(p->p);
873         rte_free(p);
874         return 0;
875 }
876
877 static int pipeline_txrx_timer(void *pipeline)
878 {
879         struct pipeline *p = (struct pipeline *)pipeline;
880
881         pipeline_msg_req_handle(p);
882         rte_pipeline_flush(p->p);
883
884         return 0;
885 }
886
887 static int
888 pipeline_txrx_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
889 {
890         struct pipeline *p = (struct pipeline *)pipeline;
891
892         /* Check input arguments */
893         if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
894                 return -1;
895
896         *port_out = port_in / p->n_ports_in;
897         return 0;
898 }
899
900 struct pipeline_be_ops pipeline_txrx_be_ops = {
901         .f_init = pipeline_txrx_init,
902         .f_free = pipeline_txrx_free,
903         .f_run = NULL,
904         .f_timer = pipeline_txrx_timer,
905         .f_track = pipeline_txrx_track,
906 };