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