Merge "[SAMPLEVNF] Adding support to handle more than 16 ports"
[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 #ifndef VNF_ACL
51 #include "lib_arp.h"
52 #include "lib_icmpv6.h"
53 #include "interface.h"
54 #endif
55
56 #ifdef VNF_ACL
57
58 #define NB_ARPICMP_MBUF  64
59 #define NB_NDICMP_MBUF  64
60 #define IP_VERSION_4 0x40
61 /* default IP header length == five 32-bits words. */
62 #define IP_HDRLEN  0x05
63 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
64
65 #define is_multicast_ipv4_addr(ipv4_addr) \
66         (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
67
68
69 /*ND IPV6 */
70 #define INADDRSZ 4
71 #define IN6ADDRSZ 16
72 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
73 static int inet_pton_ipv6(const char *src, unsigned char *dst);
74 static int inet_pton_ipv4(const char *src, unsigned char *dst);
75
76 uint8_t vnf_common_arp_lib_init;
77 uint8_t vnf_common_nd_lib_init;
78 uint8_t loadb_pipeline_count;
79
80 uint32_t ARPICMP_DEBUG;
81 uint32_t NDIPV6_DEBUG;
82
83 uint32_t arp_route_tbl_index;
84 uint32_t nd_route_tbl_index;
85 uint32_t link_hw_addr_array_idx;
86
87 uint32_t lib_arp_get_mac_req;
88 uint32_t lib_arp_nh_found;
89 uint32_t lib_arp_no_nh_found;
90 uint32_t lib_arp_arp_entry_found;
91 uint32_t lib_arp_no_arp_entry_found;
92 uint32_t lib_arp_populate_called;
93 uint32_t lib_arp_delete_called;
94 uint32_t lib_arp_duplicate_found;
95
96 uint32_t lib_nd_get_mac_req;
97 uint32_t lib_nd_nh_found;
98 uint32_t lib_nd_no_nh_found;
99 uint32_t lib_nd_nd_entry_found;
100 uint32_t lib_nd_no_arp_entry_found;
101 uint32_t lib_nd_populate_called;
102 uint32_t lib_nd_delete_called;
103 uint32_t lib_nd_duplicate_found;
104
105 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
106 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
107
108 struct rte_mbuf *lib_arp_pkt;
109 struct rte_mbuf *lib_nd_pkt;
110
111 static struct rte_hash_parameters arp_hash_params = {
112         .name = "ARP",
113         .entries = 64,
114         .reserved = 0,
115         .key_len = sizeof(struct arp_key_ipv4),
116         .hash_func = rte_jhash,
117         .hash_func_init_val = 0,
118 };
119
120 static struct rte_hash_parameters nd_hash_params = {
121         .name = "ND",
122         .entries = 64,
123         .reserved = 0,
124         .key_len = sizeof(struct nd_key_ipv6),
125         .hash_func = rte_jhash,
126         .hash_func_init_val = 0,
127 };
128
129 struct rte_hash *arp_hash_handle;
130 struct rte_hash *nd_hash_handle;
131
132 #endif
133 /* Shared among all VNFs including LB */
134 struct app_params *myApp;
135 struct rte_pipeline *myP;
136 struct pipeline_arpicmp *gp_arp;
137 uint8_t num_vnf_threads;
138
139 #ifdef VNF_ACL
140
141 struct arp_port_address {
142         uint32_t ip;
143         uint64_t mac_addr;
144 };
145
146 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
147
148 uint16_t arp_meta_offset;
149 #endif
150
151 struct pipeline_arpicmp {
152         struct pipeline p;
153         pipeline_msg_req_handler
154                 custom_handlers[PIPELINE_ARPICMP_MSG_REQS];
155         uint64_t receivedPktCount;
156         uint64_t droppedPktCount;
157         uint64_t sentPktCount;
158         uint8_t links_map[PIPELINE_MAX_PORT_IN];
159         uint8_t outport_id[PIPELINE_MAX_PORT_IN];
160         uint8_t pipeline_num;
161 } __rte_cache_aligned;
162
163 #ifdef VNF_ACL
164
165 #define MAX_NUM_ARP_ENTRIES 64
166 #define MAX_NUM_ND_ENTRIES 64
167
168
169 struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
170         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
171          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
172         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
173          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
174         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
175          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
176         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
177          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
178         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
179          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
180         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
181          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
182         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
183          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
184         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
185          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
186         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
187          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
188         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
189          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
190         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
191          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
192         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
193          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
194         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
195          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
196         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
197          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
198         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
199          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
200         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
201          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
202         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
203          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
204         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
205          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
206         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
207          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
208         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
209          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
210         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
211          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
212         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
213          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
214         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
215          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
216         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
217          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
218         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
219          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
220         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
221          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
222         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
223          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
224         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
225          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
226         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
227          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
228         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
229          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
230         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
231          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
232         {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
233          {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
234 };
235
236 struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
237 //   {0xac102814, 1, 0xac102814},
238 //   {0xac106414, 0, 0xac106414},
239         {0, 0, 0, 0},
240         {0, 0, 0, 0},
241         {0, 0, 0, 0},
242         {0, 0, 0, 0},
243         {0, 0, 0, 0},
244         {0, 0, 0, 0},
245         {0, 0, 0, 0},
246         {0, 0, 0, 0},
247         {0, 0, 0, 0},
248         {0, 0, 0, 0},
249         {0, 0, 0, 0},
250         {0, 0, 0, 0},
251         {0, 0, 0, 0},
252         {0, 0, 0, 0},
253         {0, 0, 0, 0},
254         {0, 0, 0, 0},
255         {0, 0, 0, 0},
256         {0, 0, 0, 0},
257         {0, 0, 0, 0},
258         {0, 0, 0, 0},
259         {0, 0, 0, 0},
260         {0, 0, 0, 0},
261         {0, 0, 0, 0},
262         {0, 0, 0, 0},
263         {0, 0, 0, 0},
264         {0, 0, 0, 0},
265         {0, 0, 0, 0},
266         {0, 0, 0, 0},
267         {0, 0, 0, 0},
268         {0, 0, 0, 0},
269         {0, 0, 0, 0},
270         {0, 0, 0, 0}
271 };
272
273 #endif
274
275 void pipelines_port_info(void)
276 {
277         struct app_params *app = myApp;
278         uint8_t i, pipeline;
279         for (pipeline = 0; pipeline < app->n_pipelines; pipeline++) {
280                 printf("*** PIPELINE %d ***\n\n", pipeline);
281
282                 printf("*** OUTPORTs ***\n");
283                 for (i = 1; i < app->pipeline_params[pipeline].n_pktq_out;
284                         i++) {
285                         switch (app->pipeline_params[pipeline].pktq_out[i].
286                         type) {
287                         case APP_PKTQ_OUT_SWQ:
288                                 printf("pktq_out[%d]:%s\n", i,
289                                                          app->swq_params[app->pipeline_params
290                                                                          [pipeline].
291                                                                          pktq_out[i].id].name);
292                                 break;
293                         case APP_PKTQ_OUT_HWQ:
294                                 printf("pktq_out[%d]:%s\n", i,
295                                                          app->hwq_out_params[app->pipeline_params
296                                                                  [pipeline].pktq_out
297                                                                  [i].id].name);
298                                 break;
299                         default:
300                                 printf("Not OUT SWQ or HWQ\n");
301                         }
302                 }
303                 printf("*** INPORTs ***\n");
304                 for (i = 0; i < app->pipeline_params[pipeline].n_pktq_in; i++) {
305                         switch (app->pipeline_params[pipeline].pktq_in[i]
306                         .type) {
307                         case APP_PKTQ_IN_SWQ:
308                                 printf("pktq_in[%d]:%s\n", i,
309                                                          app->swq_params[app->pipeline_params
310                                                                          [pipeline].
311                                                                          pktq_in[i].id].name);
312                                 break;
313                         case APP_PKTQ_IN_HWQ:
314                                 printf("pktq_in[%d]:%s\n", i,
315                                                          app->hwq_in_params[app->pipeline_params
316                                                                 [pipeline].
317                                                                 pktq_in[i].id].name);
318                                 break;
319                         default:
320                                 printf("Not IN SWQ or HWQ\n");
321                         }
322                 }
323         }                       //for
324 }
325
326 void pipelines_map_info(void)
327 {
328          int i = 0;
329
330         printf("PIPELINE_MAX_PORT_IN %d\n", PIPELINE_MAX_PORT_IN);
331         printf("lb_outport_id[%d", lb_outport_id[0]);
332         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
333                 printf(",%d", lb_outport_id[i]);
334         printf("]\n");
335
336         printf("vnf_to_loadb_map[%d", vnf_to_loadb_map[0]);
337         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
338                 printf(",%d", vnf_to_loadb_map[i]);
339         printf("]\n");
340
341         printf("port_to_loadb_map[%d", port_to_loadb_map[0]);
342         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
343                 printf(",%d", port_to_loadb_map[i]);
344         printf("]\n");
345
346         printf("loadb_pipeline_nums[%d", loadb_pipeline_nums[0]);
347         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
348                 printf(",%d", loadb_pipeline_nums[i]);
349         printf("]\n");
350
351         printf("loadb_pipeline[%p", loadb_pipeline[0]);
352         for (i = 1; i < PIPELINE_MAX_PORT_IN; i++)
353                 printf(",%p", loadb_pipeline[i]);
354         printf("]\n");
355 }
356
357 void register_pipeline_Qs(uint8_t pipeline_num, struct pipeline *p)
358 {
359         struct rte_port_ethdev_reader *hwq;
360         struct rte_port_ring_writer *out_swq;
361         struct rte_port_ring_reader *in_swq;
362         struct rte_pipeline *rte = p->p;
363         uint8_t port_count = 0;
364         int queue_out = 0xff, queue_in = 0xff;
365
366         printf("Calling register_pipeline_Qs in PIPELINE%d\n", pipeline_num);
367         for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
368
369         switch (myApp->pipeline_params[pipeline_num].
370                                 pktq_out[port_count].type){
371
372         case APP_PKTQ_OUT_SWQ:
373
374                 if (port_count >= rte->num_ports_in) {
375
376                         /* Dont register ARP output Q */
377                         if (rte->num_ports_out % rte->num_ports_in)
378                                 if (port_count == rte->num_ports_out - 1)
379                                         return;
380                         int temp;
381                         temp = ((port_count) % rte->num_ports_in);
382
383                         in_swq = rte->ports_in[temp].h_port;
384                         out_swq = rte->ports_out[port_count].h_port;
385                         printf("in_swq : %s\n",
386                                 in_swq->ring->name);
387                         int status =
388                         sscanf(in_swq->ring->name, "SWQ%d",
389                                         &queue_in);
390                         if (status < 0) {
391                                 printf("Unable to read SWQ number\n");
392                                 return;
393                         }
394                         printf("out_swq: %s\n",
395                                         out_swq->ring->name);
396                         status =
397                         sscanf(out_swq->ring->name, "SWQ%d",
398                                         &queue_out);
399                         if (status < 0) {
400                                 printf("Unable to read SWQ number\n");
401                                 return;
402                         }
403                         if (queue_in < 128 && queue_out < 128) {
404                                 SWQ_to_Port_map[queue_out] =
405                                         SWQ_to_Port_map[queue_in];
406                          printf("SWQ_to_Port_map[%d]%d\n", queue_out,
407                                  SWQ_to_Port_map[queue_out]);
408                         }
409                         continue;
410                 }
411
412                 switch (myApp->pipeline_params[pipeline_num].
413                          pktq_in[port_count].type){
414
415                 case APP_PKTQ_OUT_HWQ:
416                          hwq = rte->ports_in[port_count].h_port;
417                          out_swq = rte->ports_out[port_count].h_port;
418                          printf("out_swq: %s\n",
419                                  out_swq->ring->name);
420                         int status =
421                         sscanf(out_swq->ring->name, "SWQ%d",
422                                  &queue_out);
423
424                         if (status < 0) {
425                                 printf("Unable to read SWQ number\n");
426                                 return;
427                         }
428                         if (queue_out < 128) {
429                                 SWQ_to_Port_map[queue_out] = hwq->port_id;
430                                 printf("SWQ_to_Port_map[%d]%d\n", queue_out,
431                                         SWQ_to_Port_map[queue_out]);
432                         }
433                 break;
434
435                 case APP_PKTQ_OUT_SWQ:
436                          in_swq = rte->ports_in[port_count].h_port;
437                          out_swq = rte->ports_out[port_count].h_port;
438                          printf("in_swq : %s\n",
439                                  in_swq->ring->name);
440                         status =
441                         sscanf(in_swq->ring->name, "SWQ%d",
442                                          &queue_in);
443                         if (status < 0) {
444                                 printf("Unable to read SWQ number\n");
445                                 return;
446                         }
447                         printf("out_swq: %s\n",
448                                          out_swq->ring->name);
449                         status =
450                         sscanf(out_swq->ring->name, "SWQ%d",
451                                          &queue_out);
452                         if (status < 0) {
453                                 printf("Unable to read SWQ number\n");
454                                 return;
455                         }
456                         if (queue_in < 128 && queue_out < 128){
457                                 SWQ_to_Port_map[queue_out] =
458                                         SWQ_to_Port_map[queue_in];
459                          printf("SWQ_to_Port_map[%d]%d\n", queue_out,
460                                  SWQ_to_Port_map[queue_out]);
461                           }
462                 break;
463
464                 default:
465                          printf("This never hits\n");
466                 }
467
468         break;
469
470         case APP_PKTQ_OUT_HWQ:
471                  printf("This is HWQ\n");
472         break;
473
474         default:
475                  printf("set_phy_outport_map: This never hits\n");
476         }
477         }
478 }
479
480 void set_link_map(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
481 {
482                 struct rte_port_ethdev_writer *hwq;
483                 struct rte_port_ring_writer *out_swq;
484                 struct rte_pipeline *rte = p->p;
485
486                 uint8_t port_count = 0;
487                 int index = 0, queue_out = 0xff;
488
489         printf("Calling set_link_map in PIPELINE%d\n", pipeline_num);
490         for (port_count = 0; port_count < rte->num_ports_out; port_count++) {
491
492                 switch (myApp->pipeline_params[pipeline_num].
493                                 pktq_out[port_count].type){
494
495                 case APP_PKTQ_OUT_HWQ:
496                         hwq = rte->ports_out[port_count].h_port;
497                         map[index++] = hwq->port_id;
498                         printf("links_map[%d]:%d\n", index - 1, map[index - 1]);
499                 break;
500
501                 case APP_PKTQ_OUT_SWQ:
502                         out_swq = rte->ports_out[port_count].h_port;
503                         printf("set_link_map out_swq: %s\n",
504                                 out_swq->ring->name);
505                         int status = sscanf(out_swq->ring->name, "SWQ%d",
506                                         &queue_out);
507                         if (status < 0) {
508                                 printf("Unable to read SWQ number\n");
509                                 return;
510                         }
511
512                         if (queue_out < 128) {
513                         map[index++] = SWQ_to_Port_map[queue_out];
514                         printf("links_map[%s]:%d\n", out_swq->ring->name,
515                                         map[index - 1]);
516                         }
517                 break;
518
519                 default:
520                         printf("set_phy_outport_map: This never hits\n");
521                 }
522                 }
523 }
524
525 void set_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
526 {
527         uint8_t port_count = 0;
528         int queue_out = 0xff, index = 0;
529
530         struct rte_port_ethdev_writer *hwq;
531         struct rte_port_ring_writer *out_swq;
532         struct rte_pipeline *rte = p->p;
533
534         printf("\n**** set_outport_id() with pipeline_num:%d ****\n\n",
535                 pipeline_num);
536         for (port_count = 0;
537                 port_count < rte->num_ports_out;
538                 port_count++) {
539
540         switch (myApp->pipeline_params[pipeline_num].
541                         pktq_out[port_count].type) {
542
543         case APP_PKTQ_OUT_HWQ:
544                 hwq = rte->ports_out[port_count].h_port;
545                 //if (index >= 0)
546                 {
547                         map[hwq->port_id] = index;
548                         printf("hwq port_id:%d index:%d\n",
549                                 hwq->port_id, index);
550                         map[hwq->port_id] = index++;
551                         printf("hwq port_id:%d index:%d\n",
552                                 hwq->port_id, index-1);
553                         printf("outport_id[%d]:%d\n", index - 1,
554                                 map[index - 1]);
555                 }
556                 break;
557
558         case APP_PKTQ_OUT_SWQ:
559
560                 /* Dont register ARP output Q */
561                 if (port_count >= rte->num_ports_in)
562                         if (rte->num_ports_out % rte->num_ports_in)
563                                 if (port_count == rte->num_ports_out - 1)
564                                         return;
565                  out_swq = rte->ports_out[port_count].h_port;
566                  printf("set_outport_id out_swq: %s\n",
567                          out_swq->ring->name);
568                 int temp = sscanf(out_swq->ring->name, "SWQ%d",
569                                  &queue_out);
570                 if (temp < 0) {
571                         printf("Unable to read SWQ number\n");
572                         return;
573                 }
574
575                 if (queue_out < 128 && index >= 0) {
576                         map[SWQ_to_Port_map[queue_out]] = index++;
577                         printf("outport_id[%s]:%d\n", out_swq->ring->name,
578                                          map[SWQ_to_Port_map[queue_out]]);
579                 }
580                 break;
581
582                 default:
583                          printf(" ");
584
585                 }
586         }
587 }
588
589 void set_phy_outport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
590 {
591         uint8_t port_count = 0;
592         int index = 0;
593
594         struct rte_port_ethdev_writer *hwq;
595         struct rte_pipeline *rte = p->p;
596
597         printf("\n**** set_phy_outport_id() with pipeline_num:%d ****\n\n",
598                 pipeline_num);
599         for (port_count = 0;
600                 port_count < myApp->pipeline_params[pipeline_num].n_pktq_out;
601                 port_count++) {
602
603         switch (myApp->pipeline_params[pipeline_num].
604                         pktq_out[port_count].type) {
605
606         case APP_PKTQ_OUT_HWQ:
607                 hwq = rte->ports_out[port_count].h_port;
608                 map[hwq->port_id] = index++;
609                 printf("outport_id[%d]:%d\n", index - 1,
610                         map[index - 1]);
611         break;
612
613         default:
614                  printf(" ");
615
616                 }
617         }
618 }
619
620 void set_phy_inport_id(uint8_t pipeline_num, struct pipeline *p, uint8_t *map)
621 {
622         uint8_t port_count = 0;
623         int index = 0;
624
625         struct rte_port_ethdev_reader *hwq;
626         struct rte_pipeline *rte = p->p;
627
628         printf("\n**** set_phy_inport_id() with pipeline_num:%d ****\n\n",
629                                  pipeline_num);
630         for (port_count = 0;
631                 port_count < myApp->pipeline_params[pipeline_num].n_pktq_in;
632                 port_count++) {
633
634                 switch (myApp->pipeline_params[pipeline_num].
635                         pktq_in[port_count].type) {
636
637                 case APP_PKTQ_OUT_HWQ:
638                         hwq = rte->ports_in[port_count].h_port;
639                         map[hwq->port_id] = index++;
640                         printf("outport_id[%d]:%d\n", index - 1,
641                                 map[index - 1]);
642                 break;
643
644                 default:
645                         printf(" ");
646
647                 }
648         }
649 }
650
651 #ifdef VNF_ACL
652
653 uint32_t get_nh(uint32_t ip, uint32_t *port)
654 {
655         int i = 0;
656         for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
657                 if (((lib_arp_route_table[i].
658                         ip & lib_arp_route_table[i].mask) ==
659                         (ip & lib_arp_route_table[i].mask))) {
660
661                         *port = lib_arp_route_table[i].port;
662                         lib_arp_nh_found++;
663                         return lib_arp_route_table[i].nh;
664                 }
665         if (ARPICMP_DEBUG > 1)
666                 printf("No nh match ip 0x%x, port %u, t_ip "
667                 "0x%x, t_port %u, mask 0x%x, r1 %x, r2 %x\n",
668                 ip, *port, lib_arp_route_table[i].ip,
669                 lib_arp_route_table[i].port,
670                 lib_arp_route_table[i].mask,
671                 (lib_arp_route_table[i].ip &
672                 lib_arp_route_table[i].mask),
673                 (ip & lib_arp_route_table[i].mask));
674         }
675         if (ARPICMP_DEBUG && ip)
676                 printf("No NH - ip 0x%x, port %u\n", ip, *port);
677         lib_arp_no_nh_found++;
678         return 0;
679 }
680
681 /*ND IPv6 */
682 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
683 {
684         int i = 0;
685         uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
686         uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
687         memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
688         memset(netip_nd, 0, sizeof(netip_nd));
689         memset(netip_in, 0, sizeof(netip_in));
690         if (!ipv6)
691                 return;
692         for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
693
694                 convert_prefixlen_to_netmask_ipv6(
695                                         lib_nd_route_table[i].depth,
696                                         netmask_ipv6);
697
698                 for (k = 0; k < 16; k++) {
699                         if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
700                                 depthflags++;
701                                 netip_nd[k] = lib_nd_route_table[i].ipv6[k];
702                         }
703                 }
704
705                 for (l = 0; l < 16; l++) {
706                         if (ipv6[l] & netmask_ipv6[l]) {
707                                 depthflags1++;
708                                 netip_in[l] = ipv6[l];
709                         }
710                 }
711                 int j = 0;
712                 if ((depthflags == depthflags1)
713                         && (memcmp(netip_nd, netip_in,
714                                 sizeof(netip_nd)) == 0)) {
715                         //&& (lib_nd_route_table[i].port == port))
716                         *port = lib_nd_route_table[i].port;
717                         lib_nd_nh_found++;
718
719                         for (j = 0; j < 16; j++)
720                                 nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
721
722                         return;
723                 }
724
725                 if (NDIPV6_DEBUG > 1)
726                         printf("No nh match\n");
727                 depthflags = 0;
728                 depthflags1 = 0;
729         }
730         if (NDIPV6_DEBUG && ipv6)
731                 printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
732         lib_nd_no_nh_found++;
733 }
734
735 /* Added for Multiport changes*/
736 int get_dest_mac_addr_port(const uint32_t ipaddr,
737                                         uint32_t *phy_port, struct ether_addr *hw_addr)
738 {
739         lib_arp_get_mac_req++;
740         uint32_t nhip = 0;
741
742         nhip = get_nh(ipaddr, phy_port);
743         if (nhip == 0) {
744                 if (ARPICMP_DEBUG && ipaddr)
745                         printf("ARPICMP no nh found for ip %x, port %d\n",
746                                                  ipaddr, *phy_port);
747                 //return 0;
748                 return NH_NOT_FOUND;
749         }
750
751         struct arp_entry_data *ret_arp_data = NULL;
752         struct arp_key_ipv4 tmp_arp_key;
753         tmp_arp_key.port_id = *phy_port;/* Changed for Multi Port*/
754         tmp_arp_key.ip = nhip;
755
756         ret_arp_data = retrieve_arp_entry(tmp_arp_key);
757         if (ret_arp_data == NULL) {
758                 if (ARPICMP_DEBUG && ipaddr) {
759                         printf
760                                         ("ARPICMP no arp entry found for ip %x, port %d\n",
761                                          ipaddr, *phy_port);
762                         print_arp_table();
763                 }
764                 lib_arp_no_arp_entry_found++;
765                 return ARP_NOT_FOUND;
766         }
767         ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
768         lib_arp_arp_entry_found++;
769         return ARP_FOUND;
770 }
771
772 /*ND IPv6 */
773 int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t phy_port,
774                                                  struct ether_addr *hw_addr, uint8_t nhipv6[])
775 {
776         int i = 0, j = 0, flag = 0;
777         lib_nd_get_mac_req++;
778
779         if (ipv6addr)
780         get_nh_ipv6(ipv6addr, &phy_port, nhipv6);
781         for (j = 0; j < 16; j++) {
782                 if (nhipv6[j])
783                         flag++;
784         }
785         if (flag == 0) {
786                 if (ipv6addr) {
787                 if (NDIPV6_DEBUG && ipv6addr)
788                         printf("NDIPV6 no nh found for ipv6 "
789                         "%02x%02x%02x%02x%02x%02x%02x%02x%02x"
790                         "%02x%02x%02x%02x%02x%02x%02x, port %d\n",
791                         ipv6addr[0], ipv6addr[1], ipv6addr[2], ipv6addr[3],
792                         ipv6addr[4], ipv6addr[5], ipv6addr[6], ipv6addr[7],
793                         ipv6addr[8], ipv6addr[9], ipv6addr[10],
794                         ipv6addr[11], ipv6addr[12], ipv6addr[13],
795                         ipv6addr[14], ipv6addr[15], phy_port);
796                         return 0;
797         }
798         }
799
800          struct nd_entry_data *ret_nd_data = NULL;
801          struct nd_key_ipv6 tmp_nd_key;
802          tmp_nd_key.port_id = phy_port;
803
804         for (i = 0; i < 16; i++)
805                 tmp_nd_key.ipv6[i] = nhipv6[i];
806
807          ret_nd_data = retrieve_nd_entry(tmp_nd_key);
808         if (ret_nd_data == NULL) {
809                 if (NDIPV6_DEBUG && ipv6addr) {
810                         printf("NDIPV6 no nd entry found for ip %x, port %d\n",
811                                 ipv6addr[0], phy_port);
812                 }
813                  lib_nd_no_arp_entry_found++;
814                 return 0;
815         }
816          ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
817          lib_nd_nd_entry_found++;
818         return 1;
819
820 }
821
822 /*ND IPv6 */
823 int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
824                                                  struct ether_addr *hw_addr, uint8_t nhipv6[])
825 {
826         int i = 0, j = 0, flag = 0;
827         lib_nd_get_mac_req++;
828
829         get_nh_ipv6(ipv6addr, phy_port, nhipv6);
830         for (j = 0; j < 16; j++) {
831                 if (nhipv6[j])
832                         flag++;
833         }
834         if (flag == 0) {
835                 if (NDIPV6_DEBUG && ipv6addr)
836                         printf("NDIPV6 no nh found for ipv6 "
837                         "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
838                         "%02x%02x%02x%02x%02x%02x, port %d\n",
839                         ipv6addr[0], ipv6addr[1], ipv6addr[2], ipv6addr[3],
840                         ipv6addr[4], ipv6addr[5], ipv6addr[6], ipv6addr[7],
841                         ipv6addr[8], ipv6addr[9], ipv6addr[10],
842                         ipv6addr[11], ipv6addr[12], ipv6addr[13],
843                         ipv6addr[14], ipv6addr[15], *phy_port);
844                         return 0;
845         }
846
847          struct nd_entry_data *ret_nd_data = NULL;
848          struct nd_key_ipv6 tmp_nd_key;
849          tmp_nd_key.port_id = *phy_port;
850
851         for (i = 0; i < 16; i++)
852                 tmp_nd_key.ipv6[i] = nhipv6[i];
853
854          ret_nd_data = retrieve_nd_entry(tmp_nd_key);
855         if (ret_nd_data == NULL) {
856                 if (NDIPV6_DEBUG && ipv6addr) {
857                         printf("NDIPV6 no nd entry found for ip %x, port %d\n",
858                                 ipv6addr[0], *phy_port);
859                 }
860                  lib_nd_no_arp_entry_found++;
861                 return 0;
862         }
863          ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
864          lib_nd_nd_entry_found++;
865         return 1;
866
867 }
868
869 /*
870  * ARP table
871  */
872 struct lib_arp_arp_table_entry {
873         struct rte_pipeline_table_entry head;
874         uint64_t macaddr;
875 };
876
877 static const char *arp_op_name(uint16_t arp_op)
878 {
879         switch (CHECK_ENDIAN_16(arp_op)) {
880         case (ARP_OP_REQUEST):
881                 return "ARP Request";
882         case (ARP_OP_REPLY):
883                 return "ARP Reply";
884         case (ARP_OP_REVREQUEST):
885                 return "Reverse ARP Request";
886         case (ARP_OP_REVREPLY):
887                 return "Reverse ARP Reply";
888         case (ARP_OP_INVREQUEST):
889                 return "Peer Identify Request";
890         case (ARP_OP_INVREPLY):
891                 return "Peer Identify Reply";
892         default:
893                 break;
894         }
895         return "Unkwown ARP op";
896 }
897
898 static void print_icmp_packet(struct icmp_hdr *icmp_h)
899 {
900         printf("  ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
901                                  icmp_h->icmp_type,
902                                  (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
903                 (icmp_h->icmp_type ==
904                  IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")), icmp_h->icmp_code,
905                                  CHECK_ENDIAN_16(icmp_h->icmp_ident),
906                                  CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
907 }
908
909 static void print_ipv4_h(struct ipv4_hdr *ip_h)
910 {
911         struct icmp_hdr *icmp_h =
912                         (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
913         printf("  IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
914                                  (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
915                                  ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
916         if (ip_h->next_proto_id == IPPROTO_ICMP)
917                 print_icmp_packet(icmp_h);
918 }
919
920 static void print_arp_packet(struct arp_hdr *arp_h)
921 {
922         printf("  ARP:  hrd=%d proto=0x%04x hln=%d "
923                                  "pln=%d op=%u (%s)\n",
924                                  CHECK_ENDIAN_16(arp_h->arp_hrd),
925                                  CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
926                                  arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
927                                  arp_op_name(arp_h->arp_op));
928
929         if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
930                 printf("incorrect arp_hrd format for IPv4 ARP (%d)\n",
931                                          (arp_h->arp_hrd));
932         } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
933                 printf("incorrect arp_pro format for IPv4 ARP (%d)\n",
934                                          (arp_h->arp_pro));
935         } else if (arp_h->arp_hln != 6) {
936                 printf("incorrect arp_hln format for IPv4 ARP (%d)\n",
937                                          arp_h->arp_hln);
938         } else if (arp_h->arp_pln != 4) {
939                 printf("incorrect arp_pln format for IPv4 ARP (%d)\n",
940                                          arp_h->arp_pln);
941         } else {
942                 // print remainder of ARP request
943                 printf("        sha=%02X:%02X:%02X:%02X:%02X:%02X",
944                                          arp_h->arp_data.arp_sha.addr_bytes[0],
945                                          arp_h->arp_data.arp_sha.addr_bytes[1],
946                                          arp_h->arp_data.arp_sha.addr_bytes[2],
947                                          arp_h->arp_data.arp_sha.addr_bytes[3],
948                                          arp_h->arp_data.arp_sha.addr_bytes[4],
949                                          arp_h->arp_data.arp_sha.addr_bytes[5]);
950                 printf(" sip=%d.%d.%d.%d\n",
951                                          (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
952                                          (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
953                                          (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
954                                          CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
955                 printf("        tha=%02X:%02X:%02X:%02X:%02X:%02X",
956                                          arp_h->arp_data.arp_tha.addr_bytes[0],
957                                          arp_h->arp_data.arp_tha.addr_bytes[1],
958                                          arp_h->arp_data.arp_tha.addr_bytes[2],
959                                          arp_h->arp_data.arp_tha.addr_bytes[3],
960                                          arp_h->arp_data.arp_tha.addr_bytes[4],
961                                          arp_h->arp_data.arp_tha.addr_bytes[5]);
962                 printf(" tip=%d.%d.%d.%d\n",
963                                          (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
964                                          (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
965                                          (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
966                                          CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
967         }
968 }
969
970 static void print_eth(struct ether_hdr *eth_h)
971 {
972         printf("  ETH:  src=%02X:%02X:%02X:%02X:%02X:%02X",
973                                  eth_h->s_addr.addr_bytes[0],
974                                  eth_h->s_addr.addr_bytes[1],
975                                  eth_h->s_addr.addr_bytes[2],
976                                  eth_h->s_addr.addr_bytes[3],
977                                  eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
978         printf(" dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
979                                  eth_h->d_addr.addr_bytes[0],
980                                  eth_h->d_addr.addr_bytes[1],
981                                  eth_h->d_addr.addr_bytes[2],
982                                  eth_h->d_addr.addr_bytes[3],
983                                  eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
984
985 }
986
987 static void
988 print_mbuf(const char *rx_tx, unsigned int portid, struct rte_mbuf *mbuf,
989                  unsigned int line)
990 {
991         struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
992         struct arp_hdr *arp_h =
993                         (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
994         struct ipv4_hdr *ipv4_h =
995                         (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
996
997         printf("%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
998                                  rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
999         print_eth(eth_h);
1000         switch (rte_cpu_to_be_16(eth_h->ether_type)) {
1001         case ETHER_TYPE_IPv4:
1002                 print_ipv4_h(ipv4_h);
1003                 break;
1004         case ETHER_TYPE_ARP:
1005                 print_arp_packet(arp_h);
1006                 break;
1007         default:
1008                 printf("  unknown packet type\n");
1009                 break;
1010         }
1011         fflush(stdout);
1012 }
1013
1014 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key)
1015 {
1016         struct arp_entry_data *ret_arp_data = NULL;
1017         arp_key.filler1 = 0;
1018         arp_key.filler2 = 0;
1019         arp_key.filler3 = 0;
1020
1021         int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
1022                                                          (void **)&ret_arp_data);
1023         if (ret < 0) {
1024                 if (ARPICMP_DEBUG)
1025                         printf("arp-hash lookup failed ret %d, "
1026                         "EINVAL %d, ENOENT %d\n",
1027                         ret, EINVAL, ENOENT);
1028         } else {
1029                 return ret_arp_data;
1030         }
1031
1032         return NULL;
1033 }
1034
1035 /*
1036 * ND IPv6
1037 * Validate if key-value pair already exists in the hash table
1038 * for given key - ND IPv6
1039 *
1040 */
1041 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
1042 {
1043         struct nd_entry_data *ret_nd_data = NULL;
1044         nd_key.filler1 = 0;
1045         nd_key.filler2 = 0;
1046         nd_key.filler3 = 0;
1047
1048         /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
1049         int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
1050                                                          (void **)&ret_nd_data);
1051         if (ret < 0) {
1052                 if (NDIPV6_DEBUG)
1053                         printf("nd-hash: no lookup Entry Found - "
1054                         "ret %d, EINVAL %d, ENOENT %d\n",
1055                         ret, EINVAL, ENOENT);
1056         } else {
1057                 return ret_nd_data;
1058         }
1059
1060         return NULL;
1061 }
1062
1063 void print_arp_table(void)
1064 {
1065         const void *next_key;
1066         void *next_data;
1067         uint32_t iter = 0;
1068
1069         printf("\tport  hw addr            status     ip addr\n");
1070
1071         while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
1072                                  >= 0) {
1073
1074                 struct arp_entry_data *tmp_arp_data =
1075                                 (struct arp_entry_data *)next_data;
1076                 struct arp_key_ipv4 tmp_arp_key;
1077                 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
1078                 printf
1079                                 ("\t%4d  %02X:%02X:%02X:%02X:%02X:%02X  %10s %d.%d.%d.%d\n",
1080                                  tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
1081                                  tmp_arp_data->eth_addr.addr_bytes[1],
1082                                  tmp_arp_data->eth_addr.addr_bytes[2],
1083                                  tmp_arp_data->eth_addr.addr_bytes[3],
1084                                  tmp_arp_data->eth_addr.addr_bytes[4],
1085                                  tmp_arp_data->eth_addr.addr_bytes[5],
1086                                  tmp_arp_data->status ==
1087                                  COMPLETE ? "COMPLETE" : "INCOMPLETE",
1088                                  (tmp_arp_data->ip >> 24),
1089                                  ((tmp_arp_data->ip & 0x00ff0000) >> 16),
1090                                  ((tmp_arp_data->ip & 0x0000ff00) >> 8),
1091                                  ((tmp_arp_data->ip & 0x000000ff)));
1092         }
1093
1094         uint32_t i = 0;
1095         printf("\nARP routing table has %d entries\n", arp_route_tbl_index);
1096         printf("\nIP_Address    Mask          Port    NH_IP_Address\n");
1097         for (i = 0; i < arp_route_tbl_index; i++) {
1098                 printf("0x%x    0x%x    %d       0x%x\n",
1099                                          lib_arp_route_table[i].ip,
1100                                          lib_arp_route_table[i].mask,
1101                                          lib_arp_route_table[i].port, lib_arp_route_table[i].nh);
1102         }
1103
1104         printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, "
1105         "ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1106                          lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
1107                          lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
1108                          lib_arp_populate_called, lib_arp_delete_called,
1109                          lib_arp_duplicate_found);
1110
1111         printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
1112 }
1113
1114 /* ND IPv6 */
1115 void print_nd_table(void)
1116 {
1117         const void *next_key;
1118         void *next_data;
1119         uint32_t iter = 0;
1120         uint8_t ii = 0, j = 0, k = 0;
1121
1122         printf("\tport  hw addr            status         ip addr\n");
1123
1124         while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
1125                                  0) {
1126
1127                 struct nd_entry_data *tmp_nd_data =
1128                                 (struct nd_entry_data *)next_data;
1129                 struct nd_key_ipv6 tmp_nd_key;
1130                 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
1131                 printf("\t%4d  %02X:%02X:%02X:%02X:%02X:%02X  %10s\n",
1132                                          tmp_nd_data->port,
1133                                          tmp_nd_data->eth_addr.addr_bytes[0],
1134                                          tmp_nd_data->eth_addr.addr_bytes[1],
1135                                          tmp_nd_data->eth_addr.addr_bytes[2],
1136                                          tmp_nd_data->eth_addr.addr_bytes[3],
1137                                          tmp_nd_data->eth_addr.addr_bytes[4],
1138                                          tmp_nd_data->eth_addr.addr_bytes[5],
1139                                          tmp_nd_data->status ==
1140                                          COMPLETE ? "COMPLETE" : "INCOMPLETE");
1141                 printf("\t\t\t\t\t\t");
1142                 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
1143                         printf("%02X%02X ", tmp_nd_data->ipv6[ii],
1144                                                  tmp_nd_data->ipv6[ii + 1]);
1145                 }
1146                 printf("\n");
1147         }
1148
1149         uint32_t i = 0;
1150         printf("\n\nND IPV6 routing table has %d entries\n",
1151                                  nd_route_tbl_index);
1152         printf("\nIP_Address    Depth           Port    NH_IP_Address\n");
1153         for (i = 0; i < nd_route_tbl_index; i++) {
1154                 printf("\n");
1155
1156                 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
1157                         printf("%02X%02X ", lib_nd_route_table[i].ipv6[j],
1158                                                  lib_nd_route_table[i].ipv6[j + 1]);
1159                 }
1160
1161                 printf
1162                                 ("\n\t\t\t                      %d                                       %d\n",
1163                                  lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
1164                 printf("\t\t\t\t\t\t\t\t\t");
1165                 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
1166                         printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
1167                                                  lib_nd_route_table[i].ipv6[k + 1]);
1168                 }
1169         }
1170         printf("\nND IPV6 Stats:\nTotal Queries %u, ok_NH %u, no_NH %u,"
1171                 "ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1172                          lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
1173                          lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
1174                          lib_nd_populate_called, lib_nd_delete_called,
1175                          lib_nd_duplicate_found);
1176         printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
1177 }
1178
1179 void remove_arp_entry(uint32_t ipaddr, uint8_t portid)
1180 {
1181
1182         /* need to lock here if multi-threaded... */
1183         /* rte_hash_del_key is not thread safe */
1184         struct arp_key_ipv4 arp_key;
1185         arp_key.port_id = portid;
1186         arp_key.ip = ipaddr;
1187         arp_key.filler1 = 0;
1188         arp_key.filler2 = 0;
1189         arp_key.filler3 = 0;
1190
1191         lib_arp_delete_called++;
1192
1193         if (ARPICMP_DEBUG)
1194                 printf("remove_arp_entry ip %x, port %d\n", arp_key.ip,
1195                                          arp_key.port_id);
1196         rte_hash_del_key(arp_hash_handle, &arp_key);
1197 }
1198
1199 /* ND IPv6 */
1200 void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
1201 {
1202         /* need to lock here if multi-threaded */
1203         /* rte_hash_del_key is not thread safe */
1204         int i = 0;
1205         struct nd_key_ipv6 nd_key;
1206         nd_key.port_id = portid;
1207         /* arp_key.ip = rte_bswap32(ipaddr); */
1208
1209         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
1210                 nd_key.ipv6[i] = ipv6addr[i];
1211
1212         nd_key.filler1 = 0;
1213         nd_key.filler2 = 0;
1214         nd_key.filler3 = 0;
1215
1216         lib_nd_delete_called++;
1217
1218         if (NDIPV6_DEBUG) {
1219                 printf("Deletes rte hash table nd entry for port %d ipv6=",
1220                                          nd_key.port_id);
1221                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2)
1222                         printf("%02X%02X ", nd_key.ipv6[i], nd_key.ipv6[i + 1]);
1223         }
1224         rte_hash_del_key(nd_hash_handle, &nd_key);
1225 }
1226
1227 void
1228 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1229                          uint8_t portid)
1230 {
1231         /* need to lock here if multi-threaded */
1232         /* rte_hash_add_key_data is not thread safe */
1233         struct arp_key_ipv4 arp_key;
1234         arp_key.port_id = portid;
1235         arp_key.ip = ipaddr;
1236         arp_key.filler1 = 0;
1237         arp_key.filler2 = 0;
1238         arp_key.filler3 = 0;
1239
1240         lib_arp_populate_called++;
1241
1242         if (ARPICMP_DEBUG)
1243                 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip,
1244                                          arp_key.port_id);
1245         struct arp_entry_data *new_arp_data = retrieve_arp_entry(arp_key);
1246         if (new_arp_data
1247                         && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1248                 if (ARPICMP_DEBUG)
1249                         printf("arp_entry exists ip%x, port %d\n", arp_key.ip,
1250                                                  arp_key.port_id);
1251                 lib_arp_duplicate_found++;
1252                 return;
1253         }
1254         new_arp_data = (struct arp_entry_data *)
1255                         malloc(sizeof(struct arp_entry_data));
1256         if (new_arp_data == NULL) {
1257         printf("populate_arp_entry:new_arp_data is NULL\n");
1258                 return;
1259         }
1260         new_arp_data->eth_addr = *hw_addr;
1261         new_arp_data->status = INCOMPLETE;
1262         new_arp_data->port = portid;
1263         new_arp_data->ip = ipaddr;
1264         rte_hash_add_key_data(arp_hash_handle, &arp_key, new_arp_data);
1265
1266         if (ARPICMP_DEBUG) {
1267                 // print entire hash table
1268                 printf("\tARP: table update - hwaddr= "
1269                 "%02x:%02x:%02x:%02x:%02x:%02x  ip=%d.%d.%d.%d  "
1270                 "on port=%d\n",
1271                 new_arp_data->eth_addr.addr_bytes[0],
1272                 new_arp_data->eth_addr.addr_bytes[1],
1273                 new_arp_data->eth_addr.addr_bytes[2],
1274                 new_arp_data->eth_addr.addr_bytes[3],
1275                 new_arp_data->eth_addr.addr_bytes[4],
1276                 new_arp_data->eth_addr.addr_bytes[5],
1277                 (arp_key.ip >> 24),
1278                 ((arp_key.ip & 0x00ff0000) >> 16),
1279                 ((arp_key.ip & 0x0000ff00) >> 8),
1280                 ((arp_key.ip & 0x000000ff)), portid);
1281                 /* print_arp_table(); */
1282                 puts("");
1283         }
1284 }
1285
1286 /*
1287 * ND IPv6
1288 *
1289 * Install key - data pair in Hash table - From Pipeline Configuration
1290 *
1291 */
1292 int
1293 populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1294                         uint8_t portid)
1295 {
1296
1297         /* need to lock here if multi-threaded */
1298         /* rte_hash_add_key_data is not thread safe */
1299         uint8_t i;
1300         struct nd_key_ipv6 nd_key;
1301         nd_key.port_id = portid;
1302
1303         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++ /*i+=2 */)
1304                 nd_key.ipv6[i] = ipv6[i];
1305
1306         printf("\n");
1307         nd_key.filler1 = 0;
1308         nd_key.filler2 = 0;
1309         nd_key.filler3 = 0;
1310
1311         lib_nd_populate_called++;
1312
1313         /*Validate if key-value pair already
1314         * exists in the hash table for ND IPv6
1315         */
1316         struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
1317
1318         if (new_nd_data && is_same_ether_addr(&new_nd_data->eth_addr,
1319                 hw_addr)) {
1320
1321                 if (NDIPV6_DEBUG) {
1322                         printf("nd_entry exists port %d ipv6 = ",
1323                                                  nd_key.port_id);
1324                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1325
1326                                 printf("%02X%02X ", nd_key.ipv6[i],
1327                                                          nd_key.ipv6[i + 1]);
1328                         }
1329                 }
1330
1331                 lib_nd_duplicate_found++;
1332                 if (NDIPV6_DEBUG)
1333                         printf("nd_entry exists\n");
1334                 return 0;
1335         }
1336
1337         new_nd_data = (struct nd_entry_data *)
1338                         malloc(sizeof(struct nd_entry_data));
1339         if (new_nd_data == NULL) {
1340                 printf("populate_nd_entry: new_nd_data is NULL\n");
1341                 return 0;
1342         }
1343         new_nd_data->eth_addr = *hw_addr;
1344         new_nd_data->status = COMPLETE;
1345         new_nd_data->port = portid;
1346
1347         if (NDIPV6_DEBUG)
1348                 printf("populate_nd_entry ipv6=");
1349
1350         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++ /*i+=2 */)
1351                 new_nd_data->ipv6[i] = ipv6[i];
1352
1353         if (NDIPV6_DEBUG) {
1354                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1355
1356                         printf("%02X%02X ", new_nd_data->ipv6[i],
1357                                                  new_nd_data->ipv6[i + 1]);
1358                 }
1359         }
1360
1361         /*Add a key-data pair at hash table for ND IPv6 static routing */
1362         rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
1363
1364         if (NDIPV6_DEBUG)
1365                 printf("\n....Added a key-data pair at rte hash table "
1366                 "for ND IPv6 static routing\n");
1367
1368         if (NDIPV6_DEBUG) {
1369                 /* print entire hash table */
1370                 printf("\tND: table update - hwaddr= "
1371                 "%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1372                 new_nd_data->eth_addr.addr_bytes[0],
1373                 new_nd_data->eth_addr.addr_bytes[1],
1374                 new_nd_data->eth_addr.addr_bytes[2],
1375                 new_nd_data->eth_addr.addr_bytes[3],
1376                 new_nd_data->eth_addr.addr_bytes[4],
1377                 new_nd_data->eth_addr.addr_bytes[5], portid);
1378                 printf("\tipv6=");
1379                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1380                         new_nd_data->ipv6[i] = ipv6[i];
1381                         printf("%02X%02X ", new_nd_data->ipv6[i],
1382                                                  new_nd_data->ipv6[i + 1]);
1383                 }
1384
1385                 printf("\n");
1386
1387                 puts("");
1388         }
1389         return 1;
1390 }
1391
1392 void print_pkt1(struct rte_mbuf *pkt)
1393 {
1394         uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1395         int i = 0, j = 0;
1396         printf("\nPacket Contents...\n");
1397         for (i = 0; i < 20; i++) {
1398                 for (j = 0; j < 20; j++)
1399                         printf("%02x ", rd[(20 * i) + j]);
1400                 printf("\n");
1401         }
1402 }
1403
1404 struct ether_addr broadcast_ether_addr = {
1405         .addr_bytes[0] = 0xFF,
1406         .addr_bytes[1] = 0xFF,
1407         .addr_bytes[2] = 0xFF,
1408         .addr_bytes[3] = 0xFF,
1409         .addr_bytes[4] = 0xFF,
1410         .addr_bytes[5] = 0xFF,
1411 };
1412
1413 static const struct ether_addr null_ether_addr = {
1414         .addr_bytes[0] = 0x00,
1415         .addr_bytes[1] = 0x00,
1416         .addr_bytes[2] = 0x00,
1417         .addr_bytes[3] = 0x00,
1418         .addr_bytes[4] = 0x00,
1419         .addr_bytes[5] = 0x00,
1420 };
1421
1422 #define MAX_NUM_MAC_ADDRESS 16
1423 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1424 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1425 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1426 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1427 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1428 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1429 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1430 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1431 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1432 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1433 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1434 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1435 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1436 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1437 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1438 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1439 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1440 };
1441
1442 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1443 {
1444         return &link_hw_addr[out_port];
1445 }
1446
1447 static void
1448 request_icmp_echo(unsigned int port_id, uint32_t ip, struct ether_addr *gw_addr)
1449 {
1450         struct ether_hdr *eth_h;
1451         struct ipv4_hdr *ip_h;
1452         struct icmp_hdr *icmp_h;
1453
1454         struct app_link_params *link;
1455         link = &myApp->link_params[port_id];
1456         arp_port_addresses[port_id].ip = link->ip;
1457         arp_port_addresses[port_id].mac_addr = link->mac_addr;
1458
1459         struct rte_mbuf *icmp_pkt = lib_arp_pkt;
1460         if (icmp_pkt == NULL) {
1461                 if (ARPICMP_DEBUG)
1462                         printf("Error allocating icmp_pkt rte_mbuf\n");
1463                 return;
1464         }
1465
1466         eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1467         ether_addr_copy(gw_addr, &eth_h->d_addr);
1468         ether_addr_copy((struct ether_addr *)
1469                         &arp_port_addresses[port_id].mac_addr, &eth_h->s_addr);
1470         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1471
1472         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1473         icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1474
1475         ip_h->version_ihl = IP_VHL_DEF;
1476         ip_h->type_of_service = 0;
1477         ip_h->total_length =
1478                         rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1479         ip_h->packet_id = 0xaabb;
1480         ip_h->fragment_offset = 0x0000;
1481         ip_h->time_to_live = 64;
1482         ip_h->next_proto_id = IPPROTO_ICMP;
1483         ip_h->src_addr = rte_bswap32(arp_port_addresses[port_id].ip);
1484         ip_h->dst_addr = ip;
1485
1486         ip_h->hdr_checksum = 0;
1487         ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1488
1489         icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1490         icmp_h->icmp_code = 0;
1491         icmp_h->icmp_ident = 0xdead;
1492         icmp_h->icmp_seq_nb = 0xbeef;
1493
1494         icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1495
1496         icmp_pkt->pkt_len =
1497                         sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1498                         sizeof(struct icmp_hdr);
1499         icmp_pkt->data_len = icmp_pkt->pkt_len;
1500
1501         if (ARPICMP_DEBUG) {
1502                 printf("Sending echo request\n");
1503                 print_mbuf("TX", port_id, icmp_pkt, __LINE__);
1504         }
1505
1506         rte_pipeline_port_out_packet_insert(gp_arp->p.p,
1507                 gp_arp->outport_id[port_id], icmp_pkt);
1508         gp_arp->sentPktCount++;
1509 }
1510
1511 void request_echo(unsigned int port_id, uint32_t ip)
1512 {
1513         (void)port_id;
1514         (void)ip;
1515
1516         struct ether_addr gw_addr;
1517         uint32_t dest_ip = rte_bswap32(ip);
1518         uint32_t phy_port;
1519
1520         if (get_dest_mac_addr_port(dest_ip, &phy_port, &gw_addr) == ARP_FOUND) {
1521                 request_icmp_echo(phy_port, ip, &gw_addr);
1522                 return;
1523         }
1524
1525         if (ARPICMP_DEBUG)
1526                 printf("Sending echo request ... get mac failed.\n");
1527 }
1528
1529 void request_arp(uint8_t port_id, uint32_t ip, struct rte_pipeline *rte_p)
1530 {
1531         (void)port_id;
1532         (void)ip;
1533
1534         struct ether_hdr *eth_h;
1535         struct arp_hdr *arp_h;
1536
1537         struct app_link_params *link;
1538         link = &myApp->link_params[port_id];
1539         arp_port_addresses[port_id].ip = link->ip;
1540         arp_port_addresses[port_id].mac_addr = link->mac_addr;
1541
1542         struct rte_mbuf *arp_pkt = lib_arp_pkt;
1543
1544         if (arp_pkt == NULL) {
1545                 if (ARPICMP_DEBUG)
1546                         printf("Error allocating arp_pkt rte_mbuf\n");
1547                 return;
1548         }
1549
1550         eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1551
1552         ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
1553         ether_addr_copy((struct ether_addr *)
1554                         &arp_port_addresses[port_id].mac_addr, &eth_h->s_addr);
1555         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1556
1557         arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1558         arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1559         arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1560         arp_h->arp_hln = ETHER_ADDR_LEN;
1561         arp_h->arp_pln = sizeof(uint32_t);
1562         arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1563
1564         ether_addr_copy((struct ether_addr *)
1565                         &arp_port_addresses[port_id].mac_addr,
1566                         &arp_h->arp_data.arp_sha);
1567         arp_h->arp_data.arp_sip =
1568                         rte_cpu_to_be_32(arp_port_addresses[port_id].ip);
1569         ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1570         arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1571         printf("arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
1572                                  arp_h->arp_data.arp_sip);
1573         /* mmcd changed length from 60 to 42 -
1574         * real length of arp request, no padding on ethernet needed -
1575         * looks now like linux arp
1576         */
1577
1578         arp_pkt->pkt_len = 42;
1579         arp_pkt->data_len = 42;
1580
1581         if (ARPICMP_DEBUG) {
1582                 printf("Sending arp request\n");
1583                 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1584         }
1585
1586         rte_pipeline_port_out_packet_insert(rte_p, port_id, arp_pkt);
1587         gp_arp->sentPktCount++;
1588
1589 }
1590
1591 void request_arp_wrap(uint8_t port_id, uint32_t ip)
1592 {
1593         request_arp(port_id, ip, gp_arp->p.p);
1594 }
1595
1596 void process_arpicmp_pkt(
1597         struct rte_mbuf *pkt,
1598         uint32_t out_port,
1599         uint32_t pkt_mask)
1600 {
1601         uint8_t in_port_id = pkt->port;
1602         struct app_link_params *link;
1603         struct ether_hdr *eth_h;
1604         struct arp_hdr *arp_h;
1605         struct ipv4_hdr *ip_h;
1606         struct icmp_hdr *icmp_h;
1607         uint32_t cksum;
1608         uint32_t ip_addr;
1609         uint32_t req_tip;
1610
1611
1612         eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1613
1614         if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1615                 arp_h =
1616                                 (struct arp_hdr *)((char *)eth_h +
1617                                                          sizeof(struct ether_hdr));
1618                 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1619                         printf
1620                                         ("Invalid hardware format of hardware address - "
1621                                 "not processing ARP req\n");
1622                 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1623                         printf
1624                                         ("Invalid protocol address format - "
1625                                 "not processing ARP req\n");
1626                 else if (arp_h->arp_hln != 6)
1627                         printf
1628                                         ("Invalid hardware address length - "
1629                                 "not processing ARP req\n");
1630                 else if (arp_h->arp_pln != 4)
1631                         printf
1632                                         ("Invalid protocol address length - "
1633                                 "not processing ARP req\n");
1634                 else {
1635                         link = &myApp->link_params[in_port_id];
1636                         arp_port_addresses[in_port_id].ip = link->ip;
1637                         arp_port_addresses[in_port_id].mac_addr =
1638                                         link->mac_addr;
1639
1640                         if (arp_h->arp_data.arp_tip !=
1641                                         rte_bswap32(arp_port_addresses[in_port_id].ip)) {
1642                                 printf
1643                                                 ("ARP requested IP address mismatches "
1644                                         "interface IP - discarding\n");
1645                                 printf("arp_tip = %x\n",
1646                                                          arp_h->arp_data.arp_tip);
1647                                 printf("arp_port_addresses = %x\n",
1648                                                          arp_port_addresses[in_port_id].ip);
1649                                 printf("in_port_id = %x\n", in_port_id);
1650                                 printf("arp_port_addresses[0] = %x\n",
1651                                                          arp_port_addresses[0].ip);
1652
1653                                 rte_pipeline_ah_packet_drop(gp_arp->p.p,
1654                                                 pkt_mask);
1655                                 gp_arp->droppedPktCount++;
1656
1657                         }
1658                         /* revise conditionals to allow processing of
1659                         * requests with target ip = this ip and
1660                         * processing of replies to destination ip = this ip
1661                         */
1662                         else if (arp_h->arp_op ==
1663                                  rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1664
1665                                 if (ARPICMP_DEBUG) {
1666                                 printf("arp_op %d, ARP_OP_REQUEST %d\n",
1667                                                          arp_h->arp_op,
1668                                                          rte_cpu_to_be_16(ARP_OP_REQUEST));
1669                                 print_mbuf("RX", in_port_id, pkt, __LINE__);
1670                                 }
1671
1672                                 populate_arp_entry((struct ether_addr *)
1673                                                          &arp_h->arp_data.arp_sha,
1674                                                          rte_cpu_to_be_32
1675                                                          (arp_h->arp_data.arp_sip),
1676                                                          in_port_id);
1677
1678                                 /* build reply */
1679                                 req_tip = arp_h->arp_data.arp_tip;
1680                                 ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
1681
1682                                 // set sender mac address -
1683                                 ether_addr_copy((struct ether_addr *)&
1684                                 arp_port_addresses[in_port_id].mac_addr,
1685                                 &eth_h->s_addr);
1686
1687                                 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1688                                 ether_addr_copy(&eth_h->s_addr,
1689                                                 &arp_h->arp_data.arp_sha);
1690                                 arp_h->arp_data.arp_tip =
1691                                                 arp_h->arp_data.arp_sip;
1692                                 arp_h->arp_data.arp_sip = req_tip;
1693                                 ether_addr_copy(&eth_h->d_addr,
1694                                                 &arp_h->arp_data.arp_tha);
1695
1696                                 rte_pipeline_port_out_packet_insert(gp_arp->p.p,
1697                                                 out_port, pkt);
1698                                 gp_arp->sentPktCount++;
1699
1700                         } else if (arp_h->arp_op ==
1701                                          rte_cpu_to_be_16(ARP_OP_REPLY)) {
1702                                 // TODO: be sure that ARP request
1703                                 //was actually sent!!!
1704                                 if (ARPICMP_DEBUG) {
1705                                         printf("ARP_OP_REPLY received");
1706                                         print_mbuf("RX", in_port_id, pkt,
1707                                                          __LINE__);
1708                                 }
1709                                 populate_arp_entry((struct ether_addr *)
1710                                                          &arp_h->arp_data.arp_sha,
1711                                                          rte_bswap32(arp_h->
1712                                                         arp_data.arp_sip),
1713                                                          in_port_id);
1714
1715                                 /* To drop the packet from LB */
1716                                 rte_pipeline_ah_packet_drop(gp_arp->p.p,
1717                                                 pkt_mask);
1718                                 gp_arp->droppedPktCount++;
1719
1720                         } else {
1721                                 if (ARPICMP_DEBUG)
1722                                         printf("Invalid ARP opcode - not "
1723                                         "processing ARP req %x\n",
1724                                         arp_h->arp_op);
1725                         }
1726                 }
1727         } else {
1728                 ip_h =
1729                                 (struct ipv4_hdr *)((char *)eth_h +
1730                                         sizeof(struct ether_hdr));
1731                 icmp_h =
1732                                 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1733
1734                 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1735
1736                         link = &myApp->link_params[in_port_id];
1737                         arp_port_addresses[in_port_id].ip = link->ip;
1738                         arp_port_addresses[in_port_id].mac_addr =
1739                                         link->mac_addr;
1740
1741                         if (!is_same_ether_addr((struct ether_addr *)
1742                                                 &arp_port_addresses[in_port_id].
1743                                                 mac_addr, &eth_h->d_addr)) {
1744
1745                                 if (ARPICMP_DEBUG)
1746                                         printf("Ethernet frame not destined "
1747                                         "for MAC address of received network "
1748                                         "interface - discarding\n");
1749
1750                         } else if (ip_h->next_proto_id != IPPROTO_ICMP) {
1751                                 if (ARPICMP_DEBUG)
1752                                         printf("IP protocol ID is not set to "
1753                                         "ICMP - discarding\n");
1754
1755                         } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1756                                 if (ARPICMP_DEBUG)
1757                                         printf("IP version other than 4 - "
1758                                         "discarding\n");
1759
1760                         } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1761                                 if (ARPICMP_DEBUG)
1762                                         printf("Unknown IHL - discarding\n");
1763
1764                         } else {
1765                                 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1766                                                 && icmp_h->icmp_code == 0) {
1767                                 if (ARPICMP_DEBUG)
1768                                         print_mbuf("RX", in_port_id,
1769                                                                  pkt, __LINE__);
1770
1771                                 ip_addr = ip_h->src_addr;
1772                                 ether_addr_copy(&eth_h->s_addr,
1773                                                 &eth_h->d_addr);
1774                                 ether_addr_copy((struct ether_addr *)
1775                                                 &arp_port_addresses
1776                                                 [in_port_id].mac_addr,
1777                                                 &eth_h->s_addr);
1778
1779                                 if (ip_h->dst_addr !=
1780                                         rte_bswap32(arp_port_addresses
1781                                         [in_port_id].ip)) {
1782                                         if (ARPICMP_DEBUG) {
1783                                         printf("IPv4 packet not destined for "
1784                                         "configured IP on RX port - "
1785                                         "discarding\n");
1786                                         printf("ip_h->dst_addr = %u, "
1787                                         "in_port_id = %u, "
1788                                         "arp_port_addresses.ip = %u\n",
1789                                         ip_h->dst_addr, in_port_id,
1790                                         arp_port_addresses[in_port_id].ip);
1791                                         }
1792                                 } else {
1793
1794                                         if (is_multicast_ipv4_addr
1795                                                 (ip_h->dst_addr)) {
1796                                                 uint32_t ip_src;
1797
1798                                         ip_src = rte_be_to_cpu_32
1799                                                                         (ip_addr);
1800                                         if ((ip_src & 0x00000003) == 1)
1801                                                 ip_src = (ip_src &
1802                                                                 0xFFFFFFFC)
1803                                                         | 0x00000002;
1804                                         else
1805                                                 ip_src = (ip_src &
1806                                                                 0xFFFFFFFC)
1807                                                         | 0x00000001;
1808
1809                                         ip_h->src_addr =
1810                                                                 rte_cpu_to_be_32(ip_src);
1811                                         ip_h->dst_addr = ip_addr;
1812
1813                                         ip_h->hdr_checksum = 0;
1814                                         ip_h->hdr_checksum = ~rte_raw_cksum(
1815                                                         ip_h, sizeof(struct
1816                                                         ipv4_hdr));
1817                         } else {
1818                                 ip_h->src_addr = ip_h->dst_addr;
1819                                 ip_h->dst_addr = ip_addr;
1820                                 }
1821
1822                         icmp_h->icmp_type =
1823                                                 IP_ICMP_ECHO_REPLY;
1824                         cksum = ~icmp_h->icmp_cksum & 0xffff;
1825                         cksum += ~htons(IP_ICMP_ECHO_REQUEST << 8) & 0xffff;
1826                         cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1827                         cksum = (cksum & 0xffff) + (cksum >> 16);
1828                         cksum = (cksum & 0xffff) + (cksum >> 16);
1829                         icmp_h->icmp_cksum = ~cksum;
1830
1831                         if (ARPICMP_DEBUG)
1832                                 print_mbuf("TX", in_port_id, pkt, __LINE__);
1833
1834                                 rte_pipeline_port_out_packet_insert(gp_arp->p.p,
1835                                                 out_port, pkt);
1836                                 gp_arp->sentPktCount++;
1837
1838                         }
1839                         }
1840                         else if (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY
1841                                 && icmp_h->icmp_code == 0) {
1842                         if (ARPICMP_DEBUG)
1843                                 print_mbuf("RX", in_port_id,
1844                                                          pkt, __LINE__);
1845
1846                         struct arp_key_ipv4 arp_key;
1847                         arp_key.port_id = in_port_id;
1848                         arp_key.ip =
1849                         rte_bswap32(ip_h->src_addr);
1850                         arp_key.filler1 = 0;
1851                         arp_key.filler2 = 0;
1852                         arp_key.filler3 = 0;
1853
1854                         struct arp_entry_data *arp_entry =
1855                                                 retrieve_arp_entry(arp_key);
1856                         if (arp_entry == NULL) {
1857                                 printf("Received unsolicited "
1858                                 "ICMP echo reply from ip%x, "
1859                                         "port %d\n",
1860                                                  arp_key.ip,
1861                                                  arp_key.port_id);
1862                                         return;
1863                         }
1864
1865                                 arp_entry->status = COMPLETE;
1866                                 /* To drop the packet from LB */
1867                                 rte_pipeline_ah_packet_drop(gp_arp->p.p,
1868                                                 pkt_mask);
1869                                 gp_arp->droppedPktCount++;
1870                         }
1871                         }
1872                 }
1873         }
1874 }
1875
1876
1877
1878 /* int
1879  * inet_pton(af, src, dst)
1880  *      convert from presentation format (which usually means ASCII printable)
1881  *      to network format (which is usually some kind of binary format).
1882  * return:
1883  *      1 if the address was valid for the specified address family
1884  *      0 if the address wasn't valid (`dst' is untouched in this case)
1885  *      -1 if some other error occurred (`dst' is untouched in this case, too)
1886  * author:
1887  *      Paul Vixie, 1996.
1888  */
1889 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
1890 {
1891         switch (af) {
1892         case AF_INET:
1893                 return inet_pton_ipv4(src, dst);
1894         case AF_INET6:
1895                 return inet_pton_ipv6(src, dst);
1896         default:
1897                 errno = EAFNOSUPPORT;
1898                 return -1;
1899         }
1900         /* NOTREACHED */
1901 }
1902
1903 /* int
1904  * inet_pton_ipv4(src, dst)
1905  *      like inet_aton() but without all the hexadecimal and shorthand.
1906  * return:
1907  *      1 if `src' is a valid dotted quad, else 0.
1908  * notice:
1909  *      does not touch `dst' unless it's returning 1.
1910  * author:
1911  *      Paul Vixie, 1996.
1912  */
1913 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1914 {
1915         static const char digits[] = "0123456789";
1916         int saw_digit, octets, ch;
1917         unsigned char tmp[INADDRSZ], *tp;
1918
1919         saw_digit = 0;
1920         octets = 0;
1921         *(tp = tmp) = 0;
1922         while ((ch = *src++) != '\0') {
1923                 const char *pch;
1924
1925                 pch = strchr(digits, ch);
1926                 if (pch != NULL) {
1927                         unsigned int new = *tp * 10 + (pch - digits);
1928
1929                         if (new > 255)
1930                                 return 0;
1931                         if (!saw_digit) {
1932                                 if (++octets > 4)
1933                                         return 0;
1934                                 saw_digit = 1;
1935                         }
1936                         *tp = (unsigned char)new;
1937                 } else if (ch == '.' && saw_digit) {
1938                         if (octets == 4)
1939                                 return 0;
1940                         *++tp = 0;
1941                         saw_digit = 0;
1942                 } else
1943                         return 0;
1944         }
1945         if (octets < 4)
1946                 return 0;
1947
1948         memcpy(dst, tmp, INADDRSZ);
1949         return 1;
1950 }
1951
1952 /* int
1953  * inet_pton_ipv6(src, dst)
1954  *      convert presentation level address to network order binary form.
1955  * return:
1956  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
1957  * notice:
1958  *      (1) does not touch `dst' unless it's returning 1.
1959  *      (2) :: in a full address is silently ignored.
1960  * credit:
1961  *      inspired by Mark Andrews.
1962  * author:
1963  *      Paul Vixie, 1996.
1964  */
1965 static int inet_pton_ipv6(const char *src, unsigned char *dst)
1966 {
1967         static const char xdigits_l[] = "0123456789abcdef",
1968                         xdigits_u[] = "0123456789ABCDEF";
1969         unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
1970         const char *xdigits = 0, *curtok = 0;
1971         int ch = 0, saw_xdigit = 0, count_xdigit = 0;
1972         unsigned int val = 0;
1973         unsigned int dbloct_count = 0;
1974
1975         memset((tp = tmp), '\0', IN6ADDRSZ);
1976         endp = tp + IN6ADDRSZ;
1977         colonp = NULL;
1978         /* Leading :: requires some special handling. */
1979         if (*src == ':')
1980                 if (*++src != ':')
1981                         return 0;
1982         curtok = src;
1983         saw_xdigit = count_xdigit = 0;
1984         val = 0;
1985
1986         while ((ch = *src++) != '\0') {
1987                 const char *pch;
1988
1989                 pch = strchr((xdigits = xdigits_l), ch);
1990                 if (pch  == NULL)
1991                         pch = strchr((xdigits = xdigits_u), ch);
1992                 if (pch != NULL) {
1993                         if (count_xdigit >= 4)
1994                                 return 0;
1995                         val <<= 4;
1996                         val |= (pch - xdigits);
1997                         if (val > 0xffff)
1998                                 return 0;
1999                         saw_xdigit = 1;
2000                         count_xdigit++;
2001                         continue;
2002                 }
2003                 if (ch == ':') {
2004                         curtok = src;
2005                         if (!saw_xdigit) {
2006                                 if (colonp)
2007                                         return 0;
2008                                 colonp = tp;
2009                                 continue;
2010                         } else if (*src == '\0') {
2011                                 return 0;
2012                         }
2013                         if (tp + sizeof(int16_t) > endp)
2014                                 return 0;
2015                         *tp++ = (unsigned char)((val >> 8) & 0xff);
2016                         *tp++ = (unsigned char)(val & 0xff);
2017                         saw_xdigit = 0;
2018                         count_xdigit = 0;
2019                         val = 0;
2020                         dbloct_count++;
2021                         continue;
2022                 }
2023                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2024                                 inet_pton_ipv4(curtok, tp) > 0) {
2025                         tp += INADDRSZ;
2026                         saw_xdigit = 0;
2027                         dbloct_count += 2;
2028                         break;  /* '\0' was seen by inet_pton4(). */
2029                 }
2030                 return 0;
2031         }
2032         if (saw_xdigit) {
2033                 if (tp + sizeof(int16_t) > endp)
2034                         return 0;
2035                 *tp++ = (unsigned char)((val >> 8) & 0xff);
2036                 *tp++ = (unsigned char)(val & 0xff);
2037                 dbloct_count++;
2038         }
2039         if (colonp != NULL) {
2040                 /* if we already have 8 double octets,
2041                 * having a colon means error
2042                 */
2043                 if (dbloct_count == 8)
2044                         return 0;
2045
2046                 /*
2047                  * Since some memmove()'s erroneously fail to handle
2048                  * overlapping regions, we'll do the shift by hand.
2049                  */
2050                 const int n = tp - colonp;
2051                 int i;
2052
2053                 for (i = 1; i <= n; i++) {
2054                         endp[-i] = colonp[n - i];
2055                         colonp[n - i] = 0;
2056                 }
2057                 tp = endp;
2058         }
2059         if (tp != endp)
2060                 return 0;
2061         memcpy(dst, tmp, IN6ADDRSZ);
2062         return 1;
2063 }
2064
2065 /**
2066  * Function to classify ICMPv6 Packets based on NextHeader field in IPv6 Header.
2067  * Updates ND Cache table with link layer addresses as received from Neighbor.
2068  * Processes ICMPv6 Echo destined to local port and replys.
2069  *
2070  * @param pkt
2071  *   A pointer to the packet received from Loadbalancer pipeline
2072  * @param out_port
2073  *  A pointer to the output port action
2074  * @param pkt_num
2075  *  A packet number
2076  *
2077  * @return
2078  *  NULL
2079  */
2080
2081 void
2082 process_icmpv6_pkt(
2083         struct rte_mbuf *pkt,
2084         uint32_t out_port,
2085         __rte_unused uint32_t pkt_num)
2086 {
2087
2088         uint8_t in_port_id = pkt->port;
2089         struct app_link_params *link;
2090         struct ether_hdr *eth_h;
2091         struct ipv6_hdr *ipv6_h;
2092         struct icmpv6_hdr *icmpv6_h;
2093         struct icmpv6_nd_hdr *icmpv6_nd_h;
2094         uint8_t ipv6_addr[16];
2095         uint8_t i = 0, flag = 1;
2096         uint8_t req_tipv6[16];
2097
2098         eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
2099         ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2100         icmpv6_h =
2101                         (struct icmpv6_hdr *)((char *)ipv6_h + sizeof(struct ipv6_hdr));
2102         struct rte_mbuf *icmpv6_pkt = pkt;
2103
2104         link = &myApp->link_params[in_port_id];
2105         icmpv6_port_addresses[in_port_id].mac_addr = link->mac_addr;
2106
2107         if (!is_same_ether_addr
2108                         ((struct ether_addr *)&icmpv6_port_addresses[in_port_id].mac_addr,
2109                          &eth_h->d_addr)) {
2110                 if (ARPICMP_DEBUG) {
2111                         printf("Ethernet frame not destined for MAC address "
2112                         "of received network interface - discarding\n");
2113                 }
2114         } else {
2115                 if ((icmpv6_h->icmpv6_type == ICMPV6_ECHO_REQUEST)
2116                                 && (icmpv6_h->icmpv6_code == 0)) {
2117                         for (i = 0; i < 16; i++)
2118                                 ipv6_addr[i] = ipv6_h->src_addr[i];
2119
2120                         for (i = 0; i < 16; i++) {
2121                                 if (ipv6_h->dst_addr[i] !=
2122                                                 icmpv6_port_addresses[in_port_id].ipv6[i]) {
2123                                         flag++;
2124                                 }
2125                         }
2126                         if (!flag) {
2127                                 printf("IPv6 packet not destined for "
2128                                 "configured IP on RX port - discarding\n");
2129                         } else {
2130                                 {
2131
2132                                         ether_addr_copy(&eth_h->s_addr,
2133                                                         &eth_h->d_addr);
2134                                         ether_addr_copy((struct ether_addr *)
2135                                                         &icmpv6_port_addresses
2136                                                         [in_port_id].mac_addr,
2137                                                         &eth_h->s_addr);
2138
2139                                         for (i = 0; i < 16; i++)
2140                                                 ipv6_h->src_addr[i] =
2141                                                                 ipv6_h->dst_addr[i];
2142                                         for (i = 0; i < 16; i++)
2143                                                 ipv6_h->dst_addr[i] =
2144                                                                 ipv6_addr[i];
2145
2146                                         icmpv6_h->icmpv6_type =
2147                                                         ICMPV6_ECHO_REPLY;
2148
2149                                         rte_pipeline_port_out_packet_insert
2150                                                         (gp_arp->p.p, out_port, icmpv6_pkt);
2151                                         gp_arp->sentPktCount++;
2152                                 }
2153                         }
2154
2155                 } else if ((icmpv6_h->icmpv6_type == ICMPV6_ECHO_REPLY)
2156                                  && (icmpv6_h->icmpv6_code == 0)) {
2157                         struct nd_key_ipv6 nd_key;
2158                         nd_key.port_id = in_port_id;
2159
2160                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2161                                 nd_key.ipv6[i] = ipv6_h->src_addr[i];
2162
2163                         nd_key.filler1 = 0;
2164                         nd_key.filler2 = 0;
2165                         nd_key.filler3 = 0;
2166
2167                         /* Validate if key-value pair already
2168                         * exists in the hash table for ND IPv6
2169                         */
2170                         struct nd_entry_data *new_nd_data =
2171                                         retrieve_nd_entry(nd_key);
2172
2173                         if (new_nd_data == NULL) {
2174                                 printf("Received unsolicited ICMPv6 echo "
2175                                 "reply on port %d\n",
2176                                                  nd_key.port_id);
2177                                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
2178                                         printf("%02X%02X ", nd_key.ipv6[i],
2179                                                                  nd_key.ipv6[i + 1]);
2180                                 }
2181                                 return;
2182                         }
2183
2184                         new_nd_data->status = COMPLETE;
2185
2186                 } else
2187                 if ((icmpv6_h->icmpv6_type == ICMPV6_NEIGHBOR_SOLICITATION)
2188                         && (icmpv6_h->icmpv6_code == 0)) {
2189
2190                         icmpv6_nd_h =
2191                                         (struct icmpv6_nd_hdr *)((char *)icmpv6_h +
2192                                                                  sizeof(struct icmpv6_hdr));
2193                         struct ether_addr *src_hw_addr = &eth_h->s_addr;
2194                         uint8_t src_ipv6[16], dst_ipv6[16];
2195
2196                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2197                                 src_ipv6[i] = ipv6_h->src_addr[i];
2198                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2199                                 dst_ipv6[i] = ipv6_h->dst_addr[i];
2200
2201                         // Check for Multicast Address
2202                         if ((IPV6_MULTICAST
2203                                          && ((dst_ipv6[0] << 8) | dst_ipv6[1]))) {
2204                                 if (populate_nd_entry
2205                                                 (src_hw_addr, src_ipv6, in_port_id)) {
2206
2207                                         //build a Neighbor Advertisement message
2208                                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2209                                                 req_tipv6[i] =
2210                                                                 icmpv6_nd_h->target_ipv6[i];
2211
2212                                         ether_addr_copy(&eth_h->s_addr,
2213                                                         &eth_h->d_addr);
2214                                         ether_addr_copy((struct ether_addr *)
2215                                                         &icmpv6_port_addresses
2216                                                         [in_port_id].mac_addr,
2217                                                         &eth_h->s_addr);
2218
2219                                         // set sender mac address
2220                                         ether_addr_copy(&eth_h->s_addr,
2221                                                         &icmpv6_nd_h->
2222                                                         link_layer_address);
2223                                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2224                                                 ipv6_h->dst_addr[i] =
2225                                                                 ipv6_h->src_addr[i];
2226                                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2227                                                 ipv6_h->src_addr[i] =
2228                                                                 req_tipv6[i];
2229                                         icmpv6_h->icmpv6_type =
2230                                                         ICMPV6_NEIGHBOR_ADVERTISEMENT;
2231                                         icmpv6_nd_h->type =
2232                                                         e_Target_Link_Layer_Address;
2233                                         icmpv6_nd_h->icmpv6_reserved |=
2234                                                         rte_cpu_to_be_32
2235                                                         (NEIGHBOR_SOLICITATION_SET);
2236
2237                                         rte_pipeline_port_out_packet_insert
2238                                                         (gp_arp->p.p, out_port, icmpv6_pkt);
2239                                         gp_arp->sentPktCount++;
2240                                 }
2241                         } else {
2242                                 if (ARPICMP_DEBUG) {
2243                                         printf("Non-Multicasted Neighbor "
2244                                         "Solicitation Message Received, "
2245                                         "can't do Address Resolution\n");
2246                                         printf("............Some one else "
2247                                         "is the target host here !!!\n");
2248                                 }
2249                         }
2250
2251                 } else
2252                 if ((icmpv6_h->icmpv6_type == ICMPV6_NEIGHBOR_ADVERTISEMENT)
2253                         && (icmpv6_h->icmpv6_code == 0)) {
2254                         struct ether_addr *src_hw_addr = &eth_h->s_addr;
2255                         uint8_t ipv6[16];
2256                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2257                                 ipv6[i] = ipv6_h->src_addr[i];
2258
2259                         if (populate_nd_entry(src_hw_addr, ipv6, in_port_id))
2260                                 if (ARPICMP_DEBUG)
2261                                         printf("Now on, unicast IPv6 traffic "
2262                                         "is possible\n");
2263                         // Now on, unicast IPv6 traffic is possible
2264                 } else {
2265                         if (ARPICMP_DEBUG) {
2266                                 printf("ICMPv6 Type %d Not Supported yet !!!\n",
2267                                                          icmpv6_h->icmpv6_type);
2268                         }
2269                 }
2270
2271         }
2272
2273 }
2274
2275 void request_icmpv6_echo(uint32_t port_id, uint8_t ipv6[])
2276 {
2277         (void)port_id;
2278         (void)ipv6;
2279         int i;
2280
2281         struct ether_addr gw_addr;
2282         uint8_t nhipv6[16];
2283         uint8_t dest_ipv6[16];
2284         uint32_t phy_port;
2285
2286         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
2287                 dest_ipv6[i] = ipv6[i];
2288
2289         if (get_dest_mac_address_ipv6_port(dest_ipv6, &phy_port,
2290                         &gw_addr, nhipv6)) {
2291                 request_icmpv6_echo_message(phy_port, ipv6, &gw_addr);
2292                 return;
2293         }
2294
2295         if (ARPICMP_DEBUG)
2296                 printf("Sending icmpv6 echo request ... get mac failed.\n");
2297 }
2298
2299 void
2300 request_icmpv6_echo_message(uint16_t port_id, uint8_t ipv6[],
2301                                         struct ether_addr *gw_addr)
2302 {
2303         struct ether_hdr *eth_h;
2304         struct ipv6_hdr *ipv6_h;
2305         struct icmpv6_hdr *icmpv6_h;
2306         struct icmpv6_info_hdr *icmpv6_info_h;
2307         int i;
2308         struct app_link_params *link;
2309         link = &mylink[port_id];
2310
2311         for (i = 0; i < 16; i++)
2312                 icmpv6_port_addresses[port_id].ipv6[i] = link->ipv6[i];
2313
2314         icmpv6_port_addresses[port_id].mac_addr = link->mac_addr;
2315
2316         struct rte_mbuf *icmpv6_pkt = lib_icmpv6_pkt;
2317         if (icmpv6_pkt == NULL) {
2318                 if (ARPICMP_DEBUG)
2319                         printf("Error allocating icmpv6_pkt rte_mbuf\n");
2320                 return;
2321         }
2322
2323         eth_h = rte_pktmbuf_mtod(icmpv6_pkt, struct ether_hdr *);
2324         ether_addr_copy(gw_addr, &eth_h->d_addr);
2325         ether_addr_copy((struct ether_addr *)&icmpv6_port_addresses[port_id].
2326                         mac_addr, &eth_h->s_addr);
2327         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_IPv6);
2328
2329         ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2330         icmpv6_h =
2331                         (struct icmpv6_hdr *)((char *)ipv6_h + sizeof(struct ipv6_hdr));
2332         icmpv6_info_h =
2333                         (struct icmpv6_info_hdr *)((char *)icmpv6_h +
2334                                                          sizeof(struct icmpv6_hdr));
2335
2336         ipv6_h->vtc_flow = 0x60000000;
2337         ipv6_h->payload_len = 64;
2338         ipv6_h->proto = 58;
2339         ipv6_h->hop_limits = 64;
2340
2341         for (i = 0; i < 16; i++) {
2342                 ipv6_h->src_addr[i] = icmpv6_port_addresses[port_id].ipv6[i];
2343                 ipv6_h->dst_addr[i] = ipv6[i];
2344         }
2345
2346         icmpv6_h->icmpv6_type = ICMPV6_ECHO_REQUEST;
2347         icmpv6_h->icmpv6_code = 0;
2348         icmpv6_info_h->icmpv6_ident = 0x5151;
2349         icmpv6_info_h->icmpv6_seq_nb = 0x1;
2350
2351         icmpv6_h->icmpv6_cksum =
2352                         ~rte_raw_cksum(icmpv6_h, sizeof(struct icmpv6_hdr));
2353
2354         icmpv6_pkt->pkt_len =
2355                         sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr) +
2356                         sizeof(struct icmpv6_hdr);
2357         icmpv6_pkt->data_len = icmpv6_pkt->pkt_len;
2358
2359         if (ARPICMP_DEBUG)
2360                 printf("Sending icmpv6 echo request\n");
2361
2362         rte_pipeline_port_out_packet_insert(gp_arp->p.p,
2363                 gp_arp->outport_id[port_id],
2364                 icmpv6_pkt);
2365
2366         gp_arp->sentPktCount++;
2367 }
2368
2369
2370 #endif
2371
2372 static void *pipeline_arpicmp_msg_req_custom_handler(struct pipeline *p,
2373                                                         void *msg);
2374
2375 static pipeline_msg_req_handler handlers[] = {
2376         [PIPELINE_MSG_REQ_PING] =
2377                 pipeline_msg_req_ping_handler,
2378         [PIPELINE_MSG_REQ_STATS_PORT_IN] =
2379                 pipeline_msg_req_stats_port_in_handler,
2380         [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
2381                 pipeline_msg_req_stats_port_out_handler,
2382         [PIPELINE_MSG_REQ_STATS_TABLE] =
2383                 pipeline_msg_req_stats_table_handler,
2384         [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
2385                 pipeline_msg_req_port_in_enable_handler,
2386         [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
2387                 pipeline_msg_req_port_in_disable_handler,
2388         [PIPELINE_MSG_REQ_CUSTOM] =
2389                 pipeline_arpicmp_msg_req_custom_handler,
2390
2391 };
2392
2393 static void *pipeline_arpicmp_msg_req_entry_dbg_handler(struct pipeline *p,
2394                                                                  void *msg);
2395 static void *pipeline_arpicmp_msg_req_entry_dbg_handler(
2396         __rte_unused struct pipeline *p,
2397         __rte_unused void *msg)
2398 {
2399         /*have to handle dbg commands*/
2400         return NULL;
2401 }
2402
2403 static __rte_unused pipeline_msg_req_handler custom_handlers[] = {
2404         [PIPELINE_ARPICMP_MSG_REQ_ENTRY_DBG] =
2405                         pipeline_arpicmp_msg_req_entry_dbg_handler,
2406 };
2407
2408 /**
2409  * Function for pipeline custom handlers
2410  *
2411  * @param pipeline
2412  *  A void pointer to pipeline
2413  * @param msg
2414  *  void pointer for incoming data
2415  *
2416  * @return
2417  *  void pointer of response
2418  */
2419 void *pipeline_arpicmp_msg_req_custom_handler(struct pipeline *p, void *msg)
2420 {
2421         struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)p;
2422         struct pipeline_custom_msg_req *req = msg;
2423         pipeline_msg_req_handler f_handle;
2424
2425         f_handle = (req->subtype < PIPELINE_ARPICMP_MSG_REQS) ?
2426                         p_arp->custom_handlers[req->subtype] :
2427                         pipeline_msg_req_invalid_handler;
2428
2429         if (f_handle == NULL)
2430                 f_handle = pipeline_msg_req_invalid_handler;
2431
2432         return f_handle(p, req);
2433 }
2434
2435 #ifdef VNF_ACL
2436
2437 /* Not needed as no arguments are needed for TxRX
2438  * ARP arguments are handled in ARP module
2439  */
2440 int
2441 pipeline_arpicmp_parse_args(struct pipeline_arpicmp *p,
2442                          struct pipeline_params *params);
2443 int
2444 pipeline_arpicmp_parse_args(
2445         __rte_unused struct pipeline_arpicmp *p,
2446         struct pipeline_params *params)
2447 {
2448
2449         uint32_t i;
2450         uint32_t arp_meta_offset_present = 0;
2451
2452         uint32_t arp_route_tbl_present = 0;
2453         uint32_t nd_route_tbl_present = 0;
2454         uint32_t ports_mac_list_present = 0;
2455         uint32_t pktq_in_prv_present = 0;
2456         uint32_t prv_to_pub_map_present = 0;
2457
2458         uint8_t n_prv_in_port = 0;
2459         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2460                 in_port_dir_a[i] = 0;   //make all RX ports ingress initially
2461                 prv_to_pub_map[i] = 0xff;
2462                 pub_to_prv_map[i] = 0xff;
2463         }
2464
2465         for (i = 0; i < params->n_args; i++) {
2466                 char *arg_name = params->args_name[i];
2467                 char *arg_value = params->args_value[i];
2468
2469                 if (ARPICMP_DEBUG > 2) {
2470                         printf("ARP args[%d]: %s %d, %s\n", i, arg_name,
2471                                         atoi(arg_value), arg_value);
2472                 }
2473                 if (strcmp(arg_name, "arp_meta_offset") == 0) {
2474                         if (arp_meta_offset_present) {
2475                                 printf("arp_meta_offset "
2476                                 "initialized already\n");
2477                                 return -1;
2478                         }
2479                         arp_meta_offset_present = 1;
2480                         arp_meta_offset = atoi(arg_value);
2481                         continue;
2482                 }
2483                 /* pktq_in_prv */
2484                 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2485                         if (pktq_in_prv_present) {
2486                                 printf("Duplicate pktq_in_prv ... "
2487                                 "parse failed..\n\n");
2488                                 return -1;
2489                         }
2490                         pktq_in_prv_present = 1;
2491
2492                         int rxport = 0, j = 0;
2493                         char phy_port_num[5];
2494                         char *token = strtok(arg_value, "RXQ");
2495                         while (token) {
2496                                 j = 0;
2497                                 while ((j < 4) && (token[j] != '.')) {
2498                                         phy_port_num[j] = token[j];
2499                                         j++;
2500                                 }
2501                                 phy_port_num[j] = '\0';
2502                                 rxport = atoi(phy_port_num);
2503                                 printf("token: %s, phy_port_str: %s, "
2504                                 "phy_port_num %d\n",
2505                                                  token, phy_port_num, rxport);
2506
2507                                 prv_in_port_a[n_prv_in_port++] = rxport;
2508                                 // set rxport egress
2509                                 if(rxport < PIPELINE_MAX_PORT_IN)
2510                                 in_port_dir_a[rxport] = 1;
2511                                 token = strtok(NULL, "RXQ");
2512                         }
2513
2514                         if (n_prv_in_port == 0) {
2515                                 printf
2516                                                 ("VNF common parse error - "
2517                                         "no prv RX phy port\n");
2518                                 return -1;
2519                         }
2520                         continue;
2521                 }
2522
2523                 /* prv_to_pub_map */
2524                 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2525                         if (prv_to_pub_map_present) {
2526                                 printf
2527                                                 ("Duplicated prv_to_pub_map ... "
2528                                         "parse failed ...\n");
2529                                 return -1;
2530                         }
2531                         prv_to_pub_map_present = 1;
2532
2533                         int rxport = 0, txport = 0, j = 0, k = 0;
2534                         char rx_phy_port_num[5];
2535                         char tx_phy_port_num[5];
2536                         char *token = strtok(arg_value, "(");
2537                         while (token) {
2538                                 j = 0;
2539                                 while ((j < 4) && (token[j] != ',')) {
2540                                         rx_phy_port_num[j] = token[j];
2541                                         j++;
2542                                 }
2543                                 rx_phy_port_num[j] = '\0';
2544                                 rxport = atoi(rx_phy_port_num);
2545
2546                                 j++;
2547                                 k = 0;
2548                                 while ((k < 4) && (token[j + k] != ')')) {
2549                                         tx_phy_port_num[k] = token[j + k];
2550                                         k++;
2551                                 }
2552                                 tx_phy_port_num[k] = '\0';
2553                                 txport = atoi(tx_phy_port_num);
2554                                 if (rxport < PIPELINE_MAX_PORT_IN && txport < PIPELINE_MAX_PORT_IN){
2555                                 printf("token: %s,"
2556                                                          "rx_phy_port_str: %s, phy_port_num %d,"
2557                                                          "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2558                                                          token, rx_phy_port_num, rxport,
2559                                                          tx_phy_port_num, txport);
2560                                 }
2561                                 else
2562                                        return -1;
2563                                 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2564                                                 (txport >= PIPELINE_MAX_PORT_IN) ||
2565                                                 (in_port_dir_a[rxport] != 1)) {
2566                                         printf("CG-NAPT parse error - "
2567                                         "incorrect prv-pub translation. "
2568                                         "Rx %d, Tx %d, Rx Dir %d\n",
2569                                         rxport, txport, in_port_dir_a[rxport]);
2570                                         return -1;
2571                                 }
2572
2573                                 prv_to_pub_map[rxport] = txport;
2574                                 pub_to_prv_map[txport] = rxport;
2575                                 token = strtok(NULL, "(");
2576                         }
2577
2578                         continue;
2579                 }
2580
2581                 /* lib_arp_debug */
2582                 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2583                         ARPICMP_DEBUG = atoi(arg_value);
2584
2585                         continue;
2586                 }
2587
2588                 /* ports_mac_list */
2589                 if (strcmp(arg_name, "ports_mac_list") == 0) {
2590                         ports_mac_list_present = 1;
2591
2592                         uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
2593
2594                         char byteStr[MAC_NUM_BYTES][3];
2595                         uint32_t byte[MAC_NUM_BYTES];
2596
2597                         char *token = strtok(arg_value, " ");
2598                         while (token) {
2599                                 k = 0;
2600                                 for (i = 0; i < MAC_NUM_BYTES; i++) {
2601                                         for (j = 0; j < 2; j++)
2602                                                 byteStr[i][j] = token[k++];
2603                                         byteStr[i][j] = '\0';
2604                                         k++;
2605                                 }
2606
2607                                 for (i = 0; i < MAC_NUM_BYTES; i++)
2608                                         byte[i] = strtoul(byteStr[i], NULL, 16);
2609
2610                                 if (ARPICMP_DEBUG) {
2611                                         printf("token: %s", token);
2612                                         for (i = 0; i < MAC_NUM_BYTES; i++)
2613                                                 printf(", byte[%u] %u", i,
2614                                                                          byte[i]);
2615                                         printf("\n");
2616                                 }
2617                                 //Populate the static arp_route_table
2618                                 for (i = 0; i < MAC_NUM_BYTES; i++)
2619                                         link_hw_addr
2620                                                         [link_hw_addr_array_idx].addr_bytes
2621                                                         [i] = byte[i];
2622
2623                                 link_hw_addr_array_idx++;
2624                                 token = strtok(NULL, " ");
2625                         }
2626
2627                         continue;
2628                 }
2629
2630                 /* arp_route_tbl */
2631                 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2632                         arp_route_tbl_present = 1;
2633
2634                         uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2635                                         0, i = 0, j = 0, k = 0, l = 0;
2636                         uint32_t arp_route_tbl_str_max_len = 10;
2637                         char dest_ip_str[arp_route_tbl_str_max_len];
2638                         char mask_str[arp_route_tbl_str_max_len];
2639                         char tx_port_str[arp_route_tbl_str_max_len];
2640                         char nh_ip_str[arp_route_tbl_str_max_len];
2641                         char *token = strtok(arg_value, "(");
2642                         while (token) {
2643                                 i = 0;
2644                                 while ((i < (arp_route_tbl_str_max_len - 1))
2645                                                          && (token[i] != ',')) {
2646                                         dest_ip_str[i] = token[i];
2647                                         i++;
2648                                 }
2649                                 dest_ip_str[i] = '\0';
2650                                 dest_ip = strtoul(dest_ip_str, NULL, 16);
2651
2652                                 i++;
2653                                 j = 0;
2654                                 while ((j < (arp_route_tbl_str_max_len - 1))
2655                                                          && (token[i + j] != ',')) {
2656                                         mask_str[j] = token[i + j];
2657                                         j++;
2658                                 }
2659                                 mask_str[j] = '\0';
2660                                 mask = strtoul(mask_str, NULL, 16);
2661
2662                                 j++;
2663                                 k = 0;
2664                                 while ((k < (arp_route_tbl_str_max_len - 1))
2665                                                          && (token[i + j + k] != ',')) {
2666                                         tx_port_str[k] = token[i + j + k];
2667                                         k++;
2668                                 }
2669                                 tx_port_str[k] = '\0';
2670                                 //atoi(tx_port_str);
2671                                 tx_port = strtoul(tx_port_str, NULL, 16);
2672
2673                                 k++;
2674                                 l = 0;
2675                                 while ((l < (arp_route_tbl_str_max_len - 1))
2676                                                          && (token[i + j + k + l] != ')')) {
2677                                         nh_ip_str[l] = token[i + j + k + l];
2678                                         l++;
2679                                 }
2680                                 nh_ip_str[l] = '\0';
2681                                 //atoi(nh_ip_str);
2682                                 nh_ip = strtoul(nh_ip_str, NULL, 16);
2683
2684                                 if (ARPICMP_DEBUG) {
2685                                         printf("token: %s, "
2686                                                                  "dest_ip_str: %s, dest_ip %u, "
2687                                                                  "mask_str: %s, mask %u, "
2688                                                                  "tx_port_str: %s, tx_port %u, "
2689                                                                  "nh_ip_str: %s, nh_ip %u\n",
2690                                                                  token, dest_ip_str, dest_ip,
2691                                                                  mask_str, mask, tx_port_str,
2692                                                                  tx_port, nh_ip_str, nh_ip);
2693                                 }
2694                                 #if 0
2695                                 if (tx_port >= params->n_ports_out) {
2696                                         printf("ARP-ICMP parse error - "
2697                                         "incorrect tx_port %d, max %d\n",
2698                                         tx_port, params->n_ports_out);
2699                                         return -1;
2700                                 }
2701                                 #endif
2702
2703                                 //Populate the static arp_route_table
2704                                 lib_arp_route_table[arp_route_tbl_index].ip =
2705                                                 dest_ip;
2706                                 lib_arp_route_table[arp_route_tbl_index].mask =
2707                                                 mask;
2708                                 lib_arp_route_table[arp_route_tbl_index].port =
2709                                                 tx_port;
2710                                 lib_arp_route_table[arp_route_tbl_index].nh =
2711                                                 nh_ip;
2712                                 arp_route_tbl_index++;
2713                                 token = strtok(NULL, "(");
2714                         }
2715
2716                         continue;
2717                 }
2718                 /*ND IPv6 */
2719                 /* nd_route_tbl */
2720                 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2721                         nd_route_tbl_present = 1;
2722
2723                         uint8_t dest_ipv6[16], depth = 0, tx_port =
2724                                         0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2725                         uint8_t nd_route_tbl_str_max_len = 128; //64;
2726                         char dest_ipv6_str[nd_route_tbl_str_max_len];
2727                         char depth_str[nd_route_tbl_str_max_len];
2728                         char tx_port_str[nd_route_tbl_str_max_len];
2729                         char nh_ipv6_str[nd_route_tbl_str_max_len];
2730                         char *token = strtok(arg_value, "(");
2731                         while (token) {
2732                                 i = 0;
2733                                 while ((i < (nd_route_tbl_str_max_len - 1))
2734                                                          && (token[i] != ',')) {
2735                                         dest_ipv6_str[i] = token[i];
2736                                         i++;
2737                                 }
2738                                 dest_ipv6_str[i] = '\0';
2739                                 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2740                                                         &dest_ipv6);
2741
2742                                 i++;
2743                                 j = 0;
2744                                 while ((j < (nd_route_tbl_str_max_len - 1))
2745                                                          && (token[i + j] != ',')) {
2746                                         depth_str[j] = token[i + j];
2747                                         j++;
2748                                 }
2749                                 depth_str[j] = '\0';
2750                                 //converting string char to integer
2751                                 int s;
2752                                 for (s = 0; depth_str[s] != '\0'; ++s)
2753                                         depth = depth * 10 + depth_str[s] - '0';
2754
2755                                 j++;
2756                                 k = 0;
2757                                 while ((k < (nd_route_tbl_str_max_len - 1))
2758                                                          && (token[i + j + k] != ',')) {
2759                                         tx_port_str[k] = token[i + j + k];
2760                                         k++;
2761                                 }
2762                                 tx_port_str[k] = '\0';
2763                                 //atoi(tx_port_str);
2764                                 tx_port = strtoul(tx_port_str, NULL, 16);
2765
2766                                 k++;
2767                                 l = 0;
2768                                 while ((l < (nd_route_tbl_str_max_len - 1))
2769                                                          && (token[i + j + k + l] != ')')) {
2770                                         nh_ipv6_str[l] = token[i + j + k + l];
2771                                         l++;
2772                                 }
2773                                 nh_ipv6_str[l] = '\0';
2774                                 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2775                                                         &nh_ipv6);
2776
2777                                 //Populate the static arp_route_table
2778                                 for (i = 0; i < 16; i++) {
2779                                         lib_nd_route_table
2780                                                         [nd_route_tbl_index].ipv6[i] =
2781                                                         dest_ipv6[i];
2782                                         lib_nd_route_table
2783                                                         [nd_route_tbl_index].nhipv6[i] =
2784                                                         nh_ipv6[i];
2785                                 }
2786                                 lib_nd_route_table[nd_route_tbl_index].depth =
2787                                                 depth;
2788                                 lib_nd_route_table[nd_route_tbl_index].port =
2789                                                 tx_port;
2790
2791                                 nd_route_tbl_index++;
2792                                 token = strtok(NULL, "(");
2793                         } //while
2794
2795                         continue;
2796                 }
2797                 /* any other */
2798
2799         }
2800
2801         #if 0
2802         if (!arp_meta_offset_present) {
2803                 printf("ARPICMP: arp_meta_offset not initialized\n");
2804                 return -1;
2805         }
2806         #endif
2807
2808         if (!arp_route_tbl_present && !nd_route_tbl_present) {
2809                 printf("Neither arp_route_tbl_present nor "
2810                         "nd_route_tbl_present declared\n");
2811                 return -1;
2812         }
2813
2814         if (!pktq_in_prv_present) {
2815                 printf("pktq_in_prv not declared\n");
2816                 return -1;
2817         }
2818
2819         if (!ports_mac_list_present) {
2820                 printf("ports_mac_list not declared\n");
2821                 return -1;
2822         }
2823
2824         return 0;
2825 }
2826
2827 #endif
2828
2829 uint32_t arpicmp_pkt_print_count;
2830 static inline void
2831 pkt_key_arpicmp(struct rte_mbuf *pkt, uint32_t pkt_num, void *arg)
2832 {
2833
2834         struct pipeline_arpicmp_in_port_h_arg *ap = arg;
2835         struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
2836
2837         p_arp->receivedPktCount++;
2838
2839         uint8_t in_port_id = pkt->port;
2840         #ifdef VNF_ACL
2841         struct app_link_params *link;
2842         #endif
2843         uint8_t *protocol;
2844         uint32_t pkt_mask = 1 << pkt_num;
2845         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
2846
2847         uint32_t prot_offset =
2848                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
2849
2850         #ifdef VNF_ACL
2851         uint32_t out_port;
2852         #endif
2853
2854         uint16_t *eth_proto =
2855                 RTE_MBUF_METADATA_UINT16_PTR(pkt, eth_proto_offset);
2856
2857         /* header room + eth hdr size + src_aadr offset in ip header */
2858         #ifdef VNF_ACL
2859         uint32_t dst_addr_offset =
2860                 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
2861         uint32_t *dst_addr = RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset);
2862         #endif
2863
2864         #ifdef IPV6
2865          uint32_t prot_offset_ipv6 =
2866                          MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
2867
2868         if (rte_be_to_cpu_16(*eth_proto) == ETHER_TYPE_IPv6)
2869                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset_ipv6);
2870         else
2871                 protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
2872         #else
2873         protocol = RTE_MBUF_METADATA_UINT8_PTR(pkt, prot_offset);
2874         #endif
2875
2876
2877         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
2878                 print_pkt1(pkt);
2879                 arpicmp_pkt_print_count++;
2880                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
2881                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
2882                                  rte_be_to_cpu_16(*eth_proto), *protocol, ETH_TYPE_ARP,
2883                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
2884         }
2885
2886         #ifdef VNF_ACL
2887         link = &myApp->link_params[in_port_id];
2888         #endif
2889
2890         /* Classifier for ICMP pass-through*/
2891         if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_ARP) ||
2892                         ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV4)
2893                          && (*protocol == IP_PROTOCOL_ICMP)
2894                 #ifdef VNF_ACL
2895                 && (link->ip == rte_be_to_cpu_32(*dst_addr))
2896                 #endif
2897                 )) {
2898
2899                 #ifdef VNF_ACL
2900                 out_port = p_arp->outport_id[in_port_id];
2901                 process_arpicmp_pkt(pkt, out_port, pkt_mask);
2902                 #else
2903                 process_arpicmp_pkt(pkt, ifm_get_port(in_port_id));
2904                 #endif
2905                 return;
2906         }
2907         #ifdef IPV6
2908         else if ((rte_be_to_cpu_16(*eth_proto) == ETH_TYPE_IPV6)
2909                 && (*protocol == ICMPV6_PROTOCOL_ID)) {
2910                 #ifdef VNF_ACL
2911                 out_port = p_arp->outport_id[in_port_id];
2912                 process_icmpv6_pkt(pkt, out_port, pkt_mask);
2913                 #else
2914                 process_icmpv6_pkt(pkt, ifm_get_port(in_port_id));
2915                 #endif
2916
2917                 return;
2918         }
2919         #endif
2920
2921         /* Drop the pkt if not ARP/ICMP */
2922         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask);
2923         p_arp->droppedPktCount++;
2924
2925 }
2926
2927 static inline void
2928 pkt4_key_arpicmp(struct rte_mbuf **pkt, uint32_t pkt_num, void *arg)
2929 {
2930
2931         struct pipeline_arpicmp_in_port_h_arg *ap = arg;
2932         struct pipeline_arpicmp *p_arp = (struct pipeline_arpicmp *)ap->p;
2933
2934         p_arp->receivedPktCount += 4;
2935
2936         uint32_t eth_proto_offset = MBUF_HDR_ROOM + 12;
2937         uint8_t in_port_id = pkt[0]->port;
2938
2939         uint32_t prot_offset =
2940                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_PROTOCOL_OFST;
2941
2942         /* header room + eth hdr size + src_aadr offset in ip header */
2943         #ifdef VNF_ACL
2944         uint32_t dst_addr_offset =
2945                 MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST;
2946         #endif
2947
2948         uint32_t pkt_mask0 = 1 << pkt_num;
2949         uint32_t pkt_mask1 = 1 << (pkt_num + 1);
2950         uint32_t pkt_mask2 = 1 << (pkt_num + 2);
2951         uint32_t pkt_mask3 = 1 << (pkt_num + 3);
2952
2953         #ifdef VNF_ACL
2954         uint32_t out_port0;
2955         uint32_t out_port1;
2956         uint32_t out_port2;
2957         uint32_t out_port3;
2958         #endif
2959
2960         uint16_t *eth_proto0 =
2961                 RTE_MBUF_METADATA_UINT16_PTR(pkt[0], eth_proto_offset);
2962         uint16_t *eth_proto1 =
2963                 RTE_MBUF_METADATA_UINT16_PTR(pkt[1], eth_proto_offset);
2964         uint16_t *eth_proto2 =
2965                 RTE_MBUF_METADATA_UINT16_PTR(pkt[2], eth_proto_offset);
2966         uint16_t *eth_proto3 =
2967                 RTE_MBUF_METADATA_UINT16_PTR(pkt[3], eth_proto_offset);
2968
2969         uint8_t *protocol0;
2970         uint8_t *protocol1;
2971         uint8_t *protocol2;
2972         uint8_t *protocol3;
2973
2974         #ifdef VNF_ACL
2975         uint32_t *dst_addr0 =
2976                         RTE_MBUF_METADATA_UINT32_PTR(pkt[0], dst_addr_offset);
2977         uint32_t *dst_addr1 =
2978                         RTE_MBUF_METADATA_UINT32_PTR(pkt[1], dst_addr_offset);
2979         uint32_t *dst_addr2 =
2980                         RTE_MBUF_METADATA_UINT32_PTR(pkt[2], dst_addr_offset);
2981         uint32_t *dst_addr3 =
2982                         RTE_MBUF_METADATA_UINT32_PTR(pkt[3], dst_addr_offset);
2983
2984         struct app_link_params *link0;
2985         struct app_link_params *link1;
2986         struct app_link_params *link2;
2987         struct app_link_params *link3;
2988
2989         link0 = &myApp->link_params[pkt[0]->port];
2990         link1 = &myApp->link_params[pkt[1]->port];
2991         link2 = &myApp->link_params[pkt[2]->port];
2992         link3 = &myApp->link_params[pkt[3]->port];
2993         #endif
2994
2995         #ifdef IPV6
2996         uint32_t prot_offset_ipv6 =
2997                         MBUF_HDR_ROOM + ETH_HDR_SIZE + IPV6_HDR_PROTOCOL_OFST;
2998
2999         #endif
3000
3001         #ifdef IPV6
3002 /* --0-- */
3003         if (rte_be_to_cpu_16(*eth_proto0) == ETHER_TYPE_IPv6)
3004                 protocol0 =
3005                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset_ipv6);
3006         else
3007                 protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
3008
3009 /* --1-- */
3010         if (rte_be_to_cpu_16(*eth_proto1) == ETHER_TYPE_IPv6)
3011                 protocol1 =
3012                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset_ipv6);
3013         else
3014                 protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
3015
3016 /* --2-- */
3017         if (rte_be_to_cpu_16(*eth_proto2) == ETHER_TYPE_IPv6)
3018                 protocol2 =
3019                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset_ipv6);
3020         else
3021                 protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
3022
3023 /* --3-- */
3024         if (rte_be_to_cpu_16(*eth_proto3) == ETHER_TYPE_IPv6)
3025                 protocol3 =
3026                                 RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset_ipv6);
3027         else
3028                 protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
3029         #else
3030         protocol0 = RTE_MBUF_METADATA_UINT8_PTR(pkt[0], prot_offset);
3031         protocol1 = RTE_MBUF_METADATA_UINT8_PTR(pkt[1], prot_offset);
3032         protocol2 = RTE_MBUF_METADATA_UINT8_PTR(pkt[2], prot_offset);
3033         protocol3 = RTE_MBUF_METADATA_UINT8_PTR(pkt[3], prot_offset);
3034         #endif
3035
3036         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3037                 print_pkt1(pkt[0]);
3038                 arpicmp_pkt_print_count++;
3039                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3040                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3041                                  rte_be_to_cpu_16(*eth_proto0), *protocol0, ETH_TYPE_ARP,
3042                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3043         }
3044
3045
3046         if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_ARP) ||
3047                         ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV4)
3048                          && (*protocol0 == IP_PROTOCOL_ICMP)
3049                 #ifdef VNF_ACL
3050                                 && (link0->ip == rte_be_to_cpu_32(*dst_addr0))
3051                 #endif
3052                 )) {
3053
3054                 #ifdef VNF_ACL
3055                 out_port0 = p_arp->outport_id[pkt[0]->port];
3056                 process_arpicmp_pkt(pkt[0], out_port0, pkt_mask0);
3057                 #else
3058                 process_arpicmp_pkt(pkt[0], ifm_get_port(in_port_id));
3059                 #endif
3060
3061                 goto PKT1;
3062         }
3063         #ifdef IPV6
3064         else if ((rte_be_to_cpu_16(*eth_proto0) == ETH_TYPE_IPV6)
3065                          && (*protocol0 == ICMPV6_PROTOCOL_ID)) {
3066
3067                 #ifdef VNF_ACL
3068                 out_port0 = p_arp->outport_id[pkt[0]->port];
3069                 process_icmpv6_pkt(pkt[0], out_port0, pkt_mask0);
3070                 #else
3071                 process_icmpv6_pkt(pkt[0], ifm_get_port(in_port_id));
3072                 #endif
3073
3074                 goto PKT1;
3075         }
3076         #endif
3077
3078         /* Drop the pkt if not ARP/ICMP */
3079         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask0);
3080         p_arp->droppedPktCount++;
3081
3082 PKT1:
3083         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3084                 print_pkt1(pkt[1]);
3085                 arpicmp_pkt_print_count++;
3086                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3087                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3088                                  rte_be_to_cpu_16(*eth_proto1), *protocol1, ETH_TYPE_ARP,
3089                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3090         }
3091
3092         if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_ARP) ||
3093                         ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV4)
3094                          && (*protocol1 == IP_PROTOCOL_ICMP)
3095                 #ifdef VNF_ACL
3096                                 && (link1->ip == rte_be_to_cpu_32(*dst_addr1))
3097                 #endif
3098                 )) {
3099
3100                 #ifdef VNF_ACL
3101                 out_port1 = p_arp->outport_id[pkt[1]->port];
3102                 process_arpicmp_pkt(pkt[1], out_port1, pkt_mask1);
3103                 #else
3104                 process_arpicmp_pkt(pkt[1], ifm_get_port(in_port_id));
3105                 #endif
3106                 goto PKT2;
3107         }
3108         #ifdef IPV6
3109         else if ((rte_be_to_cpu_16(*eth_proto1) == ETH_TYPE_IPV6)
3110                 && (*protocol1 == ICMPV6_PROTOCOL_ID)) {
3111
3112                 #ifdef VNF_ACL
3113                 out_port1 = p_arp->outport_id[pkt[1]->port];
3114                 process_icmpv6_pkt(pkt[1], out_port1, pkt_mask1);
3115                 #else
3116                 process_icmpv6_pkt(pkt[1], ifm_get_port(in_port_id));
3117                 #endif
3118
3119                 goto PKT2;
3120         }
3121         #endif
3122
3123         /* Drop the pkt if not ARP/ICMP */
3124         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask1);
3125         p_arp->droppedPktCount++;
3126
3127 PKT2:
3128         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3129                 print_pkt1(pkt[2]);
3130                 arpicmp_pkt_print_count++;
3131                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3132                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3133                                  rte_be_to_cpu_16(*eth_proto2), *protocol2, ETH_TYPE_ARP,
3134                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3135         }
3136
3137         if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_ARP) ||
3138                         ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV4)
3139                          && (*protocol2 == IP_PROTOCOL_ICMP)
3140                 #ifdef VNF_ACL
3141                                 && (link2->ip == rte_be_to_cpu_32(*dst_addr2))
3142                 #endif
3143                 )) {
3144
3145                 #ifdef VNF_ACL
3146                 out_port2 = p_arp->outport_id[pkt[2]->port];
3147                 process_arpicmp_pkt(pkt[2], out_port2, pkt_mask2);
3148                 #else
3149                 process_arpicmp_pkt(pkt[2], ifm_get_port(in_port_id));
3150                 #endif
3151
3152                 goto PKT3;
3153         }
3154         #ifdef IPV6
3155         else if ((rte_be_to_cpu_16(*eth_proto2) == ETH_TYPE_IPV6)
3156                 && (*protocol2 == ICMPV6_PROTOCOL_ID)) {
3157
3158                 #ifdef VNF_ACL
3159                 out_port2 = p_arp->outport_id[pkt[2]->port];
3160                 process_icmpv6_pkt(pkt[2], out_port2, pkt_mask2);
3161                 #else
3162                 process_icmpv6_pkt(pkt[2], ifm_get_port(in_port_id));
3163                 #endif
3164
3165                 goto PKT3;
3166         }
3167         #endif
3168
3169         /* Drop the pkt if not ARP/ICMP */
3170         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask2);
3171         p_arp->droppedPktCount++;
3172
3173 PKT3:
3174         if ((ARPICMP_DEBUG > 2) && (arpicmp_pkt_print_count < 10)) {
3175                 print_pkt1(pkt[3]);
3176                 arpicmp_pkt_print_count++;
3177                 printf("\nEth Typ %x, Prot %x, ETH_TYPE_ARP %x, "
3178                         "ETH_TYPE_IPV4 %x, IP_PROTOCOL_ICMP %x\n",
3179                                  rte_be_to_cpu_16(*eth_proto3), *protocol3, ETH_TYPE_ARP,
3180                                  ETH_TYPE_IPV4, IP_PROTOCOL_ICMP);
3181         }
3182
3183         if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_ARP) ||
3184                         ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV4)
3185                          && (*protocol3 == IP_PROTOCOL_ICMP)
3186
3187                 #ifdef VNF_ACL
3188                 && (link3->ip == rte_be_to_cpu_32(*dst_addr3))
3189                 #endif
3190                 )) {
3191
3192                 #ifdef VNF_ACL
3193                 out_port3 = p_arp->outport_id[pkt[3]->port];
3194                 process_arpicmp_pkt(pkt[3], out_port3, pkt_mask3);
3195                 #else
3196                 process_arpicmp_pkt(pkt[3], ifm_get_port(in_port_id));
3197                 #endif
3198
3199                 return;
3200         }
3201         #ifdef IPV6
3202         else if ((rte_be_to_cpu_16(*eth_proto3) == ETH_TYPE_IPV6)
3203                 && (*protocol3 == ICMPV6_PROTOCOL_ID)) {
3204
3205                 #ifdef VNF_ACL
3206                 out_port3 = p_arp->outport_id[pkt[3]->port];
3207                 process_icmpv6_pkt(pkt[3], out_port3, pkt_mask3);
3208                 #else
3209                 process_icmpv6_pkt(pkt[3], ifm_get_port(in_port_id));
3210                 #endif
3211                 return;
3212         }
3213         #endif
3214
3215         /* Drop the pkt if not ARP/ICMP */
3216         rte_pipeline_ah_packet_drop(p_arp->p.p, pkt_mask3);
3217         p_arp->droppedPktCount++;
3218
3219
3220 }
3221
3222 PIPELINE_ARPICMP_KEY_PORT_IN_AH(
3223         port_in_ah_arpicmp,
3224         pkt_key_arpicmp,
3225         pkt4_key_arpicmp);
3226
3227 static void *pipeline_arpicmp_init(struct pipeline_params *params,
3228                                 __rte_unused void *arg)
3229 {
3230         struct pipeline *p;
3231         struct pipeline_arpicmp *p_arp;
3232         uint32_t size, i, in_ports_arg_size;
3233
3234         printf("Start pipeline_arpicmp_init\n");
3235
3236         /* Check input arguments */
3237         if ((params == NULL) ||
3238                         (params->n_ports_in == 0) ||
3239                         (params->n_ports_out == 0))
3240                 return NULL;
3241
3242         /* Memory allocation */
3243         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_arpicmp));
3244         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
3245         p_arp = (struct pipeline_arpicmp *)p;
3246         if (p == NULL)
3247                 return NULL;
3248
3249         //gp_arp = p_arp;
3250         struct app_params *app = (struct app_params *)arg;
3251         myApp = arg;
3252
3253         PLOG(p, HIGH, "ARPICMP");
3254         strcpy(p->name, params->name);
3255         p->log_level = params->log_level;
3256
3257         p_arp->receivedPktCount = 0;
3258         p_arp->droppedPktCount = 0;
3259
3260 #ifdef VNF_ACL
3261         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++)
3262                 p_arp->links_map[i] = 0xff;
3263
3264         p_arp->pipeline_num = 0;
3265
3266         /* Parse arguments */
3267         if (pipeline_arpicmp_parse_args(p_arp, params))
3268                 return NULL;
3269 #endif
3270         #ifndef VNF_ACL
3271         lib_arp_init(params, app);
3272         #endif
3273
3274         /* Pipeline */
3275         {
3276                 struct rte_pipeline_params pipeline_params = {
3277                         .name = "ARPICMP",
3278                         .socket_id = params->socket_id,
3279                         .offset_port_id = 0,
3280                         //.offset_port_id = arp_meta_offset,
3281                 };
3282
3283                 p->p = rte_pipeline_create(&pipeline_params);
3284                 if (p->p == NULL) {
3285                         rte_free(p);
3286                         return NULL;
3287                 }
3288         }
3289
3290         p->n_ports_in = params->n_ports_in;
3291         p->n_ports_out = params->n_ports_out;
3292         p->n_tables = 1;
3293
3294         /* Memory allocation for in_port_h_arg */
3295         in_ports_arg_size = RTE_CACHE_LINE_ROUNDUP(
3296                 (sizeof(struct pipeline_arpicmp_in_port_h_arg)) *
3297                                 (params->n_ports_in));
3298         struct pipeline_arpicmp_in_port_h_arg *ap =
3299                 (struct pipeline_arpicmp_in_port_h_arg *)rte_zmalloc(NULL,
3300                                 in_ports_arg_size,
3301                                 RTE_CACHE_LINE_SIZE);
3302         if (ap == NULL)
3303                 return NULL;
3304
3305         /*Input ports */
3306         for (i = 0; i < p->n_ports_in; i++) {
3307                 /* passing our txrx pipeline in call back arg */
3308                 (ap[i]).p = p_arp;
3309                 (ap[i]).in_port_id = i;
3310                 struct rte_pipeline_port_in_params port_params = {
3311                         .ops =
3312                                         pipeline_port_in_params_get_ops(&params->
3313                                                                         port_in[i]),
3314                         .arg_create =
3315                                         pipeline_port_in_params_convert(&params->
3316                                                                         port_in[i]),
3317                         .f_action = NULL,
3318                         .arg_ah = &(ap[i]),
3319                         .burst_size = params->port_in[i].burst_size,
3320                 };
3321
3322                         port_params.f_action = port_in_ah_arpicmp;
3323
3324                 int status = rte_pipeline_port_in_create(p->p,
3325                                                          &port_params,
3326                                                          &p->port_in_id[i]);
3327
3328                 if (status) {
3329                         rte_pipeline_free(p->p);
3330                         rte_free(p);
3331                         return NULL;
3332                 }
3333         }
3334
3335         /* Output ports */
3336         for (i = 0; i < p->n_ports_out; i++) {
3337                 struct rte_pipeline_port_out_params port_params = {
3338                         .ops =
3339                                         pipeline_port_out_params_get_ops(&params->
3340                                                                          port_out[i]),
3341                         .arg_create =
3342                                         pipeline_port_out_params_convert(&params->
3343                                                                          port_out[i]),
3344                         .f_action = NULL,
3345                         .arg_ah = NULL,
3346                 };
3347
3348                 int status = rte_pipeline_port_out_create(p->p,
3349                                                                 &port_params,
3350                                                                 &p->port_out_id[i]);
3351
3352                 if (status) {
3353                         rte_pipeline_free(p->p);
3354                         rte_free(p);
3355                         return NULL;
3356                 }
3357         }
3358         int pipeline_num = 0;
3359
3360         int status = sscanf(params->name, "PIPELINE%d", &pipeline_num);
3361
3362         if (status < 0) {
3363                 return NULL;
3364                 printf("Unable to read pipeline number\n");
3365         }
3366
3367         p_arp->pipeline_num = (uint8_t) pipeline_num;
3368
3369         register_pipeline_Qs(p_arp->pipeline_num, p);
3370         set_phy_outport_id(p_arp->pipeline_num, p, p_arp->outport_id);
3371
3372         /* Tables */
3373         {
3374                 struct rte_pipeline_table_params table_params = {
3375                         .ops = &rte_table_stub_ops,
3376                         .arg_create = NULL,
3377                         .f_action_hit = NULL,
3378                         .f_action_miss = NULL,
3379                         .arg_ah = NULL,
3380                         .action_data_size = 0,
3381                 };
3382
3383                 int status = rte_pipeline_table_create(p->p,
3384                                                                          &table_params,
3385                                                                          &p->table_id[0]);
3386
3387                 if (status) {
3388                         rte_pipeline_free(p->p);
3389                         rte_free(p);
3390                         return NULL;
3391                 }
3392         }
3393
3394         /* Connecting input ports to tables */
3395         for (i = 0; i < p->n_ports_in; i++) {
3396
3397                 int status = rte_pipeline_port_in_connect_to_table(p->p,
3398                                                                          p->
3399                                                                          port_in_id
3400                                                                          [i],
3401                                                                          p->
3402                                                                          table_id[0]);
3403
3404                 if (status) {
3405                         rte_pipeline_free(p->p);
3406                         rte_free(p);
3407                         return NULL;
3408                 }
3409
3410         }
3411
3412         /* Enable input ports */
3413         for (i = 0; i < p->n_ports_in; i++) {
3414                 int status = rte_pipeline_port_in_enable(p->p,
3415                                                          p->port_in_id[i]);
3416
3417                 if (status) {
3418                         rte_pipeline_free(p->p);
3419                         rte_free(p);
3420                         return NULL;
3421                 }
3422         }
3423
3424         /* Check pipeline consistency */
3425         if (rte_pipeline_check(p->p) < 0) {
3426                 rte_pipeline_free(p->p);
3427                 rte_free(p);
3428                 return NULL;
3429         }
3430
3431         /* Message queues */
3432         p->n_msgq = params->n_msgq;
3433         for (i = 0; i < p->n_msgq; i++)
3434                 p->msgq_in[i] = params->msgq_in[i];
3435         for (i = 0; i < p->n_msgq; i++)
3436                 p->msgq_out[i] = params->msgq_out[i];
3437
3438         /* Message handlers */
3439         memcpy(p->handlers, handlers, sizeof(p->handlers));
3440
3441 #ifdef VNF_ACL
3442
3443         /* create the arpicmp mbuf rx pool */
3444         lib_arp_pktmbuf_tx_pool = rte_pktmbuf_pool_create(
3445                                 "lib_arp_mbuf_tx_pool",
3446                                 NB_ARPICMP_MBUF, 32,
3447                                 0, RTE_MBUF_DEFAULT_BUF_SIZE,
3448                                 rte_socket_id());
3449
3450         if (lib_arp_pktmbuf_tx_pool == NULL) {
3451                 printf("ARP mbuf pool create failed.\n");
3452                 return NULL;
3453         }
3454
3455         lib_arp_pkt = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
3456         if (lib_arp_pkt == NULL) {
3457                 printf("ARP lib_arp_pkt alloc failed.\n");
3458                 return NULL;
3459         }
3460
3461         /* ARP Table */
3462         arp_hash_params.socket_id = rte_socket_id();
3463         arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
3464         arp_hash_handle = rte_hash_create(&arp_hash_params);
3465
3466         if (arp_hash_handle == NULL) {
3467                 printf("ARP rte_hash_create failed. socket %d ...\n",
3468                                          arp_hash_params.socket_id);
3469                 return NULL;
3470         }
3471         printf("arp_hash_handle %p\n\n", (void *)arp_hash_handle);
3472
3473         /* ND IPv6 */
3474         nd_hash_params.socket_id = rte_socket_id();
3475         nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
3476         nd_hash_handle = rte_hash_create(&nd_hash_params);
3477
3478         if (nd_hash_handle == NULL) {
3479                 printf("ND rte_hash_create failed. socket %d ...\n",
3480                                          nd_hash_params.socket_id);
3481                 return NULL;
3482         }
3483
3484         printf("nd_hash_handle %p\n\n", (void *)nd_hash_handle);
3485 #endif
3486         return p;
3487 }
3488
3489 static int pipeline_arpicmp_free(void *pipeline)
3490 {
3491         struct pipeline *p = (struct pipeline *)pipeline;
3492
3493         /* Check input arguments */
3494         if (p == NULL)
3495                 return -1;
3496
3497         /* Free resources */
3498         rte_pipeline_free(p->p);
3499         rte_free(p);
3500         return 0;
3501 }
3502
3503 static int pipeline_arpicmp_timer(void *pipeline)
3504 {
3505         struct pipeline *p = (struct pipeline *)pipeline;
3506
3507         pipeline_msg_req_handle(p);
3508         rte_pipeline_flush(p->p);
3509
3510         return 0;
3511 }
3512
3513 static int
3514 pipeline_arpicmp_track(void *pipeline, uint32_t port_in, uint32_t *port_out)
3515 {
3516         struct pipeline *p = (struct pipeline *)pipeline;
3517
3518         /* Check input arguments */
3519         if ((p == NULL) || (port_in >= p->n_ports_in) || (port_out == NULL))
3520                 return -1;
3521
3522         *port_out = port_in / p->n_ports_in;
3523         return 0;
3524 }
3525
3526 struct pipeline_be_ops pipeline_arpicmp_be_ops = {
3527         .f_init = pipeline_arpicmp_init,
3528         .f_free = pipeline_arpicmp_free,
3529         .f_run = NULL,
3530         .f_timer = pipeline_arpicmp_timer,
3531         .f_track = pipeline_arpicmp_track,
3532 };