common: Adding common library for sample vnf
[samplevnf.git] / common / VIL / l2l3_stack / lib_arp.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 <execinfo.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <rte_common.h>
24 #include <rte_malloc.h>
25 #include <rte_ip.h>
26 #include <rte_byteorder.h>
27 #include <rte_log.h>
28 #include <rte_table_lpm.h>
29 #include <rte_table_hash.h>
30 #include <rte_pipeline.h>
31 #include <rte_arp.h>
32 #include <rte_icmp.h>
33 #include <rte_hash.h>
34 #include <rte_jhash.h>
35 #include <rte_cycles.h>
36 #include <rte_timer.h>
37 #include "interface.h"
38 #include "l2_proto.h"
39 #include "lib_arp.h"
40 #include "l3fwd_lpm4.h"
41 #include "vnf_common.h"
42
43 #if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN)
44 #define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x)
45 #define CHECK_ENDIAN_32(x) rte_be_to_cpu_32(x)
46 #else
47 #define CHECK_ENDIAN_16(x) (x)
48 #define CHECK_ENDIAN_32(x) (x)
49 #endif
50
51 #define NB_ARPICMP_MBUF  64
52 #define NB_NDICMP_MBUF  64
53 #define IP_VERSION_4 0x40
54 #define IP_HDRLEN  0x05         /**< default IP header length == five 32-bits words. */
55 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
56
57 #define is_multicast_ipv4_addr(ipv4_addr) \
58         (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
59
60 extern uint8_t prv_in_port_a[16];
61 extern uint32_t timer_lcore;
62 uint32_t arp_timeout = ARP_TIMER_EXPIRY;
63
64 /*ND IPV6 */
65 #define INADDRSZ 4
66 #define IN6ADDRSZ 16
67 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
68 static int inet_pton_ipv6(const char *src, unsigned char *dst);
69 static int inet_pton_ipv4(const char *src, unsigned char *dst);
70 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
71                                                                 uint8_t netmask_ipv6[]);
72
73 uint8_t vnf_common_arp_lib_init;
74 uint8_t vnf_common_nd_lib_init;
75 uint8_t loadb_pipeline_count;
76
77 uint32_t ARPICMP_DEBUG;
78 uint32_t NDIPV6_DEBUG;
79
80 uint32_t arp_route_tbl_index;
81 uint32_t nd_route_tbl_index;
82 uint32_t link_hw_addr_array_idx;
83
84 uint32_t lib_arp_get_mac_req;
85 uint32_t lib_arp_nh_found;
86 uint32_t lib_arp_no_nh_found;
87 uint32_t lib_arp_arp_entry_found;
88 uint32_t lib_arp_no_arp_entry_found;
89 uint32_t lib_arp_populate_called;
90 uint32_t lib_arp_delete_called;
91 uint32_t lib_arp_duplicate_found;
92
93 uint32_t lib_nd_get_mac_req;
94 uint32_t lib_nd_nh_found;
95 uint32_t lib_nd_no_nh_found;
96 uint32_t lib_nd_nd_entry_found;
97 uint32_t lib_nd_no_arp_entry_found;
98 uint32_t lib_nd_populate_called;
99 uint32_t lib_nd_delete_called;
100 uint32_t lib_nd_duplicate_found;
101 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
102 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
103
104 struct rte_mbuf *lib_arp_pkt;
105 struct rte_mbuf *lib_nd_pkt;
106
107 uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
108 uint8_t default_ip[4] = { 0, 0, 1, 1 };
109
110 static struct rte_hash_parameters arp_hash_params = {
111         .name = "ARP",
112         .entries = 64,
113         .reserved = 0,
114         .key_len = sizeof(struct arp_key_ipv4),
115         .hash_func = rte_jhash,
116         .hash_func_init_val = 0,
117 };
118
119 static struct rte_hash_parameters nd_hash_params = {
120         .name = "ND",
121         .entries = 64,
122         .reserved = 0,
123         .key_len = sizeof(struct nd_key_ipv6),
124         .hash_func = rte_jhash,
125         .hash_func_init_val = 0,
126 };
127
128 struct rte_hash *arp_hash_handle;
129 struct rte_hash *nd_hash_handle;
130
131 void print_pkt1(struct rte_mbuf *pkt);
132
133 struct app_params *myApp;
134 struct rte_pipeline *myP;
135 uint8_t num_vnf_threads;
136
137 /**
138 * A structure for Arp port address
139 */
140 struct arp_port_address {
141         uint32_t ip;                     /**< Ip address */
142         uint8_t mac_addr[6]; /**< Mac address */
143 };
144
145 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
146 struct rte_mempool *timer_mempool_arp;
147
148 int timer_objs_mempool_count = 70000;
149
150 #define MAX_NUM_ARP_ENTRIES 64
151 #define MAX_NUM_ND_ENTRIES 64
152
153 uint32_t get_nh(uint32_t, uint32_t *);
154 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[]);
155
156 #define MAX_ARP_DATA_ENTRY_TABLE 7
157
158 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = {
159         {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(192, 168, 0, 2)},
160         {{0, 0, 0, 0, 0, 2}, 0, INCOMPLETE, IPv4(192, 168, 0, 3)},
161         {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(30, 40, 50, 60)},
162         {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(120, 0, 0, 2)},
163         {{0, 0, 0, 0, 0, 4}, 3, INCOMPLETE, IPv4(1, 1, 1, 4)},
164         {{0, 0, 0, 0, 0, 5}, 4, INCOMPLETE, IPv4(1, 1, 1, 5)},
165         {{0, 0, 0, 0, 0, 6}, 1, INCOMPLETE, IPv4(1, 1, 1, 7)},
166 };
167
168 #define MAX_ND_DATA_ENTRY_TABLE 7
169 struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = {
170         {{0, 0, 0, 0, 0, 8}, 1, INCOMPLETE,
171          {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, 0},
172
173         {{0, 0, 0, 0, 0, 9}, 1, INCOMPLETE,
174          {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, 0},
175         {{0, 0, 0, 0, 0, 10}, 2, INCOMPLETE,
176          {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
177         {{0, 0, 0, 0, 0, 11}, 3, INCOMPLETE,
178          {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
179         {{0, 0, 0, 0, 0, 12}, 4, INCOMPLETE,
180          {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
181         {{0, 0, 0, 0, 0, 13}, 5, INCOMPLETE,
182          {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
183         {{0, 0, 0, 0, 0, 14}, 6, INCOMPLETE,
184          {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
185 };
186
187 struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
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 };
221
222 struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
223         {0, 0, 0, 0},
224         {0, 0, 0, 0},
225         {0, 0, 0, 0},
226         {0, 0, 0, 0},
227         {0, 0, 0, 0},
228         {0, 0, 0, 0},
229         {0, 0, 0, 0},
230         {0, 0, 0, 0},
231         {0, 0, 0, 0},
232         {0, 0, 0, 0},
233         {0, 0, 0, 0},
234         {0, 0, 0, 0},
235         {0, 0, 0, 0},
236         {0, 0, 0, 0},
237         {0, 0, 0, 0},
238         {0, 0, 0, 0}
239 };
240
241 void print_trace(void);
242
243 /* Obtain a backtrace and print it to stdout. */
244 void print_trace(void)
245 {
246         void *array[10];
247         size_t size;
248         char **strings;
249         size_t i;
250
251         size = backtrace(array, 10);
252         strings = backtrace_symbols(array, size);
253
254         RTE_LOG(INFO, LIBARP, "Obtained %zd stack frames.\n", size);
255
256         for (i = 0; i < size; i++)
257                 RTE_LOG(INFO, LIBARP, "%s\n", strings[i]);
258
259         free(strings);
260 }
261
262 uint32_t get_nh(uint32_t ip, uint32_t *port)
263 {
264         int i = 0;
265         for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
266                 if (((lib_arp_route_table[i].
267                                         ip & lib_arp_route_table[i].mask) ==
268                                  (ip & lib_arp_route_table[i].mask))) {
269
270                         *port = lib_arp_route_table[i].port;
271                         lib_arp_nh_found++;
272                         return lib_arp_route_table[i].nh;
273                 }
274                 if (ARPICMP_DEBUG)
275                         printf("No nh match ip 0x%x, port %u, t_ip "
276                                                  "0x%x, t_port %u, mask 0x%x, r1 %x, r2 %x\n",
277                                                  ip, *port, lib_arp_route_table[i].ip,
278                                                  lib_arp_route_table[i].port,
279                                                  lib_arp_route_table[i].mask,
280                                                  (lib_arp_route_table[i].ip &
281                                 lib_arp_route_table[i].mask),
282                                                  (ip & lib_arp_route_table[i].mask));
283         }
284         if (ARPICMP_DEBUG)
285                 printf("No NH - ip 0x%x, port %u\n", ip, *port);
286         lib_arp_no_nh_found++;
287         return 0;
288 }
289
290 /*ND IPv6 */
291 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
292 {
293         int i = 0;
294         uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
295         uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
296         memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
297         memset(netip_nd, 0, sizeof(netip_nd));
298         memset(netip_in, 0, sizeof(netip_in));
299         if (!ipv6)
300                 return;
301         for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
302
303                 convert_prefixlen_to_netmask_ipv6(lib_nd_route_table[i].depth,
304                                                         netmask_ipv6);
305
306                 for (k = 0; k < 16; k++) {
307                         if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
308                                 depthflags++;
309                                 netip_nd[k] = lib_nd_route_table[i].ipv6[k];
310                         }
311                 }
312
313                 for (l = 0; l < 16; l++) {
314                         if (ipv6[l] & netmask_ipv6[l]) {
315                                 depthflags1++;
316                                 netip_in[l] = ipv6[l];
317                         }
318                 }
319                 int j = 0;
320                 if ((depthflags == depthflags1)
321                                 && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) {
322                         //&& (lib_nd_route_table[i].port == port))
323                         *port = lib_nd_route_table[i].port;
324                         lib_nd_nh_found++;
325
326                         for (j = 0; j < 16; j++)
327                                 nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
328
329                         return;
330                 }
331
332                 if (NDIPV6_DEBUG)
333                         printf("No nh match\n");
334                 depthflags = 0;
335                 depthflags1 = 0;
336         }
337         if (NDIPV6_DEBUG)
338                 printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
339         lib_nd_no_nh_found++;
340 }
341
342 /* Added for Multiport changes*/
343 int get_dest_mac_addr_port(const uint32_t ipaddr,
344                                  uint32_t *phy_port, struct ether_addr *hw_addr)
345 {
346         lib_arp_get_mac_req++;
347         uint32_t nhip = 0;
348
349         nhip = get_nh(ipaddr, phy_port);
350         if (nhip == 0) {
351                 if (ARPICMP_DEBUG)
352                         printf("ARPICMP no nh found for ip %x, port %d\n",
353                                                  ipaddr, *phy_port);
354                 //return 0;
355                 return NH_NOT_FOUND;
356         }
357
358         struct arp_entry_data *ret_arp_data = NULL;
359         struct arp_key_ipv4 tmp_arp_key;
360         tmp_arp_key.port_id = *phy_port;        /* Changed for Multi Port */
361         tmp_arp_key.ip = nhip;
362
363         if (ARPICMP_DEBUG)
364                 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
365                                          *phy_port);
366
367         ret_arp_data = retrieve_arp_entry(tmp_arp_key);
368         if (ret_arp_data == NULL) {
369                 if (ARPICMP_DEBUG) {
370                         printf
371                                         ("ARPICMP no arp entry found for ip %x, port %d\n",
372                                          ipaddr, *phy_port);
373                         print_arp_table();
374                 }
375                 if (nhip != 0) {
376                         if (ARPICMP_DEBUG)
377                                 printf("CG-NAPT requesting ARP for ip %x, "
378                                                          "port %d\n", nhip, *phy_port);
379                         request_arp(*phy_port, nhip);   //Changed for Multiport
380
381                 }
382                 lib_arp_no_arp_entry_found++;
383                 return ARP_NOT_FOUND;
384         }
385         ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
386         lib_arp_arp_entry_found++;
387         if (ARPICMP_DEBUG)
388                 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
389         return ARP_FOUND;
390 }
391
392 int get_dest_mac_address(const uint32_t ipaddr, uint32_t *phy_port,
393                          struct ether_addr *hw_addr, uint32_t *nhip)
394 {
395         lib_arp_get_mac_req++;
396
397         *nhip = get_nh(ipaddr, phy_port);
398         if (*nhip == 0) {
399                 if (ARPICMP_DEBUG && ipaddr)
400                         RTE_LOG(INFO, LIBARP,
401                                 "ARPICMP no nh found for ip %x, port %d\n",
402                                 ipaddr, *phy_port);
403                 return 0;
404         }
405
406         struct arp_entry_data *ret_arp_data = NULL;
407         struct arp_key_ipv4 tmp_arp_key;
408         tmp_arp_key.port_id = *phy_port;
409         tmp_arp_key.ip = *nhip;
410
411         ret_arp_data = retrieve_arp_entry(tmp_arp_key);
412         if (ret_arp_data == NULL) {
413                 if (ARPICMP_DEBUG && ipaddr) {
414                         RTE_LOG(INFO, LIBARP,
415                                 "ARPICMP no arp entry found for ip %x, port %d\n",
416                                 ipaddr, *phy_port);
417                         print_arp_table();
418                 }
419                 lib_arp_no_arp_entry_found++;
420                 return 0;
421         }
422         ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
423         lib_arp_arp_entry_found++;
424         return 1;
425
426 }
427
428 int get_dest_mac_addr(const uint32_t ipaddr,
429                                         uint32_t *phy_port, struct ether_addr *hw_addr)
430 {
431         lib_arp_get_mac_req++;
432         uint32_t nhip = 0;
433
434         nhip = get_nh(ipaddr, phy_port);
435         if (nhip == 0) {
436                 if (ARPICMP_DEBUG && ipaddr)
437                         RTE_LOG(INFO, LIBARP,
438                                 "ARPICMP no nh found for ip %x, port %d\n",
439                                 ipaddr, *phy_port);
440                 return 0;
441         }
442
443         struct arp_entry_data *ret_arp_data = NULL;
444         struct arp_key_ipv4 tmp_arp_key;
445         tmp_arp_key.port_id = *phy_port;
446         tmp_arp_key.ip = nhip;
447
448         ret_arp_data = retrieve_arp_entry(tmp_arp_key);
449         if (ret_arp_data == NULL) {
450                 if (ARPICMP_DEBUG && ipaddr) {
451                         printf
452                                         ("ARPICMP no arp entry found for ip %x, port %d\n",
453                                          ipaddr, *phy_port);
454                         print_arp_table();
455                 }
456
457                 if (nhip != 0) {
458                         if (ARPICMP_DEBUG > 4)
459                                 printf
460                                                 ("CG-NAPT requesting ARP for ip %x, port %d\n",
461                                                  nhip, *phy_port);
462                         if (ifm_chk_port_ipv4_enabled(*phy_port)) {
463                                 request_arp(*phy_port, nhip);
464                         } else {
465                                 if (ARPICMP_DEBUG)
466                                         RTE_LOG(INFO, LIBARP,
467                                                 "%s: IP is not enabled on port %u, not sending ARP REQ\n\r",
468                                                 __FUNCTION__, *phy_port);
469                         }
470
471                 }
472                 lib_arp_no_arp_entry_found++;
473                 return 0;
474         }
475         ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
476         lib_arp_arp_entry_found++;
477         return 1;
478 }
479
480 int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
481                                          struct ether_addr *hw_addr, uint8_t nhipv6[])
482 {
483         int i = 0, j = 0, flag = 0;
484         lib_nd_get_mac_req++;
485
486         get_nh_ipv6(ipv6addr, phy_port, nhipv6);
487         for (j = 0; j < 16; j++) {
488                 if (nhipv6[j])
489                         flag++;
490         }
491         if (flag == 0) {
492                 if (NDIPV6_DEBUG)
493                         printf("NDIPV6 no nh found for ipv6 "
494                                                  "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
495                                                  "%02x%02x%02x%02x%02x%02x, port %d\n",
496                                                  ipv6addr[0], ipv6addr[1], ipv6addr[2],
497                                                  ipv6addr[3], ipv6addr[4], ipv6addr[5],
498                                                  ipv6addr[6], ipv6addr[7], ipv6addr[8],
499                                                  ipv6addr[9], ipv6addr[10], ipv6addr[11],
500                                                  ipv6addr[12], ipv6addr[13], ipv6addr[14],
501                                                  ipv6addr[15], *phy_port);
502                 return 0;
503         }
504
505         struct nd_entry_data *ret_nd_data = NULL;
506         struct nd_key_ipv6 tmp_nd_key;
507         tmp_nd_key.port_id = *phy_port;
508
509         for (i = 0; i < 16; i++)
510                 tmp_nd_key.ipv6[i] = nhipv6[i];
511
512         ret_nd_data = retrieve_nd_entry(tmp_nd_key);
513         if (ret_nd_data == NULL) {
514                 if (NDIPV6_DEBUG) {
515                         printf("NDIPV6 no nd entry found for ip %x, port %d\n",
516                                                  ipv6addr[0], *phy_port);
517                 }
518                 lib_nd_no_arp_entry_found++;
519                 return 0;
520         }
521         ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
522         lib_nd_nd_entry_found++;
523         return 1;
524 }
525
526 int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t *phy_port,
527                                                 struct ether_addr *hw_addr, uint8_t nhipv6[])
528 {
529         int i = 0, j = 0, flag = 0;
530         lib_nd_get_mac_req++;
531
532         get_nh_ipv6(ipv6addr, phy_port, nhipv6);
533         for (j = 0; j < 16; j++) {
534                 if (nhipv6[j]) {
535                         flag++;
536                 }
537         }
538         if (flag == 0) {
539                 if (NDIPV6_DEBUG && ipv6addr)
540                         RTE_LOG(INFO, LIBARP,
541                                 "NDIPV6 no nh found for ipv6 %x, port %d\n",
542                                 ipv6addr[0], *phy_port);
543                 return 0;
544         }
545
546         struct nd_entry_data *ret_nd_data = NULL;
547         struct nd_key_ipv6 tmp_nd_key;
548         tmp_nd_key.port_id = *phy_port;
549
550         for (i = 0; i < 16; i++) {
551                 tmp_nd_key.ipv6[i] = nhipv6[i];
552         }
553
554         ret_nd_data = retrieve_nd_entry(tmp_nd_key);
555         if (ret_nd_data == NULL) {
556                 if (NDIPV6_DEBUG && ipv6addr) {
557                         RTE_LOG(INFO, LIBARP,
558                                 "NDIPV6 no nd entry found for ip %x, port %d\n",
559                                 ipv6addr[0], *phy_port);
560                 }
561                 if (flag != 0) {
562                         if (ARPICMP_DEBUG > 4)
563                                 printf
564                                                 ("Requesting ARP for ipv6 addr and port %d\n",
565                                                  *phy_port);
566                         request_nd(&nhipv6[0], ifm_get_port(*phy_port));
567
568                 }
569
570                 lib_nd_no_arp_entry_found++;
571                 return 0;
572         }
573         ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
574         lib_nd_nd_entry_found++;
575         return 1;
576 }
577
578 /**
579 * A structure for arp entries in Arp table
580 *
581 */
582 struct lib_arp_arp_table_entry {
583         struct rte_pipeline_table_entry head;
584         uint64_t macaddr;  /**< Mac address */
585 };
586
587 static const char *arp_op_name(uint16_t arp_op)
588 {
589         switch (CHECK_ENDIAN_16(arp_op)) {
590         case (ARP_OP_REQUEST):
591                 return "ARP Request";
592         case (ARP_OP_REPLY):
593                 return "ARP Reply";
594         case (ARP_OP_REVREQUEST):
595                 return "Reverse ARP Request";
596         case (ARP_OP_REVREPLY):
597                 return "Reverse ARP Reply";
598         case (ARP_OP_INVREQUEST):
599                 return "Peer Identify Request";
600         case (ARP_OP_INVREPLY):
601                 return "Peer Identify Reply";
602         default:
603                 break;
604         }
605         return "Unkwown ARP op";
606 }
607
608 static void print_icmp_packet(struct icmp_hdr *icmp_h)
609 {
610         RTE_LOG(INFO, LIBARP, "  ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
611                 icmp_h->icmp_type,
612                 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
613                  (icmp_h->icmp_type ==
614                         IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
615                 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
616                 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
617 }
618
619 static void print_ipv4_h(struct ipv4_hdr *ip_h)
620 {
621         struct icmp_hdr *icmp_h =
622                         (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
623         RTE_LOG(INFO, LIBARP, "  IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
624                 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
625                 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
626         if (ip_h->next_proto_id == IPPROTO_ICMP) {
627                 print_icmp_packet(icmp_h);
628         }
629 }
630
631 static void print_arp_packet(struct arp_hdr *arp_h)
632 {
633         RTE_LOG(INFO, LIBARP, "  ARP:  hrd=%d proto=0x%04x hln=%d "
634                 "pln=%d op=%u (%s)\n",
635                 CHECK_ENDIAN_16(arp_h->arp_hrd),
636                 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
637                 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
638                 arp_op_name(arp_h->arp_op));
639
640         if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
641                 RTE_LOG(INFO, LIBARP,
642                         "incorrect arp_hrd format for IPv4 ARP (%d)\n",
643                         (arp_h->arp_hrd));
644         } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
645                 RTE_LOG(INFO, LIBARP,
646                         "incorrect arp_pro format for IPv4 ARP (%d)\n",
647                         (arp_h->arp_pro));
648         } else if (arp_h->arp_hln != 6) {
649                 RTE_LOG(INFO, LIBARP,
650                         "incorrect arp_hln format for IPv4 ARP (%d)\n",
651                         arp_h->arp_hln);
652         } else if (arp_h->arp_pln != 4) {
653                 RTE_LOG(INFO, LIBARP,
654                         "incorrect arp_pln format for IPv4 ARP (%d)\n",
655                         arp_h->arp_pln);
656         } else {
657                 RTE_LOG(INFO, LIBARP,
658                         "        sha=%02X:%02X:%02X:%02X:%02X:%02X",
659                         arp_h->arp_data.arp_sha.addr_bytes[0],
660                         arp_h->arp_data.arp_sha.addr_bytes[1],
661                         arp_h->arp_data.arp_sha.addr_bytes[2],
662                         arp_h->arp_data.arp_sha.addr_bytes[3],
663                         arp_h->arp_data.arp_sha.addr_bytes[4],
664                         arp_h->arp_data.arp_sha.addr_bytes[5]);
665                 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
666                         (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
667                         (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
668                         (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
669                         CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
670                 RTE_LOG(INFO, LIBARP,
671                         "        tha=%02X:%02X:%02X:%02X:%02X:%02X",
672                         arp_h->arp_data.arp_tha.addr_bytes[0],
673                         arp_h->arp_data.arp_tha.addr_bytes[1],
674                         arp_h->arp_data.arp_tha.addr_bytes[2],
675                         arp_h->arp_data.arp_tha.addr_bytes[3],
676                         arp_h->arp_data.arp_tha.addr_bytes[4],
677                         arp_h->arp_data.arp_tha.addr_bytes[5]);
678                 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
679                         (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
680                         (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
681                         (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
682                         CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
683         }
684 }
685
686 static void print_eth(struct ether_hdr *eth_h)
687 {
688         RTE_LOG(INFO, LIBARP, "  ETH:  src=%02X:%02X:%02X:%02X:%02X:%02X",
689                 eth_h->s_addr.addr_bytes[0],
690                 eth_h->s_addr.addr_bytes[1],
691                 eth_h->s_addr.addr_bytes[2],
692                 eth_h->s_addr.addr_bytes[3],
693                 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
694         RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
695                 eth_h->d_addr.addr_bytes[0],
696                 eth_h->d_addr.addr_bytes[1],
697                 eth_h->d_addr.addr_bytes[2],
698                 eth_h->d_addr.addr_bytes[3],
699                 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
700
701 }
702
703 static void
704 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
705                  unsigned line)
706 {
707         struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
708         struct arp_hdr *arp_h =
709                         (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
710         struct ipv4_hdr *ipv4_h =
711                         (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
712
713         RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
714                 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
715         print_eth(eth_h);
716         switch (rte_cpu_to_be_16(eth_h->ether_type)) {
717         case ETHER_TYPE_IPv4:
718                 print_ipv4_h(ipv4_h);
719                 break;
720         case ETHER_TYPE_ARP:
721                 print_arp_packet(arp_h);
722                 break;
723         default:
724                 RTE_LOG(INFO, LIBARP, "  unknown packet type\n");
725                 break;
726         }
727         fflush(stdout);
728 }
729
730 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key)
731 {
732         struct arp_entry_data *ret_arp_data = NULL;
733         arp_key.filler1 = 0;
734         arp_key.filler2 = 0;
735         arp_key.filler3 = 0;
736
737         int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
738                                                          (void **)&ret_arp_data);
739         if (ret < 0) {
740                 //      RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
741         } else {
742
743                 if (ret_arp_data->mode == DYNAMIC_ARP) {
744                         struct arp_timer_key callback_key;
745                         callback_key.port_id = ret_arp_data->port;
746                         callback_key.ip = ret_arp_data->ip;
747                         /*lcore need to check which parameter need to be put */
748                         if (rte_timer_reset(ret_arp_data->timer,
749                                                         (arp_timeout * rte_get_tsc_hz()),
750                                                         SINGLE, timer_lcore,
751                                                         arp_timer_callback,
752                                                         &callback_key) < 0)
753                                 if (ARPICMP_DEBUG)
754                                         RTE_LOG(INFO, LIBARP,
755                                                 "Err : Timer already running\n");
756                 }
757
758                 return ret_arp_data;
759         }
760
761         return NULL;
762 }
763
764 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
765 {
766         struct nd_entry_data *ret_nd_data = NULL;
767         nd_key.filler1 = 0;
768         nd_key.filler2 = 0;
769         nd_key.filler3 = 0;
770         int i = 0;
771
772         /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
773         int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
774                                                          (void **)&ret_nd_data);
775         if (ret < 0) {
776 /*              RTE_LOG(INFO, LIBARP,"nd-hash: no lookup Entry Found - ret %d, EINVAL %d, ENOENT %d\n",
777                                 ret, EINVAL, ENOENT);*/
778         } else {
779                 if (ret_nd_data->mode == DYNAMIC_ND) {
780                         struct nd_timer_key callback_key;
781                         callback_key.port_id = ret_nd_data->port;
782
783                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
784                                 callback_key.ipv6[i] = ret_nd_data->ipv6[i];
785
786                         }
787
788                         if (rte_timer_reset
789                                         (ret_nd_data->timer,
790                                          (arp_timeout * rte_get_tsc_hz()), SINGLE,
791                                          timer_lcore, nd_timer_callback, &callback_key) < 0)
792                                 if (ARPICMP_DEBUG)
793                                         RTE_LOG(INFO, LIBARP,
794                                                 "Err : Timer already running\n");
795                 }
796                 return ret_nd_data;
797         }
798
799         return NULL;
800 }
801
802 void print_arp_table(void)
803 {
804         const void *next_key;
805         void *next_data;
806         uint32_t iter = 0;
807
808         printf
809                         ("------------------------ ARP CACHE -----------------------------------------\n");
810         printf
811                         ("----------------------------------------------------------------------------\n");
812         printf("\tport  hw addr            status     ip addr\n");
813         printf
814                         ("----------------------------------------------------------------------------\n");
815
816         while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
817                                  >= 0) {
818
819                 struct arp_entry_data *tmp_arp_data =
820                                 (struct arp_entry_data *)next_data;
821                 struct arp_key_ipv4 tmp_arp_key;
822                 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
823                 printf
824                                 ("\t%4d  %02X:%02X:%02X:%02X:%02X:%02X  %10s %d.%d.%d.%d\n",
825                                  tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
826                                  tmp_arp_data->eth_addr.addr_bytes[1],
827                                  tmp_arp_data->eth_addr.addr_bytes[2],
828                                  tmp_arp_data->eth_addr.addr_bytes[3],
829                                  tmp_arp_data->eth_addr.addr_bytes[4],
830                                  tmp_arp_data->eth_addr.addr_bytes[5],
831                                  tmp_arp_data->status ==
832                                  COMPLETE ? "COMPLETE" : "INCOMPLETE",
833                                  (tmp_arp_data->ip >> 24),
834                                  ((tmp_arp_data->ip & 0x00ff0000) >> 16),
835                                  ((tmp_arp_data->ip & 0x0000ff00) >> 8),
836                                  ((tmp_arp_data->ip & 0x000000ff)));
837         }
838
839         uint32_t i = 0;
840         printf("\nARP routing table has %d entries\n", arp_route_tbl_index);
841         printf("\nIP_Address    Mask          Port    NH_IP_Address\n");
842         for (i = 0; i < arp_route_tbl_index; i++) {
843                 printf("0x%x    0x%x    %d       0x%x\n",
844                                          lib_arp_route_table[i].ip,
845                                          lib_arp_route_table[i].mask,
846                                          lib_arp_route_table[i].port, lib_arp_route_table[i].nh);
847         }
848
849         printf
850                         ("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
851                          lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
852                          lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
853                          lib_arp_populate_called, lib_arp_delete_called,
854                          lib_arp_duplicate_found);
855
856         printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
857 }
858
859 /* ND IPv6 */
860 void print_nd_table(void)
861 {
862         const void *next_key;
863         void *next_data;
864         uint32_t iter = 0;
865         uint8_t ii = 0, j = 0, k = 0;
866         printf
867                         ("------------------------------------------------------------------------------------------------------\n");
868         printf("\tport  hw addr            status         ip addr\n");
869
870         printf
871                         ("------------------------------------------------------------------------------------------------------\n");
872         while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
873                                  0) {
874
875                 struct nd_entry_data *tmp_nd_data =
876                                 (struct nd_entry_data *)next_data;
877                 struct nd_key_ipv6 tmp_nd_key;
878                 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
879                 printf("\t%4d  %02X:%02X:%02X:%02X:%02X:%02X  %10s\n",
880                                          tmp_nd_data->port,
881                                          tmp_nd_data->eth_addr.addr_bytes[0],
882                                          tmp_nd_data->eth_addr.addr_bytes[1],
883                                          tmp_nd_data->eth_addr.addr_bytes[2],
884                                          tmp_nd_data->eth_addr.addr_bytes[3],
885                                          tmp_nd_data->eth_addr.addr_bytes[4],
886                                          tmp_nd_data->eth_addr.addr_bytes[5],
887                                          tmp_nd_data->status ==
888                                          COMPLETE ? "COMPLETE" : "INCOMPLETE");
889                 printf("\t\t\t\t\t\t");
890                 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
891                         printf("%02X%02X ", tmp_nd_data->ipv6[ii],
892                                                  tmp_nd_data->ipv6[ii + 1]);
893                 }
894                 printf("\n");
895         }
896
897         uint32_t i = 0;
898         printf("\n\nND IPV6 routing table has %d entries\n",
899                                  nd_route_tbl_index);
900         printf
901                         ("\nIP_Address                                          Depth          Port                             NH_IP_Address\n");
902         for (i = 0; i < nd_route_tbl_index; i++) {
903                 printf("\n");
904
905                 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
906                         RTE_LOG(INFO, LIBARP, "%02X%02X ",
907                                 lib_nd_route_table[i].ipv6[j],
908                                 lib_nd_route_table[i].ipv6[j + 1]);
909                 }
910
911                 printf
912                                 ("\n\t\t\t                      %d                                       %d                                     \n",
913                                  lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
914                 printf("\t\t\t\t\t\t\t\t\t");
915                 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
916                         printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
917                                                  lib_nd_route_table[i].ipv6[k + 1]);
918                 }
919         }
920         printf
921                         ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
922                          lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
923                          lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
924                          lib_nd_populate_called, lib_nd_delete_called,
925                          lib_nd_duplicate_found);
926         printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
927 }
928
929 void remove_arp_entry(uint32_t ipaddr, uint8_t portid, void *arg)
930 {
931
932         struct arp_key_ipv4 arp_key;
933         arp_key.port_id = portid;
934         arp_key.ip = ipaddr;
935         arp_key.filler1 = 0;
936         arp_key.filler2 = 0;
937         arp_key.filler3 = 0;
938
939         lib_arp_delete_called++;
940
941         struct arp_entry_data *ret_arp_data = NULL;
942
943         int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
944                                                          (void **)&ret_arp_data);
945         if (ret < 0) {
946 //              RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
947                 return;
948         } else {
949                 if (ret_arp_data->mode == DYNAMIC_ARP) {
950                         if (ret_arp_data->retry_count == 3) {
951                                 rte_timer_stop(ret_arp_data->timer);
952                                 rte_free(ret_arp_data->timer_key);
953                                 if (ARPICMP_DEBUG) {
954                                         RTE_LOG(INFO, LIBARP,
955                                                 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
956                                                 (arp_key.ip >> 24),
957                                                 ((arp_key.ip & 0x00ff0000) >>
958                                                  16),
959                                                 ((arp_key.ip & 0x0000ff00) >>
960                                                  8),
961                                                 ((arp_key.ip & 0x000000ff)),
962                                                 arp_key.port_id);
963                                 }
964                                 rte_hash_del_key(arp_hash_handle, &arp_key);
965                                 //print_arp_table();
966                         } else {
967                                 ret_arp_data->retry_count++;
968                                 if (ARPICMP_DEBUG)
969                                         RTE_LOG(INFO, LIBARP,
970                                                 "RETRY ARP..retry count : %u\n",
971                                                 ret_arp_data->retry_count);
972                                 //print_arp_table();
973                                 if (ARPICMP_DEBUG)
974                                         RTE_LOG(INFO, LIBARP,
975                                                 "TIMER STARTED FOR %u seconds\n",
976                                                 ARP_TIMER_EXPIRY);
977                                 if (ifm_chk_port_ipv4_enabled
978                                                 (ret_arp_data->port)) {
979                                         request_arp(ret_arp_data->port,
980                                                                 ret_arp_data->ip);
981                                 } else {
982                                         if (ARPICMP_DEBUG)
983                                                 RTE_LOG(INFO, LIBARP,
984                                                         "%s: IP is not enabled on port %u, not sending GARP\n\r",
985                                                         __FUNCTION__,
986                                                         ret_arp_data->port);
987                                 }
988                                 if (rte_timer_reset(ret_arp_data->timer,
989                                                                 (arp_timeout *
990                                                                  rte_get_tsc_hz()), SINGLE,
991                                                                 timer_lcore,
992                                                                 arp_timer_callback,
993                                                                 arg) < 0)
994                                         if (ARPICMP_DEBUG)
995                                                 RTE_LOG(INFO, LIBARP,
996                                                         "Err : Timer already running\n");
997
998                         }
999                 } else {
1000                         rte_hash_del_key(arp_hash_handle, &arp_key);
1001                 }
1002         }
1003 }
1004
1005 /* ND IPv6 */
1006 void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
1007 {
1008         int i = 0;
1009         struct nd_entry_data *ret_nd_data = NULL;
1010         struct nd_key_ipv6 nd_key;
1011         nd_key.port_id = portid;
1012
1013         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1014                 nd_key.ipv6[i] = ipv6addr[i];
1015         }
1016
1017         nd_key.filler1 = 0;
1018         nd_key.filler2 = 0;
1019         nd_key.filler3 = 0;
1020
1021         lib_nd_delete_called++;
1022
1023         if (NDIPV6_DEBUG) {
1024                 RTE_LOG(INFO, LIBARP,
1025                         "Deletes rte hash table nd entry for port %d ipv6=",
1026                         nd_key.port_id);
1027                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1028                         RTE_LOG(INFO, LIBARP, "%02X%02X ", nd_key.ipv6[i],
1029                                 nd_key.ipv6[i + 1]);
1030                 }
1031         }
1032         struct nd_timer_key callback_key;
1033         callback_key.port_id = portid;
1034
1035         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1036                 callback_key.ipv6[i] = ipv6addr[i];
1037
1038         }
1039         int ret = rte_hash_lookup_data(arp_hash_handle, &callback_key,
1040                                                          (void **)&ret_nd_data);
1041         if (ret < 0) {
1042 //              RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
1043         } else {
1044                 if (ret_nd_data->mode == DYNAMIC_ND) {
1045                         rte_timer_stop(ret_nd_data->timer);
1046                         rte_free(ret_nd_data->timer);
1047                 }
1048         }
1049         rte_hash_del_key(nd_hash_handle, &nd_key);
1050 }
1051
1052 void
1053 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1054                          uint8_t portid, uint8_t mode)
1055 {
1056         struct arp_key_ipv4 arp_key;
1057         arp_key.port_id = portid;
1058         arp_key.ip = ipaddr;
1059         arp_key.filler1 = 0;
1060         arp_key.filler2 = 0;
1061         arp_key.filler3 = 0;
1062
1063         lib_arp_populate_called++;
1064
1065         if (ARPICMP_DEBUG)
1066                 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1067                         arp_key.ip, arp_key.port_id);
1068
1069         struct arp_entry_data *new_arp_data = retrieve_arp_entry(arp_key);
1070         if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1071                 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1072                 && mode == STATIC_ARP))) {
1073                 if (ARPICMP_DEBUG)
1074                         RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry already exists(%d %d)\n",
1075                                 new_arp_data->mode, mode);
1076
1077                 return;
1078         }
1079
1080         if (mode == DYNAMIC_ARP) {
1081                 if (new_arp_data
1082                                 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1083                         if (ARPICMP_DEBUG) {
1084                                 RTE_LOG(INFO, LIBARP,
1085                                         "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1086                                         (arp_key.ip >> 24),
1087                                         ((arp_key.ip & 0x00ff0000) >> 16),
1088                                         ((arp_key.ip & 0x0000ff00) >> 8),
1089                                         ((arp_key.ip & 0x000000ff)),
1090                                         arp_key.port_id);
1091                         }
1092                         lib_arp_duplicate_found++;
1093                         new_arp_data->retry_count = 0;  // Reset
1094                         if (rte_timer_reset(new_arp_data->timer,
1095                                                         (arp_timeout * rte_get_tsc_hz()),
1096                                                         SINGLE, timer_lcore,
1097                                                         arp_timer_callback,
1098                                                         new_arp_data->timer_key) < 0)
1099                                 if (ARPICMP_DEBUG)
1100                                         RTE_LOG(INFO, LIBARP,
1101                                                 "Err : Timer already running\n");
1102                         return;
1103                 }
1104
1105                 uint32_t size =
1106                                 RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_entry_data));
1107                 new_arp_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1108                 new_arp_data->eth_addr = *hw_addr;
1109                 new_arp_data->status = COMPLETE;
1110                 new_arp_data->port = portid;
1111                 new_arp_data->ip = ipaddr;
1112                 new_arp_data->mode = mode;
1113                 if (rte_mempool_get
1114                                 (timer_mempool_arp, (void **)&(new_arp_data->timer)) < 0) {
1115                         RTE_LOG(INFO, LIBARP,
1116                                 "TIMER - Error in getting timer alloc buffer\n");
1117                         return;
1118                 }
1119
1120                 rte_hash_add_key_data(arp_hash_handle, &arp_key, new_arp_data);
1121                 if (ARPICMP_DEBUG) {
1122                         RTE_LOG(INFO, LIBARP,
1123                                 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1124                                 (arp_key.ip >> 24),
1125                                 ((arp_key.ip & 0x00ff0000) >> 16),
1126                                 ((arp_key.ip & 0x0000ff00) >> 8),
1127                                 ((arp_key.ip & 0x000000ff)), arp_key.port_id);
1128                 }
1129                 // Call l3fwd module for resolving 2_adj structure.
1130                 resolve_l2_adj(ipaddr, portid, hw_addr);
1131
1132                 rte_timer_init(new_arp_data->timer);
1133                 struct arp_timer_key *callback_key =
1134                                 (struct arp_timer_key *)rte_malloc(NULL,
1135                                                                          sizeof(struct
1136                                                                                 arp_timer_key *),
1137                                                                          RTE_CACHE_LINE_SIZE);
1138                 callback_key->port_id = portid;
1139                 callback_key->ip = ipaddr;
1140
1141                 if (ARPICMP_DEBUG)
1142                         RTE_LOG(INFO, LIBARP, "TIMER STARTED FOR %u seconds\n",
1143                                 ARP_TIMER_EXPIRY);
1144                 if (rte_timer_reset
1145                                 (new_arp_data->timer, (arp_timeout * rte_get_tsc_hz()),
1146                                  SINGLE, timer_lcore, arp_timer_callback, callback_key) < 0)
1147                         if (ARPICMP_DEBUG)
1148                                 RTE_LOG(INFO, LIBARP,
1149                                         "Err : Timer already running\n");
1150
1151                 new_arp_data->timer_key = callback_key;
1152         } else {
1153                 if (new_arp_data
1154                                 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1155                         if (ARPICMP_DEBUG) {
1156                                 RTE_LOG(INFO, LIBARP,
1157                                         "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1158                                         (arp_key.ip >> 24),
1159                                         ((arp_key.ip & 0x00ff0000) >> 16),
1160                                         ((arp_key.ip & 0x0000ff00) >> 8),
1161                                         ((arp_key.ip & 0x000000ff)),
1162                                         arp_key.port_id);
1163                         }
1164                         lib_arp_duplicate_found++;
1165                 } else {
1166                         uint32_t size =
1167                                         RTE_CACHE_LINE_ROUNDUP(sizeof
1168                                                          (struct arp_entry_data));
1169                         new_arp_data =
1170                                         rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1171                         new_arp_data->eth_addr = *hw_addr;
1172                         new_arp_data->status = COMPLETE;
1173                         new_arp_data->port = portid;
1174                         new_arp_data->ip = ipaddr;
1175                         new_arp_data->mode = mode;
1176
1177                         rte_hash_add_key_data(arp_hash_handle, &arp_key,
1178                                                                 new_arp_data);
1179                         if (ARPICMP_DEBUG) {
1180                                 RTE_LOG(INFO, LIBARP,
1181                                         "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1182                                         (arp_key.ip >> 24),
1183                                         ((arp_key.ip & 0x00ff0000) >> 16),
1184                                         ((arp_key.ip & 0x0000ff00) >> 8),
1185                                         ((arp_key.ip & 0x000000ff)),
1186                                         arp_key.port_id);
1187                         }
1188                         // Call l3fwd module for resolving 2_adj structure.
1189                         resolve_l2_adj(ipaddr, portid, hw_addr);
1190                 }
1191         }
1192         if (ARPICMP_DEBUG) {
1193                 /* print entire hash table */
1194                 RTE_LOG(INFO, LIBARP,
1195                         "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x  ip=%d.%d.%d.%d  on port=%d\n",
1196                         new_arp_data->eth_addr.addr_bytes[0],
1197                         new_arp_data->eth_addr.addr_bytes[1],
1198                         new_arp_data->eth_addr.addr_bytes[2],
1199                         new_arp_data->eth_addr.addr_bytes[3],
1200                         new_arp_data->eth_addr.addr_bytes[4],
1201                         new_arp_data->eth_addr.addr_bytes[5],
1202                         (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1203                         ((arp_key.ip & 0x0000ff00) >> 8),
1204                         ((arp_key.ip & 0x000000ff)), portid);
1205                 puts("");
1206         }
1207 }
1208
1209 /*
1210  * ND IPv6
1211  *
1212  * Install key - data pair in Hash table - From Pipeline Configuration
1213  *
1214  */
1215
1216 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1217                                          uint8_t portid, uint8_t mode)
1218 {
1219
1220         /* need to lock here if multi-threaded */
1221         /* rte_hash_add_key_data is not thread safe */
1222         uint8_t i;
1223         struct nd_key_ipv6 nd_key;
1224         nd_key.port_id = portid;
1225
1226         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
1227                 nd_key.ipv6[i] = ipv6[i];
1228
1229 //      RTE_LOG(INFO, LIBARP,"\n");
1230         nd_key.filler1 = 0;
1231         nd_key.filler2 = 0;
1232         nd_key.filler3 = 0;
1233
1234         lib_nd_populate_called++;
1235
1236         /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1237         struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
1238
1239         if (mode == DYNAMIC_ND) {
1240                 if (new_nd_data
1241                                 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1242
1243                         if (NDIPV6_DEBUG) {
1244                                 RTE_LOG(INFO, LIBARP,
1245                                         "nd_entry exists port %d ipv6 = ",
1246                                         nd_key.port_id);
1247                                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1248
1249                                         RTE_LOG(INFO, LIBARP, "%02X%02X ",
1250                                                 nd_key.ipv6[i],
1251                                                 nd_key.ipv6[i + 1]);
1252                                 }
1253                         }
1254
1255                         lib_nd_duplicate_found++;
1256                         RTE_LOG(INFO, LIBARP, "nd_entry exists\n");
1257                         return;
1258                 }
1259                 uint32_t size =
1260                                 RTE_CACHE_LINE_ROUNDUP(sizeof(struct nd_entry_data));
1261                 new_nd_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1262
1263                 //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
1264                 new_nd_data->eth_addr = *hw_addr;
1265                 new_nd_data->status = COMPLETE;
1266                 new_nd_data->port = portid;
1267                 new_nd_data->mode = mode;
1268                 if (rte_mempool_get
1269                                 (timer_mempool_arp, (void **)&(new_nd_data->timer)) < 0) {
1270                         RTE_LOG(INFO, LIBARP,
1271                                 "TIMER - Error in getting timer alloc buffer\n");
1272                         return;
1273                 }
1274
1275                 if (NDIPV6_DEBUG)
1276                         RTE_LOG(INFO, LIBARP, "populate_nd_entry ipv6=");
1277
1278                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1279                         new_nd_data->ipv6[i] = ipv6[i];
1280                 }
1281
1282                 if (NDIPV6_DEBUG) {
1283                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1284
1285                                 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1286                                         new_nd_data->ipv6[i],
1287                                         new_nd_data->ipv6[i + 1]);
1288                         }
1289                 }
1290
1291                 /*Add a key-data pair at hash table for ND IPv6 static routing */
1292                 rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
1293                 /* need to check the return value of the hash add */
1294
1295                 /* after the hash is created then time is started */
1296                 rte_timer_init(new_nd_data->timer);
1297                 struct nd_timer_key *callback_key =
1298                                 (struct nd_timer_key *)rte_malloc(NULL,
1299                                                                         sizeof(struct nd_timer_key
1300                                                                          *),
1301                                                                         RTE_CACHE_LINE_SIZE);
1302                 callback_key->port_id = portid;
1303
1304                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1305                         callback_key->ipv6[i] = ipv6[i];
1306                 }
1307                 if (rte_timer_reset
1308                                 (new_nd_data->timer, (arp_timeout * rte_get_tsc_hz()),
1309                                  SINGLE, timer_lcore, nd_timer_callback, callback_key) < 0)
1310                         RTE_LOG(INFO, LIBARP, "Err : Timer already running\n");
1311         } else {
1312                 if (new_nd_data
1313                                 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1314                         if (NDIPV6_DEBUG) {
1315                                 RTE_LOG(INFO, LIBARP,
1316                                         "nd_entry exists port %d ipv6 = ",
1317                                         nd_key.port_id);
1318                                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1319
1320                                         RTE_LOG(INFO, LIBARP, "%02X%02X ",
1321                                                 nd_key.ipv6[i],
1322                                                 nd_key.ipv6[i + 1]);
1323                                 }
1324                         }
1325
1326                         lib_nd_duplicate_found++;
1327                 } else {
1328                         uint32_t size =
1329                                         RTE_CACHE_LINE_ROUNDUP(sizeof
1330                                                          (struct nd_entry_data));
1331                         new_nd_data =
1332                                         rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1333
1334                         //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
1335                         new_nd_data->eth_addr = *hw_addr;
1336                         new_nd_data->status = COMPLETE;
1337                         new_nd_data->port = portid;
1338                         new_nd_data->mode = mode;
1339                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1340                                 new_nd_data->ipv6[i] = ipv6[i];
1341                         }
1342
1343                         /*Add a key-data pair at hash table for ND IPv6 static routing */
1344                         rte_hash_add_key_data(nd_hash_handle, &nd_key,
1345                                                                 new_nd_data);
1346                         /* need to check the return value of the hash add */
1347                 }
1348         }
1349         if (NDIPV6_DEBUG)
1350                 printf
1351                                 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1352
1353         if (1) {
1354                 /* print entire hash table */
1355                 printf
1356                                 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1357                                  new_nd_data->eth_addr.addr_bytes[0],
1358                                  new_nd_data->eth_addr.addr_bytes[1],
1359                                  new_nd_data->eth_addr.addr_bytes[2],
1360                                  new_nd_data->eth_addr.addr_bytes[3],
1361                                  new_nd_data->eth_addr.addr_bytes[4],
1362                                  new_nd_data->eth_addr.addr_bytes[5], portid);
1363                 RTE_LOG(INFO, LIBARP, "\tipv6=");
1364                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1365                         new_nd_data->ipv6[i] = ipv6[i];
1366                         RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1367                                 new_nd_data->ipv6[i + 1]);
1368                 }
1369
1370                 RTE_LOG(INFO, LIBARP, "\n");
1371
1372                 puts("");
1373         }
1374 }
1375
1376 void print_pkt1(struct rte_mbuf *pkt)
1377 {
1378         uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1379         int i = 0, j = 0;
1380         RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1381         for (i = 0; i < 20; i++) {
1382                 for (j = 0; j < 20; j++)
1383                         RTE_LOG(INFO, LIBARP, "%02x ", rd[(20 * i) + j]);
1384                 RTE_LOG(INFO, LIBARP, "\n");
1385         }
1386 }
1387
1388 struct ether_addr broadcast_ether_addr = {
1389         .addr_bytes[0] = 0xFF,
1390         .addr_bytes[1] = 0xFF,
1391         .addr_bytes[2] = 0xFF,
1392         .addr_bytes[3] = 0xFF,
1393         .addr_bytes[4] = 0xFF,
1394         .addr_bytes[5] = 0xFF,
1395 };
1396
1397 static const struct ether_addr null_ether_addr = {
1398         .addr_bytes[0] = 0x00,
1399         .addr_bytes[1] = 0x00,
1400         .addr_bytes[2] = 0x00,
1401         .addr_bytes[3] = 0x00,
1402         .addr_bytes[4] = 0x00,
1403         .addr_bytes[5] = 0x00,
1404 };
1405
1406 #define MAX_NUM_MAC_ADDRESS 16
1407 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1408 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1409 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1410 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1411 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1412 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1413 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1414 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1415 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1416 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1417 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1418 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1419 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1420 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1421 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1422 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1423 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1424 };
1425
1426 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1427 {
1428         return &link_hw_addr[out_port];
1429 }
1430
1431 void request_arp(uint8_t port_id, uint32_t ip)
1432 {
1433
1434         struct ether_hdr *eth_h;
1435         struct arp_hdr *arp_h;
1436
1437         l2_phy_interface_t *link;
1438         link = ifm_get_port(port_id);
1439         struct rte_mbuf *arp_pkt = lib_arp_pkt;
1440
1441         if (arp_pkt == NULL) {
1442                 if (ARPICMP_DEBUG)
1443                         RTE_LOG(INFO, LIBARP,
1444                                 "Error allocating arp_pkt rte_mbuf\n");
1445                 return;
1446         }
1447
1448         eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1449
1450         ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
1451         ether_addr_copy((struct ether_addr *)
1452                         &link->macaddr[0], &eth_h->s_addr);
1453         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1454
1455         arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1456         arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1457         arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1458         arp_h->arp_hln = ETHER_ADDR_LEN;
1459         arp_h->arp_pln = sizeof(uint32_t);
1460         arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1461
1462         ether_addr_copy((struct ether_addr *)
1463                         &link->macaddr[0], &arp_h->arp_data.arp_sha);
1464         if (link && link->ipv4_list) {
1465                 arp_h->arp_data.arp_sip =
1466                                 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1467         }
1468         ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1469         arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1470         if (ARPICMP_DEBUG)
1471                 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1472                         arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1473         // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1474         arp_pkt->pkt_len = 42;
1475         arp_pkt->data_len = 42;
1476
1477         if (ARPICMP_DEBUG) {
1478                 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1479                 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1480         }
1481         if (link)
1482                 link->transmit_single_pkt(link, arp_pkt);
1483 }
1484
1485 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1486 {
1487         struct ether_hdr *eth_h;
1488         struct ipv4_hdr *ip_h;
1489         struct icmp_hdr *icmp_h;
1490         l2_phy_interface_t *port = ifm_get_port(port_id);
1491
1492         struct rte_mbuf *icmp_pkt = lib_arp_pkt;
1493         if (icmp_pkt == NULL) {
1494                 if (ARPICMP_DEBUG)
1495                         RTE_LOG(INFO, LIBARP,
1496                                 "Error allocating icmp_pkt rte_mbuf\n");
1497                 return NULL;
1498         }
1499
1500         eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1501
1502         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1503         icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1504
1505         ip_h->version_ihl = IP_VHL_DEF;
1506         ip_h->type_of_service = 0;
1507         ip_h->total_length =
1508                         rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1509         ip_h->packet_id = 0xaabb;
1510         ip_h->fragment_offset = 0x0000;
1511         ip_h->time_to_live = 64;
1512         ip_h->next_proto_id = IPPROTO_ICMP;
1513         if (port && port->ipv4_list)
1514                 ip_h->src_addr =
1515                                 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1516         ip_h->dst_addr = rte_cpu_to_be_32(ip);
1517
1518         ip_h->hdr_checksum = 0;
1519         ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1520
1521         icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1522         icmp_h->icmp_code = 0;
1523         icmp_h->icmp_ident = 0xdead;
1524         icmp_h->icmp_seq_nb = 0xbeef;
1525
1526         icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1527
1528         icmp_pkt->pkt_len =
1529                         sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1530                         sizeof(struct icmp_hdr);
1531         icmp_pkt->data_len = icmp_pkt->pkt_len;
1532
1533         print_mbuf("TX", 0, icmp_pkt, __LINE__);
1534
1535         return icmp_pkt;
1536 }
1537
1538 #if 0
1539 /**
1540  * Function to send ICMP dest unreachable msg
1541  *
1542  */
1543 struct rte_mbuf *send_icmp_dest_unreachable_msg(uint32_t src_ip,
1544                                                 uint32_t dest_ip)
1545 {
1546         struct ether_hdr *eth_h;
1547         struct ipv4_hdr *ip_h;
1548         struct icmp_hdr *icmp_h;
1549         struct rte_mbuf *icmp_pkt = lib_arp_pkt;
1550
1551         if (icmp_pkt == NULL) {
1552                 if (ARPICMP_DEBUG)
1553                         RTE_LOG(INFO, LIBARP,
1554                                 "Error allocating icmp_pkt rte_mbuf\n");
1555                 return NULL;
1556         }
1557
1558         eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1559         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1560         icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1561
1562         ip_h->version_ihl = IP_VHL_DEF;
1563         ip_h->type_of_service = 0;
1564         ip_h->total_length =
1565                         rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1566         ip_h->packet_id = 0xaabb;
1567         ip_h->fragment_offset = 0x0000;
1568         ip_h->time_to_live = 64;
1569         ip_h->next_proto_id = 1;
1570
1571         ip_h->dst_addr = rte_bswap32(dest_ip);
1572         ip_h->src_addr = rte_bswap32(src_ip);
1573
1574         ip_h->hdr_checksum = 0;
1575         ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1576
1577         icmp_h->icmp_type = 3;  /* Destination Unreachable */
1578         icmp_h->icmp_code = 13; /* Communication administratively prohibited */
1579
1580         icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1581
1582         icmp_pkt->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1583                         sizeof(struct icmp_hdr);
1584         icmp_pkt->data_len = icmp_pkt->pkt_len;
1585
1586         return icmp_pkt;
1587 }
1588 #endif
1589 void
1590 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1591                                 uint64_t pkt_mask, l2_phy_interface_t *port)
1592 {
1593         RTE_SET_USED(pkt_num);
1594         if (ARPICMP_DEBUG)
1595                 RTE_LOG(INFO, LIBARP,
1596                         "============ARP ENTRY================\n");
1597         if (pkt_mask) {
1598                 if (ARPICMP_DEBUG)
1599                         RTE_LOG(INFO, LIBARP,
1600                                 "============ARP PROCESS================\n");
1601         }
1602
1603         uint64_t pkts_for_process = pkt_mask;
1604         for (; pkts_for_process;) {
1605 /**< process only valid packets. */
1606                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1607                 uint64_t pkts_mask = 1LLU << pos;    /** <bitmask representing only this packet. */
1608                 pkts_for_process &= ~pkts_mask;                         /** <remove this packet from the mask. */
1609                 process_arpicmp_pkt(pkt[pos], port);
1610         }
1611
1612 }
1613
1614 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1615 {
1616         uint8_t in_port_id = pkt->port;
1617         struct ether_hdr *eth_h;
1618         struct arp_hdr *arp_h;
1619         struct ipv4_hdr *ip_h;
1620         struct icmp_hdr *icmp_h;
1621
1622         uint32_t cksum;
1623         uint32_t ip_addr;
1624
1625         uint32_t req_tip;
1626
1627         eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1628
1629         if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1630                 if (ARPICMP_DEBUG)
1631                         RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1632                                 __FUNCTION__, port->pmdid, __LINE__);
1633                 arp_h =
1634                                 (struct arp_hdr *)((char *)eth_h +
1635                                                          sizeof(struct ether_hdr));
1636                 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1637                         RTE_LOG(INFO, LIBARP,
1638                                 "Invalid hardware format of hardware address - not processing ARP req\n");
1639                 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1640                         RTE_LOG(INFO, LIBARP,
1641                                 "Invalid protocol address format - not processing ARP req\n");
1642                 else if (arp_h->arp_hln != 6)
1643                         RTE_LOG(INFO, LIBARP,
1644                                 "Invalid hardware address length - not processing ARP req\n");
1645                 else if (arp_h->arp_pln != 4)
1646                         RTE_LOG(INFO, LIBARP,
1647                                 "Invalid protocol address length - not processing ARP req\n");
1648                 else {
1649                         if (port->ipv4_list == NULL) {
1650                                 RTE_LOG(INFO, LIBARP,
1651                                         "Ports IPV4 List is NULL.. Unable to Process\n");
1652                                 return;
1653                         }
1654
1655                         if (arp_h->arp_data.arp_tip !=
1656                                         ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1657                                 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1658                                         populate_arp_entry(
1659                                                         (struct ether_addr *)&arp_h->arp_data.arp_sha,
1660                                                         rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1661                                                         in_port_id,
1662                                                         DYNAMIC_ARP);
1663
1664                                 } else {
1665                                         RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1666                                 }
1667                         }
1668                         /// revise conditionals to allow processing of requests with target ip = this ip and
1669                         //                               processing of replies to destination ip = this ip
1670                         else if (arp_h->arp_op ==
1671                                  rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1672                                 if (ARPICMP_DEBUG) {
1673                                         RTE_LOG(INFO, LIBARP,
1674                                                 "%s, portid %u. Line %d\n\r",
1675                                                 __FUNCTION__, port->pmdid,
1676                                                 __LINE__);
1677
1678                                         RTE_LOG(INFO, LIBARP,
1679                                                 "arp_op %d, ARP_OP_REQUEST %d\n",
1680                                                 arp_h->arp_op,
1681                                                 rte_cpu_to_be_16
1682                                                 (ARP_OP_REQUEST));
1683                                         print_mbuf("RX", in_port_id, pkt,
1684                                                          __LINE__);
1685                                 }
1686
1687                                 populate_arp_entry((struct ether_addr *)
1688                                                          &arp_h->arp_data.arp_sha,
1689                                                          rte_cpu_to_be_32
1690                                                          (arp_h->arp_data.arp_sip),
1691                                                          in_port_id, DYNAMIC_ARP);
1692
1693                                 /*build reply */
1694                                 req_tip = arp_h->arp_data.arp_tip;
1695                                 ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
1696                                 ether_addr_copy((struct ether_addr *)&port->macaddr[0], &eth_h->s_addr);  /**< set sender mac address*/
1697                                 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1698                                 ether_addr_copy(&eth_h->s_addr,
1699                                                 &arp_h->arp_data.arp_sha);
1700                                 arp_h->arp_data.arp_tip =
1701                                                 arp_h->arp_data.arp_sip;
1702                                 arp_h->arp_data.arp_sip = req_tip;
1703                                 ether_addr_copy(&eth_h->d_addr,
1704                                                 &arp_h->arp_data.arp_tha);
1705
1706                                 if (ARPICMP_DEBUG)
1707                                         print_mbuf("TX ARP REPLY PKT",
1708                                                          port->pmdid, pkt, __LINE__);
1709                                 port->transmit_bulk_pkts(port, &pkt, 1);
1710                                 if (ARPICMP_DEBUG)
1711                                         print_mbuf("TX", port->pmdid, pkt,
1712                                                          __LINE__);
1713
1714                                 return;
1715                         } else if (arp_h->arp_op ==
1716                                          rte_cpu_to_be_16(ARP_OP_REPLY)) {
1717                                 if (ARPICMP_DEBUG) {
1718                                         RTE_LOG(INFO, LIBARP,
1719                                                 "ARP_OP_REPLY received");
1720                                         print_mbuf("RX", port->pmdid, pkt,
1721                                                          __LINE__);
1722                                 }
1723                                 populate_arp_entry((struct ether_addr *)
1724                                                          &arp_h->arp_data.arp_sha,
1725                                                          rte_bswap32(arp_h->
1726                                                                                  arp_data.arp_sip),
1727                                                          in_port_id, DYNAMIC_ARP);
1728
1729                                 return;
1730                         } else {
1731                                 if (ARPICMP_DEBUG)
1732                                         RTE_LOG(INFO, LIBARP,
1733                                                 "Invalid ARP opcode - not processing ARP req %x\n",
1734                                                 arp_h->arp_op);
1735                         }
1736                 }
1737
1738                 rte_pktmbuf_free(pkt);
1739         } else {
1740                 ip_h =
1741                                 (struct ipv4_hdr *)((char *)eth_h +
1742                                         sizeof(struct ether_hdr));
1743                 icmp_h =
1744                                 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1745
1746                 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1747
1748                         if (ip_h->next_proto_id != IPPROTO_ICMP) {
1749                                 if (ARPICMP_DEBUG) {
1750                                         RTE_LOG(INFO, LIBARP,
1751                                                 "IP protocol ID is not set to ICMP - discarding\n");
1752                                 }
1753                         } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1754                                 if (ARPICMP_DEBUG) {
1755                                         RTE_LOG(INFO, LIBARP,
1756                                                 "IP version other than 4 - discarding\n");
1757                                 }
1758                         } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1759                                 if (ARPICMP_DEBUG) {
1760                                         RTE_LOG(INFO, LIBARP,
1761                                                 "Unknown IHL - discarding\n");
1762                                 }
1763                         } else {
1764                                 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1765                                                 && icmp_h->icmp_code == 0) {
1766                                         if (ARPICMP_DEBUG)
1767                                                 print_mbuf("RX", in_port_id,
1768                                                                  pkt, __LINE__);
1769
1770                                         ip_addr = ip_h->src_addr;
1771                                         ether_addr_copy(&eth_h->s_addr,
1772                                                         &eth_h->d_addr);
1773                                         ether_addr_copy((struct ether_addr *)
1774                                                         &port->macaddr[0],
1775                                                         &eth_h->s_addr);
1776                                         if (ARPICMP_DEBUG)
1777                                                 RTE_LOG(INFO, LIBARP,
1778                                                         "%s, portid %u. Line %d\n\r",
1779                                                         __FUNCTION__,
1780                                                         port->pmdid, __LINE__);
1781
1782                                         if (is_multicast_ipv4_addr
1783                                                         (ip_h->dst_addr)) {
1784                                                 uint32_t ip_src;
1785
1786                                                 ip_src =
1787                                                                 rte_be_to_cpu_32(ip_addr);
1788                                                 if ((ip_src & 0x00000003) == 1)
1789                                                         ip_src =
1790                                                                         (ip_src &
1791                                                                          0xFFFFFFFC) |
1792                                                                         0x00000002;
1793                                                 else
1794                                                         ip_src =
1795                                                                         (ip_src &
1796                                                                          0xFFFFFFFC) |
1797                                                                         0x00000001;
1798                                                 ip_h->src_addr =
1799                                                                 rte_cpu_to_be_32(ip_src);
1800                                                 ip_h->dst_addr = ip_addr;
1801
1802                                                 ip_h->hdr_checksum = 0;
1803                                                 ip_h->hdr_checksum =
1804                                                                 ~rte_raw_cksum(ip_h,
1805                                                                          sizeof(struct
1806                                                                                 ipv4_hdr));
1807                                         } else {
1808                                                 if (ARPICMP_DEBUG)
1809                                                         RTE_LOG(INFO, LIBARP,
1810                                                                 "%s, portid %u. Line %d\n\r",
1811                                                                 __FUNCTION__,
1812                                                                 port->pmdid,
1813                                                                 __LINE__);
1814                                                 ip_h->src_addr = ip_h->dst_addr;
1815                                                 ip_h->dst_addr = ip_addr;
1816                                         }
1817
1818                                         icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1819                                         cksum = ~icmp_h->icmp_cksum & 0xffff;
1820                                         cksum +=
1821                                                         ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1822                                                         0xffff;
1823                                         cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1824                                         cksum =
1825                                                         (cksum & 0xffff) + (cksum >> 16);
1826                                         cksum =
1827                                                         (cksum & 0xffff) + (cksum >> 16);
1828                                         icmp_h->icmp_cksum = ~cksum;
1829
1830                                         if (ARPICMP_DEBUG)
1831                                                 print_mbuf
1832                                                                 ("TX ICMP ECHO REPLY PKT",
1833                                                                  in_port_id, pkt, __LINE__);
1834                                         port->transmit_bulk_pkts(port, &pkt, 1);
1835                                         if (ARPICMP_DEBUG)
1836                                                 print_mbuf("TX", port->pmdid,
1837                                                                  pkt, __LINE__);
1838
1839                                         return;
1840                                 } else if (icmp_h->icmp_type ==
1841                                                  IP_ICMP_ECHO_REPLY
1842                                                  && icmp_h->icmp_code == 0) {
1843                                         if (ARPICMP_DEBUG)
1844                                                 print_mbuf("RX", in_port_id,
1845                                                                  pkt, __LINE__);
1846
1847                                         struct arp_key_ipv4 arp_key;
1848                                         arp_key.port_id = in_port_id;
1849                                         arp_key.ip =
1850                                                         rte_bswap32(ip_h->src_addr);
1851                                         arp_key.filler1 = 0;
1852                                         arp_key.filler2 = 0;
1853                                         arp_key.filler3 = 0;
1854
1855                                         struct arp_entry_data *arp_entry =
1856                                                         retrieve_arp_entry(arp_key);
1857                                         if (arp_entry == NULL) {
1858                                                 if (ARPICMP_DEBUG)
1859                                                         RTE_LOG(INFO, LIBARP,
1860                                                                 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1861                                                                 arp_key.ip,
1862                                                                 arp_key.port_id);
1863                                                 return;
1864                                         }
1865                                         arp_entry->status = COMPLETE;
1866                                 }
1867                         }
1868                 }
1869
1870                 rte_pktmbuf_free(pkt);
1871         }
1872 }
1873
1874 /* int
1875  * inet_pton(af, src, dst)
1876  *      convert from presentation format (which usually means ASCII printable)
1877  *      to network format (which is usually some kind of binary format).
1878  * return:
1879  *      1 if the address was valid for the specified address family
1880  *      0 if the address wasn't valid (`dst' is untouched in this case)
1881  *      -1 if some other error occurred (`dst' is untouched in this case, too)
1882  * author:
1883  *      Paul Vixie, 1996.
1884  */
1885 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
1886 {
1887         switch (af) {
1888         case AF_INET:
1889                 return inet_pton_ipv4(src, dst);
1890         case AF_INET6:
1891                 return inet_pton_ipv6(src, dst);
1892         default:
1893                 errno = EAFNOSUPPORT;
1894                 return -1;
1895         }
1896         /* NOTREACHED */
1897 }
1898
1899 /* int
1900  * inet_pton_ipv4(src, dst)
1901  *      like inet_aton() but without all the hexadecimal and shorthand.
1902  * return:
1903  *      1 if `src' is a valid dotted quad, else 0.
1904  * notice:
1905  *      does not touch `dst' unless it's returning 1.
1906  * author:
1907  *      Paul Vixie, 1996.
1908  */
1909 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1910 {
1911         static const char digits[] = "0123456789";
1912         int saw_digit, octets, ch;
1913         unsigned char tmp[INADDRSZ], *tp;
1914
1915         saw_digit = 0;
1916         octets = 0;
1917         *(tp = tmp) = 0;
1918         while ((ch = *src++) != '\0') {
1919                 const char *pch;
1920
1921                 pch = strchr(digits, ch);
1922                 if (pch != NULL) {
1923                         unsigned int new = *tp * 10 + (pch - digits);
1924
1925                         if (new > 255)
1926                                 return 0;
1927                         if (!saw_digit) {
1928                                 if (++octets > 4)
1929                                         return 0;
1930                                 saw_digit = 1;
1931                         }
1932                         *tp = (unsigned char)new;
1933                 } else if (ch == '.' && saw_digit) {
1934                         if (octets == 4)
1935                                 return 0;
1936                         *++tp = 0;
1937                         saw_digit = 0;
1938                 } else
1939                         return 0;
1940         }
1941         if (octets < 4)
1942                 return 0;
1943
1944         memcpy(dst, tmp, INADDRSZ);
1945         return 1;
1946 }
1947
1948 /* int
1949  * inet_pton_ipv6(src, dst)
1950  *      convert presentation level address to network order binary form.
1951  * return:
1952  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
1953  * notice:
1954  *      (1) does not touch `dst' unless it's returning 1.
1955  *      (2) :: in a full address is silently ignored.
1956  * credit:
1957  *      inspired by Mark Andrews.
1958  * author:
1959  *      Paul Vixie, 1996.
1960  */
1961 static int inet_pton_ipv6(const char *src, unsigned char *dst)
1962 {
1963         static const char xdigits_l[] = "0123456789abcdef",
1964                         xdigits_u[] = "0123456789ABCDEF";
1965         unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
1966         const char *xdigits = 0, *curtok = 0;
1967         int ch = 0, saw_xdigit = 0, count_xdigit = 0;
1968         unsigned int val = 0;
1969         unsigned int dbloct_count = 0;
1970
1971         memset((tp = tmp), '\0', IN6ADDRSZ);
1972         endp = tp + IN6ADDRSZ;
1973         colonp = NULL;
1974         /* Leading :: requires some special handling. */
1975         if (*src == ':')
1976                 if (*++src != ':')
1977                         return 0;
1978         curtok = src;
1979         saw_xdigit = count_xdigit = 0;
1980         val = 0;
1981
1982         while ((ch = *src++) != '\0') {
1983                 const char *pch;
1984
1985                 pch = strchr((xdigits = xdigits_l), ch);
1986                 if (pch == NULL)
1987                         pch = strchr((xdigits = xdigits_u), ch);
1988                 if (pch != NULL) {
1989                         if (count_xdigit >= 4)
1990                                 return 0;
1991                         val <<= 4;
1992                         val |= (pch - xdigits);
1993                         if (val > 0xffff)
1994                                 return 0;
1995                         saw_xdigit = 1;
1996                         count_xdigit++;
1997                         continue;
1998                 }
1999                 if (ch == ':') {
2000                         curtok = src;
2001                         if (!saw_xdigit) {
2002                                 if (colonp)
2003                                         return 0;
2004                                 colonp = tp;
2005                                 continue;
2006                         } else if (*src == '\0') {
2007                                 return 0;
2008                         }
2009                         if (tp + sizeof(int16_t) > endp)
2010                                 return 0;
2011                         *tp++ = (unsigned char)((val >> 8) & 0xff);
2012                         *tp++ = (unsigned char)(val & 0xff);
2013                         saw_xdigit = 0;
2014                         count_xdigit = 0;
2015                         val = 0;
2016                         dbloct_count++;
2017                         continue;
2018                 }
2019                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2020                                 inet_pton_ipv4(curtok, tp) > 0) {
2021                         tp += INADDRSZ;
2022                         saw_xdigit = 0;
2023                         dbloct_count += 2;
2024                         break;  /* '\0' was seen by inet_pton4(). */
2025                 }
2026                 return 0;
2027         }
2028         if (saw_xdigit) {
2029                 if (tp + sizeof(int16_t) > endp)
2030                         return 0;
2031                 *tp++ = (unsigned char)((val >> 8) & 0xff);
2032                 *tp++ = (unsigned char)(val & 0xff);
2033                 dbloct_count++;
2034         }
2035         if (colonp != NULL) {
2036                 /* if we already have 8 double octets, having a colon means error */
2037                 if (dbloct_count == 8)
2038                         return 0;
2039
2040                 /*
2041                  * Since some memmove()'s erroneously fail to handle
2042                  * overlapping regions, we'll do the shift by hand.
2043                  */
2044                 const int n = tp - colonp;
2045                 int i;
2046
2047                 for (i = 1; i <= n; i++) {
2048                         endp[-i] = colonp[n - i];
2049                         colonp[n - i] = 0;
2050                 }
2051                 tp = endp;
2052         }
2053         if (tp != endp)
2054                 return 0;
2055         memcpy(dst, tmp, IN6ADDRSZ);
2056         return 1;
2057 }
2058
2059 static int arp_parse_args(struct pipeline_params *params)
2060 {
2061         uint32_t arp_route_tbl_present = 0;
2062         uint32_t nd_route_tbl_present = 0;
2063         uint32_t ports_mac_list_present = 0;
2064         uint32_t numArg;
2065         uint32_t n_vnf_threads_present = 0;
2066
2067         uint32_t pktq_in_prv_present = 0;
2068         uint32_t prv_to_pub_map_present = 0;
2069
2070         uint8_t n_prv_in_port = 0;
2071         int i;
2072         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2073                 in_port_dir_a[i] = 0;   //make all RX ports ingress initially
2074                 prv_to_pub_map[i] = 0xff;
2075                 pub_to_prv_map[i] = 0xff;
2076         }
2077
2078         RTE_SET_USED(ports_mac_list_present);
2079         RTE_SET_USED(nd_route_tbl_present);
2080         RTE_SET_USED(arp_route_tbl_present);
2081         for (numArg = 0; numArg < params->n_args; numArg++) {
2082                 char *arg_name = params->args_name[numArg];
2083                 char *arg_value = params->args_value[numArg];
2084
2085                 /* arp timer expiry */
2086                 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2087                         arp_timeout = atoi(arg_value);
2088                 }
2089
2090                 /* pktq_in_prv */
2091                 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2092                         if (pktq_in_prv_present) {
2093                                 printf
2094                                                 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2095                                 return -1;
2096                         }
2097                         pktq_in_prv_present = 1;
2098
2099                         int rxport = 0, j = 0;
2100                         char phy_port_num[5];
2101                         char *token = strtok(arg_value, "RXQ");
2102                         while (token) {
2103                                 j = 0;
2104                                 while ((j < 4) && (token[j] != '.')) {
2105                                         phy_port_num[j] = token[j];
2106                                         j++;
2107                                 }
2108                                 phy_port_num[j] = '\0';
2109                                 rxport = atoi(phy_port_num);
2110                                 prv_in_port_a[n_prv_in_port++] = rxport;
2111                                 if (rxport < 0)
2112                                         rxport = 0;
2113                                 printf
2114                                                 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2115                                                  token, phy_port_num, rxport);
2116                                 prv_in_port_a[n_prv_in_port++] = rxport;
2117                                 if(rxport < PIPELINE_MAX_PORT_IN)
2118                                 in_port_dir_a[rxport] = 1;      // set rxport egress
2119                                 token = strtok(NULL, "RXQ");
2120                         }
2121
2122                         if (n_prv_in_port == 0) {
2123                                 printf
2124                                                 ("VNF common parse error - no prv RX phy port\n");
2125                                 return -1;
2126                         }
2127                         continue;
2128                 }
2129
2130                 /* prv_to_pub_map */
2131                 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2132                         if (prv_to_pub_map_present) {
2133                                 printf
2134                                                 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2135                                 return -1;
2136                         }
2137                         prv_to_pub_map_present = 1;
2138
2139                         int rxport = 0, txport = 0, j = 0, k = 0;
2140                         char rx_phy_port_num[5];
2141                         char tx_phy_port_num[5];
2142                         char *token = strtok(arg_value, "(");
2143                         while (token) {
2144                                 j = 0;
2145                                 while ((j < 4) && (token[j] != ',')) {
2146                                         rx_phy_port_num[j] = token[j];
2147                                         j++;
2148                                 }
2149                                 rx_phy_port_num[j] = '\0';
2150                                 rxport = atoi(rx_phy_port_num);
2151                                 if (rxport < 0)
2152                                         rxport = 0;
2153
2154                                 j++;
2155                                 k = 0;
2156                                 while ((k < 4) && (token[j + k] != ')')) {
2157                                         tx_phy_port_num[k] = token[j + k];
2158                                         k++;
2159                                 }
2160                                 tx_phy_port_num[k] = '\0';
2161                                 txport = atoi(tx_phy_port_num);
2162                                 if (txport < 0)
2163                                         txport = 0;
2164
2165                                 RTE_LOG(INFO, LIBARP, "token: %s,"
2166                                         "rx_phy_port_str: %s, phy_port_num %d,"
2167                                         "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2168                                         token, rx_phy_port_num, rxport,
2169                                         tx_phy_port_num, txport);
2170
2171                                 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2172                                                 (txport >= PIPELINE_MAX_PORT_IN) ||
2173                                                 (in_port_dir_a[rxport] != 1)) {
2174                                         printf
2175                                                         ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2176                                                          rxport, txport,
2177                                                          in_port_dir_a[rxport]);
2178                                         return -1;
2179                                 }
2180
2181                                 prv_to_pub_map[rxport] = txport;
2182                                 pub_to_prv_map[txport] = rxport;
2183                                 token = strtok(NULL, "(");
2184                         }
2185
2186                         continue;
2187                 }
2188                 //n_vnf_threads = 3
2189                 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2190                         if (n_vnf_threads_present)
2191                                 return -1;
2192                         n_vnf_threads_present = 1;
2193                         trim(arg_value);
2194                         num_vnf_threads = atoi(arg_value);
2195                         if (num_vnf_threads <= 0) {
2196                                 RTE_LOG(INFO, LIBARP,
2197                                         "n_vnf_threads is invalid\n");
2198                                 return -1;
2199                         }
2200                         RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2201                                 num_vnf_threads);
2202                 }
2203
2204                 /* lib_arp_debug */
2205                 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2206                         ARPICMP_DEBUG = atoi(arg_value);
2207
2208                         continue;
2209                 }
2210
2211                 /* ports_mac_list */
2212                 if (strcmp(arg_name, "ports_mac_list") == 0) {
2213                         ports_mac_list_present = 1;
2214
2215                         uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
2216
2217                         char byteStr[MAC_NUM_BYTES][3];
2218                         uint32_t byte[MAC_NUM_BYTES];
2219
2220                         char *token = strtok(arg_value, " ");
2221                         while (token) {
2222                                 k = 0;
2223                                 for (i = 0; i < MAC_NUM_BYTES; i++) {
2224                                         for (j = 0; j < 2; j++) {
2225                                                 byteStr[i][j] = token[k++];
2226                                         }
2227                                         byteStr[i][j] = '\0';
2228                                         k++;
2229                                 }
2230
2231                                 for (i = 0; i < MAC_NUM_BYTES; i++) {
2232                                         byte[i] = strtoul(byteStr[i], NULL, 16);
2233                                 }
2234
2235                                 if (ARPICMP_DEBUG) {
2236                                         RTE_LOG(INFO, LIBARP, "token: %s",
2237                                                 token);
2238                                         for (i = 0; i < MAC_NUM_BYTES; i++)
2239                                                 RTE_LOG(INFO, LIBARP,
2240                                                         ", byte[%u] %u", i,
2241                                                         byte[i]);
2242                                         RTE_LOG(INFO, LIBARP, "\n");
2243                                 }
2244                                 //Populate the static arp_route_table
2245                                 for (i = 0; i < MAC_NUM_BYTES; i++)
2246                                         link_hw_addr
2247                                                         [link_hw_addr_array_idx].addr_bytes
2248                                                         [i] = byte[i];
2249
2250                                 link_hw_addr_array_idx++;
2251                                 token = strtok(NULL, " ");
2252                         }
2253
2254                         continue;
2255                 }
2256
2257                 /* arp_route_tbl */
2258                 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2259                         arp_route_tbl_present = 1;
2260
2261                         uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2262                                         0, i = 0, j = 0, k = 0, l = 0;
2263                         uint32_t arp_route_tbl_str_max_len = 10;
2264                         char dest_ip_str[arp_route_tbl_str_max_len];
2265                         char mask_str[arp_route_tbl_str_max_len];
2266                         char tx_port_str[arp_route_tbl_str_max_len];
2267                         char nh_ip_str[arp_route_tbl_str_max_len];
2268                         char *token = strtok(arg_value, "(");
2269                         while (token) {
2270                                 i = 0;
2271                                 while ((i < (arp_route_tbl_str_max_len - 1))
2272                                                          && (token[i] != ',')) {
2273                                         dest_ip_str[i] = token[i];
2274                                         i++;
2275                                 }
2276                                 dest_ip_str[i] = '\0';
2277                                 dest_ip = strtoul(dest_ip_str, NULL, 16);
2278
2279                                 i++;
2280                                 j = 0;
2281                                 while ((j < (arp_route_tbl_str_max_len - 1))
2282                                                          && (token[i + j] != ',')) {
2283                                         mask_str[j] = token[i + j];
2284                                         j++;
2285                                 }
2286                                 mask_str[j] = '\0';
2287                                 mask = strtoul(mask_str, NULL, 16);
2288
2289                                 j++;
2290                                 k = 0;
2291                                 while ((k < (arp_route_tbl_str_max_len - 1))
2292                                                          && (token[i + j + k] != ',')) {
2293                                         tx_port_str[k] = token[i + j + k];
2294                                         k++;
2295                                 }
2296                                 tx_port_str[k] = '\0';
2297                                 tx_port = strtoul(tx_port_str, NULL, 16);       //atoi(tx_port_str);
2298
2299                                 k++;
2300                                 l = 0;
2301                                 while ((l < (arp_route_tbl_str_max_len - 1))
2302                                                          && (token[i + j + k + l] != ')')) {
2303                                         nh_ip_str[l] = token[i + j + k + l];
2304                                         l++;
2305                                 }
2306                                 nh_ip_str[l] = '\0';
2307                                 nh_ip = strtoul(nh_ip_str, NULL, 16);   //atoi(nh_ip_str);
2308
2309                                 if (1) {
2310                                         RTE_LOG(INFO, LIBARP, "token: %s, "
2311                                                 "dest_ip_str: %s, dest_ip %u, "
2312                                                 "mask_str: %s, mask %u, "
2313                                                 "tx_port_str: %s, tx_port %u, "
2314                                                 "nh_ip_str: %s, nh_ip %u\n",
2315                                                 token, dest_ip_str, dest_ip,
2316                                                 mask_str, mask, tx_port_str,
2317                                                 tx_port, nh_ip_str, nh_ip);
2318                                 }
2319
2320                                 /*  if (tx_port >= params->n_ports_out)
2321                                          {
2322                                          RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2323                                          tx_port, params->n_ports_out);
2324                                          return -1;
2325                                          }
2326                                  */
2327                                 //Populate the static arp_route_table
2328                                 lib_arp_route_table[arp_route_tbl_index].ip =
2329                                                 dest_ip;
2330                                 lib_arp_route_table[arp_route_tbl_index].mask =
2331                                                 mask;
2332                                 lib_arp_route_table[arp_route_tbl_index].port =
2333                                                 tx_port;
2334                                 lib_arp_route_table[arp_route_tbl_index].nh =
2335                                                 nh_ip;
2336                                 arp_route_tbl_index++;
2337                                 token = strtok(NULL, "(");
2338                         }
2339
2340                         continue;
2341                 }
2342                 /*ND IPv6 */
2343                 /* nd_route_tbl */
2344                 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2345                         nd_route_tbl_present = 1;
2346
2347                         uint8_t dest_ipv6[16], depth = 0, tx_port =
2348                                         0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2349                         uint8_t nd_route_tbl_str_max_len = 128; //64;
2350                         char dest_ipv6_str[nd_route_tbl_str_max_len];
2351                         char depth_str[nd_route_tbl_str_max_len];
2352                         char tx_port_str[nd_route_tbl_str_max_len];
2353                         char nh_ipv6_str[nd_route_tbl_str_max_len];
2354                         char *token = strtok(arg_value, "(");
2355                         while (token) {
2356                                 i = 0;
2357                                 while ((i < (nd_route_tbl_str_max_len - 1))
2358                                                          && (token[i] != ',')) {
2359                                         dest_ipv6_str[i] = token[i];
2360                                         i++;
2361                                 }
2362                                 dest_ipv6_str[i] = '\0';
2363                                 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2364                                                         &dest_ipv6);
2365
2366                                 i++;
2367                                 j = 0;
2368                                 while ((j < (nd_route_tbl_str_max_len - 1))
2369                                                          && (token[i + j] != ',')) {
2370                                         depth_str[j] = token[i + j];
2371                                         j++;
2372                                 }
2373                                 depth_str[j] = '\0';
2374                                 //converting string char to integer
2375                                 int s;
2376                                 for (s = 0; depth_str[s] != '\0'; ++s)
2377                                         depth = depth * 10 + depth_str[s] - '0';
2378
2379                                 j++;
2380                                 k = 0;
2381                                 while ((k < (nd_route_tbl_str_max_len - 1))
2382                                                          && (token[i + j + k] != ',')) {
2383                                         tx_port_str[k] = token[i + j + k];
2384                                         k++;
2385                                 }
2386                                 tx_port_str[k] = '\0';
2387                                 tx_port = strtoul(tx_port_str, NULL, 16);       //atoi(tx_port_str);
2388
2389                                 k++;
2390                                 l = 0;
2391                                 while ((l < (nd_route_tbl_str_max_len - 1))
2392                                                          && (token[i + j + k + l] != ')')) {
2393                                         nh_ipv6_str[l] = token[i + j + k + l];
2394                                         l++;
2395                                 }
2396                                 nh_ipv6_str[l] = '\0';
2397                                 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2398                                                         &nh_ipv6);
2399
2400                                 //Populate the static arp_route_table
2401                                 for (i = 0; i < 16; i++) {
2402                                         lib_nd_route_table
2403                                                         [nd_route_tbl_index].ipv6[i] =
2404                                                         dest_ipv6[i];
2405                                         lib_nd_route_table
2406                                                         [nd_route_tbl_index].nhipv6[i] =
2407                                                         nh_ipv6[i];
2408                                 }
2409                                 lib_nd_route_table[nd_route_tbl_index].depth =
2410                                                 depth;
2411                                 lib_nd_route_table[nd_route_tbl_index].port =
2412                                                 tx_port;
2413
2414                                 nd_route_tbl_index++;
2415                                 token = strtok(NULL, "(");
2416                         }
2417
2418                         continue;
2419                 }
2420                 /* any other */
2421                 //return -1;
2422         }
2423         /* Check that mandatory arguments are present */
2424         /*
2425                  if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2426                  RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2427                  RTE_LOG(INFO, LIBARP,"%d, %d \n",
2428                  arp_route_tbl_present, ports_mac_list_present);
2429                  return -1;
2430                  }
2431          */
2432
2433         return 0;
2434 }
2435
2436 void lib_arp_init(struct pipeline_params *params,
2437                         __rte_unused struct app_params *app)
2438 {
2439
2440         RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2441
2442         /* Parse arguments */
2443         if (arp_parse_args(params)) {
2444                 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2445                 return;
2446         }
2447
2448         /* create the arp_icmp mbuf rx pool */
2449         lib_arp_pktmbuf_tx_pool =
2450                         rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2451                                                 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2452                                                 rte_socket_id());
2453
2454         if (lib_arp_pktmbuf_tx_pool == NULL) {
2455                 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2456                 return;
2457         }
2458
2459         lib_arp_pkt = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2460         if (lib_arp_pkt == NULL) {
2461                 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2462                 return;
2463         }
2464
2465         arp_hash_params.socket_id = rte_socket_id();
2466         arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2467         arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2468         arp_hash_handle = rte_hash_create(&arp_hash_params);
2469
2470         if (arp_hash_handle == NULL) {
2471                 RTE_LOG(INFO, LIBARP,
2472                         "ARP rte_hash_create failed. socket %d ... \n",
2473                         arp_hash_params.socket_id);
2474         } else {
2475                 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2476                         (void *)arp_hash_handle);
2477         }
2478
2479         /* Create port alloc buffer */
2480
2481         timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2482                                                                  timer_objs_mempool_count,
2483                                                                  sizeof(struct rte_timer),
2484                                                                  0, 0,
2485                                                                  NULL, NULL,
2486                                                                  NULL, NULL, rte_socket_id(), 0);
2487         if (timer_mempool_arp == NULL) {
2488                 rte_panic("timer_mempool create error\n");
2489         }
2490         rte_timer_subsystem_init();
2491         list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2492
2493         /* ND IPv6 */
2494         nd_hash_params.socket_id = rte_socket_id();
2495         nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2496         nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2497         nd_hash_handle = rte_hash_create(&nd_hash_params);
2498         if (nd_hash_handle == NULL) {
2499                 RTE_LOG(INFO, LIBARP,
2500                         "ND rte_hash_create failed. socket %d ... \n",
2501                         nd_hash_params.socket_id);
2502         } else {
2503                 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2504                         (void *)nd_hash_handle);
2505         }
2506
2507         return;
2508 }
2509
2510 void arp_timer_callback(struct rte_timer *timer, void *arg)
2511 {
2512         struct arp_timer_key *remove_key = (struct arp_timer_key *)arg;
2513         if (ARPICMP_DEBUG)
2514                 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d\n",
2515                         (int)timer->expire);
2516         if (ARPICMP_DEBUG)
2517                 RTE_LOG(INFO, LIBARP,
2518                         "Remove ARP Entry for IP :%d.%d.%d.%d , port %d\n",
2519                         (remove_key->ip >> 24),
2520                         ((remove_key->ip & 0x00ff0000) >> 16),
2521                         ((remove_key->ip & 0x0000ff00) >> 8),
2522                         ((remove_key->ip & 0x000000ff)), remove_key->port_id);
2523         remove_arp_entry((uint32_t) remove_key->ip,
2524                          (uint8_t) remove_key->port_id, arg);
2525         return;
2526 }
2527
2528 void nd_timer_callback(struct rte_timer *timer, void *arg)
2529 {
2530         struct nd_timer_key *remove_key = (struct nd_timer_key *)arg;
2531         if (ARPICMP_DEBUG)
2532                 RTE_LOG(INFO, LIBARP, "nd  time callback : expire :%d\n",
2533                         (int)timer->expire);
2534         remove_nd_entry_ipv6(remove_key->ipv6, remove_key->port_id);
2535         return;
2536 }
2537
2538 void create_arp_table(void)
2539 {
2540
2541         int i;
2542         for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2543                 populate_arp_entry((const struct ether_addr *)
2544                                          &arp_entry_data_table[i].eth_addr,
2545                                          arp_entry_data_table[i].ip,
2546                                          (uint8_t) arp_entry_data_table[i].port,
2547                                          STATIC_ARP);
2548         }
2549         print_arp_table();
2550         return;
2551 }
2552
2553 void create_nd_table(void)
2554 {
2555
2556         int i;
2557         for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2558                 populate_nd_entry((const struct ether_addr *)
2559                                         nd_entry_data_table[i].eth_addr,
2560                                         nd_entry_data_table[i].ipv6,
2561                                         (uint8_t) nd_entry_data_table[i].port,
2562                                         STATIC_ND);
2563         }
2564         print_nd_table();
2565         return;
2566 }
2567
2568 void send_gratuitous_arp(l2_phy_interface_t *port)
2569 {
2570         struct ether_hdr *eth_h;
2571         struct arp_hdr *arp_h;
2572
2573         struct rte_mbuf *arp_pkt = lib_arp_pkt;
2574
2575         if (port == NULL) {
2576                 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2577                 return;
2578
2579         }
2580
2581         if (arp_pkt == NULL) {
2582                 if (ARPICMP_DEBUG)
2583                         RTE_LOG(INFO, LIBARP,
2584                                 "Error allocating arp_pkt rte_mbuf\n");
2585                 return;
2586         }
2587
2588         eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2589
2590         ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
2591         ether_addr_copy((struct ether_addr *)
2592                         &port->macaddr[0], &eth_h->s_addr);
2593         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2594
2595         arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2596         arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2597         arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2598         arp_h->arp_hln = ETHER_ADDR_LEN;
2599         arp_h->arp_pln = sizeof(uint32_t);
2600         arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2601
2602         ether_addr_copy((struct ether_addr *)
2603                         &port->macaddr[0], &arp_h->arp_data.arp_sha);
2604         if (port->ipv4_list == NULL) {
2605                 if (ARPICMP_DEBUG)
2606                         RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2607                                 __FUNCTION__);
2608                 return;
2609         }
2610         arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2611         ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2612         //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2613         arp_h->arp_data.arp_tip = 0;    //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2614         //  RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2615         //arp_h->arp_data.arp_sip);
2616         // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2617         arp_pkt->pkt_len = 42;
2618         arp_pkt->data_len = 42;
2619
2620         if (ARPICMP_DEBUG) {
2621                 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2622                 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2623         }
2624         port->transmit_single_pkt(port, arp_pkt);
2625 }
2626
2627 void set_arpdebug(int flag)
2628 {
2629         if (flag) {
2630                 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2631                 ARPICMP_DEBUG = 1;
2632                 NDIPV6_DEBUG = 1;
2633
2634         } else {
2635                 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2636                 ARPICMP_DEBUG = 0;
2637                 NDIPV6_DEBUG = 0;
2638         }
2639 }
2640
2641 void set_arptimeout(uint32_t timeout_val)
2642 {
2643         if (timeout_val == 0) {
2644                 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2645                 return;
2646         }
2647         if (ARPICMP_DEBUG)
2648                 RTE_LOG(INFO, LIBARP,
2649                         "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2650                         arp_timeout, timeout_val);
2651         arp_timeout = timeout_val;
2652         if (ARPICMP_DEBUG)
2653                 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",
2654                         arp_timeout);
2655 }