Merge "update userguide alignment"
[samplevnf.git] / common / VIL / l2l3_stack / lib_arp.c
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <execinfo.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdint.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <rte_common.h>
24 #include <rte_malloc.h>
25 #include <rte_ip.h>
26 #include <rte_byteorder.h>
27 #include <rte_log.h>
28 #include <rte_table_lpm.h>
29 #include <rte_table_hash.h>
30 #include <rte_pipeline.h>
31 #include <rte_arp.h>
32 #include <rte_icmp.h>
33 #include <rte_hash.h>
34 #include <rte_jhash.h>
35 #include <rte_cycles.h>
36 #include <rte_timer.h>
37 #include <tsx.h>
38 #include "interface.h"
39 #include "l2_proto.h"
40 #include "lib_arp.h"
41 #include "l3fwd_lpm4.h"
42 #include "vnf_common.h"
43 #include "gateway.h"
44
45 #if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN)
46 #define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x)
47 #define CHECK_ENDIAN_32(x) rte_be_to_cpu_32(x)
48 #else
49 #define CHECK_ENDIAN_16(x) (x)
50 #define CHECK_ENDIAN_32(x) (x)
51 #endif
52
53 #define NB_ARPICMP_MBUF  64
54 #define NB_NDICMP_MBUF  64
55 #define IP_VERSION_4 0x40
56 #define IP_HDRLEN  0x05         /**< default IP header length == five 32-bits words. */
57 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
58 #define MAX_POOL                32
59 #define is_multicast_ipv4_addr(ipv4_addr) \
60         (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
61
62 extern uint8_t prv_in_port_a[PIPELINE_MAX_PORT_IN];
63 extern uint32_t timer_lcore;
64 extern int USE_RTM_LOCKS;
65 uint32_t arp_timeout = ARP_TIMER_EXPIRY;
66 uint32_t arp_buffer = ARP_BUF_DEFAULT;
67 uint32_t nd_buffer = ARP_BUF_DEFAULT;
68
69 /*ND IPV6 */
70 #define INADDRSZ 4
71 #define IN6ADDRSZ 16
72 #define MAX_PORTS       32
73
74 int my_inet_pton_ipv6(int af, const char *src, void *dst);
75 static int inet_pton_ipv6(const char *src, unsigned char *dst);
76 static int inet_pton_ipv4(const char *src, unsigned char *dst);
77 static void local_arp_cache_init(void);
78 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]);
79 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
80                                                                 uint8_t netmask_ipv6[]);
81
82 uint8_t vnf_common_arp_lib_init;
83 uint8_t vnf_common_nd_lib_init;
84 uint8_t loadb_pipeline_count;
85
86 uint32_t ARPICMP_DEBUG;
87 uint32_t NDIPV6_DEBUG;
88
89 uint32_t arp_route_tbl_index;
90 uint32_t nd_route_tbl_index;
91 uint32_t link_hw_addr_array_idx;
92
93 uint32_t lib_arp_get_mac_req;
94 uint32_t lib_arp_nh_found;
95 uint32_t lib_arp_no_nh_found;
96 uint32_t lib_arp_arp_entry_found;
97 uint32_t lib_arp_no_arp_entry_found;
98 uint32_t lib_arp_populate_called;
99 uint32_t lib_arp_delete_called;
100 uint32_t lib_arp_duplicate_found;
101
102 uint32_t lib_nd_get_mac_req;
103 uint32_t lib_nd_nh_found;
104 uint32_t lib_nd_no_nh_found;
105 uint32_t lib_nd_nd_entry_found;
106 uint32_t lib_nd_no_arp_entry_found;
107 uint32_t lib_nd_populate_called;
108 uint32_t lib_nd_delete_called;
109 uint32_t lib_nd_duplicate_found;
110 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
111 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
112
113 struct rte_mbuf *lib_arp_pkt[MAX_PORTS];
114 struct rte_mbuf *lib_nd_pkt[MAX_PORTS];
115
116 uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
117 uint8_t default_ip[4] = { 0, 0, 1, 1 };
118
119 uint64_t start_tsc[4];
120 uint64_t end_tsc[4];
121 #define ticks_per_ms  (rte_get_tsc_hz()/1000)
122
123 #define MAX_NUM_ARP_CACHE_MAC_ADDRESS           16
124
125 /***** ARP local cache *****/
126 struct arp_data *p_arp_data;
127 //struct arp_cache arp_local_cache[MAX_PORTS];
128 uint8_t arp_cache_hw_laddr_valid[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
129         0, 0, 0, 0, 0, 0, 0, 0,
130         0, 0, 0, 0, 0, 0, 0, 0
131 };
132
133 /**
134  * handler lock.
135  */
136 rte_rwlock_t arp_hash_handle_lock;
137 rte_rwlock_t nd_hash_handle_lock;
138
139 void update_nhip_access(uint8_t dest_if)
140 {
141         p_arp_data->update_tsc[dest_if] = rte_rdtsc();
142 }
143
144 static struct arp_entry_data arp_entry_data_default = {
145         .status = COMPLETE,
146         .num_pkts = 0,
147 };
148
149 static struct nd_entry_data nd_entry_data_default = {
150         .status = COMPLETE,
151         .num_pkts = 0,
152 };
153
154 /**
155  * memory pool for queued up user pkts.
156  */
157 struct rte_mempool *arp_icmp_pktmbuf_tx_pool;
158
159 static struct rte_hash_parameters arp_hash_params = {
160         .name = "ARP",
161         .entries = 64,
162         .reserved = 0,
163         .key_len = sizeof(struct arp_key_ipv4),
164         .hash_func = rte_jhash,
165         .hash_func_init_val = 0,
166 };
167
168 static struct rte_hash_parameters nd_hash_params = {
169         .name = "ND",
170         .entries = 64,
171         .reserved = 0,
172         .key_len = sizeof(struct nd_key_ipv6),
173         .hash_func = rte_jhash,
174         .hash_func_init_val = 0,
175 };
176
177 struct ether_addr broadcast_ether_addr = {
178        .addr_bytes[0] = 0xFF,
179        .addr_bytes[1] = 0xFF,
180        .addr_bytes[2] = 0xFF,
181        .addr_bytes[3] = 0xFF,
182        .addr_bytes[4] = 0xFF,
183        .addr_bytes[5] = 0xFF,
184 };
185
186 static const struct ether_addr null_ether_addr = {
187     .addr_bytes[0] = 0x00,
188     .addr_bytes[1] = 0x00,
189     .addr_bytes[2] = 0x00,
190     .addr_bytes[3] = 0x00,
191     .addr_bytes[4] = 0x00,
192     .addr_bytes[5] = 0x00,
193 };
194
195 struct rte_hash *arp_hash_handle;
196 struct rte_hash *nd_hash_handle;
197
198 void print_pkt1(struct rte_mbuf *pkt);
199
200 struct app_params *myApp;
201 struct rte_pipeline *myP;
202 uint8_t num_vnf_threads;
203
204 /**
205 * A structure for Arp port address
206 */
207 struct arp_port_address {
208         uint32_t ip;                     /**< Ip address */
209         uint8_t mac_addr[6]; /**< Mac address */
210 };
211
212 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
213 struct rte_mempool *timer_mempool_arp;
214
215 int timer_objs_mempool_count = 70000;
216
217 #define MAX_NUM_ARP_ENTRIES 64
218 #define MAX_NUM_ND_ENTRIES 64
219 #define MAX_ARP_DATA_ENTRY_TABLE 7
220
221 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = {
222         {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 1)},
223         {{0, 0, 0, 0, 0, 2}, 0, INCOMPLETE, IPv4(1, 1, 1, 2)},
224         {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 3)},
225         {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 4)},
226         {{0, 0, 0, 0, 0, 4}, 1, INCOMPLETE, IPv4(1, 1, 1, 5)},
227         {{0, 0, 0, 0, 0, 5}, 0, INCOMPLETE, IPv4(1, 1, 1, 6)},
228         {{0, 0, 0, 0, 0, 6}, 1, INCOMPLETE, IPv4(1, 1, 1, 7)},
229 };
230
231 #define MAX_ND_DATA_ENTRY_TABLE 7
232 struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = {
233         {{0, 0, 0, 0, 0, 8}, 1, INCOMPLETE,
234          {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, 0},
235
236         {{0, 0, 0, 0, 0, 9}, 1, INCOMPLETE,
237          {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, 0},
238         {{0, 0, 0, 0, 0, 10}, 2, INCOMPLETE,
239          {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
240         {{0, 0, 0, 0, 0, 11}, 3, INCOMPLETE,
241          {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
242         {{0, 0, 0, 0, 0, 12}, 4, INCOMPLETE,
243          {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
244         {{0, 0, 0, 0, 0, 13}, 5, INCOMPLETE,
245          {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
246         {{0, 0, 0, 0, 0, 14}, 6, INCOMPLETE,
247          {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
248 };
249
250 void print_trace(void);
251
252 uint32_t get_arp_buf(void)
253 {
254        return arp_buffer;
255 }
256
257 uint32_t get_nd_buf(void)
258 {
259         return nd_buffer;
260 }
261
262 uint8_t arp_cache_dest_mac_present(uint32_t out_port)
263 {
264         return p_arp_data->arp_cache_hw_laddr_valid[out_port];
265 }
266
267 uint8_t nd_cache_dest_mac_present(uint32_t out_port)
268 {
269         return p_arp_data->nd_cache_hw_laddr_valid[out_port];
270 }
271
272 /* Obtain a backtrace and print it to stdout. */
273 void print_trace(void)
274 {
275         void *array[10];
276         size_t size;
277         char **strings;
278         size_t i;
279
280         size = backtrace(array, 10);
281         strings = backtrace_symbols(array, size);
282
283         RTE_LOG(INFO, LIBARP, "Obtained %zd stack frames.\n", size);
284
285         for (i = 0; i < size; i++)
286                 RTE_LOG(INFO, LIBARP, "%s\n", strings[i]);
287
288         free(strings);
289 }
290
291
292 /* Added for Multiport changes*/
293 struct arp_entry_data *get_dest_mac_addr_ipv4(const uint32_t nhip,
294                                  uint32_t phy_port, struct ether_addr *hw_addr)
295 {
296         struct arp_entry_data *ret_arp_data = NULL;
297         uint8_t index;
298
299         /* as part of optimization we store mac address in cache
300          * & thus can be sent without having to retrieve
301          */
302         if (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         if (ret_arp_data->timer) {
987                 rte_timer_stop(ret_arp_data->timer);
988                 rte_free(ret_arp_data->timer_key);
989                 rte_free(ret_arp_data->buf_pkts);
990                 ret_arp_data->buf_pkts = NULL;
991         }
992
993         if (ARPICMP_DEBUG) {
994                 RTE_LOG(INFO, LIBARP,
995                         "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
996                         (arp_key->ip >> 24),
997                         ((arp_key->ip & 0x00ff0000) >> 16),
998                         ((arp_key->ip & 0x0000ff00) >>  8),
999                         ((arp_key->ip & 0x000000ff)),
1000                         arp_key->port_id);
1001         }
1002         rte_hash_del_key(arp_hash_handle, arp_key);
1003         print_arp_table();
1004 }
1005
1006 /* ND IPv6 */
1007 void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg)
1008 {
1009         int i = 0;
1010         struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
1011
1012         lib_nd_delete_called++;
1013
1014         rte_timer_stop(ret_nd_data->timer);
1015         rte_free(ret_nd_data->timer_key);
1016         rte_free(ret_nd_data->buf_pkts);
1017         ret_nd_data->buf_pkts = NULL;
1018
1019         if (NDIPV6_DEBUG) {
1020                 RTE_LOG(INFO, LIBARP,
1021                         "Deletes rte hash table nd entry for port %d ipv6=",
1022                         timer_key->port_id);
1023                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1024                         RTE_LOG(INFO, LIBARP, "%02X%02X ", timer_key->ipv6[i],
1025                                 timer_key->ipv6[i + 1]);
1026                 }
1027         }
1028         rte_hash_del_key(nd_hash_handle, timer_key);
1029 }
1030
1031 int
1032 arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
1033 {
1034         rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1035         if (ret_arp_data->num_pkts  == NUM_DESC) {
1036                 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1037                 return 0;
1038         }
1039
1040         ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
1041         rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1042         return 0;
1043 }
1044
1045 void
1046 arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
1047         struct ether_addr *hw_addr, uint8_t port_id)
1048 {
1049         l2_phy_interface_t *port = ifm_get_port(port_id);
1050         struct rte_mbuf *pkt, *tmp;
1051         uint8_t *eth_dest, *eth_src;
1052         int i;
1053
1054
1055         if (!hw_addr || !ret_arp_data)
1056                 return;
1057
1058         rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1059         for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
1060                 pkt = ret_arp_data->buf_pkts[i];
1061
1062                 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1063                 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1064
1065                 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1066                 memcpy(eth_src, get_link_hw_addr(port_id),
1067                                 sizeof(struct ether_addr));
1068                 port->transmit_single_pkt(port, pkt);
1069                 tmp = pkt;
1070                 rte_pktmbuf_free(tmp);
1071         }
1072         printf("arp send buffered pkts = %d\n",ret_arp_data->num_pkts);
1073         ret_arp_data->num_pkts = 0;
1074         rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1075 }
1076
1077 int
1078 nd_queue_unresolved_packet(struct nd_entry_data *ret_nd_data, struct rte_mbuf *pkt)
1079 {
1080         rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1081         if (ret_nd_data->num_pkts  == get_nd_buf()) {
1082                 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1083                 return 0;
1084         }
1085
1086         ret_nd_data->buf_pkts[ret_nd_data->num_pkts++] = pkt;
1087         rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1088         return 0;
1089 }
1090
1091 void
1092 nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
1093         struct ether_addr *hw_addr, uint8_t port_id)
1094 {
1095         l2_phy_interface_t *port = ifm_get_port(port_id);
1096         struct rte_mbuf *pkt, *tmp;
1097         uint8_t *eth_dest, *eth_src;
1098         int i;
1099
1100         if (!hw_addr || !ret_nd_data)
1101                 return;
1102
1103         rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1104         for (i=0;i<(int)ret_nd_data->num_pkts;i++) {
1105                 pkt = ret_nd_data->buf_pkts[i];
1106                 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1107                 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1108
1109                 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1110                 memcpy(eth_src, get_link_hw_addr(port_id),
1111                                 sizeof(struct ether_addr));
1112                 port->transmit_single_pkt(port, pkt);
1113                 tmp = pkt;
1114                 rte_pktmbuf_free(tmp);
1115         }
1116         ret_nd_data->num_pkts = 0;
1117         rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1118 }
1119
1120 void
1121 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1122                          uint8_t portid, uint8_t mode)
1123 {
1124         struct arp_key_ipv4 arp_key;
1125         struct arp_entry_data *new_arp_data;
1126         arp_key.port_id = portid;
1127         arp_key.ip = ipaddr;
1128         arp_key.filler1 = 0;
1129         arp_key.filler2 = 0;
1130         arp_key.filler3 = 0;
1131
1132         lib_arp_populate_called++;
1133         printf("populate_arp_entry ip %x, port %d\n", arp_key.ip, arp_key.port_id);
1134
1135         if (ARPICMP_DEBUG)
1136                 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1137                         arp_key.ip, arp_key.port_id);
1138
1139         new_arp_data = retrieve_arp_entry(arp_key, mode);
1140         if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1141                 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1142                 && mode == STATIC_ARP))) {
1143                 if (ARPICMP_DEBUG)
1144                         RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry "
1145                                 "already exists(%d %d)\n", new_arp_data->mode, mode);
1146                 return;
1147         }
1148
1149         if (mode == DYNAMIC_ARP) {
1150
1151                 if (new_arp_data
1152                                 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1153                         printf("entry exists\n");
1154
1155                         if (ARPICMP_DEBUG) {
1156                                 RTE_LOG(INFO, LIBARP,
1157                                         "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1158                                         (arp_key.ip >> 24),
1159                                         ((arp_key.ip & 0x00ff0000) >> 16),
1160                                         ((arp_key.ip & 0x0000ff00) >> 8),
1161                                         ((arp_key.ip & 0x000000ff)),
1162                                         arp_key.port_id);
1163                         }
1164                         lib_arp_duplicate_found++;
1165                         rte_rwlock_write_lock(&new_arp_data->queue_lock);
1166                         new_arp_data->retry_count = 0;  // Reset
1167                         if (new_arp_data->status == STALE) {
1168                                 new_arp_data->status = PROBE;
1169                                 if (ifm_chk_port_ipv4_enabled
1170                                         (new_arp_data->port) != IFM_FAILURE) {
1171                                         request_arp(new_arp_data->port,
1172                                                         new_arp_data->ip);
1173                                 } else {
1174                                         if (ARPICMP_DEBUG)
1175                                                 RTE_LOG(INFO, LIBARP,
1176                                                 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1177                                                 __FUNCTION__,
1178                                                 new_arp_data->port);
1179                                 }
1180                         }
1181
1182                         if (rte_timer_reset(new_arp_data->timer,
1183                                                 (arp_timeout * rte_get_tsc_hz()),
1184                                                 SINGLE, timer_lcore,
1185                                                 arp_timer_callback,
1186                                                 new_arp_data->timer_key) < 0) {
1187                                 if (ARPICMP_DEBUG)
1188                                         RTE_LOG(INFO, LIBARP,
1189                                                 "Err : Timer already running\n");
1190                         }
1191                         rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1192                         return;
1193                 } else {
1194                         rte_rwlock_write_lock(&new_arp_data->queue_lock);
1195                         ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
1196                         if ((new_arp_data->status == INCOMPLETE) ||
1197                                 (new_arp_data->status == PROBE)) {
1198                                 new_arp_data->status = COMPLETE;
1199                                 new_arp_data->mode = mode;
1200                                 new_arp_data->n_confirmed = rte_rdtsc();
1201                                 new_arp_data->retry_count = 0;
1202                                 if (rte_timer_reset(new_arp_data->timer,
1203                                                 (arp_timeout * rte_get_tsc_hz()),
1204                                                 SINGLE, timer_lcore,
1205                                                 arp_timer_callback,
1206                                                 new_arp_data->timer_key) < 0) {
1207                                         if (ARPICMP_DEBUG)
1208                                                 RTE_LOG(INFO, LIBARP,
1209                                                 "Err : Timer already running\n");
1210                                 }
1211                         }
1212                         rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1213                         return;
1214                 }
1215         } else {
1216                 if (new_arp_data
1217                                 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1218
1219                         if (ARPICMP_DEBUG) {
1220                                 RTE_LOG(INFO, LIBARP,
1221                                         "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1222                                         (arp_key.ip >> 24),
1223                                         ((arp_key.ip & 0x00ff0000) >> 16),
1224                                         ((arp_key.ip & 0x0000ff00) >> 8),
1225                                         ((arp_key.ip & 0x000000ff)),
1226                                         arp_key.port_id);
1227                         }
1228                         lib_arp_duplicate_found++;
1229                 } else {
1230                         uint32_t size =
1231                                         RTE_CACHE_LINE_ROUNDUP(sizeof
1232                                                          (struct arp_entry_data));
1233                         new_arp_data =
1234                                         rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1235                         new_arp_data->eth_addr = *hw_addr;
1236                         new_arp_data->status = COMPLETE;
1237                         new_arp_data->port = portid;
1238                         new_arp_data->ip = ipaddr;
1239                         new_arp_data->mode = mode;
1240                         new_arp_data->num_pkts = 0;
1241
1242                         /* attempt to add arp_entry to hash */
1243                         int ret;
1244                         ret = add_arp_data(&arp_key, new_arp_data);
1245                         if (ret) {
1246                                 /* Some other thread created an entry for this ip */
1247                                 rte_free(new_arp_data);
1248                         }
1249
1250                         if (ARPICMP_DEBUG) {
1251                                 RTE_LOG(INFO, LIBARP,
1252                                         "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1253                                         (arp_key.ip >> 24),
1254                                         ((arp_key.ip & 0x00ff0000) >> 16),
1255                                         ((arp_key.ip & 0x0000ff00) >> 8),
1256                                         ((arp_key.ip & 0x000000ff)),
1257                                         arp_key.port_id);
1258                         }
1259                         #ifdef L3_STACK_SUPPORT
1260                         // Call l3fwd module for resolving 2_adj structure.
1261                         resolve_l2_adj(ipaddr, portid, hw_addr);
1262                         #endif
1263                 }
1264         }
1265
1266         if (ARPICMP_DEBUG) {
1267                 /* print entire hash table */
1268                 RTE_LOG(INFO, LIBARP,
1269                         "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x  ip=%d.%d.%d.%d  on port=%d\n",
1270                         new_arp_data->eth_addr.addr_bytes[0],
1271                         new_arp_data->eth_addr.addr_bytes[1],
1272                         new_arp_data->eth_addr.addr_bytes[2],
1273                         new_arp_data->eth_addr.addr_bytes[3],
1274                         new_arp_data->eth_addr.addr_bytes[4],
1275                         new_arp_data->eth_addr.addr_bytes[5],
1276                         (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1277                         ((arp_key.ip & 0x0000ff00) >> 8),
1278                         ((arp_key.ip & 0x000000ff)), portid);
1279                 puts("");
1280         }
1281 }
1282
1283 /*
1284  * ND IPv6
1285  *
1286  * Install key - data pair in Hash table - From Pipeline Configuration
1287  *
1288  */
1289 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1290                                          uint8_t portid, uint8_t mode)
1291 {
1292
1293         /* need to lock here if multi-threaded */
1294         /* rte_hash_add_key_data is not thread safe */
1295         uint8_t i, val = 0;
1296         struct nd_key_ipv6 nd_key;
1297         nd_key.port_id = portid;
1298
1299         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1300                 nd_key.ipv6[i] = ipv6[i];
1301                 val |= ipv6[i];
1302         }
1303
1304         if (!val)
1305                 return;
1306
1307         nd_key.filler1 = 0;
1308         nd_key.filler2 = 0;
1309         nd_key.filler3 = 0;
1310
1311         lib_nd_populate_called++;
1312
1313         /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1314         struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, mode);
1315         if (new_nd_data && ((new_nd_data->mode == STATIC_ND
1316                 && mode == DYNAMIC_ND) || (new_nd_data->mode == DYNAMIC_ND
1317                 && mode == STATIC_ND))) {
1318                 if (ARPICMP_DEBUG)
1319                 RTE_LOG(INFO, LIBARP, "populate_arp_entry: ND entry already"
1320                                 " exists(%d %d)\n", new_nd_data->mode, mode);
1321                 return;
1322         }
1323
1324         if (mode == DYNAMIC_ND) {
1325                 if (new_nd_data
1326                                 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1327
1328                         if (NDIPV6_DEBUG) {
1329                                 RTE_LOG(INFO, LIBARP,
1330                                         "nd_entry exists port %d ipv6 = ",
1331                                         nd_key.port_id);
1332                                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1333
1334                                         RTE_LOG(INFO, LIBARP, "%02X%02X ",
1335                                                 nd_key.ipv6[i],
1336                                                 nd_key.ipv6[i + 1]);
1337                                 }
1338                         }
1339
1340                         lib_nd_duplicate_found++;
1341                         rte_rwlock_write_lock(&new_nd_data->queue_lock);
1342                         if (new_nd_data->status == STALE) {
1343                                 new_nd_data->retry_count = 0;   // Reset
1344                                 new_nd_data->status = PROBE;
1345                                 request_nd(new_nd_data->ipv6,
1346                                          ifm_get_port(new_nd_data->port));
1347
1348                                 if (rte_timer_reset(new_nd_data->timer,
1349                                                 (arp_timeout * rte_get_tsc_hz()),
1350                                                 SINGLE, timer_lcore,
1351                                                 nd_timer_callback,
1352                                                 new_nd_data->timer_key) < 0) {
1353                                         if (ARPICMP_DEBUG)
1354                                                 RTE_LOG(INFO, LIBARP,
1355                                                 "Err : Timer already running\n");
1356                                 }
1357                         }
1358                         rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1359                         return;
1360                 } else {
1361                         rte_rwlock_write_lock(&new_nd_data->queue_lock);
1362                         ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
1363                         if ((new_nd_data->status == INCOMPLETE) ||
1364                                 (new_nd_data->status == PROBE)) {
1365                                 new_nd_data->status = COMPLETE;
1366                                 new_nd_data->mode = mode;
1367                                 new_nd_data->n_confirmed = rte_rdtsc();
1368                                 new_nd_data->retry_count = 0;
1369                                 if (rte_timer_reset(new_nd_data->timer,
1370                                         (arp_timeout * rte_get_tsc_hz()),
1371                                         SINGLE, timer_lcore,
1372                                         nd_timer_callback,
1373                                         new_nd_data->timer_key) < 0) {
1374                                         if (ARPICMP_DEBUG)
1375                                                 RTE_LOG(INFO, LIBARP,
1376                                                 "Err : Timer already running\n");
1377                                 }
1378                         }
1379                         rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1380                         return;
1381                 }
1382
1383         } else {
1384                 if (new_nd_data
1385                                 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1386                         if (NDIPV6_DEBUG) {
1387                                 RTE_LOG(INFO, LIBARP,
1388                                         "nd_entry exists port %d ipv6 = ",
1389                                         nd_key.port_id);
1390                                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1391
1392                                         RTE_LOG(INFO, LIBARP, "%02X%02X ",
1393                                                 nd_key.ipv6[i],
1394                                                 nd_key.ipv6[i + 1]);
1395                                 }
1396                         }
1397
1398                         lib_nd_duplicate_found++;
1399                 } else {
1400                         uint32_t size =
1401                                         RTE_CACHE_LINE_ROUNDUP(sizeof
1402                                                          (struct nd_entry_data));
1403                         new_nd_data =
1404                                         rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1405
1406                         new_nd_data->eth_addr = *hw_addr;
1407                         new_nd_data->status = COMPLETE;
1408                         new_nd_data->port = portid;
1409                         new_nd_data->mode = mode;
1410                         for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1411                                 new_nd_data->ipv6[i] = ipv6[i];
1412                         }
1413                         new_nd_data->mode = mode;
1414                         new_nd_data->num_pkts = 0;
1415
1416                         /*Add a key-data pair at hash table for ND IPv6 static routing */
1417                         /* attempt to add arp_entry to hash */
1418                         int ret;
1419                         ret = add_nd_data(&nd_key, new_nd_data);
1420                         if (ret) {
1421                                 rte_free(new_nd_data);
1422                         }
1423
1424                         /* need to check the return value of the hash add */
1425                         #ifdef L3_STACK_SUPPORT
1426                         // Call l3fwd module for resolving 2_adj structure.
1427                         resolve_l2_adj(ipaddr, portid, hw_addr);
1428                         #endif
1429                 }
1430         }
1431
1432         if (NDIPV6_DEBUG)
1433                 printf
1434                                 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1435
1436         if (1) {
1437                 /* print entire hash table */
1438                 printf
1439                                 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1440                                  new_nd_data->eth_addr.addr_bytes[0],
1441                                  new_nd_data->eth_addr.addr_bytes[1],
1442                                  new_nd_data->eth_addr.addr_bytes[2],
1443                                  new_nd_data->eth_addr.addr_bytes[3],
1444                                  new_nd_data->eth_addr.addr_bytes[4],
1445                                  new_nd_data->eth_addr.addr_bytes[5], portid);
1446                 RTE_LOG(INFO, LIBARP, "\tipv6=");
1447                 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1448                         new_nd_data->ipv6[i] = ipv6[i];
1449                         RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1450                                 new_nd_data->ipv6[i + 1]);
1451                 }
1452
1453                 RTE_LOG(INFO, LIBARP, "\n");
1454
1455                 puts("");
1456         }
1457 }
1458
1459 void print_pkt1(struct rte_mbuf *pkt)
1460 {
1461         uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1462         int i = 0, j = 0;
1463         RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1464         for (i = 0; i < 20; i++) {
1465                 for (j = 0; j < 20; j++)
1466                         printf("%02x ", rd[(20 * i) + j]);
1467                 RTE_LOG(INFO, LIBARP, "\n");
1468         }
1469 }
1470
1471 #define MAX_NUM_MAC_ADDRESS 16
1472 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1473 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1474 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1475 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1476 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1477 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1478 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1479 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1480 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1481 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1482 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1483 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1484 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1485 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1486 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1487 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1488 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1489 };
1490
1491 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1492 {
1493         return &p_arp_data->link_hw_addr[out_port];
1494 }
1495
1496 void request_arp(uint8_t port_id, uint32_t ip)
1497 {
1498
1499         struct ether_hdr *eth_h;
1500         struct arp_hdr *arp_h;
1501
1502         l2_phy_interface_t *link;
1503         link = ifm_get_port(port_id);
1504         struct rte_mbuf *arp_pkt = lib_arp_pkt[port_id];
1505
1506         if (arp_pkt == NULL) {
1507                 if (ARPICMP_DEBUG)
1508                         RTE_LOG(INFO, LIBARP,
1509                                 "Error allocating arp_pkt rte_mbuf\n");
1510                 return;
1511         }
1512         eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1513
1514         ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
1515         ether_addr_copy((struct ether_addr *)
1516                         &link->macaddr[0], &eth_h->s_addr);
1517         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1518
1519         arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1520         arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1521         arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1522         arp_h->arp_hln = ETHER_ADDR_LEN;
1523         arp_h->arp_pln = sizeof(uint32_t);
1524         arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1525
1526         if (link && link->ipv4_list) {
1527                 arp_h->arp_data.arp_sip =
1528                                 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1529         }
1530         ether_addr_copy((struct ether_addr *)
1531                         &link->macaddr[0], &arp_h->arp_data.arp_sha);
1532         ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1533         arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1534         if (ARPICMP_DEBUG)
1535                 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1536                         arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1537         // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1538         arp_pkt->pkt_len = 42;
1539         arp_pkt->data_len = 42;
1540
1541         if (ARPICMP_DEBUG) {
1542                 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1543                 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1544         }
1545         if (link)
1546                 link->transmit_single_pkt(link, arp_pkt);
1547 //      start_tsc[port_id] = rte_rdtsc();
1548         printf("Sent ARP Request %x \n", arp_h->arp_data.arp_tip);
1549 }
1550
1551 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1552 {
1553         struct ether_hdr *eth_h;
1554         struct ipv4_hdr *ip_h;
1555         struct icmp_hdr *icmp_h;
1556         l2_phy_interface_t *port = ifm_get_port(port_id);
1557
1558         struct rte_mbuf *icmp_pkt = lib_arp_pkt[port_id];
1559         if (icmp_pkt == NULL) {
1560                 if (ARPICMP_DEBUG)
1561                         RTE_LOG(INFO, LIBARP,
1562                                 "Error allocating icmp_pkt rte_mbuf\n");
1563                 return NULL;
1564         }
1565
1566         eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1567
1568         ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1569         icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1570
1571         ip_h->version_ihl = IP_VHL_DEF;
1572         ip_h->type_of_service = 0;
1573         ip_h->total_length =
1574                         rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1575         ip_h->packet_id = 0xaabb;
1576         ip_h->fragment_offset = 0x0000;
1577         ip_h->time_to_live = 64;
1578         ip_h->next_proto_id = IPPROTO_ICMP;
1579         if (port && port->ipv4_list)
1580                 ip_h->src_addr =
1581                                 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1582         ip_h->dst_addr = rte_cpu_to_be_32(ip);
1583
1584         ip_h->hdr_checksum = 0;
1585         ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1586
1587         icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1588         icmp_h->icmp_code = 0;
1589         icmp_h->icmp_ident = 0xdead;
1590         icmp_h->icmp_seq_nb = 0xbeef;
1591
1592         icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1593
1594         icmp_pkt->pkt_len =
1595                         sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1596                         sizeof(struct icmp_hdr);
1597         icmp_pkt->data_len = icmp_pkt->pkt_len;
1598
1599         print_mbuf("TX", 0, icmp_pkt, __LINE__);
1600
1601         return icmp_pkt;
1602 }
1603
1604 void
1605 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1606                                 uint64_t pkt_mask, l2_phy_interface_t *port)
1607 {
1608         RTE_SET_USED(pkt_num);
1609         if (ARPICMP_DEBUG)
1610                 RTE_LOG(INFO, LIBARP,
1611                         "============ARP ENTRY================\n");
1612         if (pkt_mask) {
1613                 if (ARPICMP_DEBUG)
1614                         RTE_LOG(INFO, LIBARP,
1615                                 "============ARP PROCESS================\n");
1616         }
1617
1618         uint64_t pkts_for_process = pkt_mask;
1619         for (; pkts_for_process;) {
1620 /**< process only valid packets. */
1621                 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1622                 uint64_t pkts_mask = 1LLU << pos;    /** <bitmask representing only this packet. */
1623                 pkts_for_process &= ~pkts_mask;                         /** <remove this packet from the mask. */
1624                 process_arpicmp_pkt(pkt[pos], port);
1625         }
1626
1627 }
1628
1629 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1630 {
1631         uint8_t in_port_id = pkt->port;
1632         struct ether_hdr *eth_h;
1633         struct arp_hdr *arp_h;
1634         struct ipv4_hdr *ip_h;
1635         struct icmp_hdr *icmp_h;
1636
1637         uint32_t cksum;
1638         uint32_t ip_addr;
1639
1640         uint32_t req_tip;
1641         eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1642
1643         if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1644                 if (ARPICMP_DEBUG)
1645                         RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1646                                 __FUNCTION__, port->pmdid, __LINE__);
1647                 arp_h =
1648                                 (struct arp_hdr *)((char *)eth_h +
1649                                                          sizeof(struct ether_hdr));
1650                 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1651                         RTE_LOG(INFO, LIBARP,
1652                                 "Invalid hardware format of hardware address - not processing ARP req\n");
1653                 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1654                         RTE_LOG(INFO, LIBARP,
1655                                 "Invalid protocol address format - not processing ARP req\n");
1656                 else if (arp_h->arp_hln != 6)
1657                         RTE_LOG(INFO, LIBARP,
1658                                 "Invalid hardware address length - not processing ARP req\n");
1659                 else if (arp_h->arp_pln != 4)
1660                         RTE_LOG(INFO, LIBARP,
1661                                 "Invalid protocol address length - not processing ARP req\n");
1662                 else {
1663                         if (port->ipv4_list == NULL) {
1664                                 RTE_LOG(INFO, LIBARP,
1665                                         "Ports IPV4 List is NULL.. Unable to Process\n");
1666                                 return;
1667                         }
1668
1669                         if (arp_h->arp_data.arp_tip !=
1670                                         ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1671                                 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1672                                         printf("gratuitous arp received\n");
1673                                         populate_arp_entry(
1674                                                         (struct ether_addr *)&arp_h->arp_data.arp_sha,
1675                                                         rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1676                                                         in_port_id,
1677                                                         DYNAMIC_ARP);
1678
1679                                 } else {
1680                    if (ARPICMP_DEBUG)
1681                                             RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1682                                 }
1683                         }
1684                         /// revise conditionals to allow processing of requests with target ip = this ip and
1685                         //                               processing of replies to destination ip = this ip
1686                         else if (arp_h->arp_op ==
1687                                  rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1688                                 if (ARPICMP_DEBUG) {
1689                                         RTE_LOG(INFO, LIBARP,
1690                                                 "%s, portid %u. Line %d\n\r",
1691                                                 __FUNCTION__, port->pmdid,
1692                                                 __LINE__);
1693
1694                                         RTE_LOG(INFO, LIBARP,
1695                                                 "arp_op %d, ARP_OP_REQUEST %d\n",
1696                                                 arp_h->arp_op,
1697                                                 rte_cpu_to_be_16
1698                                                 (ARP_OP_REQUEST));
1699                                         print_mbuf("RX", in_port_id, pkt,
1700                                                          __LINE__);
1701                                 }
1702                                 populate_arp_entry((struct ether_addr *)
1703                                                          &arp_h->arp_data.arp_sha,
1704                                                          rte_cpu_to_be_32
1705                                                          (arp_h->arp_data.arp_sip),
1706                                                          in_port_id, DYNAMIC_ARP);
1707
1708                                 /*build reply */
1709                                 req_tip = arp_h->arp_data.arp_tip;
1710                                 ether_addr_copy(&eth_h->s_addr, &eth_h->d_addr);
1711                                 ether_addr_copy((struct ether_addr *)&port->macaddr[0], &eth_h->s_addr);  /**< set sender mac address*/
1712                                 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1713                                 ether_addr_copy(&eth_h->s_addr,
1714                                                 &arp_h->arp_data.arp_sha);
1715                                 arp_h->arp_data.arp_tip =
1716                                                 arp_h->arp_data.arp_sip;
1717                                 arp_h->arp_data.arp_sip = req_tip;
1718                                 ether_addr_copy(&eth_h->d_addr,
1719                                                 &arp_h->arp_data.arp_tha);
1720                                 if (ARPICMP_DEBUG)
1721                                         print_mbuf("TX ARP REPLY PKT",
1722                                                          port->pmdid, pkt, __LINE__);
1723                                 port->transmit_bulk_pkts(port, &pkt, 1);
1724                                 if (ARPICMP_DEBUG)
1725                                         print_mbuf("TX", port->pmdid, pkt,
1726                                                          __LINE__);
1727                                 printf("replying arp pkt done\n");
1728                                 return;
1729                         } else if (arp_h->arp_op ==
1730                                          rte_cpu_to_be_16(ARP_OP_REPLY)) {
1731                                 if (ARPICMP_DEBUG) {
1732                                         RTE_LOG(INFO, LIBARP,
1733                                                 "ARP_OP_REPLY received");
1734                                         print_mbuf("RX", port->pmdid, pkt,
1735                                                          __LINE__);
1736                                 }
1737                                 populate_arp_entry((struct ether_addr *)
1738                                                          &arp_h->arp_data.arp_sha,
1739                                                          rte_bswap32(arp_h->
1740                                                                                  arp_data.arp_sip),
1741                                                          in_port_id, DYNAMIC_ARP);
1742
1743                                 return;
1744                         } else {
1745                                 if (ARPICMP_DEBUG)
1746                                         RTE_LOG(INFO, LIBARP,
1747                                                 "Invalid ARP opcode - not processing ARP req %x\n",
1748                                                 arp_h->arp_op);
1749                         }
1750                 }
1751
1752                 rte_pktmbuf_free(pkt);
1753         } else {
1754                 ip_h =
1755                                 (struct ipv4_hdr *)((char *)eth_h +
1756                                         sizeof(struct ether_hdr));
1757                 icmp_h =
1758                                 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1759
1760                 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1761
1762                         if (ip_h->next_proto_id != IPPROTO_ICMP) {
1763                                 if (ARPICMP_DEBUG) {
1764                                         RTE_LOG(INFO, LIBARP,
1765                                                 "IP protocol ID is not set to ICMP - discarding\n");
1766                                 }
1767                         } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1768                                 if (ARPICMP_DEBUG) {
1769                                         RTE_LOG(INFO, LIBARP,
1770                                                 "IP version other than 4 - discarding\n");
1771                                 }
1772                         } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1773                                 if (ARPICMP_DEBUG) {
1774                                         RTE_LOG(INFO, LIBARP,
1775                                                 "Unknown IHL - discarding\n");
1776                                 }
1777                         } else {
1778                                 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1779                                                 && icmp_h->icmp_code == 0) {
1780                                         if (ARPICMP_DEBUG)
1781                                                 print_mbuf("RX", in_port_id,
1782                                                                  pkt, __LINE__);
1783
1784                                         ip_addr = ip_h->src_addr;
1785                                         ether_addr_copy(&eth_h->s_addr,
1786                                                         &eth_h->d_addr);
1787                                         ether_addr_copy((struct ether_addr *)
1788                                                         &port->macaddr[0],
1789                                                         &eth_h->s_addr);
1790                                         if (ARPICMP_DEBUG)
1791                                                 RTE_LOG(INFO, LIBARP,
1792                                                         "%s, portid %u. Line %d\n\r",
1793                                                         __FUNCTION__,
1794                                                         port->pmdid, __LINE__);
1795
1796                                         if (is_multicast_ipv4_addr
1797                                                         (ip_h->dst_addr)) {
1798                                                 uint32_t ip_src;
1799
1800                                                 ip_src =
1801                                                                 rte_be_to_cpu_32(ip_addr);
1802                                                 if ((ip_src & 0x00000003) == 1)
1803                                                         ip_src =
1804                                                                         (ip_src &
1805                                                                          0xFFFFFFFC) |
1806                                                                         0x00000002;
1807                                                 else
1808                                                         ip_src =
1809                                                                         (ip_src &
1810                                                                          0xFFFFFFFC) |
1811                                                                         0x00000001;
1812                                                 ip_h->src_addr =
1813                                                                 rte_cpu_to_be_32(ip_src);
1814                                                 ip_h->dst_addr = ip_addr;
1815
1816                                                 ip_h->hdr_checksum = 0;
1817                                                 ip_h->hdr_checksum =
1818                                                                 ~rte_raw_cksum(ip_h,
1819                                                                          sizeof(struct
1820                                                                                 ipv4_hdr));
1821                                         } else {
1822                                                 if (ARPICMP_DEBUG)
1823                                                         RTE_LOG(INFO, LIBARP,
1824                                                                 "%s, portid %u. Line %d\n\r",
1825                                                                 __FUNCTION__,
1826                                                                 port->pmdid,
1827                                                                 __LINE__);
1828                                                 ip_h->src_addr = ip_h->dst_addr;
1829                                                 ip_h->dst_addr = ip_addr;
1830                                         }
1831
1832                                         icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1833                                         cksum = ~icmp_h->icmp_cksum & 0xffff;
1834                                         cksum +=
1835                                                         ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1836                                                         0xffff;
1837                                         cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1838                                         cksum =
1839                                                         (cksum & 0xffff) + (cksum >> 16);
1840                                         cksum =
1841                                                         (cksum & 0xffff) + (cksum >> 16);
1842                                         icmp_h->icmp_cksum = ~cksum;
1843
1844                                         if (ARPICMP_DEBUG)
1845                                                 print_mbuf
1846                                                                 ("TX ICMP ECHO REPLY PKT",
1847                                                                  in_port_id, pkt, __LINE__);
1848                                         port->transmit_bulk_pkts(port, &pkt, 1);
1849                                         if (ARPICMP_DEBUG)
1850                                                 print_mbuf("TX", port->pmdid,
1851                                                                  pkt, __LINE__);
1852
1853                                         return;
1854                                 } else if (icmp_h->icmp_type ==
1855                                                  IP_ICMP_ECHO_REPLY
1856                                                  && icmp_h->icmp_code == 0) {
1857                                         if (ARPICMP_DEBUG)
1858                                                 print_mbuf("RX", in_port_id,
1859                                                                  pkt, __LINE__);
1860
1861                                         struct arp_key_ipv4 arp_key;
1862                                         arp_key.port_id = in_port_id;
1863                                         arp_key.ip =
1864                                                         rte_bswap32(ip_h->src_addr);
1865                                         arp_key.filler1 = 0;
1866                                         arp_key.filler2 = 0;
1867                                         arp_key.filler3 = 0;
1868
1869                                         struct arp_entry_data *arp_entry =
1870                                                         retrieve_arp_entry(arp_key,
1871                                                                  DYNAMIC_ARP);
1872                                         if (arp_entry == NULL) {
1873                                                 if (ARPICMP_DEBUG)
1874                                                         RTE_LOG(INFO, LIBARP,
1875                                                                 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1876                                                                 arp_key.ip,
1877                                                                 arp_key.port_id);
1878                                                 return;
1879                                         }
1880                                         arp_entry->status = COMPLETE;
1881                                 }
1882                         }
1883                 }
1884
1885                 rte_pktmbuf_free(pkt);
1886         }
1887 }
1888
1889 /* int
1890  * inet_pton(af, src, dst)
1891  *      convert from presentation format (which usually means ASCII printable)
1892  *      to network format (which is usually some kind of binary format).
1893  * return:
1894  *      1 if the address was valid for the specified address family
1895  *      0 if the address wasn't valid (`dst' is untouched in this case)
1896  *      -1 if some other error occurred (`dst' is untouched in this case, too)
1897  * author:
1898  *      Paul Vixie, 1996.
1899  */
1900 int my_inet_pton_ipv6(int af, const char *src, void *dst)
1901 {
1902         switch (af) {
1903         case AF_INET:
1904                 return inet_pton_ipv4(src, dst);
1905         case AF_INET6:
1906                 return inet_pton_ipv6(src, dst);
1907         default:
1908                 errno = EAFNOSUPPORT;
1909                 return -1;
1910         }
1911         /* NOTREACHED */
1912 }
1913
1914 /* int
1915  * inet_pton_ipv4(src, dst)
1916  *      like inet_aton() but without all the hexadecimal and shorthand.
1917  * return:
1918  *      1 if `src' is a valid dotted quad, else 0.
1919  * notice:
1920  *      does not touch `dst' unless it's returning 1.
1921  * author:
1922  *      Paul Vixie, 1996.
1923  */
1924 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1925 {
1926         static const char digits[] = "0123456789";
1927         int saw_digit, octets, ch;
1928         unsigned char tmp[INADDRSZ], *tp;
1929
1930         saw_digit = 0;
1931         octets = 0;
1932         *(tp = tmp) = 0;
1933         while ((ch = *src++) != '\0') {
1934                 const char *pch;
1935
1936                 pch = strchr(digits, ch);
1937                 if (pch != NULL) {
1938                         unsigned int new = *tp * 10 + (pch - digits);
1939
1940                         if (new > 255)
1941                                 return 0;
1942                         if (!saw_digit) {
1943                                 if (++octets > 4)
1944                                         return 0;
1945                                 saw_digit = 1;
1946                         }
1947                         *tp = (unsigned char)new;
1948                 } else if (ch == '.' && saw_digit) {
1949                         if (octets == 4)
1950                                 return 0;
1951                         *++tp = 0;
1952                         saw_digit = 0;
1953                 } else
1954                         return 0;
1955         }
1956         if (octets < 4)
1957                 return 0;
1958
1959         memcpy(dst, tmp, INADDRSZ);
1960         return 1;
1961 }
1962
1963 /* int
1964  * inet_pton_ipv6(src, dst)
1965  *      convert presentation level address to network order binary form.
1966  * return:
1967  *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
1968  * notice:
1969  *      (1) does not touch `dst' unless it's returning 1.
1970  *      (2) :: in a full address is silently ignored.
1971  * credit:
1972  *      inspired by Mark Andrews.
1973  * author:
1974  *      Paul Vixie, 1996.
1975  */
1976 static int inet_pton_ipv6(const char *src, unsigned char *dst)
1977 {
1978         static const char xdigits_l[] = "0123456789abcdef",
1979                         xdigits_u[] = "0123456789ABCDEF";
1980         unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
1981         const char *xdigits = 0, *curtok = 0;
1982         int ch = 0, saw_xdigit = 0, count_xdigit = 0;
1983         unsigned int val = 0;
1984         unsigned int dbloct_count = 0;
1985
1986         memset((tp = tmp), '\0', IN6ADDRSZ);
1987         endp = tp + IN6ADDRSZ;
1988         colonp = NULL;
1989         /* Leading :: requires some special handling. */
1990         if (*src == ':')
1991                 if (*++src != ':')
1992                         return 0;
1993         curtok = src;
1994         saw_xdigit = count_xdigit = 0;
1995         val = 0;
1996
1997         while ((ch = *src++) != '\0') {
1998                 const char *pch;
1999
2000                 pch = strchr((xdigits = xdigits_l), ch);
2001                 if (pch == NULL)
2002                         pch = strchr((xdigits = xdigits_u), ch);
2003                 if (pch != NULL) {
2004                         if (count_xdigit >= 4)
2005                                 return 0;
2006                         val <<= 4;
2007                         val |= (pch - xdigits);
2008                         if (val > 0xffff)
2009                                 return 0;
2010                         saw_xdigit = 1;
2011                         count_xdigit++;
2012                         continue;
2013                 }
2014                 if (ch == ':') {
2015                         curtok = src;
2016                         if (!saw_xdigit) {
2017                                 if (colonp)
2018                                         return 0;
2019                                 colonp = tp;
2020                                 continue;
2021                         } else if (*src == '\0') {
2022                                 return 0;
2023                         }
2024                         if (tp + sizeof(int16_t) > endp)
2025                                 return 0;
2026                         *tp++ = (unsigned char)((val >> 8) & 0xff);
2027                         *tp++ = (unsigned char)(val & 0xff);
2028                         saw_xdigit = 0;
2029                         count_xdigit = 0;
2030                         val = 0;
2031                         dbloct_count++;
2032                         continue;
2033                 }
2034                 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2035                                 inet_pton_ipv4(curtok, tp) > 0) {
2036                         tp += INADDRSZ;
2037                         saw_xdigit = 0;
2038                         dbloct_count += 2;
2039                         break;  /* '\0' was seen by inet_pton4(). */
2040                 }
2041                 return 0;
2042         }
2043         if (saw_xdigit) {
2044                 if (tp + sizeof(int16_t) > endp)
2045                         return 0;
2046                 *tp++ = (unsigned char)((val >> 8) & 0xff);
2047                 *tp++ = (unsigned char)(val & 0xff);
2048                 dbloct_count++;
2049         }
2050         if (colonp != NULL) {
2051                 /* if we already have 8 double octets, having a colon means error */
2052                 if (dbloct_count == 8)
2053                         return 0;
2054
2055                 /*
2056                  * Since some memmove()'s erroneously fail to handle
2057                  * overlapping regions, we'll do the shift by hand.
2058                  */
2059                 const int n = tp - colonp;
2060                 int i;
2061
2062                 for (i = 1; i <= n; i++) {
2063                         endp[-i] = colonp[n - i];
2064                         colonp[n - i] = 0;
2065                 }
2066                 tp = endp;
2067         }
2068         if (tp != endp)
2069                 return 0;
2070         memcpy(dst, tmp, IN6ADDRSZ);
2071         return 1;
2072 }
2073
2074 static int arp_parse_args(struct pipeline_params *params)
2075 {
2076         uint32_t arp_route_tbl_present = 0;
2077         uint32_t nd_route_tbl_present = 0;
2078         uint32_t numArg;
2079         uint32_t n_vnf_threads_present = 0;
2080
2081         uint32_t pktq_in_prv_present = 0;
2082         uint32_t prv_to_pub_map_present = 0;
2083
2084         uint8_t n_prv_in_port = 0;
2085         int i;
2086         for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2087                 in_port_dir_a[i] = 0;   //make all RX ports ingress initially
2088                 prv_to_pub_map[i] = 0xff;
2089                 pub_to_prv_map[i] = 0xff;
2090         }
2091
2092         RTE_SET_USED(nd_route_tbl_present);
2093         RTE_SET_USED(arp_route_tbl_present);
2094         for (numArg = 0; numArg < params->n_args; numArg++) {
2095                 char *arg_name = params->args_name[numArg];
2096                 char *arg_value = params->args_value[numArg];
2097
2098                 /* arp timer expiry */
2099                 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2100                         arp_timeout = atoi(arg_value);
2101                 }
2102
2103                 /* pktq_in_prv */
2104                 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2105                         if (pktq_in_prv_present) {
2106                                 printf
2107                                                 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2108                                 return -1;
2109                         }
2110                         pktq_in_prv_present = 1;
2111
2112                         int rxport = 0, j = 0;
2113                         char phy_port_num[5];
2114                         char *token = strtok(arg_value, "RXQ");
2115                         while (token) {
2116                                 j = 0;
2117                                 while ((j < 4) && (token[j] != '.')) {
2118                                         phy_port_num[j] = token[j];
2119                                         j++;
2120                                 }
2121                                 phy_port_num[j] = '\0';
2122                                 rxport = atoi(phy_port_num);
2123                                 prv_in_port_a[n_prv_in_port++] = rxport;
2124                                 if (rxport < 0)
2125                                         rxport = 0;
2126                                 printf
2127                                                 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2128                                                  token, phy_port_num, rxport);
2129                                 prv_in_port_a[n_prv_in_port++] = rxport;
2130                                 if(rxport < PIPELINE_MAX_PORT_IN)
2131                                 in_port_dir_a[rxport] = 1;      // set rxport egress
2132                                 token = strtok(NULL, "RXQ");
2133                         }
2134
2135                         if (n_prv_in_port == 0) {
2136                                 printf
2137                                                 ("VNF common parse error - no prv RX phy port\n");
2138                                 return -1;
2139                         }
2140                         continue;
2141                 }
2142
2143                 if (strcmp(arg_name, "arp_buf") == 0) {
2144                         arp_buffer = atoi(arg_value);
2145                         continue;
2146                 }
2147
2148                 if (strcmp(arg_name, "nd_buf") == 0) {
2149                         nd_buffer = atoi(arg_value);
2150                         continue;
2151                 }
2152
2153                 /* prv_to_pub_map */
2154                 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2155                         if (prv_to_pub_map_present) {
2156                                 printf
2157                                                 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2158                                 return -1;
2159                         }
2160                         prv_to_pub_map_present = 1;
2161
2162                         int rxport = 0, txport = 0, j = 0, k = 0;
2163                         char rx_phy_port_num[5];
2164                         char tx_phy_port_num[5];
2165                         char *token = strtok(arg_value, "(");
2166                         while (token) {
2167                                 j = 0;
2168                                 while ((j < 4) && (token[j] != ',')) {
2169                                         rx_phy_port_num[j] = token[j];
2170                                         j++;
2171                                 }
2172                                 rx_phy_port_num[j] = '\0';
2173                                 rxport = atoi(rx_phy_port_num);
2174                                 if (rxport < 0)
2175                                         rxport = 0;
2176
2177                                 j++;
2178                                 k = 0;
2179                                 while ((k < 4) && (token[j + k] != ')')) {
2180                                         tx_phy_port_num[k] = token[j + k];
2181                                         k++;
2182                                 }
2183                                 tx_phy_port_num[k] = '\0';
2184                                 txport = atoi(tx_phy_port_num);
2185                                 if (txport < 0)
2186                                         txport = 0;
2187
2188                                 RTE_LOG(INFO, LIBARP, "token: %s,"
2189                                         "rx_phy_port_str: %s, phy_port_num %d,"
2190                                         "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2191                                         token, rx_phy_port_num, rxport,
2192                                         tx_phy_port_num, txport);
2193
2194                                 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2195                                                 (txport >= PIPELINE_MAX_PORT_IN) ||
2196                                                 (in_port_dir_a[rxport] != 1)) {
2197                                         printf
2198                                                         ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2199                                                          rxport, txport,
2200                                                          in_port_dir_a[rxport]);
2201                                         return -1;
2202                                 }
2203
2204                                 prv_to_pub_map[rxport] = txport;
2205                                 pub_to_prv_map[txport] = rxport;
2206                                 token = strtok(NULL, "(");
2207                         }
2208
2209                         continue;
2210                 }
2211                 //n_vnf_threads = 3
2212                 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2213                         if (n_vnf_threads_present)
2214                                 return -1;
2215                         n_vnf_threads_present = 1;
2216                         trim(arg_value);
2217                         num_vnf_threads = atoi(arg_value);
2218                         if (num_vnf_threads <= 0) {
2219                                 RTE_LOG(INFO, LIBARP,
2220                                         "n_vnf_threads is invalid\n");
2221                                 return -1;
2222                         }
2223                         RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2224                                 num_vnf_threads);
2225                 }
2226
2227                 /* lib_arp_debug */
2228                 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2229                         ARPICMP_DEBUG = atoi(arg_value);
2230
2231                         continue;
2232                 }
2233
2234                 /* arp_route_tbl */
2235                 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2236                         arp_route_tbl_present = 1;
2237                         uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip = 0,
2238                                  i = 0, j = 0, k = 0;
2239                         uint32_t arp_route_tbl_str_max_len = 10;
2240                         char dest_ip_str[arp_route_tbl_str_max_len];
2241                         char mask_str[arp_route_tbl_str_max_len];
2242                         char tx_port_str[arp_route_tbl_str_max_len];
2243                         char nh_ip_str[arp_route_tbl_str_max_len];
2244                         char *token = strtok(arg_value, "(");
2245                         while (token) {
2246                                 i = 0;
2247                                 while ((i < (arp_route_tbl_str_max_len - 1))
2248                                                          && (token[i] != ',')) {
2249                                         nh_ip_str[i] = token[i];
2250                                         i++;
2251                                 }
2252                                 nh_ip_str[i] = '\0';
2253                                 nh_ip = strtoul(nh_ip_str, NULL, 16);
2254
2255                                 i++;
2256                                 j = 0;
2257                                 while ((j < (arp_route_tbl_str_max_len - 1))
2258                                                          && (token[i + j] != ',')) {
2259                                         mask_str[j] = token[i + j];
2260                                         j++;
2261                                 }
2262                                 mask_str[j] = '\0';
2263                                 mask = strtoul(mask_str, NULL, 16);
2264
2265                                 j++;
2266                                 k = 0;
2267                                 while ((k < (arp_route_tbl_str_max_len - 1))
2268                                                          && (token[i + j + k] != ',')) {
2269                                         tx_port_str[k] = token[i + j + k];
2270                                         k++;
2271                                 }
2272                                 tx_port_str[k] = '\0';
2273                                 tx_port = strtoul(tx_port_str, NULL, 16);       //atoi(tx_port_str);
2274
2275                                 k++;
2276
2277                                 if (1) {
2278                                         RTE_LOG(INFO, LIBARP, "token: %s, "
2279                                                 "dest_ip_str: %s, dest_ip %u, "
2280                                                 "mask_str: %s, mask %x, "
2281                                                 "tx_port_str: %s, tx_port %u, "
2282                                                 "nh_ip_str: %s, nh_ip %u\n",
2283                                                 token, dest_ip_str, dest_ip,
2284                                                 mask_str, mask, tx_port_str,
2285                                                 tx_port, nh_ip_str, nh_ip);
2286                                 }
2287
2288                                 /*  if (tx_port >= params->n_ports_out)
2289                                          {
2290                                          RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2291                                          tx_port, params->n_ports_out);
2292                                          return -1;
2293                                          }
2294                                  */
2295                                 //Populate the static arp_route_table
2296
2297                                 struct route_table_entry *lentry =
2298                                 &p_route_data[tx_port]->route_table
2299                                 [p_route_data[tx_port]->route_ent_cnt];
2300                                 lentry->mask = mask;
2301                                 lentry->port = tx_port;
2302                                 lentry->nh = nh_ip;
2303                                 lentry->nh_mask = nh_ip & mask;
2304                                 p_route_data[tx_port]->route_ent_cnt++;
2305                                 token = strtok(NULL, "(");
2306                         }
2307
2308                         continue;
2309                 }
2310                 /*ND IPv6 */
2311                 /* nd_route_tbl */
2312                 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2313                         nd_route_tbl_present = 1;
2314
2315                         uint8_t depth = 0, tx_port = 0, nh_ipv6[16];
2316                         uint8_t i = 0, j = 0, k = 0;
2317                         uint8_t nd_route_tbl_str_max_len = 128; //64;
2318 //                      char dest_ipv6_str[nd_route_tbl_str_max_len];
2319                         char depth_str[nd_route_tbl_str_max_len];
2320                         char tx_port_str[nd_route_tbl_str_max_len];
2321                         char nh_ipv6_str[nd_route_tbl_str_max_len];
2322                         char *token = strtok(arg_value, "(");
2323                         while (token) {
2324                                 i = 0;
2325                                 while ((i < (nd_route_tbl_str_max_len - 1))
2326                                                          && (token[i] != ',')) {
2327                                         nh_ipv6_str[i] = token[i];
2328                                         i++;
2329                                 }
2330                                 nh_ipv6_str[i] = '\0';
2331                                 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2332                                                         &nh_ipv6);
2333                                 i++;
2334                                 j = 0;
2335                                 while ((j < (nd_route_tbl_str_max_len - 1))
2336                                                          && (token[i + j] != ',')) {
2337                                         depth_str[j] = token[i + j];
2338                                         j++;
2339                                 }
2340                                 depth_str[j] = '\0';
2341                                 //converting string char to integer
2342                                 int s;
2343                                 for (s = 0; depth_str[s] != '\0'; ++s)
2344                                         depth = depth * 10 + depth_str[s] - '0';
2345
2346                                 j++;
2347                                 k = 0;
2348                                 while ((k < (nd_route_tbl_str_max_len - 1))
2349                                                          && (token[i + j + k] != ',')) {
2350                                         tx_port_str[k] = token[i + j + k];
2351                                         k++;
2352                                 }
2353                                 tx_port_str[k] = '\0';
2354                                 tx_port = strtoul(tx_port_str, NULL, 16);       //atoi(tx_port_str);
2355
2356                                 k++;
2357                                 struct nd_route_table_entry *lentry =
2358                                         &p_nd_route_data[tx_port]->nd_route_table
2359                                 [p_nd_route_data[tx_port]->nd_route_ent_cnt];
2360
2361                                 //Populate the static arp_route_table
2362                                 for (i = 0; i < 16; i++)
2363                                         lentry->nhipv6[i] = nh_ipv6[i];
2364
2365                                 lentry->depth = depth;
2366                                 lentry->port = tx_port;
2367
2368                                 p_nd_route_data[tx_port]->nd_route_ent_cnt++;
2369
2370                                 token = strtok(NULL, "(");
2371                         }
2372
2373                         continue;
2374                 }
2375                 /* any other */
2376                 //return -1;
2377         }
2378         /* Check that mandatory arguments are present */
2379         /*
2380                  if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2381                  RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2382                  RTE_LOG(INFO, LIBARP,"%d, %d \n",
2383                  arp_route_tbl_present, ports_mac_list_present);
2384                  return -1;
2385                  }
2386          */
2387
2388         return 0;
2389 }
2390
2391 static void local_arp_cache_init(void)
2392 {
2393         int i, j, k;
2394         for (i=0; i<MAX_PORTS;i++) {
2395                 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2396                         p_arp_data->arp_local_cache[i].nhip[j] = 0;
2397                         for (k=0;k<6;k++)
2398                                 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2399                         p_arp_data->arp_local_cache[i].num_nhip = 0;
2400                 }
2401         }
2402 }
2403
2404 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
2405 {
2406         int i, j, limit;
2407         struct ether_addr *x = NULL;
2408         limit = p_arp_data->nd_local_cache[out_port].num_nhip;
2409
2410         for (i=0; i < limit; i++) {
2411                 for (j=0;j<16;j++) {
2412                         if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
2413                                 continue;
2414                 }
2415
2416                 x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
2417
2418                 if(ARPICMP_DEBUG) {
2419                         for (j = 0; j < 6; j++)
2420                             printf("%d  %d", x->addr_bytes[j],
2421                                 p_arp_data->nd_local_cache[out_port].link_hw_laddr[i].addr_bytes[j]);
2422                 }
2423                 return x;
2424         }
2425
2426         return x;
2427 }
2428
2429 struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip)
2430 {
2431         int i, limit;
2432         uint32_t tmp;
2433         struct ether_addr *x = NULL;
2434         limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2435         for (i=0; i < limit; i++) {
2436                 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2437                 if (tmp == nhip) {
2438                         x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2439                         return x;
2440                 }
2441         }
2442         return x;
2443 }
2444
2445 void lib_arp_init(struct pipeline_params *params,
2446                         __rte_unused struct app_params *app)
2447 {
2448
2449         int i;
2450         uint32_t size;
2451         struct arp_data *p;
2452
2453         RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2454
2455         /* create arp data for table entries */
2456         size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2457         p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2458         p_arp_data = (struct arp_data *)p;
2459
2460         /* Parse arguments */
2461         if (arp_parse_args(params)) {
2462                 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2463                 return;
2464         }
2465
2466         /* acquire the mac addresses */
2467         struct ether_addr hw_addr;
2468         uint8_t nb_ports = rte_eth_dev_count();
2469
2470         for (i = 0; i < nb_ports; i++) {
2471                 rte_eth_macaddr_get(i, &hw_addr);
2472                 ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
2473                 p_arp_data->link_hw_addr_array_idx++;
2474         }
2475
2476         /* create a lock for arp/nd hash */
2477         rte_rwlock_init(&arp_hash_handle_lock);
2478         rte_rwlock_init(&nd_hash_handle_lock);
2479
2480         /* create the arp_icmp mbuf rx pool */
2481         lib_arp_pktmbuf_tx_pool =
2482                         rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2483                                                 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2484                                                 rte_socket_id());
2485
2486         if (lib_arp_pktmbuf_tx_pool == NULL) {
2487                 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2488                 return;
2489         }
2490
2491         for (i=0; i<MAX_PORTS; i++) {
2492                 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2493                 if (lib_arp_pkt[i] == NULL) {
2494                         RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2495                         return;
2496                 }
2497         }
2498
2499         /* create the nd icmp mbuf rx pool */
2500         lib_nd_pktmbuf_tx_pool =
2501                         rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2502                                                 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2503                                                 rte_socket_id());
2504
2505         if (lib_nd_pktmbuf_tx_pool == NULL) {
2506                 RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
2507                 return;
2508         }
2509
2510         for (i=0; i<MAX_PORTS; i++) {
2511                 lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
2512                 if (lib_nd_pkt[i] == NULL) {
2513                         RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
2514                         return;
2515                 }
2516         }
2517
2518         /* create the arp_icmp mbuf rx pool */
2519         arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2520                                         NB_ARPICMP_MBUF, MAX_POOL, 0,
2521                                         RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2522
2523         if (arp_icmp_pktmbuf_tx_pool == NULL) {
2524                 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2525                 return;
2526         }
2527
2528         arp_hash_params.socket_id = rte_socket_id();
2529         arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2530         arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2531         arp_hash_handle = rte_hash_create(&arp_hash_params);
2532
2533         if (arp_hash_handle == NULL) {
2534                 RTE_LOG(INFO, LIBARP,
2535                         "ARP rte_hash_create failed. socket %d ... \n",
2536                         arp_hash_params.socket_id);
2537         } else {
2538                 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2539                         (void *)arp_hash_handle);
2540         }
2541
2542         /* Create port alloc buffer */
2543
2544         timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2545                                                                  timer_objs_mempool_count,
2546                                                                  sizeof(struct rte_timer),
2547                                                                  0, 0,
2548                                                                  NULL, NULL,
2549                                                                  NULL, NULL, rte_socket_id(), 0);
2550         if (timer_mempool_arp == NULL) {
2551                 rte_panic("timer_mempool create error\n");
2552         }
2553         rte_timer_subsystem_init();
2554         list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2555
2556         /* ND IPv6 */
2557         nd_hash_params.socket_id = rte_socket_id();
2558         nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2559         nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2560         nd_hash_handle = rte_hash_create(&nd_hash_params);
2561         if (nd_hash_handle == NULL) {
2562                 RTE_LOG(INFO, LIBARP,
2563                         "ND rte_hash_create failed. socket %d ... \n",
2564                         nd_hash_params.socket_id);
2565         } else {
2566                 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2567                         (void *)nd_hash_handle);
2568         }
2569
2570         /* Initialize the local arp cache */
2571         local_arp_cache_init();
2572
2573         return;
2574 }
2575
2576 void arp_timer_callback(struct rte_timer *timer, void *arg)
2577 {
2578         struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2579         struct arp_key_ipv4 arp_key;
2580         arp_key.port_id = timer_key->port_id;
2581         arp_key.ip = timer_key->ip;
2582         arp_key.filler1 = 0;
2583         arp_key.filler2 = 0;
2584         arp_key.filler3 = 0;
2585
2586         struct arp_entry_data *ret_arp_data = NULL;
2587         uint64_t now;
2588         if (ARPICMP_DEBUG) {
2589                 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2590                 arp_key.ip, arp_key.port_id);
2591         }
2592
2593         int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2594                                          (void **)&ret_arp_data);
2595         now = rte_rdtsc();
2596
2597         if (ARPICMP_DEBUG)
2598                 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2599                         (int)timer->expire, now);
2600         if (ret < 0) {
2601                 printf("Should not have come here\n");
2602                 return;
2603         } else {
2604                 if (ret_arp_data->mode == DYNAMIC_ARP) {
2605                         rte_rwlock_write_lock(&ret_arp_data->queue_lock);
2606                         if (ret_arp_data->status == PROBE ||
2607                                 ret_arp_data->status == INCOMPLETE) {
2608                                 if (ret_arp_data->retry_count == ARP_RETRY_COUNT) {
2609                                         remove_arp_entry(ret_arp_data, arg);
2610                                 } else {
2611                                         ret_arp_data->retry_count++;
2612
2613                                         if (ARPICMP_DEBUG) {
2614                                                 RTE_LOG(INFO, LIBARP,
2615                                                 "RETRY ARP..retry count : %u\n",
2616                                                 ret_arp_data->retry_count);
2617
2618                                                 RTE_LOG(INFO, LIBARP,
2619                                                 "TIMER STARTED FOR %u seconds\n",
2620                                                         ARP_TIMER_EXPIRY);
2621                                         }
2622
2623                                         if (ifm_chk_port_ipv4_enabled
2624                                                 (ret_arp_data->port) != IFM_FAILURE) {
2625                                                 request_arp(ret_arp_data->port,
2626                                                                 ret_arp_data->ip);
2627                                         } else {
2628                                                 if (ARPICMP_DEBUG)
2629                                                         RTE_LOG(INFO, LIBARP,
2630                                                         "%s: IP is not enabled on port %u"
2631                                                         ", not sending GARP\n\r",
2632                                                         __FUNCTION__,
2633                                                         ret_arp_data->port);
2634                                         }
2635
2636                                         if (rte_timer_reset(ret_arp_data->timer,
2637                                                                 (PROBE_TIME *
2638                                                                  rte_get_tsc_hz()/ 1000),
2639                                                                 SINGLE,
2640                                                                 timer_lcore,
2641                                                                 arp_timer_callback,
2642                                                                 arg) < 0)
2643                                         if (ARPICMP_DEBUG)
2644                                                 RTE_LOG(INFO, LIBARP,
2645                                                         "Err : Timer already running\n");
2646
2647                                 }
2648                         } else if (ret_arp_data->status == COMPLETE) {
2649                                 if (now <= (ret_arp_data->n_confirmed +
2650                                          (arp_timeout * rte_get_tsc_hz()))) {
2651                                         if (rte_timer_reset(ret_arp_data->timer,
2652                                                                 (arp_timeout *
2653                                                                  rte_get_tsc_hz()), SINGLE,
2654                                                                 timer_lcore,
2655                                                                 arp_timer_callback,
2656                                                                 arg) < 0)
2657                                         if (ARPICMP_DEBUG)
2658                                                 RTE_LOG(INFO, LIBARP,
2659                                                         "Err : Timer already running\n");
2660                                 } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2661                                         if (rte_timer_reset(ret_arp_data->timer,
2662                                                                 (arp_timeout *
2663                                                                  rte_get_tsc_hz()), SINGLE,
2664                                                                 timer_lcore,
2665                                                                 arp_timer_callback,
2666                                                                 arg) < 0)
2667                                         if (ARPICMP_DEBUG)
2668                                                 RTE_LOG(INFO, LIBARP,
2669                                                         "Err : Timer already running\n");
2670                                 } else {
2671                                         ret_arp_data->status = STALE;
2672                                         p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2673                                 }
2674                         }
2675                         rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
2676                 } else {
2677                         rte_hash_del_key(arp_hash_handle, &arp_key);
2678                 }
2679         }
2680         return;
2681 }
2682
2683 void nd_timer_callback(struct rte_timer *timer, void *arg)
2684 {
2685         struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
2686         struct nd_key_ipv6 nd_key;
2687         int j;
2688         struct nd_entry_data *ret_nd_data = NULL;
2689         uint64_t now;
2690
2691         nd_key.port_id = timer_key->port_id;
2692         nd_key.filler1 = 0;
2693         nd_key.filler2 = 0;
2694         nd_key.filler3 = 0;
2695
2696         rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
2697
2698         if (ARPICMP_DEBUG) {
2699                 RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
2700                 nd_key.port_id);
2701         }
2702
2703         int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
2704                                          (void **)&ret_nd_data);
2705         now = rte_rdtsc();
2706
2707         if (ARPICMP_DEBUG)
2708                 RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
2709                         (int)timer->expire, now);
2710         if (ret < 0) {
2711                 printf("Should not have come here \n");
2712                 for (j = 0; j < 16; j++)
2713                         printf("*%d ", nd_key.ipv6[j]);
2714                 printf("*%d ", nd_key.port_id);
2715                 return;
2716         } else {
2717                 if (ret_nd_data->mode == DYNAMIC_ARP) {
2718                         rte_rwlock_write_lock(&ret_nd_data->queue_lock);
2719                         if (ret_nd_data->status == PROBE ||
2720                                 ret_nd_data->status == INCOMPLETE) {
2721                                 if (ret_nd_data->retry_count == ARP_RETRY_COUNT) {
2722                                         remove_nd_entry_ipv6(ret_nd_data, arg);
2723                                 } else {
2724                                         ret_nd_data->retry_count++;
2725
2726                                         if (ARPICMP_DEBUG) {
2727                                                 RTE_LOG(INFO, LIBARP,
2728                                                 "RETRY ND..retry count : %u\n",
2729                                                 ret_nd_data->retry_count);
2730
2731                                                 RTE_LOG(INFO, LIBARP,
2732                                                 "TIMER STARTED FOR %u seconds\n",
2733                                                         ARP_TIMER_EXPIRY);
2734                                         }
2735
2736                                         request_nd(ret_nd_data->ipv6,
2737                                                  ifm_get_port(ret_nd_data->port));
2738                                         if (rte_timer_reset(ret_nd_data->timer,
2739                                                                 (PROBE_TIME *
2740                                                                  rte_get_tsc_hz()/ 1000),
2741                                                                 SINGLE,
2742                                                                 timer_lcore,
2743                                                                 nd_timer_callback,
2744                                                                 arg) < 0)
2745                                         if (ARPICMP_DEBUG)
2746                                                 RTE_LOG(INFO, LIBARP,
2747                                                         "Err : Timer already running\n");
2748
2749                                 }
2750                         } else if (ret_nd_data->status == COMPLETE) {
2751                                 if (now <= (ret_nd_data->n_confirmed +
2752                                  (arp_timeout * rte_get_tsc_hz()))) {
2753                                         if (rte_timer_reset(ret_nd_data->timer,
2754                                                                 (arp_timeout *
2755                                                                  rte_get_tsc_hz()), SINGLE,
2756                                                                 timer_lcore,
2757                                                                 nd_timer_callback,
2758                                                                 arg) < 0)
2759                                         if (ARPICMP_DEBUG)
2760                                                 RTE_LOG(INFO, LIBARP,
2761                                                         "Err : Timer already running\n");
2762                                 } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2763                                         if (rte_timer_reset(ret_nd_data->timer,
2764                                                                 (arp_timeout *
2765                                                                  rte_get_tsc_hz()), SINGLE,
2766                                                                 timer_lcore,
2767                                                                 nd_timer_callback,
2768                                                                 arg) < 0)
2769                                         if (ARPICMP_DEBUG)
2770                                                 RTE_LOG(INFO, LIBARP,
2771                                                         "Err : Timer already running\n");
2772                                 } else {
2773                                         printf("making it stale\n");
2774                                         ret_nd_data->status = STALE;
2775                                         p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
2776                                 }
2777                         }
2778                         rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
2779                 } else {
2780                         rte_hash_del_key(nd_hash_handle, &nd_key);
2781                 }
2782         }
2783         return;
2784 }
2785
2786 void create_arp_table(void)
2787 {
2788
2789         int i;
2790         for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2791                 populate_arp_entry((const struct ether_addr *)
2792                                          &arp_entry_data_table[i].eth_addr,
2793                                          arp_entry_data_table[i].ip,
2794                                          (uint8_t) arp_entry_data_table[i].port,
2795                                          STATIC_ARP);
2796         }
2797         print_arp_table();
2798
2799         return;
2800 }
2801
2802 void create_nd_table(void)
2803 {
2804
2805         int i;
2806         for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2807                 populate_nd_entry((const struct ether_addr *)
2808                                         nd_entry_data_table[i].eth_addr,
2809                                         nd_entry_data_table[i].ipv6,
2810                                         (uint8_t) nd_entry_data_table[i].port,
2811                                         STATIC_ND);
2812         }
2813         print_nd_table();
2814         return;
2815 }
2816
2817 void send_gratuitous_arp(l2_phy_interface_t *port)
2818 {
2819         struct ether_hdr *eth_h;
2820         struct arp_hdr *arp_h;
2821
2822         struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
2823
2824         if (port == NULL) {
2825                 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2826                 return;
2827
2828         }
2829
2830         if (arp_pkt == NULL) {
2831                 if (ARPICMP_DEBUG)
2832                         RTE_LOG(INFO, LIBARP,
2833                                 "Error allocating arp_pkt rte_mbuf\n");
2834                 return;
2835         }
2836
2837         eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2838
2839         ether_addr_copy(&broadcast_ether_addr, &eth_h->d_addr);
2840         ether_addr_copy((struct ether_addr *)
2841                         &port->macaddr[0], &eth_h->s_addr);
2842         eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2843
2844         arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2845         arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2846         arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2847         arp_h->arp_hln = ETHER_ADDR_LEN;
2848         arp_h->arp_pln = sizeof(uint32_t);
2849         arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2850
2851         ether_addr_copy((struct ether_addr *)
2852                         &port->macaddr[0], &arp_h->arp_data.arp_sha);
2853         if (port->ipv4_list == NULL) {
2854                 if (ARPICMP_DEBUG)
2855                         RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2856                                 __FUNCTION__);
2857                 return;
2858         }
2859         arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2860         ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2861         //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2862         arp_h->arp_data.arp_tip = 0;    //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2863         //  RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2864         //arp_h->arp_data.arp_sip);
2865         // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2866         arp_pkt->pkt_len = 42;
2867         arp_pkt->data_len = 42;
2868
2869         if (ARPICMP_DEBUG) {
2870                 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2871                 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2872         }
2873         port->transmit_single_pkt(port, arp_pkt);
2874 }
2875
2876 void set_arpdebug(int flag)
2877 {
2878         if (flag) {
2879                 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2880                 ARPICMP_DEBUG = 1;
2881                 NDIPV6_DEBUG = 1;
2882
2883         } else {
2884                 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2885                 ARPICMP_DEBUG = 0;
2886                 NDIPV6_DEBUG = 0;
2887         }
2888 }
2889
2890 void set_arptimeout(uint32_t timeout_val)
2891 {
2892         if (timeout_val == 0) {
2893                 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2894                 return;
2895         }
2896         if (ARPICMP_DEBUG)
2897                 RTE_LOG(INFO, LIBARP,
2898                         "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2899                         arp_timeout, timeout_val);
2900         arp_timeout = timeout_val;
2901         if (ARPICMP_DEBUG)
2902                 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",
2903                         arp_timeout);
2904 }