Merge "tools: Support multiple version of DPDK build"
[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 struct pipeline_txrx {
41         struct pipeline p;
42         pipeline_msg_req_handler
43                 custom_handlers[PIPELINE_TXRX_MSG_REQS];
44         uint64_t receivedPktCount;
45         uint64_t droppedPktCount;
46         uint8_t links_map[PIPELINE_MAX_PORT_IN];
47         uint8_t outport_id[PIPELINE_MAX_PORT_IN];
48         uint8_t pipeline_num;
49         uint8_t txrx_type;
50 } __rte_cache_aligned;
51
52 enum{
53 TYPE_TXTX,
54 TYPE_RXRX,
55 };
56 static void *pipeline_txrx_msg_req_custom_handler(struct pipeline *p,
57                                                         void *msg);
58
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_drop(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                         #ifndef VNF_ACL
265                         if (!memcmp(ipv6_h->dst_addr, link->ipv6, 16)
266                         || !memcmp(ipv6_h->dst_addr, solicited_node_multicast_addr, 13)) {
267                         #endif
268                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
269                                         out_port, pkt);
270                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
271                         #ifndef VNF_ACL
272                         } else {
273                                 printf("Dropping the IPv6 pkt\n");
274                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
275                         }
276                         #endif
277                 }
278         break;
279         #endif
280
281         default: /* Not valid pkt */
282                 printf("Dropping the pkt\n");
283                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask);
284
285         }
286         #endif
287
288 }
289
290 static inline void
291 pkt4_work_txrx(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
292 {
293         struct pipeline_txrx_in_port_h_arg *ap = arg;
294         struct pipeline_txrx *p_txrx = (struct pipeline_txrx *)ap->p;
295         uint8_t solicited_node_multicast_addr[16] =
296                                         {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297                 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00};
298
299         if (p_txrx->txrx_type == TYPE_TXTX)
300                 return;
301
302         uint16_t in_port_id = (*pkt)->port;
303         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
304
305
306         uint32_t pkt_mask0 = 1 << pkt_num;
307         uint32_t pkt_mask1 = 1 << (pkt_num + 1);
308         uint32_t pkt_mask2 = 1 << (pkt_num + 2);
309         uint32_t pkt_mask3 = 1 << (pkt_num + 3);
310
311         /* ARP outport number */
312         uint32_t out_port = p_txrx->p.n_ports_out - 1;
313
314         uint16_t *eth_proto0 =
315                         RTE_MBUF_METADATA_UINT16_PTR(pkt[0], eth_proto_offset);
316         uint16_t *eth_proto1 =
317                         RTE_MBUF_METADATA_UINT16_PTR(pkt[1], eth_proto_offset);
318         uint16_t *eth_proto2 =
319                         RTE_MBUF_METADATA_UINT16_PTR(pkt[2], eth_proto_offset);
320         uint16_t *eth_proto3 =
321                         RTE_MBUF_METADATA_UINT16_PTR(pkt[3], eth_proto_offset);
322
323         uint8_t *protocol0, *protocol1, *protocol2, *protocol3;
324         uint32_t prot_offset =
325                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
326
327         #ifdef IPV6
328         struct ipv6_hdr *ipv6_h0, *ipv6_h1, *ipv6_h2, *ipv6_h3;
329         ipv6_h0 = rte_pktmbuf_mtod_offset (pkt[0], struct ipv6_hdr *, sizeof(struct ether_hdr));
330         uint32_t prot_offset_ipv6 =
331                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
332
333 /* --0-- */
334         if (rte_be_to_cpu_16(*eth_proto0) == ETHER_TYPE_IPv6)
335                 protocol0 =
336                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset_ipv6);
337         else
338                 protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
339
340 /* --1-- */
341         ipv6_h1 = rte_pktmbuf_mtod_offset (pkt[1], struct ipv6_hdr *, sizeof(struct ether_hdr));
342         if (rte_be_to_cpu_16(*eth_proto1) == ETHER_TYPE_IPv6)
343                 protocol1 =
344                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset_ipv6);
345         else
346                 protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
347
348 /* --2-- */
349         ipv6_h2 = rte_pktmbuf_mtod_offset (pkt[2], struct ipv6_hdr *, sizeof(struct ether_hdr));
350         if (rte_be_to_cpu_16(*eth_proto2) == ETHER_TYPE_IPv6)
351                 protocol2 =
352                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset_ipv6);
353         else
354                 protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
355
356 /* --3-- */
357         ipv6_h3 = rte_pktmbuf_mtod_offset (pkt[3], struct ipv6_hdr *, sizeof(struct ether_hdr));
358         if (rte_be_to_cpu_16(*eth_proto3) == ETHER_TYPE_IPv6)
359                 protocol3 =
360                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset_ipv6);
361         else
362                 protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
363         #else
364         protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
365         protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
366         protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
367         protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
368         #endif
369
370         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
371                 print_pkt1(pkt[0]);
372                 txrx_pkt_print_count++;
373                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
374                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
375                                  rte_be_to_cpu_16(*eth_proto0), *protocol0, ETH_TYPE_ARP,
376                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
377         }
378
379         struct app_link_params *link;
380
381         link = &myApp->link_params[in_port_id];
382
383         /* header room + eth hdr size + src_aadr offset in ip header */
384         uint32_t dst_addr_offset0 =
385                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
386         uint32_t *dst_addr0 =
387                         RTE_MBUF_METADATA_UINT32_PTR(pkt[0], dst_addr_offset0);
388
389         if (TXRX_DEBUG > 2)
390                 if (rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
391                         printf ("%s: linkIp: %x, dst_addr0: %x\n", __FUNCTION__, link->ip, *dst_addr0);
392
393         #if 1
394         switch (rte_be_to_cpu_16(*eth_proto0)) {
395         case ETH_TYPE_ARP:
396                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
397                         out_port, pkt[0]);
398                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
399         break;
400
401         case ETH_TYPE_IPV4:
402                 if ((*protocol0 == IP_PROTOCOL_ICMP)  &&
403                         (link->ip == rte_be_to_cpu_32(*dst_addr0))) {
404                         if (is_phy_port_privte(pkt[0]->port)) {
405                                 rte_pipeline_port_out_packet_insert(
406                                         p_txrx->p.p, out_port, pkt[0]);
407                                 rte_pipeline_ah_packet_drop(
408                                         p_txrx->p.p, pkt_mask0);
409                         }
410                 }
411
412         break;
413
414         #ifdef IPV6
415         case ETH_TYPE_IPV6:
416                 if (*protocol0 == ICMPV6_PROTOCOL_ID) {
417                         #ifndef VNF_ACL
418                         if (!memcmp(ipv6_h0->dst_addr, link->ipv6, 16)
419                                 || !memcmp(ipv6_h0->dst_addr, solicited_node_multicast_addr, 13)) {
420                         #endif
421                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
422                                         out_port, pkt[0]);
423                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
424
425                         #ifndef VNF_ACL
426                         } else {
427                                 printf("Dropping the IPv6 pkt\n");
428                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
429                         }
430                         #endif
431                 }
432         break;
433         #endif
434
435         default: /* Not valid pkt */
436                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask0);
437
438         }
439         #endif
440
441         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
442                 print_pkt1(pkt[1]);
443                 txrx_pkt_print_count++;
444                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
445                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
446                                  rte_be_to_cpu_16(*eth_proto1), *protocol1, ETH_TYPE_ARP,
447                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
448         }
449
450         /* header room + eth hdr size + src_aadr offset in ip header */
451         uint32_t dst_addr_offset1 =
452                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
453         uint32_t *dst_addr1 =
454                         RTE_MBUF_METADATA_UINT32_PTR(pkt[1], dst_addr_offset1);
455
456         if (TXRX_DEBUG > 2)
457                 if (rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
458                         printf ("%s: linkIp: %x, dst_addr1: %x\n", __FUNCTION__, link->ip, *dst_addr1);
459
460         switch (rte_be_to_cpu_16(*eth_proto1)) {
461         case ETH_TYPE_ARP:
462                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
463                         out_port, pkt[1]);
464                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
465         break;
466
467         case ETH_TYPE_IPV4:
468                 if ((*protocol1 == IP_PROTOCOL_ICMP)  &&
469                         (link->ip == rte_be_to_cpu_32(*dst_addr1))) {
470                         if (is_phy_port_privte(pkt[1]->port)) {
471                                 rte_pipeline_port_out_packet_insert(
472                                         p_txrx->p.p,
473                                         out_port, pkt[1]);
474                                 rte_pipeline_ah_packet_drop(
475                                         p_txrx->p.p,
476                                         pkt_mask1);
477                         }
478                 }
479
480         break;
481
482         #ifdef IPV6
483         case ETH_TYPE_IPV6:
484                 if (*protocol1 == ICMPV6_PROTOCOL_ID) {
485                         #ifndef VNF_ACL
486                         if (!memcmp(ipv6_h1->dst_addr, link->ipv6, 16)
487                                 || !memcmp(ipv6_h1->dst_addr, solicited_node_multicast_addr, 13)) {
488                         #endif
489                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
490                                         out_port, pkt[1]);
491                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
492                         #ifndef VNF_ACL
493                         } else {
494                                 printf("Dropping the IPv6 pkt\n");
495                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
496                         }
497                         #endif
498                 }
499         break;
500         #endif
501
502         default: /* Not valid pkt */
503                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask1);
504
505         }
506
507         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
508                 print_pkt1(pkt[2]);
509                 txrx_pkt_print_count++;
510                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
511                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
512                                  rte_be_to_cpu_16(*eth_proto2), *protocol2, ETH_TYPE_ARP,
513                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
514         }
515
516         /* header room + eth hdr size + src_aadr offset in ip header */
517         uint32_t dst_addr_offset2 =
518                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
519         uint32_t *dst_addr2 =
520                         RTE_MBUF_METADATA_UINT32_PTR(pkt[2], dst_addr_offset2);
521
522         if (TXRX_DEBUG > 2)
523                 if (rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
524                         printf ("%s: linkIp: %x, dst_addr2: %x\n", __FUNCTION__, link->ip, *dst_addr2);
525
526         switch (rte_be_to_cpu_16(*eth_proto2)) {
527         case ETH_TYPE_ARP:
528                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
529                         out_port, pkt[2]);
530                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
531         break;
532
533         case ETH_TYPE_IPV4:
534                 if ((*protocol2 == IP_PROTOCOL_ICMP)  &&
535                         (link->ip == rte_be_to_cpu_32(*dst_addr2))) {
536                         if (is_phy_port_privte(pkt[2]->port)) {
537                                 rte_pipeline_port_out_packet_insert(
538                                         p_txrx->p.p,
539                                         out_port, pkt[2]);
540                                 rte_pipeline_ah_packet_drop(
541                                         p_txrx->p.p,
542                                         pkt_mask2);
543                         }
544                 }
545
546         break;
547
548         #ifdef IPV6
549         case ETH_TYPE_IPV6:
550                 if (*protocol2 == ICMPV6_PROTOCOL_ID) {
551                         #ifndef VNF_ACL
552                         if (!memcmp(ipv6_h2->dst_addr, link->ipv6, 16)
553                                 || !memcmp(ipv6_h2->dst_addr, solicited_node_multicast_addr, 13)) {
554                         #endif
555                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
556                                         out_port, pkt[2]);
557                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
558                         #ifndef VNF_ACL
559                         } else {
560                                 printf("Dropping the IPv6 pkt\n");
561                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
562                         }
563                         #endif
564                 }
565         break;
566         #endif
567
568         default: /* Not valid pkt */
569                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask2);
570
571         }
572
573         if ((TXRX_DEBUG > 2) && (txrx_pkt_print_count < 10)) {
574                 print_pkt1(pkt[3]);
575                 txrx_pkt_print_count++;
576                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
577                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
578                                  rte_be_to_cpu_16(*eth_proto3), *protocol3, ETH_TYPE_ARP,
579                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
580         }
581
582         /* header room + eth hdr size + src_aadr offset in ip header */
583         uint32_t dst_addr_offset3 =
584                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
585         uint32_t *dst_addr3 =
586                         RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset3);
587
588         if (TXRX_DEBUG > 2)
589                 if (rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
590                         printf ("%s: linkIp: %x, dst_addr3: %x\n", __FUNCTION__, link->ip, *dst_addr3);
591
592         switch (rte_be_to_cpu_16(*eth_proto3)) {
593         case ETH_TYPE_ARP:
594                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
595                         out_port, pkt[3]);
596                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
597         break;
598
599         case ETH_TYPE_IPV4:
600                 if ((*protocol3 == IP_PROTOCOL_ICMP)  &&
601                         (link->ip == rte_be_to_cpu_32(*dst_addr3))) {
602                         if (is_phy_port_privte(pkt[3]->port)) {
603                                 rte_pipeline_port_out_packet_insert(
604                                         p_txrx->p.p,
605                                         out_port, pkt[3]);
606                                 rte_pipeline_ah_packet_drop(
607                                         p_txrx->p.p,
608                                         pkt_mask3);
609                         }
610                 }
611
612         break;
613
614         #ifdef IPV6
615         case ETH_TYPE_IPV6:
616                 if (*protocol3 == ICMPV6_PROTOCOL_ID) {
617                         #ifndef VNF_ACL
618                         if (!memcmp(ipv6_h3->dst_addr, link->ipv6, 16)
619                                 || !memcmp(ipv6_h3->dst_addr, solicited_node_multicast_addr, 13)) {
620                         #endif
621                                 rte_pipeline_port_out_packet_insert(p_txrx->p.p,
622                                         out_port, pkt[3]);
623                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
624                         #ifndef VNF_ACL
625                         } else {
626                                 printf("Dropping the IPv6 pkt\n");
627                                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
628                         }
629                         #endif
630                 }
631         break;
632         #endif
633
634         default: /* Not valid pkt */
635                 rte_pipeline_ah_packet_drop(p_txrx->p.p, pkt_mask3);
636
637         }
638
639         p_txrx->receivedPktCount += 4;
640
641 }
642
643 PIPELINE_TXRX_KEY_PORT_IN_AH(port_in_ah_txrx, pkt_work_txrx, pkt4_work_txrx);
644
645 static void *pipeline_txrx_init(struct pipeline_params *params,
646                                 __rte_unused void *arg)
647 {
648         struct pipeline *p;
649         struct pipeline_txrx *p_pt;
650         uint32_t size, i, in_ports_arg_size;
651
652         printf("Start pipeline_txrx_init\n");
653
654         /* Check input arguments */
655         if ((params == NULL) ||
656                         (params->n_ports_in == 0) ||
657                         (params->n_ports_out == 0))
658                 return NULL;
659
660         /* Memory allocation */
661         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_txrx));
662         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
663         p_pt = (struct pipeline_txrx *)p;
664         if (p == NULL)
665                 return NULL;
666
667         PLOG(p, HIGH, "TXRX");
668         strcpy(p->name, params->name);
669         p->log_level = params->log_level;
670
671         p_pt->receivedPktCount = 0;
672         p_pt->droppedPktCount = 0;
673         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++)
674                 p_pt->links_map[i] = 0xff;
675
676         p_pt->pipeline_num = 0;
677         printf("txrx initialization of variables done\n");
678
679         /* Parse arguments */
680         if (pipeline_txrx_parse_args(p_pt, params))
681                 return NULL;
682
683         /* Pipeline */
684         {
685                 struct rte_pipeline_params pipeline_params = {
686                         .name = "TXRX",
687                         .socket_id = params->socket_id,
688                         .offset_port_id = 0,
689                 };
690
691                 p->p = rte_pipeline_create(&pipeline_params);
692                 if (p->p == NULL) {
693                         rte_free(p);
694                         return NULL;
695                 }
696         }
697
698         p->n_ports_in = params->n_ports_in;
699         p->n_ports_out = params->n_ports_out;
700         p->n_tables = p->n_ports_in;
701
702         /* Memory allocation for in_port_h_arg */
703         in_ports_arg_size =
704                 RTE_CACHE_LINE_ROUNDUP((sizeof
705                                         (struct pipeline_txrx_in_port_h_arg)) *
706                                 (params->n_ports_in));
707         struct pipeline_txrx_in_port_h_arg *ap =
708                 (struct pipeline_txrx_in_port_h_arg *)rte_zmalloc(NULL,
709                                 in_ports_arg_size,
710                                 RTE_CACHE_LINE_SIZE);
711         if (ap == NULL)
712                 return NULL;
713         /*Input ports */
714         for (i = 0; i < p->n_ports_in; i++) {
715                 /* passing our txrx pipeline in call back arg */
716                 (ap[i]).p = p_pt;
717                 (ap[i]).in_port_id = i;
718                 struct rte_pipeline_port_in_params port_params = {
719                         .ops =
720                                         pipeline_port_in_params_get_ops(&params->
721                                                                         port_in[i]),
722                         .arg_create =
723                                         pipeline_port_in_params_convert(&params->
724                                                                         port_in[i]),
725                         .f_action = NULL,
726                         .arg_ah = &(ap[i]),
727                         .burst_size = params->port_in[i].burst_size,
728                 };
729
730                         port_params.f_action = port_in_ah_txrx;
731
732                 int status = rte_pipeline_port_in_create(p->p,
733                                                          &port_params,
734                                                          &p->port_in_id[i]);
735
736                 if (status) {
737                         rte_pipeline_free(p->p);
738                         rte_free(p);
739                         return NULL;
740                 }
741         }
742
743         /* Output ports */
744         for (i = 0; i < p->n_ports_out; i++) {
745                 struct rte_pipeline_port_out_params port_params = {
746                         .ops =
747                                         pipeline_port_out_params_get_ops(&params->
748                                                                          port_out[i]),
749                         .arg_create =
750                                         pipeline_port_out_params_convert(&params->
751                                                                          port_out[i]),
752                         .f_action = NULL,
753                         .arg_ah = NULL,
754                 };
755
756                 int status = rte_pipeline_port_out_create(p->p,
757                                                                 &port_params,
758                                                                 &p->port_out_id[i]);
759
760                 if (status) {
761                         rte_pipeline_free(p->p);
762                         rte_free(p);
763                         return NULL;
764                 }
765         }
766
767         int pipeline_num = 0;
768         int status = sscanf(params->name, "PIPELINE%d", &pipeline_num);
769         if (status < 0) {
770                 printf("Unable to read pipeline number\n");
771                 return NULL;
772         }
773         p_pt->pipeline_num = (uint8_t) pipeline_num;
774
775         register_pipeline_Qs(p_pt->pipeline_num, p);
776         set_link_map(p_pt->pipeline_num, p, p_pt->links_map);
777         set_outport_id(p_pt->pipeline_num, p, p_pt->outport_id);
778
779         /* Tables */
780         for (i = 0; i < p->n_ports_in; i++) {
781                 struct rte_pipeline_table_params table_params = {
782                         .ops = &rte_table_stub_ops,
783                         .arg_create = NULL,
784                         .f_action_hit = NULL,
785                         .f_action_miss = NULL,
786                         .arg_ah = NULL,
787                         .action_data_size = 0,
788                 };
789
790                 int status = rte_pipeline_table_create(p->p,
791                                                                          &table_params,
792                                                                          &p->table_id[i]);
793
794                 if (status) {
795                         rte_pipeline_free(p->p);
796                         rte_free(p);
797                         return NULL;
798                 }
799         }
800
801         /* Connecting input ports to tables */
802         for (i = 0; i < p->n_ports_in; i++) {
803                 int status = rte_pipeline_port_in_connect_to_table(p->p,
804                                                                          p->
805                                                                          port_in_id
806                                                                          [i],
807                                                                          p->
808                                                                          table_id[i]);
809
810                 if (status) {
811                         rte_pipeline_free(p->p);
812                         rte_free(p);
813                         return NULL;
814                 }
815         }
816
817         /* Add entries to tables */
818         for (i = 0; i < p->n_ports_in; i++) {
819                 struct rte_pipeline_table_entry default_entry = {
820                         .action = RTE_PIPELINE_ACTION_PORT,
821                         .port_id = p->port_out_id[i],
822                 };
823
824                 struct rte_pipeline_table_entry *default_entry_ptr;
825
826                 int status = rte_pipeline_table_default_entry_add(
827                                 p->p,
828                                 p->
829                                 table_id[i],
830                                 &default_entry,
831                                 &default_entry_ptr);
832
833                 if (status) {
834                         rte_pipeline_free(p->p);
835                         rte_free(p);
836                         return NULL;
837                 }
838         }
839
840         /* Enable input ports */
841         for (i = 0; i < p->n_ports_in; i++) {
842                 int status = rte_pipeline_port_in_enable(p->p,
843                                                          p->port_in_id[i]);
844
845                 if (status) {
846                         rte_pipeline_free(p->p);
847                         rte_free(p);
848                         return NULL;
849                 }
850         }
851
852         /* Check pipeline consistency */
853         if (rte_pipeline_check(p->p) < 0) {
854                 rte_pipeline_free(p->p);
855                 rte_free(p);
856                 return NULL;
857         }
858
859         /* Message queues */
860         p->n_msgq = params->n_msgq;
861         for (i = 0; i < p->n_msgq; i++)
862                 p->msgq_in[i] = params->msgq_in[i];
863         for (i = 0; i < p->n_msgq; i++)
864                 p->msgq_out[i] = params->msgq_out[i];
865
866         /* Message handlers */
867         memcpy(p->handlers, handlers, sizeof(p->handlers));
868
869         return p;
870 }
871
872 static int pipeline_txrx_free(void *pipeline)
873 {
874         struct pipeline *p = (struct pipeline *)pipeline;
875
876         /* Check input arguments */
877         if (p == NULL)
878                 return -1;
879
880         /* Free resources */
881         rte_pipeline_free(p->p);
882         rte_free(p);
883         return 0;
884 }
885
886 static int pipeline_txrx_timer(void *pipeline)
887 {
888         struct pipeline *p = (struct pipeline *)pipeline;
889
890         pipeline_msg_req_handle(p);
891         rte_pipeline_flush(p->p);
892
893         return 0;
894 }
895
896 static int
897 pipeline_txrx_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
898 {
899         struct pipeline *p = (struct pipeline *)pipeline;
900
901         /* Check input arguments */
902         if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
903                 return -1;
904
905         *port_out = port_in / p->n_ports_in;
906         return 0;
907 }
908
909 struct pipeline_be_ops pipeline_txrx_be_ops = {
910         .f_init = pipeline_txrx_init,
911         .f_free = pipeline_txrx_free,
912         .f_run = NULL,
913         .f_timer = pipeline_txrx_timer,
914         .f_track = pipeline_txrx_track,
915 };