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