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