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