[l2l3 stack] implements new nd state machine & nd buffering
[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                                         RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1859                                 }
1860                         }
1861                         /// revise conditionals to allow processing of requests with target ip = this ip and
1862                         //                               processing of replies to destination ip = this ip
1863                         else if (arp_h->arp_op ==
1864                                  rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1865                                 if (ARPICMP_DEBUG) {
1866                                         RTE_LOG(INFO, LIBARP,
1867                                                 "%s, portid %u. Line %d\n\r",
1868                                                 __FUNCTION__, port->pmdid,
1869                                                 __LINE__);
1870
1871                                         RTE_LOG(INFO, LIBARP,
1872                                                 "arp_op %d, ARP_OP_REQUEST %d\n",
1873                                                 arp_h->arp_op,
1874                                                 rte_cpu_to_be_16
1875                                                 (ARP_OP_REQUEST));
1876                                         print_mbuf("RX", in_port_id, pkt,
1877                                                          __LINE__);
1878                                 }
1879                                 populate_arp_entry((struct ether_addr *)
1880                                                          &arp_h->arp_data.arp_sha,
1881                                                          rte_cpu_to_be_32
1882                                                          (arp_h->arp_data.arp_sip),
1883                                                          in_port_id, DYNAMIC_ARP);
1884
1885                                 /*build reply */
1886                                 req_tip = arp_h->arp_data.arp_tip;
1887                                 ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
1888                                 ether_addr_copy((struct ether_addr *)&port->macaddr[0], &eth_h->s_addr);  /**< set sender mac address*/
1889                                 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1890                                 ether_addr_copy(&eth_h->s_addr,
1891                                                 &arp_h->arp_data.arp_sha);
1892                                 arp_h->arp_data.arp_tip =
1893                                                 arp_h->arp_data.arp_sip;
1894                                 arp_h->arp_data.arp_sip = req_tip;
1895                                 ether_addr_copy(&eth_h->d_addr,
1896                                                 &arp_h->arp_data.arp_tha);
1897                                 if (ARPICMP_DEBUG)
1898                                         print_mbuf("TX ARP REPLY PKT",
1899                                                          port->pmdid, pkt, __LINE__);
1900                                 port->transmit_bulk_pkts(port, &pkt, 1);
1901                                 if (ARPICMP_DEBUG)
1902                                         print_mbuf("TX", port->pmdid, pkt,
1903                                                          __LINE__);
1904                                 printf("replying arp pkt done\n");
1905                                 return;
1906                         } else if (arp_h->arp_op ==
1907                                          rte_cpu_to_be_16(ARP_OP_REPLY)) {
1908                                 if (ARPICMP_DEBUG) {
1909                                         RTE_LOG(INFO, LIBARP,
1910                                                 "ARP_OP_REPLY received");
1911                                         print_mbuf("RX", port->pmdid, pkt,
1912                                                          __LINE__);
1913                                 }
1914                                 populate_arp_entry((struct ether_addr *)
1915                                                          &arp_h->arp_data.arp_sha,
1916                                                          rte_bswap32(arp_h->
1917                                                                                  arp_data.arp_sip),
1918                                                          in_port_id, DYNAMIC_ARP);
1919
1920                                 return;
1921                         } else {
1922                                 if (ARPICMP_DEBUG)
1923                                         RTE_LOG(INFO, LIBARP,
1924                                                 "Invalid ARP opcode - not processing ARP req %x\n",
1925                                                 arp_h->arp_op);
1926                         }
1927                 }
1928
1929                 rte_pktmbuf_free(pkt);
1930         } else {
1931                 ip_h =
1932                                 (struct ipv4_hdr *)((char *)eth_h +
1933                                         sizeof(struct ether_hdr));
1934                 icmp_h =
1935                                 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1936
1937                 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1938
1939                         if (ip_h->next_proto_id != IPPROTO_ICMP) {
1940                                 if (ARPICMP_DEBUG) {
1941                                         RTE_LOG(INFO, LIBARP,
1942                                                 "IP protocol ID is not set to ICMP - discarding\n");
1943                                 }
1944                         } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1945                                 if (ARPICMP_DEBUG) {
1946                                         RTE_LOG(INFO, LIBARP,
1947                                                 "IP version other than 4 - discarding\n");
1948                                 }
1949                         } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1950                                 if (ARPICMP_DEBUG) {
1951                                         RTE_LOG(INFO, LIBARP,
1952                                                 "Unknown IHL - discarding\n");
1953                                 }
1954                         } else {
1955                                 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1956                                                 && icmp_h->icmp_code == 0) {
1957                                         if (ARPICMP_DEBUG)
1958                                                 print_mbuf("RX", in_port_id,
1959                                                                  pkt, __LINE__);
1960
1961                                         ip_addr = ip_h->src_addr;
1962                                         ether_addr_copy(&eth_h->s_addr,
1963                                                         &eth_h->d_addr);
1964                                         ether_addr_copy((struct ether_addr *)
1965                                                         &port->macaddr[0],
1966                                                         &eth_h->s_addr);
1967                                         if (ARPICMP_DEBUG)
1968                                                 RTE_LOG(INFO, LIBARP,
1969                                                         "%s, portid %u. Line %d\n\r",
1970                                                         __FUNCTION__,
1971                                                         port->pmdid, __LINE__);
1972
1973                                         if (is_multicast_ipv4_addr
1974                                                         (ip_h->dst_addr)) {
1975                                                 uint32_t ip_src;
1976
1977                                                 ip_src =
1978                                                                 rte_be_to_cpu_32(ip_addr);
1979                                                 if ((ip_src & 0x00000003) == 1)
1980                                                         ip_src =
1981                                                                         (ip_src &
1982                                                                          0xFFFFFFFC) |
1983                                                                         0x00000002;
1984                                                 else
1985                                                         ip_src =
1986                                                                         (ip_src &
1987                                                                          0xFFFFFFFC) |
1988                                                                         0x00000001;
1989                                                 ip_h->src_addr =
1990                                                                 rte_cpu_to_be_32(ip_src);
1991                                                 ip_h->dst_addr = ip_addr;
1992
1993                                                 ip_h->hdr_checksum = 0;
1994                                                 ip_h->hdr_checksum =
1995                                                                 ~rte_raw_cksum(ip_h,
1996                                                                          sizeof(struct
1997                                                                                 ipv4_hdr));
1998                                         } else {
1999                                                 if (ARPICMP_DEBUG)
2000                                                         RTE_LOG(INFO, LIBARP,
2001                                                                 "%s, portid %u. Line %d\n\r",
2002                                                                 __FUNCTION__,
2003                                                                 port->pmdid,
2004                                                                 __LINE__);
2005                                                 ip_h->src_addr = ip_h->dst_addr;
2006                                                 ip_h->dst_addr = ip_addr;
2007                                         }
2008
2009                                         icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
2010                                         cksum = ~icmp_h->icmp_cksum & 0xffff;
2011                                         cksum +=
2012                                                         ~htons(IP_ICMP_ECHO_REQUEST << 8) &
2013                                                         0xffff;
2014                                         cksum += htons(IP_ICMP_ECHO_REPLY << 8);
2015                                         cksum =
2016                                                         (cksum & 0xffff) + (cksum >> 16);
2017                                         cksum =
2018                                                         (cksum & 0xffff) + (cksum >> 16);
2019                                         icmp_h->icmp_cksum = ~cksum;
2020
2021                                         if (ARPICMP_DEBUG)
2022                                                 print_mbuf
2023                                                                 ("TX ICMP ECHO REPLY PKT",
2024                                                                  in_port_id, pkt, __LINE__);
2025                                         port->transmit_bulk_pkts(port, &pkt, 1);
2026                                         if (ARPICMP_DEBUG)
2027                                                 print_mbuf("TX", port->pmdid,
2028                                                                  pkt, __LINE__);
2029
2030                                         return;
2031                                 } else if (icmp_h->icmp_type ==
2032                                                  IP_ICMP_ECHO_REPLY
2033                                                  && icmp_h->icmp_code == 0) {
2034                                         if (ARPICMP_DEBUG)
2035                                                 print_mbuf("RX", in_port_id,
2036                                                                  pkt, __LINE__);
2037
2038                                         struct arp_key_ipv4 arp_key;
2039                                         arp_key.port_id = in_port_id;
2040                                         arp_key.ip =
2041                                                         rte_bswap32(ip_h->src_addr);
2042                                         arp_key.filler1 = 0;
2043                                         arp_key.filler2 = 0;
2044                                         arp_key.filler3 = 0;
2045
2046                                         struct arp_entry_data *arp_entry =
2047                                                         retrieve_arp_entry(arp_key,
2048                                                                  DYNAMIC_ARP);
2049                                         if (arp_entry == NULL) {
2050                                                 if (ARPICMP_DEBUG)
2051                                                         RTE_LOG(INFO, LIBARP,
2052                                                                 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
2053                                                                 arp_key.ip,
2054                                                                 arp_key.port_id);
2055                                                 return;
2056                                         }
2057                                         arp_entry->status = COMPLETE;
2058                                 }
2059                         }
2060                 }
2061
2062                 rte_pktmbuf_free(pkt);
2063         }
2064 }
2065
2066 /* int
2067  * inet_pton(af, src, dst)
2068  *      convert from presentation format (which usually means ASCII printable)
2069  *      to network format (which is usually some kind of binary format).
2070  * return:
2071  *      1 if the address was valid for the specified address family
2072  *      0 if the address wasn't valid (`dst' is untouched in this case)
2073  *      -1 if some other error occurred (`dst' is untouched in this case, too)
2074  * author:
2075  *      Paul Vixie, 1996.
2076  */
2077 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
2078 {
2079         switch (af) {
2080         case AF_INET:
2081                 return inet_pton_ipv4(src, dst);
2082         case AF_INET6:
2083                 return inet_pton_ipv6(src, dst);
2084         default:
2085                 errno = EAFNOSUPPORT;
2086                 return -1;
2087         }
2088         /* NOTREACHED */
2089 }
2090
2091 /* int
2092  * inet_pton_ipv4(src, dst)
2093  *      like inet_aton() but without all the hexadecimal and shorthand.
2094  * return:
2095  *      1 if `src' is a valid dotted quad, else 0.
2096  * notice:
2097  *      does not touch `dst' unless it's returning 1.
2098  * author:
2099  *      Paul Vixie, 1996.
2100  */
2101 static int inet_pton_ipv4(const char *src, unsigned char *dst)
2102 {
2103         static const char digits[] = "0123456789";
2104         int saw_digit, octets, ch;
2105         unsigned char tmp[INADDRSZ], *tp;
2106
2107         saw_digit = 0;
2108         octets = 0;
2109         *(tp = tmp) = 0;
2110         while ((ch = *src++) != '\0') {
2111                 const char *pch;
2112
2113                 pch = strchr(digits, ch);
2114                 if (pch != NULL) {
2115                         unsigned int new = *tp * 10 + (pch - digits);
2116
2117                         if (new > 255)
2118                                 return 0;
2119                         if (!saw_digit) {
2120                                 if (++octets > 4)
2121                                         return 0;
2122                                 saw_digit = 1;
2123                         }
2124                         *tp = (unsigned char)new;
2125                 } else if (ch == '.' && saw_digit) {
2126                         if (octets == 4)
2127                                 return 0;
2128                         *++tp = 0;
2129                         saw_digit = 0;
2130                 } else
2131                         return 0;
2132         }
2133         if (octets < 4)
2134                 return 0;
2135
2136         memcpy(dst, tmp, INADDRSZ);
2137         return 1;
2138 }
2139
2140 /* int
2141  * inet_pton_ipv6(src, dst)
2142  *      convert presentation level address to network order binary form.
2143  * return:
2144  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
2145  * notice:
2146  *      (1) does not touch `dst' unless it's returning 1.
2147  *      (2) :: in a full address is silently ignored.
2148  * credit:
2149  *      inspired by Mark Andrews.
2150  * author:
2151  *      Paul Vixie, 1996.
2152  */
2153 static int inet_pton_ipv6(const char *src, unsigned char *dst)
2154 {
2155         static const char xdigits_l[] = "0123456789abcdef",
2156                         xdigits_u[] = "0123456789ABCDEF";
2157         unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2158         const char *xdigits = 0, *curtok = 0;
2159         int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2160         unsigned int val = 0;
2161         unsigned int dbloct_count = 0;
2162
2163         memset((tp = tmp), '\0', IN6ADDRSZ);
2164         endp = tp + IN6ADDRSZ;
2165         colonp = NULL;
2166         /* Leading :: requires some special handling. */
2167         if (*src == ':')
2168                 if (*++src != ':')
2169                         return 0;
2170         curtok = src;
2171         saw_xdigit = count_xdigit = 0;
2172         val = 0;
2173
2174         while ((ch = *src++) != '\0') {
2175                 const char *pch;
2176
2177                 pch = strchr((xdigits = xdigits_l), ch);
2178                 if (pch == NULL)
2179                         pch = strchr((xdigits = xdigits_u), ch);
2180                 if (pch != NULL) {
2181                         if (count_xdigit >= 4)
2182                                 return 0;
2183                         val <<= 4;
2184                         val |= (pch - xdigits);
2185                         if (val > 0xffff)
2186                                 return 0;
2187                         saw_xdigit = 1;
2188                         count_xdigit++;
2189                         continue;
2190                 }
2191                 if (ch == ':') {
2192                         curtok = src;
2193                         if (!saw_xdigit) {
2194                                 if (colonp)
2195                                         return 0;
2196                                 colonp = tp;
2197                                 continue;
2198                         } else if (*src == '\0') {
2199                                 return 0;
2200                         }
2201                         if (tp + sizeof(int16_t) > endp)
2202                                 return 0;
2203                         *tp++ = (unsigned char)((val >> 8) & 0xff);
2204                         *tp++ = (unsigned char)(val & 0xff);
2205                         saw_xdigit = 0;
2206                         count_xdigit = 0;
2207                         val = 0;
2208                         dbloct_count++;
2209                         continue;
2210                 }
2211                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2212                                 inet_pton_ipv4(curtok, tp) > 0) {
2213                         tp += INADDRSZ;
2214                         saw_xdigit = 0;
2215                         dbloct_count += 2;
2216                         break;  /* '\0' was seen by inet_pton4(). */
2217                 }
2218                 return 0;
2219         }
2220         if (saw_xdigit) {
2221                 if (tp + sizeof(int16_t) > endp)
2222                         return 0;
2223                 *tp++ = (unsigned char)((val >> 8) & 0xff);
2224                 *tp++ = (unsigned char)(val & 0xff);
2225                 dbloct_count++;
2226         }
2227         if (colonp != NULL) {
2228                 /* if we already have 8 double octets, having a colon means error */
2229                 if (dbloct_count == 8)
2230                         return 0;
2231
2232                 /*
2233                  * Since some memmove()'s erroneously fail to handle
2234                  * overlapping regions, we'll do the shift by hand.
2235                  */
2236                 const int n = tp - colonp;
2237                 int i;
2238
2239                 for (i = 1; i <= n; i++) {
2240                         endp[-i] = colonp[n - i];
2241                         colonp[n - i] = 0;
2242                 }
2243                 tp = endp;
2244         }
2245         if (tp != endp)
2246                 return 0;
2247         memcpy(dst, tmp, IN6ADDRSZ);
2248         return 1;
2249 }
2250
2251 static int arp_parse_args(struct pipeline_params *params)
2252 {
2253         uint32_t arp_route_tbl_present = 0;
2254         uint32_t nd_route_tbl_present = 0;
2255         uint32_t numArg;
2256         uint32_t n_vnf_threads_present = 0;
2257
2258         uint32_t pktq_in_prv_present = 0;
2259         uint32_t prv_to_pub_map_present = 0;
2260
2261         uint8_t n_prv_in_port = 0;
2262         int i;
2263         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2264                 in_port_dir_a[i] = 0;   //make all RX ports ingress initially
2265                 prv_to_pub_map[i] = 0xff;
2266                 pub_to_prv_map[i] = 0xff;
2267         }
2268
2269         RTE_SET_USED(nd_route_tbl_present);
2270         RTE_SET_USED(arp_route_tbl_present);
2271         for (numArg = 0; numArg < params->n_args; numArg++) {
2272                 char *arg_name = params->args_name[numArg];
2273                 char *arg_value = params->args_value[numArg];
2274
2275                 /* arp timer expiry */
2276                 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2277                         arp_timeout = atoi(arg_value);
2278                 }
2279
2280                 /* pktq_in_prv */
2281                 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2282                         if (pktq_in_prv_present) {
2283                                 printf
2284                                                 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2285                                 return -1;
2286                         }
2287                         pktq_in_prv_present = 1;
2288
2289                         int rxport = 0, j = 0;
2290                         char phy_port_num[5];
2291                         char *token = strtok(arg_value, "RXQ");
2292                         while (token) {
2293                                 j = 0;
2294                                 while ((j < 4) && (token[j] != '.')) {
2295                                         phy_port_num[j] = token[j];
2296                                         j++;
2297                                 }
2298                                 phy_port_num[j] = '\0';
2299                                 rxport = atoi(phy_port_num);
2300                                 prv_in_port_a[n_prv_in_port++] = rxport;
2301                                 if (rxport < 0)
2302                                         rxport = 0;
2303                                 printf
2304                                                 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2305                                                  token, phy_port_num, rxport);
2306                                 prv_in_port_a[n_prv_in_port++] = rxport;
2307                                 if(rxport < PIPELINE_MAX_PORT_IN)
2308                                 in_port_dir_a[rxport] = 1;      // set rxport egress
2309                                 token = strtok(NULL, "RXQ");
2310                         }
2311
2312                         if (n_prv_in_port == 0) {
2313                                 printf
2314                                                 ("VNF common parse error - no prv RX phy port\n");
2315                                 return -1;
2316                         }
2317                         continue;
2318                 }
2319
2320                 if (strcmp(arg_name, "arp_buf") == 0) {
2321                         arp_buffer = atoi(arg_value);
2322                         continue;
2323                 }
2324
2325                 if (strcmp(arg_name, "nd_buf") == 0) {
2326                         nd_buffer = atoi(arg_value);
2327                         continue;
2328                 }
2329
2330                 /* prv_to_pub_map */
2331                 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2332                         if (prv_to_pub_map_present) {
2333                                 printf
2334                                                 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2335                                 return -1;
2336                         }
2337                         prv_to_pub_map_present = 1;
2338
2339                         int rxport = 0, txport = 0, j = 0, k = 0;
2340                         char rx_phy_port_num[5];
2341                         char tx_phy_port_num[5];
2342                         char *token = strtok(arg_value, "(");
2343                         while (token) {
2344                                 j = 0;
2345                                 while ((j < 4) && (token[j] != ',')) {
2346                                         rx_phy_port_num[j] = token[j];
2347                                         j++;
2348                                 }
2349                                 rx_phy_port_num[j] = '\0';
2350                                 rxport = atoi(rx_phy_port_num);
2351                                 if (rxport < 0)
2352                                         rxport = 0;
2353
2354                                 j++;
2355                                 k = 0;
2356                                 while ((k < 4) && (token[j + k] != ')')) {
2357                                         tx_phy_port_num[k] = token[j + k];
2358                                         k++;
2359                                 }
2360                                 tx_phy_port_num[k] = '\0';
2361                                 txport = atoi(tx_phy_port_num);
2362                                 if (txport < 0)
2363                                         txport = 0;
2364
2365                                 RTE_LOG(INFO, LIBARP, "token: %s,"
2366                                         "rx_phy_port_str: %s, phy_port_num %d,"
2367                                         "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2368                                         token, rx_phy_port_num, rxport,
2369                                         tx_phy_port_num, txport);
2370
2371                                 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2372                                                 (txport >= PIPELINE_MAX_PORT_IN) ||
2373                                                 (in_port_dir_a[rxport] != 1)) {
2374                                         printf
2375                                                         ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2376                                                          rxport, txport,
2377                                                          in_port_dir_a[rxport]);
2378                                         return -1;
2379                                 }
2380
2381                                 prv_to_pub_map[rxport] = txport;
2382                                 pub_to_prv_map[txport] = rxport;
2383                                 token = strtok(NULL, "(");
2384                         }
2385
2386                         continue;
2387                 }
2388                 //n_vnf_threads = 3
2389                 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2390                         if (n_vnf_threads_present)
2391                                 return -1;
2392                         n_vnf_threads_present = 1;
2393                         trim(arg_value);
2394                         num_vnf_threads = atoi(arg_value);
2395                         if (num_vnf_threads <= 0) {
2396                                 RTE_LOG(INFO, LIBARP,
2397                                         "n_vnf_threads is invalid\n");
2398                                 return -1;
2399                         }
2400                         RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2401                                 num_vnf_threads);
2402                 }
2403
2404                 /* lib_arp_debug */
2405                 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2406                         ARPICMP_DEBUG = atoi(arg_value);
2407
2408                         continue;
2409                 }
2410
2411                 /* arp_route_tbl */
2412                 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2413                         arp_route_tbl_present = 1;
2414
2415                         uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2416                                         0, i = 0, j = 0, k = 0, l = 0;
2417                         uint32_t arp_route_tbl_str_max_len = 10;
2418                         char dest_ip_str[arp_route_tbl_str_max_len];
2419                         char mask_str[arp_route_tbl_str_max_len];
2420                         char tx_port_str[arp_route_tbl_str_max_len];
2421                         char nh_ip_str[arp_route_tbl_str_max_len];
2422                         char *token = strtok(arg_value, "(");
2423                         while (token) {
2424                                 i = 0;
2425                                 while ((i < (arp_route_tbl_str_max_len - 1))
2426                                                          && (token[i] != ',')) {
2427                                         dest_ip_str[i] = token[i];
2428                                         i++;
2429                                 }
2430                                 dest_ip_str[i] = '\0';
2431                                 dest_ip = strtoul(dest_ip_str, NULL, 16);
2432
2433                                 i++;
2434                                 j = 0;
2435                                 while ((j < (arp_route_tbl_str_max_len - 1))
2436                                                          && (token[i + j] != ',')) {
2437                                         mask_str[j] = token[i + j];
2438                                         j++;
2439                                 }
2440                                 mask_str[j] = '\0';
2441                                 mask = strtoul(mask_str, NULL, 16);
2442
2443                                 j++;
2444                                 k = 0;
2445                                 while ((k < (arp_route_tbl_str_max_len - 1))
2446                                                          && (token[i + j + k] != ',')) {
2447                                         tx_port_str[k] = token[i + j + k];
2448                                         k++;
2449                                 }
2450                                 tx_port_str[k] = '\0';
2451                                 tx_port = strtoul(tx_port_str, NULL, 16);       //atoi(tx_port_str);
2452
2453                                 k++;
2454                                 l = 0;
2455                                 while ((l < (arp_route_tbl_str_max_len - 1))
2456                                                          && (token[i + j + k + l] != ')')) {
2457                                         nh_ip_str[l] = token[i + j + k + l];
2458                                         l++;
2459                                 }
2460                                 nh_ip_str[l] = '\0';
2461                                 nh_ip = strtoul(nh_ip_str, NULL, 16);   //atoi(nh_ip_str);
2462
2463                                 if (1) {
2464                                         RTE_LOG(INFO, LIBARP, "token: %s, "
2465                                                 "dest_ip_str: %s, dest_ip %u, "
2466                                                 "mask_str: %s, mask %u, "
2467                                                 "tx_port_str: %s, tx_port %u, "
2468                                                 "nh_ip_str: %s, nh_ip %u\n",
2469                                                 token, dest_ip_str, dest_ip,
2470                                                 mask_str, mask, tx_port_str,
2471                                                 tx_port, nh_ip_str, nh_ip);
2472                                 }
2473
2474                                 /*  if (tx_port >= params->n_ports_out)
2475                                          {
2476                                          RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2477                                          tx_port, params->n_ports_out);
2478                                          return -1;
2479                                          }
2480                                  */
2481                                 //Populate the static arp_route_table
2482                                 struct lib_arp_route_table_entry *lentry =
2483                                 &p_arp_data->lib_arp_route_table
2484                                 [p_arp_data->lib_arp_route_ent_cnt];
2485                                 lentry->ip = dest_ip;
2486                                 lentry->mask = mask;
2487                                 lentry->port = tx_port;
2488                                 lentry->nh = nh_ip;
2489                                 lentry->nh_mask = nh_ip & mask;
2490                                 p_arp_data->lib_arp_route_ent_cnt++;
2491                                 token = strtok(NULL, "(");
2492                         }
2493
2494                         continue;
2495                 }
2496                 /*ND IPv6 */
2497                 /* nd_route_tbl */
2498                 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2499                         nd_route_tbl_present = 1;
2500
2501                         uint8_t dest_ipv6[16], depth = 0, tx_port =
2502                                         0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2503                         uint8_t nd_route_tbl_str_max_len = 128; //64;
2504                         char dest_ipv6_str[nd_route_tbl_str_max_len];
2505                         char depth_str[nd_route_tbl_str_max_len];
2506                         char tx_port_str[nd_route_tbl_str_max_len];
2507                         char nh_ipv6_str[nd_route_tbl_str_max_len];
2508                         char *token = strtok(arg_value, "(");
2509                         while (token) {
2510                                 i = 0;
2511                                 while ((i < (nd_route_tbl_str_max_len - 1))
2512                                                          && (token[i] != ',')) {
2513                                         dest_ipv6_str[i] = token[i];
2514                                         i++;
2515                                 }
2516                                 dest_ipv6_str[i] = '\0';
2517                                 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2518                                                         &dest_ipv6);
2519
2520                                 i++;
2521                                 j = 0;
2522                                 while ((j < (nd_route_tbl_str_max_len - 1))
2523                                                          && (token[i + j] != ',')) {
2524                                         depth_str[j] = token[i + j];
2525                                         j++;
2526                                 }
2527                                 depth_str[j] = '\0';
2528                                 //converting string char to integer
2529                                 int s;
2530                                 for (s = 0; depth_str[s] != '\0'; ++s)
2531                                         depth = depth * 10 + depth_str[s] - '0';
2532
2533                                 j++;
2534                                 k = 0;
2535                                 while ((k < (nd_route_tbl_str_max_len - 1))
2536                                                          && (token[i + j + k] != ',')) {
2537                                         tx_port_str[k] = token[i + j + k];
2538                                         k++;
2539                                 }
2540                                 tx_port_str[k] = '\0';
2541                                 tx_port = strtoul(tx_port_str, NULL, 16);       //atoi(tx_port_str);
2542
2543                                 k++;
2544                                 l = 0;
2545                                 while ((l < (nd_route_tbl_str_max_len - 1))
2546                                                          && (token[i + j + k + l] != ')')) {
2547                                         nh_ipv6_str[l] = token[i + j + k + l];
2548                                         l++;
2549                                 }
2550                                 nh_ipv6_str[l] = '\0';
2551                                 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2552                                                         &nh_ipv6);
2553
2554                                 //Populate the static arp_route_table
2555                                 for (i = 0; i < 16; i++) {
2556                                         lib_nd_route_table
2557                                                         [nd_route_tbl_index].ipv6[i] =
2558                                                         dest_ipv6[i];
2559                                         lib_nd_route_table
2560                                                         [nd_route_tbl_index].nhipv6[i] =
2561                                                         nh_ipv6[i];
2562                                 }
2563                                 lib_nd_route_table[nd_route_tbl_index].depth =
2564                                                 depth;
2565                                 lib_nd_route_table[nd_route_tbl_index].port =
2566                                                 tx_port;
2567
2568                                 nd_route_tbl_index++;
2569                                 token = strtok(NULL, "(");
2570                         }
2571
2572                         continue;
2573                 }
2574                 /* any other */
2575                 //return -1;
2576         }
2577         /* Check that mandatory arguments are present */
2578         /*
2579                  if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2580                  RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2581                  RTE_LOG(INFO, LIBARP,"%d, %d \n",
2582                  arp_route_tbl_present, ports_mac_list_present);
2583                  return -1;
2584                  }
2585          */
2586
2587         return 0;
2588 }
2589
2590 static void local_arp_cache_init(void)
2591 {
2592         int i, j, k;
2593         for (i=0; i<MAX_PORTS;i++) {
2594                 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2595                         p_arp_data->arp_local_cache[i].nhip[j] = 0;
2596                         for (k=0;k<6;k++)
2597                                 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2598                         p_arp_data->arp_local_cache[i].num_nhip = 0;
2599                 }
2600         }
2601 }
2602
2603 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
2604 {
2605         int i, j, limit;
2606         struct ether_addr *x = NULL;
2607         limit = p_arp_data->nd_local_cache[out_port].num_nhip;
2608
2609         for (i=0; i < limit; i++) {
2610                 for (j=0;j<16;j++) {
2611                         if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
2612                                 continue;
2613                 }
2614
2615                 x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
2616                 return x;
2617         }
2618
2619         return x;
2620 }
2621
2622 struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip)
2623 {
2624         int i, limit;
2625         uint32_t tmp;
2626         struct ether_addr *x = NULL;
2627         limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2628         for (i=0; i < limit; i++) {
2629                 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2630                 if (tmp == nhip) {
2631                         x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2632                         return x;
2633                 }
2634         }
2635         return x;
2636 }
2637
2638 void lib_arp_init(struct pipeline_params *params,
2639                         __rte_unused struct app_params *app)
2640 {
2641
2642         int i;
2643         uint32_t size;
2644         struct pipeline_cgnapt *p;
2645
2646         RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2647
2648         /* create arp data for table entries */
2649         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2650         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2651         p_arp_data = (struct arp_data *)p;
2652
2653         /* Parse arguments */
2654         if (arp_parse_args(params)) {
2655                 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2656                 return;
2657         }
2658
2659         /* acquire the mac addresses */
2660         struct ether_addr hw_addr;
2661         uint8_t nb_ports = rte_eth_dev_count();
2662
2663         for (i = 0; i < nb_ports; i++) {
2664                 rte_eth_macaddr_get(i, &hw_addr);
2665                 ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
2666                 p_arp_data->link_hw_addr_array_idx++;
2667         }
2668
2669         /* create a lock for arp/nd hash */
2670         rte_rwlock_init(&arp_hash_handle_lock);
2671         rte_rwlock_init(&nd_hash_handle_lock);
2672
2673         /* create the arp_icmp mbuf rx pool */
2674         lib_arp_pktmbuf_tx_pool =
2675                         rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2676                                                 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2677                                                 rte_socket_id());
2678
2679         if (lib_arp_pktmbuf_tx_pool == NULL) {
2680                 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2681                 return;
2682         }
2683
2684         for (i=0; i<MAX_PORTS; i++) {
2685                 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2686                 if (lib_arp_pkt[i] == NULL) {
2687                         RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2688                         return;
2689                 }
2690         }
2691
2692         /* create the nd icmp mbuf rx pool */
2693         lib_nd_pktmbuf_tx_pool =
2694                         rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2695                                                 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2696                                                 rte_socket_id());
2697
2698         if (lib_nd_pktmbuf_tx_pool == NULL) {
2699                 RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
2700                 return;
2701         }
2702
2703         for (i=0; i<MAX_PORTS; i++) {
2704                 lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
2705                 if (lib_nd_pkt[i] == NULL) {
2706                         RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
2707                         return;
2708                 }
2709         }
2710
2711         /* create the arp_icmp mbuf rx pool */
2712         arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2713                                         NB_ARPICMP_MBUF, MAX_POOL, 0,
2714                                         RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2715
2716         if (arp_icmp_pktmbuf_tx_pool == NULL) {
2717                 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2718                 return;
2719         }
2720
2721         arp_hash_params.socket_id = rte_socket_id();
2722         arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2723         arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2724         arp_hash_handle = rte_hash_create(&arp_hash_params);
2725
2726         if (arp_hash_handle == NULL) {
2727                 RTE_LOG(INFO, LIBARP,
2728                         "ARP rte_hash_create failed. socket %d ... \n",
2729                         arp_hash_params.socket_id);
2730         } else {
2731                 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2732                         (void *)arp_hash_handle);
2733         }
2734
2735         /* Create port alloc buffer */
2736
2737         timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2738                                                                  timer_objs_mempool_count,
2739                                                                  sizeof(struct rte_timer),
2740                                                                  0, 0,
2741                                                                  NULL, NULL,
2742                                                                  NULL, NULL, rte_socket_id(), 0);
2743         if (timer_mempool_arp == NULL) {
2744                 rte_panic("timer_mempool create error\n");
2745         }
2746         rte_timer_subsystem_init();
2747         list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2748
2749         /* ND IPv6 */
2750         nd_hash_params.socket_id = rte_socket_id();
2751         nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2752         nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2753         nd_hash_handle = rte_hash_create(&nd_hash_params);
2754         if (nd_hash_handle == NULL) {
2755                 RTE_LOG(INFO, LIBARP,
2756                         "ND rte_hash_create failed. socket %d ... \n",
2757                         nd_hash_params.socket_id);
2758         } else {
2759                 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2760                         (void *)nd_hash_handle);
2761         }
2762
2763         /* Initialize the local arp cache */
2764         local_arp_cache_init();
2765
2766         return;
2767 }
2768
2769 void arp_timer_callback(struct rte_timer *timer, void *arg)
2770 {
2771         struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2772         struct arp_key_ipv4 arp_key;
2773         arp_key.port_id = timer_key->port_id;
2774         arp_key.ip = timer_key->ip;
2775         arp_key.filler1 = 0;
2776         arp_key.filler2 = 0;
2777         arp_key.filler3 = 0;
2778
2779         struct arp_entry_data *ret_arp_data = NULL;
2780         uint64_t now;
2781         if (ARPICMP_DEBUG) {
2782                 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2783                 arp_key.ip, arp_key.port_id);
2784         }
2785
2786         int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2787                                          (void **)&ret_arp_data);
2788         now = rte_rdtsc();
2789
2790         if (ARPICMP_DEBUG)
2791                 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2792                         (int)timer->expire, now);
2793         if (ret < 0) {
2794                 printf("Should not have come here\n");
2795                 return;
2796         } else {
2797                 if (ret_arp_data->mode == DYNAMIC_ARP) {
2798                         rte_rwlock_write_lock(&ret_arp_data->queue_lock);
2799                         if (ret_arp_data->status == PROBE ||
2800                                 ret_arp_data->status == INCOMPLETE) {
2801                                 if (ret_arp_data->retry_count == 3) {
2802                                         remove_arp_entry(ret_arp_data, arg);
2803                                 } else {
2804                                         ret_arp_data->retry_count++;
2805
2806                                         if (ARPICMP_DEBUG) {
2807                                                 RTE_LOG(INFO, LIBARP,
2808                                                 "RETRY ARP..retry count : %u\n",
2809                                                 ret_arp_data->retry_count);
2810
2811                                                 RTE_LOG(INFO, LIBARP,
2812                                                 "TIMER STARTED FOR %u seconds\n",
2813                                                         ARP_TIMER_EXPIRY);
2814                                         }
2815
2816                                         if (ifm_chk_port_ipv4_enabled
2817                                                 (ret_arp_data->port)) {
2818                                                 request_arp(ret_arp_data->port,
2819                                                                 ret_arp_data->ip);
2820                                         } else {
2821                                                 if (ARPICMP_DEBUG)
2822                                                         RTE_LOG(INFO, LIBARP,
2823                                                         "%s: IP is not enabled on port %u"
2824                                                         ", not sending GARP\n\r",
2825                                                         __FUNCTION__,
2826                                                         ret_arp_data->port);
2827                                         }
2828
2829                                         if (rte_timer_reset(ret_arp_data->timer,
2830                                                                 (PROBE_TIME *
2831                                                                  rte_get_tsc_hz()/ 1000),
2832                                                                 SINGLE,
2833                                                                 timer_lcore,
2834                                                                 arp_timer_callback,
2835                                                                 arg) < 0)
2836                                         if (ARPICMP_DEBUG)
2837                                                 RTE_LOG(INFO, LIBARP,
2838                                                         "Err : Timer already running\n");
2839
2840                                 }
2841                         } else if (ret_arp_data->status == COMPLETE) {
2842                                 if (now <= (ret_arp_data->n_confirmed +
2843                                          (arp_timeout * rte_get_tsc_hz()))) {
2844                                         if (rte_timer_reset(ret_arp_data->timer,
2845                                                                 (arp_timeout *
2846                                                                  rte_get_tsc_hz()), SINGLE,
2847                                                                 timer_lcore,
2848                                                                 arp_timer_callback,
2849                                                                 arg) < 0)
2850                                         if (ARPICMP_DEBUG)
2851                                                 RTE_LOG(INFO, LIBARP,
2852                                                         "Err : Timer already running\n");
2853                                 } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2854                                         if (rte_timer_reset(ret_arp_data->timer,
2855                                                                 (arp_timeout *
2856                                                                  rte_get_tsc_hz()), SINGLE,
2857                                                                 timer_lcore,
2858                                                                 arp_timer_callback,
2859                                                                 arg) < 0)
2860                                         if (ARPICMP_DEBUG)
2861                                                 RTE_LOG(INFO, LIBARP,
2862                                                         "Err : Timer already running\n");
2863                                 } else {
2864                                         ret_arp_data->status = STALE;
2865                                         p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2866                                 }
2867                         }
2868                         rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
2869                 } else {
2870                         rte_hash_del_key(arp_hash_handle, &arp_key);
2871                 }
2872         }
2873         return;
2874 }
2875
2876 void nd_timer_callback(struct rte_timer *timer, void *arg)
2877 {
2878         struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
2879         struct nd_key_ipv6 nd_key;
2880         int j;
2881         struct nd_entry_data *ret_nd_data = NULL;
2882         uint64_t now;
2883
2884         nd_key.port_id = timer_key->port_id;
2885         nd_key.filler1 = 0;
2886         nd_key.filler2 = 0;
2887         nd_key.filler3 = 0;
2888
2889         rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
2890
2891         if (ARPICMP_DEBUG) {
2892                 RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
2893                 nd_key.port_id);
2894         }
2895
2896         int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
2897                                          (void **)&ret_nd_data);
2898         now = rte_rdtsc();
2899
2900         if (ARPICMP_DEBUG)
2901                 RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
2902                         (int)timer->expire, now);
2903         if (ret < 0) {
2904                 printf("Should not have come here \n");
2905                 for (j = 0; j < 16; j++)
2906                         printf("*%d ", nd_key.ipv6[j]);
2907                 printf("*%d ", nd_key.port_id);
2908                 return;
2909         } else {
2910                 if (ret_nd_data->mode == DYNAMIC_ARP) {
2911                         rte_rwlock_write_lock(&ret_nd_data->queue_lock);
2912                         if (ret_nd_data->status == PROBE ||
2913                                 ret_nd_data->status == INCOMPLETE) {
2914                                 if (ret_nd_data->retry_count == 3) {
2915                                         remove_nd_entry_ipv6(ret_nd_data, arg);
2916                                 } else {
2917                                         ret_nd_data->retry_count++;
2918
2919                                         if (ARPICMP_DEBUG) {
2920                                                 RTE_LOG(INFO, LIBARP,
2921                                                 "RETRY ND..retry count : %u\n",
2922                                                 ret_nd_data->retry_count);
2923
2924                                                 RTE_LOG(INFO, LIBARP,
2925                                                 "TIMER STARTED FOR %u seconds\n",
2926                                                         ARP_TIMER_EXPIRY);
2927                                         }
2928
2929                                         request_nd(ret_nd_data->ipv6,
2930                                                  ifm_get_port(ret_nd_data->port));
2931                                         if (rte_timer_reset(ret_nd_data->timer,
2932                                                                 (PROBE_TIME *
2933                                                                  rte_get_tsc_hz()/ 1000),
2934                                                                 SINGLE,
2935                                                                 timer_lcore,
2936                                                                 nd_timer_callback,
2937                                                                 arg) < 0)
2938                                         if (ARPICMP_DEBUG)
2939                                                 RTE_LOG(INFO, LIBARP,
2940                                                         "Err : Timer already running\n");
2941
2942                                 }
2943                         } else if (ret_nd_data->status == COMPLETE) {
2944                                 if (now <= (ret_nd_data->n_confirmed +
2945                                  (arp_timeout * rte_get_tsc_hz()))) {
2946                                         if (rte_timer_reset(ret_nd_data->timer,
2947                                                                 (arp_timeout *
2948                                                                  rte_get_tsc_hz()), SINGLE,
2949                                                                 timer_lcore,
2950                                                                 nd_timer_callback,
2951                                                                 arg) < 0)
2952                                         if (ARPICMP_DEBUG)
2953                                                 RTE_LOG(INFO, LIBARP,
2954                                                         "Err : Timer already running\n");
2955                                 } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2956                                         if (rte_timer_reset(ret_nd_data->timer,
2957                                                                 (arp_timeout *
2958                                                                  rte_get_tsc_hz()), SINGLE,
2959                                                                 timer_lcore,
2960                                                                 nd_timer_callback,
2961                                                                 arg) < 0)
2962                                         if (ARPICMP_DEBUG)
2963                                                 RTE_LOG(INFO, LIBARP,
2964                                                         "Err : Timer already running\n");
2965                                 } else {
2966                                         printf("making it stale\n");
2967                                         ret_nd_data->status = STALE;
2968                                         p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
2969                                 }
2970                         }
2971                         rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
2972                 } else {
2973                         rte_hash_del_key(nd_hash_handle, &nd_key);
2974                 }
2975         }
2976         return;
2977 }
2978
2979 void create_arp_table(void)
2980 {
2981
2982         int i;
2983         for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2984                 populate_arp_entry((const struct ether_addr *)
2985                                          &arp_entry_data_table[i].eth_addr,
2986                                          arp_entry_data_table[i].ip,
2987                                          (uint8_t) arp_entry_data_table[i].port,
2988                                          STATIC_ARP);
2989         }
2990         print_arp_table();
2991
2992         return;
2993 }
2994
2995 void create_nd_table(void)
2996 {
2997
2998         int i;
2999         for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
3000                 populate_nd_entry((const struct ether_addr *)
3001                                         nd_entry_data_table[i].eth_addr,
3002                                         nd_entry_data_table[i].ipv6,
3003                                         (uint8_t) nd_entry_data_table[i].port,
3004                                         STATIC_ND);
3005         }
3006         print_nd_table();
3007         return;
3008 }
3009
3010 void send_gratuitous_arp(l2_phy_interface_t *port)
3011 {
3012         struct ether_hdr *eth_h;
3013         struct arp_hdr *arp_h;
3014
3015         struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
3016
3017         if (port == NULL) {
3018                 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
3019                 return;
3020
3021         }
3022
3023         if (arp_pkt == NULL) {
3024                 if (ARPICMP_DEBUG)
3025                         RTE_LOG(INFO, LIBARP,
3026                                 "Error allocating arp_pkt rte_mbuf\n");
3027                 return;
3028         }
3029
3030         eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
3031
3032         ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
3033         ether_addr_copy((struct ether_addr *)
3034                         &port->macaddr[0], &eth_h->s_addr);
3035         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
3036
3037         arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
3038         arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
3039         arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
3040         arp_h->arp_hln = ETHER_ADDR_LEN;
3041         arp_h->arp_pln = sizeof(uint32_t);
3042         arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
3043
3044         ether_addr_copy((struct ether_addr *)
3045                         &port->macaddr[0], &arp_h->arp_data.arp_sha);
3046         if (port->ipv4_list == NULL) {
3047                 if (ARPICMP_DEBUG)
3048                         RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
3049                                 __FUNCTION__);
3050                 return;
3051         }
3052         arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
3053         ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
3054         //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
3055         arp_h->arp_data.arp_tip = 0;    //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
3056         //  RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
3057         //arp_h->arp_data.arp_sip);
3058         // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
3059         arp_pkt->pkt_len = 42;
3060         arp_pkt->data_len = 42;
3061
3062         if (ARPICMP_DEBUG) {
3063                 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
3064                 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
3065         }
3066         port->transmit_single_pkt(port, arp_pkt);
3067 }
3068
3069 void set_arpdebug(int flag)
3070 {
3071         if (flag) {
3072                 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
3073                 ARPICMP_DEBUG = 1;
3074                 NDIPV6_DEBUG = 1;
3075
3076         } else {
3077                 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
3078                 ARPICMP_DEBUG = 0;
3079                 NDIPV6_DEBUG = 0;
3080         }
3081 }
3082
3083 void set_arptimeout(uint32_t timeout_val)
3084 {
3085         if (timeout_val == 0) {
3086                 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
3087                 return;
3088         }
3089         if (ARPICMP_DEBUG)
3090                 RTE_LOG(INFO, LIBARP,
3091                         "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
3092                         arp_timeout, timeout_val);
3093         arp_timeout = timeout_val;
3094         if (ARPICMP_DEBUG)
3095                 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",
3096                         arp_timeout);
3097 }