481f85214038ab09645a327195f8c3bfc14862ac
[samplevnf.git] / common / VIL / pipeline_arpicmp / pipeline_arpicmp_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 <stdio.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include <app.h>
26 #include <rte_common.h>
27 #include <rte_malloc.h>
28 #include <rte_ip.h>
29 #include <rte_byteorder.h>
30 #include <rte_table_stub.h>
31 #include <rte_table_hash.h>
32 #include <rte_pipeline.h>
33 #include <rte_arp.h>
34 #include <rte_icmp.h>
35 #include <rte_hash.h>
36 #include <rte_jhash.h>
37 #include <rte_cycles.h>
38 #include <rte_hexdump.h>
39 #include "pipeline_actions_common.h"
40 #include "hash_func.h"
41 #include "vnf_common.h"
42 #include "pipeline_common_be.h"
43 #include "pipeline_arpicmp_be.h"
44 #include "parser.h"
45 #include "hash_func.h"
46 #include "vnf_common.h"
47 #include "app.h"
48
49 #include"pipeline_common_fe.h"
50 #include "lib_arp.h"
51 #include "lib_icmpv6.h"
52 #include "interface.h"
53 #include "gateway.h"
54
55 /* Shared among all VNFs including LB */
56 struct app_params *myApp;
57 struct rte_pipeline *myP;
58 struct pipeline_arpicmp *gp_arp;
59 uint8_t num_vnf_threads;
60
61 struct pipeline_arpicmp {
62         struct pipeline p;
63         pipeline_msg_req_handler
64                 custom_handlers[PIPELINE_ARPICMP_MSG_REQS];
65         uint64_t receivedPktCount;
66         uint64_t droppedPktCount;
67         uint64_t sentPktCount;
68         uint8_t links_map[PIPELINE_MAX_PORT_IN];
69         uint8_t outport_id[PIPELINE_MAX_PORT_IN];
70         uint8_t pipeline_num;
71 } __rte_cache_aligned;
72
73 void pipelines_port_info(void)
74 {
75         struct app_params *app = myApp;
76         uint8_t i, pipeline;
77         for (pipeline = 0; pipeline < app->n_pipelines; pipeline++) {
78                 printf("*** PIPELINE %d ***\n\n", pipeline);
79
80                 printf("*** OUTPORTs ***\n");
81                 for (i = 1; i < app->pipeline_params[pipeline].n_pktq_out;
82                         i++) {
83                         switch (app->pipeline_params[pipeline].pktq_out[i].
84                         type) {
85                         case APP_PKTQ_OUT_SWQ:
86                                 printf("pktq_out[%d]:%s\n", i,
87                                                          app->swq_params[app->pipeline_params
88                                                                          [pipeline].
89                                                                          pktq_out[i].id].name);
90                                 break;
91                         case APP_PKTQ_OUT_HWQ:
92                                 printf("pktq_out[%d]:%s\n", i,
93                                                          app->hwq_out_params[app->pipeline_params
94                                                                  [pipeline].pktq_out
95                                                                  [i].id].name);
96                                 break;
97                         default:
98                                 printf("Not OUT SWQ or HWQ\n");
99                         }
100                 }
101                 printf("*** INPORTs ***\n");
102                 for (i = 0; i < app->pipeline_params[pipeline].n_pktq_in; i++) {
103                         switch (app->pipeline_params[pipeline].pktq_in[i]
104                         .type) {
105                         case APP_PKTQ_IN_SWQ:
106                                 printf("pktq_in[%d]:%s\n", i,
107                                                          app->swq_params[app->pipeline_params
108                                                                          [pipeline].
109                                                                          pktq_in[i].id].name);
110                                 break;
111                         case APP_PKTQ_IN_HWQ:
112                                 printf("pktq_in[%d]:%s\n", i,
113                                                          app->hwq_in_params[app->pipeline_params
114                                                                 [pipeline].
115                                                                 pktq_in[i].id].name);
116                                 break;
117                         default:
118                                 printf("Not IN SWQ or HWQ\n");
119                         }
120                 }
121         }                       //for
122 }
123
124 void pipelines_map_info(void)
125 {
126          int i = 0;
127
128         printf("PIPELINE_MAX_PORT_IN %d\n", PIPELINE_MAX_PORT_IN);
129         printf("lb_outport_id[%d", lb_outport_id[0]);
130         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
131                 printf(",%d", lb_outport_id[i]);
132         printf("]\n");
133
134         printf("vnf_to_loadb_map[%d", vnf_to_loadb_map[0]);
135         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
136                 printf(",%d", vnf_to_loadb_map[i]);
137         printf("]\n");
138
139         printf("port_to_loadb_map[%d", port_to_loadb_map[0]);
140         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
141                 printf(",%d", port_to_loadb_map[i]);
142         printf("]\n");
143
144         printf("loadb_pipeline_nums[%d", loadb_pipeline_nums[0]);
145         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
146                 printf(",%d", loadb_pipeline_nums[i]);
147         printf("]\n");
148
149         printf("loadb_pipeline[%p", loadb_pipeline[0]);
150         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
151                 printf(",%p", loadb_pipeline[i]);
152         printf("]\n");
153 }
154
155 void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p)
156 {
157         struct rte_port_ethdev_reader *hwq;
158         struct rte_port_ring_writer *out_swq;
159         struct rte_port_ring_reader *in_swq;
160         struct rte_pipeline *rte = p->p;
161         uint8_t port_count = 0;
162         int queue_out = 0xff, queue_in = 0xff;
163
164         printf("Calling register_pipeline_Qs in PIPELINE%d\n", pipeline_num);
165         for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
166
167         switch (myApp->pipeline_params[pipeline_num].
168                                 pktq_out[port_count].type){
169
170         case APP_PKTQ_OUT_SWQ:
171
172                 if (port_count >= rte->num_ports_in) {
173
174                         /* Dont register ARP output Q */
175                         if (rte->num_ports_out % rte->num_ports_in)
176                                 if (port_count == rte->num_ports_out - 1)
177                                         return;
178                         int temp;
179                         temp = ((port_count) % rte->num_ports_in);
180
181                         in_swq = rte->ports_in[temp].h_port;
182                         out_swq = rte->ports_out[port_count].h_port;
183                         printf("in_swq : %s\n",
184                                 in_swq->ring->name);
185                         int status =
186                         sscanf(in_swq->ring->name, "SWQ%d",
187                                         &queue_in);
188                         if (status < 0) {
189                                 printf("Unable to read SWQ number\n");
190                                 return;
191                         }
192                         printf("out_swq: %s\n",
193                                         out_swq->ring->name);
194                         status =
195                         sscanf(out_swq->ring->name, "SWQ%d",
196                                         &queue_out);
197                         if (status < 0) {
198                                 printf("Unable to read SWQ number\n");
199                                 return;
200                         }
201                         if (queue_in < 128 && queue_out < 128) {
202                                 SWQ_to_Port_map[queue_out] =
203                                         SWQ_to_Port_map[queue_in];
204                          printf("SWQ_to_Port_map[%d]%d\n", queue_out,
205                                  SWQ_to_Port_map[queue_out]);
206                         }
207                         continue;
208                 }
209
210                 switch (myApp->pipeline_params[pipeline_num].
211                          pktq_in[port_count].type){
212
213                 case APP_PKTQ_OUT_HWQ:
214                          hwq = rte->ports_in[port_count].h_port;
215                          out_swq = rte->ports_out[port_count].h_port;
216                          printf("out_swq: %s\n",
217                                  out_swq->ring->name);
218                         int status =
219                         sscanf(out_swq->ring->name, "SWQ%d",
220                                  &queue_out);
221
222                         if (status < 0) {
223                                 printf("Unable to read SWQ number\n");
224                                 return;
225                         }
226                         if (queue_out < 128) {
227                                 SWQ_to_Port_map[queue_out] = hwq->port_id;
228                                 printf("SWQ_to_Port_map[%d]%d\n", queue_out,
229                                         SWQ_to_Port_map[queue_out]);
230                         }
231                 break;
232
233                 case APP_PKTQ_OUT_SWQ:
234                          in_swq = rte->ports_in[port_count].h_port;
235                          out_swq = rte->ports_out[port_count].h_port;
236                          printf("in_swq : %s\n",
237                                  in_swq->ring->name);
238                         status =
239                         sscanf(in_swq->ring->name, "SWQ%d",
240                                          &queue_in);
241                         if (status < 0) {
242                                 printf("Unable to read SWQ number\n");
243                                 return;
244                         }
245                         printf("out_swq: %s\n",
246                                          out_swq->ring->name);
247                         status =
248                         sscanf(out_swq->ring->name, "SWQ%d",
249                                          &queue_out);
250                         if (status < 0) {
251                                 printf("Unable to read SWQ number\n");
252                                 return;
253                         }
254                         if (queue_in < 128 && queue_out < 128){
255                                 SWQ_to_Port_map[queue_out] =
256                                         SWQ_to_Port_map[queue_in];
257                          printf("SWQ_to_Port_map[%d]%d\n", queue_out,
258                                  SWQ_to_Port_map[queue_out]);
259                           }
260                 break;
261
262                 default:
263                          printf("This never hits\n");
264                 }
265
266         break;
267
268         case APP_PKTQ_OUT_HWQ:
269                  printf("This is HWQ\n");
270         break;
271
272         default:
273                  printf("set_phy_outport_map: This never hits\n");
274         }
275         }
276 }
277
278 void set_link_map(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
279 {
280                 struct rte_port_ethdev_writer *hwq;
281                 struct rte_port_ring_writer *out_swq;
282                 struct rte_pipeline *rte = p->p;
283
284                 uint8_t port_count = 0;
285                 int index = 0, queue_out = 0xff;
286
287         printf("Calling set_link_map in PIPELINE%d\n", pipeline_num);
288         for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
289
290                 switch (myApp->pipeline_params[pipeline_num].
291                                 pktq_out[port_count].type){
292
293                 case APP_PKTQ_OUT_HWQ:
294                         hwq = rte->ports_out[port_count].h_port;
295                         map[index++] = hwq->port_id;
296                         printf("links_map[%d]:%d\n", index - 1, map[index - 1]);
297                 break;
298
299                 case APP_PKTQ_OUT_SWQ:
300                         out_swq = rte->ports_out[port_count].h_port;
301                         printf("set_link_map out_swq: %s\n",
302                                 out_swq->ring->name);
303                         int status = sscanf(out_swq->ring->name, "SWQ%d",
304                                         &queue_out);
305                         if (status < 0) {
306                                 printf("Unable to read SWQ number\n");
307                                 return;
308                         }
309
310                         if (queue_out < 128) {
311                         map[index++] = SWQ_to_Port_map[queue_out];
312                         printf("links_map[%s]:%d\n", out_swq->ring->name,
313                                         map[index - 1]);
314                         }
315                 break;
316
317                 default:
318                         printf("set_phy_outport_map: This never hits\n");
319                 }
320                 }
321 }
322
323 void set_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
324 {
325         uint8_t port_count = 0;
326         int queue_out = 0xff, index = 0;
327
328         struct rte_port_ethdev_writer *hwq;
329         struct rte_port_ring_writer *out_swq;
330         struct rte_pipeline *rte = p->p;
331
332         printf("\n**** set_outport_id() with pipeline_num:%d ****\n\n",
333                 pipeline_num);
334         for (port_count = 0;
335                 port_count < rte->num_ports_out;
336                 port_count++) {
337
338         switch (myApp->pipeline_params[pipeline_num].
339                         pktq_out[port_count].type) {
340
341         case APP_PKTQ_OUT_HWQ:
342                 hwq = rte->ports_out[port_count].h_port;
343                 //if (index >= 0)
344                 {
345                         map[hwq->port_id] = index;
346                         printf("hwq port_id:%d index:%d\n",
347                                 hwq->port_id, index);
348                         map[hwq->port_id] = index++;
349                         printf("hwq port_id:%d index:%d\n",
350                                 hwq->port_id, index-1);
351                         printf("outport_id[%d]:%d\n", index - 1,
352                                 map[index - 1]);
353                 }
354                 break;
355
356         case APP_PKTQ_OUT_SWQ:
357
358                 /* Dont register ARP output Q */
359                 if (port_count >= rte->num_ports_in)
360                         if (rte->num_ports_out % rte->num_ports_in)
361                                 if (port_count == rte->num_ports_out - 1)
362                                         return;
363                  out_swq = rte->ports_out[port_count].h_port;
364                  printf("set_outport_id out_swq: %s\n",
365                          out_swq->ring->name);
366                 int temp = sscanf(out_swq->ring->name, "SWQ%d",
367                                  &queue_out);
368                 if (temp < 0) {
369                         printf("Unable to read SWQ number\n");
370                         return;
371                 }
372
373                 if (queue_out < 128 && index >= 0) {
374                         map[SWQ_to_Port_map[queue_out]] = index++;
375                         printf("outport_id[%s]:%d\n", out_swq->ring->name,
376                                          map[SWQ_to_Port_map[queue_out]]);
377                 }
378                 break;
379
380                 default:
381                          printf(" ");
382
383                 }
384         }
385 }
386
387 void set_phy_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
388 {
389         uint8_t port_count = 0;
390         int index = 0;
391
392         struct rte_port_ethdev_writer *hwq;
393         struct rte_pipeline *rte = p->p;
394
395         printf("\n**** set_phy_outport_id() with pipeline_num:%d ****\n\n",
396                 pipeline_num);
397         for (port_count = 0;
398                 port_count < myApp->pipeline_params[pipeline_num].n_pktq_out;
399                 port_count++) {
400
401         switch (myApp->pipeline_params[pipeline_num].
402                         pktq_out[port_count].type) {
403
404         case APP_PKTQ_OUT_HWQ:
405                 hwq = rte->ports_out[port_count].h_port;
406                 map[hwq->port_id] = index++;
407                 printf("outport_id[%d]:%d\n", index - 1,
408                         map[index - 1]);
409         break;
410
411         default:
412                  printf(" ");
413
414                 }
415         }
416 }
417
418 void set_phy_inport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
419 {
420         uint8_t port_count = 0;
421         int index = 0;
422
423         struct rte_port_ethdev_reader *hwq;
424         struct rte_pipeline *rte = p->p;
425
426         printf("\n**** set_phy_inport_id() with pipeline_num:%d ****\n\n",
427                                  pipeline_num);
428         for (port_count = 0;
429                 port_count < myApp->pipeline_params[pipeline_num].n_pktq_in;
430                 port_count++) {
431
432                 switch (myApp->pipeline_params[pipeline_num].
433                         pktq_in[port_count].type) {
434
435                 case APP_PKTQ_OUT_HWQ:
436                         hwq = rte->ports_in[port_count].h_port;
437                         map[hwq->port_id] = index++;
438                         printf("outport_id[%d]:%d\n", index - 1,
439                                 map[index - 1]);
440                 break;
441
442                 default:
443                         printf(" ");
444
445                 }
446         }
447 }
448
449 static void *pipeline_arpicmp_msg_req_custom_handler(struct pipeline *p,
450                                                         void *msg);
451
452 static pipeline_msg_req_handler handlers[] = {
453         [PIPELINE_MSG_REQ_PING] =
454                 pipeline_msg_req_ping_handler,
455         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
456                 pipeline_msg_req_stats_port_in_handler,
457         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
458                 pipeline_msg_req_stats_port_out_handler,
459         [PIPELINE_MSG_REQ_STATS_TABLE] =
460                 pipeline_msg_req_stats_table_handler,
461         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
462                 pipeline_msg_req_port_in_enable_handler,
463         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
464                 pipeline_msg_req_port_in_disable_handler,
465         [PIPELINE_MSG_REQ_CUSTOM] =
466                 pipeline_arpicmp_msg_req_custom_handler,
467
468 };
469
470 static void *pipeline_arpicmp_msg_req_entry_dbg_handler(struct pipeline *p,
471                                                                  void *msg);
472 static void *pipeline_arpicmp_msg_req_entry_dbg_handler(
473         __rte_unused struct pipeline *p,
474         __rte_unused void *msg)
475 {
476         /*have to handle dbg commands*/
477         return NULL;
478 }
479
480 static __rte_unused pipeline_msg_req_handler custom_handlers[] = {
481         [PIPELINE_ARPICMP_MSG_REQ_ENTRY_DBG] =
482                         pipeline_arpicmp_msg_req_entry_dbg_handler,
483 };
484
485 /**
486  * Function for pipeline custom handlers
487  *
488  * @param pipeline
489  *  A void pointer to pipeline
490  * @param msg
491  *  void pointer for incoming data
492  *
493  * @return
494  *  void pointer of response
495  */
496 void *pipeline_arpicmp_msg_req_custom_handler(struct pipeline *p, void *msg)
497 {
498         struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)p;
499         struct pipeline_custom_msg_req *req = msg;
500         pipeline_msg_req_handler f_handle;
501
502         f_handle = (req->subtype < PIPELINE_ARPICMP_MSG_REQS) ?
503                         p_arp->custom_handlers[req->subtype] :
504                         pipeline_msg_req_invalid_handler;
505
506         if (f_handle == NULL)
507                 f_handle = pipeline_msg_req_invalid_handler;
508
509         return f_handle(p, req);
510 }
511
512 uint32_t arpicmp_pkt_print_count;
513 static inline void
514 pkt_key_arpicmp(struct rte_mbuf *pkt, uint32_t pkt_num, void *arg)
515 {
516
517         struct pipeline_arpicmp_in_port_h_arg *ap = arg;
518         struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
519
520         p_arp->receivedPktCount++;
521
522         uint8_t in_port_id = pkt->port;
523         uint8_t *protocol;
524         uint32_t pkt_mask = 1 << pkt_num;
525         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
526
527         uint32_t prot_offset =
528                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
529
530         uint16_t *eth_proto =
531                 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
532
533         /* header room + eth hdr size + src_aadr offset in ip header */
534         #ifdef IPV6
535          uint32_t prot_offset_ipv6 =
536                          MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
537
538         if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6)
539                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset_ipv6);
540         else
541                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
542         #else
543         protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
544         #endif
545
546         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
547                 print_pkt1(pkt);
548                 arpicmp_pkt_print_count++;
549                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
550                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
551                                  rte_be_to_cpu_16(*eth_proto), *protocol, ETH_TYPE_ARP,
552                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
553         }
554
555         /* Classifier for ICMP pass-through*/
556         if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_ARP) ||
557                         ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV4)
558                          && (*protocol == IP_PROTOCOL_ICMP)
559                 )) {
560                 process_arpicmp_pkt(pkt, ifm_get_port(in_port_id));
561                 return;
562         }
563         #ifdef IPV6
564         else if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV6)
565                 && (*protocol == ICMPV6_PROTOCOL_ID)) {
566                 process_icmpv6_pkt(pkt, ifm_get_port(in_port_id));
567                 return;
568         }
569         #endif
570
571         /* Drop the pkt if not ARP/ICMP */
572         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask);
573         p_arp->droppedPktCount++;
574
575 }
576
577 static inline void
578 pkt4_key_arpicmp(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
579 {
580
581         struct pipeline_arpicmp_in_port_h_arg *ap = arg;
582         struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
583         p_arp->receivedPktCount += 4;
584
585         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
586         uint8_t in_port_id = pkt[0]->port;
587
588         uint32_t prot_offset =
589                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
590
591         /* header room + eth hdr size + src_aadr offset in ip header */
592         uint32_t pkt_mask0 = 1 << pkt_num;
593         uint32_t pkt_mask1 = 1 << (pkt_num + 1);
594         uint32_t pkt_mask2 = 1 << (pkt_num + 2);
595         uint32_t pkt_mask3 = 1 << (pkt_num + 3);
596
597         uint16_t *eth_proto0 =
598                 RTE_MBUF_METADATA_UINT16_PTR(pkt[0], eth_proto_offset);
599         uint16_t *eth_proto1 =
600                 RTE_MBUF_METADATA_UINT16_PTR(pkt[1], eth_proto_offset);
601         uint16_t *eth_proto2 =
602                 RTE_MBUF_METADATA_UINT16_PTR(pkt[2], eth_proto_offset);
603         uint16_t *eth_proto3 =
604                 RTE_MBUF_METADATA_UINT16_PTR(pkt[3], eth_proto_offset);
605
606         uint8_t *protocol0;
607         uint8_t *protocol1;
608         uint8_t *protocol2;
609         uint8_t *protocol3;
610
611         #ifdef IPV6
612         uint32_t prot_offset_ipv6 =
613                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
614
615         #endif
616
617         #ifdef IPV6
618 /* --0-- */
619         if (rte_be_to_cpu_16(*eth_proto0) == ETHER_TYPE_IPv6)
620                 protocol0 =
621                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset_ipv6);
622         else
623                 protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
624
625 /* --1-- */
626         if (rte_be_to_cpu_16(*eth_proto1) == ETHER_TYPE_IPv6)
627                 protocol1 =
628                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset_ipv6);
629         else
630                 protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
631
632 /* --2-- */
633         if (rte_be_to_cpu_16(*eth_proto2) == ETHER_TYPE_IPv6)
634                 protocol2 =
635                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset_ipv6);
636         else
637                 protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
638
639 /* --3-- */
640         if (rte_be_to_cpu_16(*eth_proto3) == ETHER_TYPE_IPv6)
641                 protocol3 =
642                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset_ipv6);
643         else
644                 protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
645         #else
646         protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
647         protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
648         protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
649         protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
650         #endif
651
652         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
653                 print_pkt1(pkt[0]);
654                 arpicmp_pkt_print_count++;
655                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
656                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
657                                  rte_be_to_cpu_16(*eth_proto0), *protocol0, ETH_TYPE_ARP,
658                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
659         }
660
661
662         if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_ARP) ||
663                         ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
664                          && (*protocol0 == IP_PROTOCOL_ICMP)
665                 )) {
666                 process_arpicmp_pkt(pkt[0], ifm_get_port(in_port_id));
667
668                 goto PKT1;
669         }
670         #ifdef IPV6
671         else if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV6)
672                          && (*protocol0 == ICMPV6_PROTOCOL_ID)) {
673                 process_icmpv6_pkt(pkt[0], ifm_get_port(in_port_id));
674
675                 goto PKT1;
676         }
677         #endif
678
679         /* Drop the pkt if not ARP/ICMP */
680         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask0);
681         p_arp->droppedPktCount++;
682
683 PKT1:
684         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
685                 print_pkt1(pkt[1]);
686                 arpicmp_pkt_print_count++;
687                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
688                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
689                                  rte_be_to_cpu_16(*eth_proto1), *protocol1, ETH_TYPE_ARP,
690                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
691         }
692
693         if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_ARP) ||
694                         ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
695                          && (*protocol1 == IP_PROTOCOL_ICMP)
696                 )) {
697                 process_arpicmp_pkt(pkt[1], ifm_get_port(in_port_id));
698                 goto PKT2;
699         }
700         #ifdef IPV6
701         else if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV6)
702                 && (*protocol1 == ICMPV6_PROTOCOL_ID)) {
703                 process_icmpv6_pkt(pkt[1], ifm_get_port(in_port_id));
704
705                 goto PKT2;
706         }
707         #endif
708
709         /* Drop the pkt if not ARP/ICMP */
710         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask1);
711         p_arp->droppedPktCount++;
712
713 PKT2:
714         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
715                 print_pkt1(pkt[2]);
716                 arpicmp_pkt_print_count++;
717                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
718                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
719                                  rte_be_to_cpu_16(*eth_proto2), *protocol2, ETH_TYPE_ARP,
720                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
721         }
722
723         if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_ARP) ||
724                         ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
725                          && (*protocol2 == IP_PROTOCOL_ICMP)
726                 )) {
727                 process_arpicmp_pkt(pkt[2], ifm_get_port(in_port_id));
728                 goto PKT3;
729         }
730         #ifdef IPV6
731         else if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV6)
732                 && (*protocol2 == ICMPV6_PROTOCOL_ID)) {
733                 process_icmpv6_pkt(pkt[2], ifm_get_port(in_port_id));
734
735                 goto PKT3;
736         }
737         #endif
738
739         /* Drop the pkt if not ARP/ICMP */
740         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask2);
741         p_arp->droppedPktCount++;
742
743 PKT3:
744         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
745                 print_pkt1(pkt[3]);
746                 arpicmp_pkt_print_count++;
747                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
748                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
749                                  rte_be_to_cpu_16(*eth_proto3), *protocol3, ETH_TYPE_ARP,
750                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
751         }
752
753         if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_ARP) ||
754                         ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
755                          && (*protocol3 == IP_PROTOCOL_ICMP)
756                 )) {
757
758                 process_arpicmp_pkt(pkt[3], ifm_get_port(in_port_id));
759
760                 return;
761         }
762         #ifdef IPV6
763         else if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV6)
764                 && (*protocol3 == ICMPV6_PROTOCOL_ID)) {
765
766                 process_icmpv6_pkt(pkt[3], ifm_get_port(in_port_id));
767                 return;
768         }
769         #endif
770
771         /* Drop the pkt if not ARP/ICMP */
772         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask3);
773         p_arp->droppedPktCount++;
774
775
776 }
777
778 PIPELINE_ARPICMP_KEY_PORT_IN_AH(
779         port_in_ah_arpicmp,
780         pkt_key_arpicmp,
781         pkt4_key_arpicmp);
782
783 static void *pipeline_arpicmp_init(struct pipeline_params *params,
784                                 __rte_unused void *arg)
785 {
786         struct pipeline *p;
787         struct pipeline_arpicmp *p_arp;
788         uint32_t size, i, in_ports_arg_size;
789
790         printf("Start pipeline_arpicmp_init\n");
791
792         /* Check input arguments */
793         if ((params == NULL) ||
794                         (params->n_ports_in == 0) ||
795                         (params->n_ports_out == 0))
796                 return NULL;
797
798         /* Memory allocation */
799         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_arpicmp));
800         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
801         p_arp = (struct pipeline_arpicmp *)p;
802         if (p == NULL)
803                 return NULL;
804
805         //gp_arp = p_arp;
806         struct app_params *app = (struct app_params *)arg;
807         myApp = arg;
808
809         PLOG(p, HIGH, "ARPICMP");
810         strcpy(p->name, params->name);
811         p->log_level = params->log_level;
812
813         p_arp->receivedPktCount = 0;
814         p_arp->droppedPktCount = 0;
815         gw_init(rte_eth_dev_count());
816         lib_arp_init(params, app);
817
818         /* Pipeline */
819         {
820                 struct rte_pipeline_params pipeline_params = {
821                         .name = "ARPICMP",
822                         .socket_id = params->socket_id,
823                         .offset_port_id = 0,
824                         //.offset_port_id = arp_meta_offset,
825                 };
826
827                 p->p = rte_pipeline_create(&pipeline_params);
828                 if (p->p == NULL) {
829                         rte_free(p);
830                         return NULL;
831                 }
832         }
833
834         p->n_ports_in = params->n_ports_in;
835         p->n_ports_out = params->n_ports_out;
836         p->n_tables = 1;
837
838         /* Memory allocation for in_port_h_arg */
839         in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
840                 (sizeof(struct pipeline_arpicmp_in_port_h_arg)) *
841                                 (params->n_ports_in));
842         struct pipeline_arpicmp_in_port_h_arg *ap =
843                 (struct pipeline_arpicmp_in_port_h_arg *)rte_zmalloc(NULL,
844                                 in_ports_arg_size,
845                                 RTE_CACHE_LINE_SIZE);
846         if (ap == NULL)
847                 return NULL;
848
849         /*Input ports */
850         for (i = 0; i < p->n_ports_in; i++) {
851                 /* passing our txrx pipeline in call back arg */
852                 (ap[i]).p = p_arp;
853                 (ap[i]).in_port_id = i;
854                 struct rte_pipeline_port_in_params port_params = {
855                         .ops =
856                                         pipeline_port_in_params_get_ops(&params->
857                                                                         port_in[i]),
858                         .arg_create =
859                                         pipeline_port_in_params_convert(&params->
860                                                                         port_in[i]),
861                         .f_action = NULL,
862                         .arg_ah = &(ap[i]),
863                         .burst_size = params->port_in[i].burst_size,
864                 };
865
866                         port_params.f_action = port_in_ah_arpicmp;
867
868                 int status = rte_pipeline_port_in_create(p->p,
869                                                          &port_params,
870                                                          &p->port_in_id[i]);
871
872                 if (status) {
873                         rte_pipeline_free(p->p);
874                         rte_free(p);
875                         return NULL;
876                 }
877         }
878
879         /* Output ports */
880         for (i = 0; i < p->n_ports_out; i++) {
881                 struct rte_pipeline_port_out_params port_params = {
882                         .ops =
883                                         pipeline_port_out_params_get_ops(&params->
884                                                                          port_out[i]),
885                         .arg_create =
886                                         pipeline_port_out_params_convert(&params->
887                                                                          port_out[i]),
888                         .f_action = NULL,
889                         .arg_ah = NULL,
890                 };
891
892                 int status = rte_pipeline_port_out_create(p->p,
893                                                                 &port_params,
894                                                                 &p->port_out_id[i]);
895
896                 if (status) {
897                         rte_pipeline_free(p->p);
898                         rte_free(p);
899                         return NULL;
900                 }
901         }
902         int pipeline_num = 0;
903
904         int status = sscanf(params->name, "PIPELINE%d", &pipeline_num);
905
906         if (status < 0) {
907                 return NULL;
908                 printf("Unable to read pipeline number\n");
909         }
910
911         p_arp->pipeline_num = (uint8_t) pipeline_num;
912
913         register_pipeline_Qs(p_arp->pipeline_num, p);
914         set_phy_outport_id(p_arp->pipeline_num, p, p_arp->outport_id);
915
916         /* Tables */
917         {
918                 struct rte_pipeline_table_params table_params = {
919                         .ops = &rte_table_stub_ops,
920                         .arg_create = NULL,
921                         .f_action_hit = NULL,
922                         .f_action_miss = NULL,
923                         .arg_ah = NULL,
924                         .action_data_size = 0,
925                 };
926
927                 int status = rte_pipeline_table_create(p->p,
928                                                                          &table_params,
929                                                                          &p->table_id[0]);
930
931                 if (status) {
932                         rte_pipeline_free(p->p);
933                         rte_free(p);
934                         return NULL;
935                 }
936         }
937
938         /* Connecting input ports to tables */
939         for (i = 0; i < p->n_ports_in; i++) {
940
941                 int status = rte_pipeline_port_in_connect_to_table(p->p,
942                                                                          p->
943                                                                          port_in_id
944                                                                          [i],
945                                                                          p->
946                                                                          table_id[0]);
947
948                 if (status) {
949                         rte_pipeline_free(p->p);
950                         rte_free(p);
951                         return NULL;
952                 }
953
954         }
955
956         /* Enable input ports */
957         for (i = 0; i < p->n_ports_in; i++) {
958                 int status = rte_pipeline_port_in_enable(p->p,
959                                                          p->port_in_id[i]);
960
961                 if (status) {
962                         rte_pipeline_free(p->p);
963                         rte_free(p);
964                         return NULL;
965                 }
966         }
967
968         /* Check pipeline consistency */
969         if (rte_pipeline_check(p->p) < 0) {
970                 rte_pipeline_free(p->p);
971                 rte_free(p);
972                 return NULL;
973         }
974
975         /* Message queues */
976         p->n_msgq = params->n_msgq;
977         for (i = 0; i < p->n_msgq; i++)
978                 p->msgq_in[i] = params->msgq_in[i];
979         for (i = 0; i < p->n_msgq; i++)
980                 p->msgq_out[i] = params->msgq_out[i];
981
982         /* Message handlers */
983         memcpy(p->handlers, handlers, sizeof(p->handlers));
984
985         return p;
986 }
987
988 static int pipeline_arpicmp_free(void *pipeline)
989 {
990         struct pipeline *p = (struct pipeline *)pipeline;
991
992         /* Check input arguments */
993         if (p == NULL)
994                 return -1;
995
996         /* Free resources */
997         rte_pipeline_free(p->p);
998         rte_free(p);
999         return 0;
1000 }
1001
1002 static int pipeline_arpicmp_timer(void *pipeline)
1003 {
1004         struct pipeline *p = (struct pipeline *)pipeline;
1005
1006         pipeline_msg_req_handle(p);
1007         rte_pipeline_flush(p->p);
1008
1009         return 0;
1010 }
1011
1012 static int
1013 pipeline_arpicmp_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
1014 {
1015         struct pipeline *p = (struct pipeline *)pipeline;
1016
1017         /* Check input arguments */
1018         if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
1019                 return -1;
1020
1021         *port_out = port_in / p->n_ports_in;
1022         return 0;
1023 }
1024
1025 struct pipeline_be_ops pipeline_arpicmp_be_ops = {
1026         .f_init = pipeline_arpicmp_init,
1027         .f_free = pipeline_arpicmp_free,
1028         .f_run = NULL,
1029         .f_timer = pipeline_arpicmp_timer,
1030         .f_track = pipeline_arpicmp_track,
1031 };