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