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