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