2 // Copyright (c) 2017 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <rte_common.h>
24 #include <rte_malloc.h>
26 #include <rte_byteorder.h>
28 #include <rte_table_lpm.h>
29 #include <rte_table_hash.h>
30 #include <rte_pipeline.h>
34 #include <rte_jhash.h>
35 #include <rte_cycles.h>
36 #include <rte_timer.h>
38 #include "interface.h"
41 #include "l3fwd_lpm4.h"
42 #include "vnf_common.h"
44 #if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN)
45 #define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x)
46 #define CHECK_ENDIAN_32(x) rte_be_to_cpu_32(x)
48 #define CHECK_ENDIAN_16(x) (x)
49 #define CHECK_ENDIAN_32(x) (x)
52 #define NB_ARPICMP_MBUF 64
53 #define NB_NDICMP_MBUF 64
54 #define IP_VERSION_4 0x40
55 #define IP_HDRLEN 0x05 /**< default IP header length == five 32-bits words. */
56 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
58 #define is_multicast_ipv4_addr(ipv4_addr) \
59 (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
61 extern uint8_t prv_in_port_a[PIPELINE_MAX_PORT_IN];
62 extern uint32_t timer_lcore;
63 extern int USE_RTM_LOCKS;
64 uint32_t arp_timeout = ARP_TIMER_EXPIRY;
65 uint32_t arp_buffer = ARP_BUF_DEFAULT;
72 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
73 static int inet_pton_ipv6(const char *src, unsigned char *dst);
74 static int inet_pton_ipv4(const char *src, unsigned char *dst);
75 static void local_arp_cache_init(void);
76 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
77 uint8_t netmask_ipv6[]);
79 uint8_t vnf_common_arp_lib_init;
80 uint8_t vnf_common_nd_lib_init;
81 uint8_t loadb_pipeline_count;
83 uint32_t ARPICMP_DEBUG;
84 uint32_t NDIPV6_DEBUG;
86 uint32_t arp_route_tbl_index;
87 uint32_t nd_route_tbl_index;
88 uint32_t link_hw_addr_array_idx;
90 uint32_t lib_arp_get_mac_req;
91 uint32_t lib_arp_nh_found;
92 uint32_t lib_arp_no_nh_found;
93 uint32_t lib_arp_arp_entry_found;
94 uint32_t lib_arp_no_arp_entry_found;
95 uint32_t lib_arp_populate_called;
96 uint32_t lib_arp_delete_called;
97 uint32_t lib_arp_duplicate_found;
99 uint32_t lib_nd_get_mac_req;
100 uint32_t lib_nd_nh_found;
101 uint32_t lib_nd_no_nh_found;
102 uint32_t lib_nd_nd_entry_found;
103 uint32_t lib_nd_no_arp_entry_found;
104 uint32_t lib_nd_populate_called;
105 uint32_t lib_nd_delete_called;
106 uint32_t lib_nd_duplicate_found;
107 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
108 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
110 struct rte_mbuf *lib_arp_pkt[MAX_PORTS];
111 struct rte_mbuf *lib_nd_pkt;
113 uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
114 uint8_t default_ip[4] = { 0, 0, 1, 1 };
116 uint64_t start_tsc[4];
118 #define ticks_per_ms (rte_get_tsc_hz()/1000)
120 #define MAX_NUM_ARP_CACHE_MAC_ADDRESS 16
122 /***** ARP local cache *****/
123 struct arp_data *p_arp_data;
124 //struct arp_cache arp_local_cache[MAX_PORTS];
125 uint8_t arp_cache_hw_laddr_valid[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
126 0, 0, 0, 0, 0, 0, 0, 0,
127 0, 0, 0, 0, 0, 0, 0, 0
132 rte_prefetch0(p_arp_data);
135 struct arp_entry_data *arp_data_ptr[MAX_NUM_ARP_CACHE_MAC_ADDRESS];
137 struct ether_addr arp_cache_hw_laddr[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
138 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
139 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
140 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
141 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
142 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
143 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
144 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
145 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
146 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
147 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
148 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
149 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
150 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
151 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
152 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
153 {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
157 * A structure defining the mbuf meta data for VFW.
159 struct mbuf_arp_meta_data {
160 /* output port stored for RTE_PIPELINE_ACTION_PORT_META */
161 uint32_t output_port;
162 struct rte_mbuf *next; /* next pointer for chained buffers */
163 } __rte_cache_aligned;
165 static struct arp_entry_data arp_entry_data_default = {
171 * memory pool for queued up user pkts.
173 struct rte_mempool *arp_icmp_pktmbuf_tx_pool;
175 static struct rte_hash_parameters arp_hash_params = {
179 .key_len = sizeof(struct arp_key_ipv4),
180 .hash_func = rte_jhash,
181 .hash_func_init_val = 0,
184 static struct rte_hash_parameters nd_hash_params = {
188 .key_len = sizeof(struct nd_key_ipv6),
189 .hash_func = rte_jhash,
190 .hash_func_init_val = 0,
193 struct ether_addr broadcast_ether_addr = {
194 .addr_bytes[0] = 0xFF,
195 .addr_bytes[1] = 0xFF,
196 .addr_bytes[2] = 0xFF,
197 .addr_bytes[3] = 0xFF,
198 .addr_bytes[4] = 0xFF,
199 .addr_bytes[5] = 0xFF,
202 static const struct ether_addr null_ether_addr = {
203 .addr_bytes[0] = 0x00,
204 .addr_bytes[1] = 0x00,
205 .addr_bytes[2] = 0x00,
206 .addr_bytes[3] = 0x00,
207 .addr_bytes[4] = 0x00,
208 .addr_bytes[5] = 0x00,
211 struct rte_hash *arp_hash_handle;
212 struct rte_hash *nd_hash_handle;
214 void print_pkt1(struct rte_mbuf *pkt);
216 struct app_params *myApp;
217 struct rte_pipeline *myP;
218 uint8_t num_vnf_threads;
221 * A structure for Arp port address
223 struct arp_port_address {
224 uint32_t ip; /**< Ip address */
225 uint8_t mac_addr[6]; /**< Mac address */
228 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
229 struct rte_mempool *timer_mempool_arp;
231 int timer_objs_mempool_count = 70000;
233 #define MAX_NUM_ARP_ENTRIES 64
234 #define MAX_NUM_ND_ENTRIES 64
236 inline uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr);
237 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[]);
239 #define MAX_ARP_DATA_ENTRY_TABLE 7
241 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = {
242 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 1)},
243 {{0, 0, 0, 0, 0, 2}, 0, INCOMPLETE, IPv4(1, 1, 1, 2)},
244 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 3)},
245 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 4)},
246 {{0, 0, 0, 0, 0, 4}, 1, INCOMPLETE, IPv4(1, 1, 1, 5)},
247 {{0, 0, 0, 0, 0, 5}, 0, INCOMPLETE, IPv4(1, 1, 1, 6)},
248 {{0, 0, 0, 0, 0, 6}, 1, INCOMPLETE, IPv4(1, 1, 1, 7)},
251 #define MAX_ND_DATA_ENTRY_TABLE 7
252 struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = {
253 {{0, 0, 0, 0, 0, 8}, 1, INCOMPLETE,
254 {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, 0},
256 {{0, 0, 0, 0, 0, 9}, 1, INCOMPLETE,
257 {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, 0},
258 {{0, 0, 0, 0, 0, 10}, 2, INCOMPLETE,
259 {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
260 {{0, 0, 0, 0, 0, 11}, 3, INCOMPLETE,
261 {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
262 {{0, 0, 0, 0, 0, 12}, 4, INCOMPLETE,
263 {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
264 {{0, 0, 0, 0, 0, 13}, 5, INCOMPLETE,
265 {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
266 {{0, 0, 0, 0, 0, 14}, 6, INCOMPLETE,
267 {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
270 struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
271 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
272 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
273 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
274 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
275 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
276 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
277 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
278 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
279 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
280 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
281 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
282 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
283 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
284 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
285 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
286 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
287 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
288 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
289 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
290 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
291 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
292 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
293 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
294 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
295 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
296 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
297 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
298 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
299 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
300 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
301 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
302 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
303 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
304 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
305 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
306 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
307 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
308 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
309 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
310 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
311 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
312 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
313 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
314 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
315 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
316 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
317 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
318 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
319 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
320 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
321 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
322 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
323 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
324 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
325 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
326 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
327 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
328 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
329 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
330 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
331 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
332 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
333 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
334 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
337 struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
372 void print_trace(void);
374 uint32_t get_arp_buf(void)
379 uint8_t arp_cache_dest_mac_present(uint32_t out_port)
381 return p_arp_data->arp_cache_hw_laddr_valid[out_port];
384 /* Obtain a backtrace and print it to stdout. */
385 void print_trace(void)
392 size = backtrace(array, 10);
393 strings = backtrace_symbols(array, size);
395 RTE_LOG(INFO, LIBARP, "Obtained %zd stack frames.\n", size);
397 for (i = 0; i < size; i++)
398 RTE_LOG(INFO, LIBARP, "%s\n", strings[i]);
403 uint32_t get_nh(uint32_t ip, uint32_t *port, struct ether_addr *addr)
406 for (i = 0; i < p_arp_data->lib_arp_route_ent_cnt; i++) {
407 if ((p_arp_data->lib_arp_route_table[i].nh_mask) ==
408 (ip & p_arp_data->lib_arp_route_table[i].mask)) {
410 *port = p_arp_data->lib_arp_route_table[i].port;
411 if (arp_cache_dest_mac_present(*port))
412 ether_addr_copy(get_local_link_hw_addr(*port, p_arp_data->lib_arp_route_table[i].nh), addr);
413 return p_arp_data->lib_arp_route_table[i].nh;
416 lib_arp_no_nh_found++;
421 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
424 uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
425 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
426 memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
427 memset(netip_nd, 0, sizeof(netip_nd));
428 memset(netip_in, 0, sizeof(netip_in));
431 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
433 convert_prefixlen_to_netmask_ipv6(lib_nd_route_table[i].depth,
436 for (k = 0; k < 16; k++) {
437 if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
439 netip_nd[k] = lib_nd_route_table[i].ipv6[k];
443 for (l = 0; l < 16; l++) {
444 if (ipv6[l] & netmask_ipv6[l]) {
446 netip_in[l] = ipv6[l];
450 if ((depthflags == depthflags1)
451 && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) {
452 //&& (lib_nd_route_table[i].port == port))
453 *port = lib_nd_route_table[i].port;
456 for (j = 0; j < 16; j++)
457 nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
463 printf("No nh match\n");
468 printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
469 lib_nd_no_nh_found++;
472 /* Added for Multiport changes*/
473 struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
474 uint32_t *phy_port, struct ether_addr *hw_addr)
476 struct arp_entry_data *ret_arp_data = NULL;
480 //lib_arp_get_mac_req++;
481 nhip = get_nh(ipaddr, phy_port, hw_addr);
482 if (unlikely(nhip == 0)) {
484 printf("ARPICMP no nh found for ip %x, port %d\n",
489 /* as part of optimization we store mac address in cache
490 * & thus can be sent without having to retrieve
492 if (arp_cache_dest_mac_present(*phy_port)) {
493 //arp_data_ptr[*phy_port]->n_last_update = time(NULL);
494 return &arp_entry_data_default;
497 struct arp_key_ipv4 tmp_arp_key;
498 tmp_arp_key.port_id = *phy_port; /* Changed for Multi Port */
499 tmp_arp_key.ip = nhip;
502 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
505 ret_arp_data = retrieve_arp_entry(tmp_arp_key, DYNAMIC_ARP);
506 if (ret_arp_data == NULL) {
507 if (ARPICMP_DEBUG && ipaddr)
509 RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x, port %u\n", ipaddr, *phy_port);
512 lib_arp_no_arp_entry_found++;
513 } else if (ret_arp_data->status == COMPLETE) {
514 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
515 printf("Setting mac found for port:%d\n", *phy_port);
516 p_arp_data->arp_cache_hw_laddr_valid[*phy_port] = 1;
517 arp_data_ptr[*phy_port] = ret_arp_data;
518 //memcpy(&arp_cache_hw_laddr[*phy_port], hw_addr,
519 // sizeof(struct ether_addr));
520 index = p_arp_data->arp_local_cache[*phy_port].num_nhip;
521 p_arp_data->arp_local_cache[*phy_port].nhip[index] = nhip;
522 ether_addr_copy(hw_addr, &p_arp_data->arp_local_cache[*phy_port].link_hw_laddr[index]);
523 p_arp_data->arp_local_cache[*phy_port].num_nhip++;
524 lib_arp_arp_entry_found++;
527 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
531 ret_arp_data->n_last_update = time(NULL);
536 int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
537 struct ether_addr *hw_addr, uint8_t nhipv6[])
539 int i = 0, j = 0, flag = 0;
540 lib_nd_get_mac_req++;
542 get_nh_ipv6(ipv6addr, phy_port, nhipv6);
543 for (j = 0; j < 16; j++) {
549 printf("NDIPV6 no nh found for ipv6 "
550 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
551 "%02x%02x%02x%02x%02x%02x, port %d\n",
552 ipv6addr[0], ipv6addr[1], ipv6addr[2],
553 ipv6addr[3], ipv6addr[4], ipv6addr[5],
554 ipv6addr[6], ipv6addr[7], ipv6addr[8],
555 ipv6addr[9], ipv6addr[10], ipv6addr[11],
556 ipv6addr[12], ipv6addr[13], ipv6addr[14],
557 ipv6addr[15], *phy_port);
561 struct nd_entry_data *ret_nd_data = NULL;
562 struct nd_key_ipv6 tmp_nd_key;
563 tmp_nd_key.port_id = *phy_port;
565 for (i = 0; i < 16; i++)
566 tmp_nd_key.ipv6[i] = nhipv6[i];
568 ret_nd_data = retrieve_nd_entry(tmp_nd_key);
569 if (ret_nd_data == NULL) {
571 printf("NDIPV6 no nd entry found for ip %x, port %d\n",
572 ipv6addr[0], *phy_port);
574 lib_nd_no_arp_entry_found++;
577 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
578 lib_nd_nd_entry_found++;
582 int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t *phy_port,
583 struct ether_addr *hw_addr, uint8_t nhipv6[])
585 int i = 0, j = 0, flag = 0;
586 lib_nd_get_mac_req++;
588 get_nh_ipv6(ipv6addr, phy_port, nhipv6);
589 for (j = 0; j < 16; j++) {
595 if (NDIPV6_DEBUG && ipv6addr)
596 RTE_LOG(INFO, LIBARP,
597 "NDIPV6 no nh found for ipv6 %x, port %d\n",
598 ipv6addr[0], *phy_port);
602 struct nd_entry_data *ret_nd_data = NULL;
603 struct nd_key_ipv6 tmp_nd_key;
604 tmp_nd_key.port_id = *phy_port;
606 for (i = 0; i < 16; i++) {
607 tmp_nd_key.ipv6[i] = nhipv6[i];
610 ret_nd_data = retrieve_nd_entry(tmp_nd_key);
611 if (ret_nd_data == NULL) {
612 if (NDIPV6_DEBUG && ipv6addr) {
613 RTE_LOG(INFO, LIBARP,
614 "NDIPV6 no nd entry found for ip %x, port %d\n",
615 ipv6addr[0], *phy_port);
618 if (ARPICMP_DEBUG > 4)
620 ("Requesting ARP for ipv6 addr and port %d\n",
622 request_nd(&nhipv6[0], ifm_get_port(*phy_port));
626 lib_nd_no_arp_entry_found++;
629 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
630 lib_nd_nd_entry_found++;
635 * A structure for arp entries in Arp table
638 struct lib_arp_arp_table_entry {
639 struct rte_pipeline_table_entry head;
640 uint64_t macaddr; /**< Mac address */
643 static const char *arp_op_name(uint16_t arp_op)
645 switch (CHECK_ENDIAN_16(arp_op)) {
646 case (ARP_OP_REQUEST):
647 return "ARP Request";
650 case (ARP_OP_REVREQUEST):
651 return "Reverse ARP Request";
652 case (ARP_OP_REVREPLY):
653 return "Reverse ARP Reply";
654 case (ARP_OP_INVREQUEST):
655 return "Peer Identify Request";
656 case (ARP_OP_INVREPLY):
657 return "Peer Identify Reply";
661 return "Unkwown ARP op";
664 static void print_icmp_packet(struct icmp_hdr *icmp_h)
666 RTE_LOG(INFO, LIBARP, " ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
668 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
669 (icmp_h->icmp_type ==
670 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
671 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
672 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
675 static void print_ipv4_h(struct ipv4_hdr *ip_h)
677 struct icmp_hdr *icmp_h =
678 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
679 RTE_LOG(INFO, LIBARP, " IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
680 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
681 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
682 if (ip_h->next_proto_id == IPPROTO_ICMP) {
683 print_icmp_packet(icmp_h);
687 static void print_arp_packet(struct arp_hdr *arp_h)
689 RTE_LOG(INFO, LIBARP, " ARP: hrd=%d proto=0x%04x hln=%d "
690 "pln=%d op=%u (%s)\n",
691 CHECK_ENDIAN_16(arp_h->arp_hrd),
692 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
693 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
694 arp_op_name(arp_h->arp_op));
696 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
697 RTE_LOG(INFO, LIBARP,
698 "incorrect arp_hrd format for IPv4 ARP (%d)\n",
700 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
701 RTE_LOG(INFO, LIBARP,
702 "incorrect arp_pro format for IPv4 ARP (%d)\n",
704 } else if (arp_h->arp_hln != 6) {
705 RTE_LOG(INFO, LIBARP,
706 "incorrect arp_hln format for IPv4 ARP (%d)\n",
708 } else if (arp_h->arp_pln != 4) {
709 RTE_LOG(INFO, LIBARP,
710 "incorrect arp_pln format for IPv4 ARP (%d)\n",
713 RTE_LOG(INFO, LIBARP,
714 " sha=%02X:%02X:%02X:%02X:%02X:%02X",
715 arp_h->arp_data.arp_sha.addr_bytes[0],
716 arp_h->arp_data.arp_sha.addr_bytes[1],
717 arp_h->arp_data.arp_sha.addr_bytes[2],
718 arp_h->arp_data.arp_sha.addr_bytes[3],
719 arp_h->arp_data.arp_sha.addr_bytes[4],
720 arp_h->arp_data.arp_sha.addr_bytes[5]);
721 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
722 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
723 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
724 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
725 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
726 RTE_LOG(INFO, LIBARP,
727 " tha=%02X:%02X:%02X:%02X:%02X:%02X",
728 arp_h->arp_data.arp_tha.addr_bytes[0],
729 arp_h->arp_data.arp_tha.addr_bytes[1],
730 arp_h->arp_data.arp_tha.addr_bytes[2],
731 arp_h->arp_data.arp_tha.addr_bytes[3],
732 arp_h->arp_data.arp_tha.addr_bytes[4],
733 arp_h->arp_data.arp_tha.addr_bytes[5]);
734 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
735 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
736 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
737 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
738 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
742 static void print_eth(struct ether_hdr *eth_h)
744 RTE_LOG(INFO, LIBARP, " ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
745 eth_h->s_addr.addr_bytes[0],
746 eth_h->s_addr.addr_bytes[1],
747 eth_h->s_addr.addr_bytes[2],
748 eth_h->s_addr.addr_bytes[3],
749 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
750 RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
751 eth_h->d_addr.addr_bytes[0],
752 eth_h->d_addr.addr_bytes[1],
753 eth_h->d_addr.addr_bytes[2],
754 eth_h->d_addr.addr_bytes[3],
755 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
760 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
763 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
764 struct arp_hdr *arp_h =
765 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
766 struct ipv4_hdr *ipv4_h =
767 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
769 RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
770 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
772 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
773 case ETHER_TYPE_IPv4:
774 print_ipv4_h(ipv4_h);
777 print_arp_packet(arp_h);
780 RTE_LOG(INFO, LIBARP, " unknown packet type\n");
786 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t mode)
788 struct arp_entry_data *ret_arp_data = NULL;
793 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
794 (void **)&ret_arp_data);
795 if (ret < 0 && (mode == DYNAMIC_ARP)) {
797 RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",arp_key.ip);
799 /* add INCOMPLETE arp entry */
800 ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data),
801 RTE_CACHE_LINE_SIZE, rte_socket_id());
802 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
803 ret_arp_data->status = INCOMPLETE;
804 ret_arp_data->port = arp_key.port_id;
805 ret_arp_data->ip = arp_key.ip;
806 ret_arp_data->mode = mode;
807 ret_arp_data->num_pkts = 0;
808 ret_arp_data->buffered_pkt_list_head = NULL;
809 ret_arp_data->buffered_pkt_list_tail = NULL;
810 rte_rwlock_init(&ret_arp_data->queue_lock);
811 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
813 if (rte_mempool_get(timer_mempool_arp,
814 (void **) &(ret_arp_data->timer) ) < 0) {
815 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
819 ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
820 NULL, sizeof(struct rte_mbuf *) * arp_buffer,
821 RTE_CACHE_LINE_SIZE, rte_socket_id());
823 rte_hash_add_key_data(arp_hash_handle, &arp_key, ret_arp_data);
825 rte_timer_init(ret_arp_data->timer);
826 struct arp_timer_key * callback_key =
827 (struct arp_timer_key*) rte_malloc(NULL,
828 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
829 callback_key->port_id = arp_key.port_id;
830 callback_key->ip = arp_key.ip;
832 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",ARP_TIMER_EXPIRY);
833 if(rte_timer_reset(ret_arp_data->timer,
834 (PROBE_TIME * rte_get_tsc_hz() / 1000),
839 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
841 ret_arp_data->timer_key = callback_key;
843 /* send arp request */
844 request_arp(arp_key.port_id, arp_key.ip);
847 ret_arp_data->mode == DYNAMIC_ARP && ret_arp_data->status == STALE) {
848 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
849 ret_arp_data->status = PROBE;
850 struct arp_timer_key * callback_key =
851 (struct arp_timer_key*) rte_malloc(NULL,
852 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
853 callback_key->port_id = arp_key.port_id;
854 callback_key->ip = arp_key.ip;
856 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",ARP_TIMER_EXPIRY);
857 if(rte_timer_reset(ret_arp_data->timer,
858 (arp_timeout * rte_get_tsc_hz()),
863 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
865 ret_arp_data->timer_key = callback_key;
867 /* send arp request */
868 request_arp(arp_key.port_id, arp_key.ip);
876 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
878 struct nd_entry_data *ret_nd_data = NULL;
884 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
885 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
886 (void **)&ret_nd_data);
888 /* RTE_LOG(INFO, LIBARP,"nd-hash: no lookup Entry Found - ret %d, EINVAL %d, ENOENT %d\n",
889 ret, EINVAL, ENOENT);*/
891 if (ret_nd_data->mode == DYNAMIC_ND) {
892 struct nd_timer_key callback_key;
893 callback_key.port_id = ret_nd_data->port;
895 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
896 callback_key.ipv6[i] = ret_nd_data->ipv6[i];
902 (arp_timeout * rte_get_tsc_hz()), SINGLE,
903 timer_lcore, nd_timer_callback, &callback_key) < 0)
905 RTE_LOG(INFO, LIBARP,
906 "Err : Timer already running\n");
914 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
916 void print_arp_table(void)
918 const void *next_key;
923 ("------------------------ ARP CACHE -----------------------------------------\n");
925 ("----------------------------------------------------------------------------\n");
926 printf("\tport hw addr status ip addr\n");
928 ("----------------------------------------------------------------------------\n");
930 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
933 struct arp_entry_data *tmp_arp_data =
934 (struct arp_entry_data *)next_data;
935 struct arp_key_ipv4 tmp_arp_key;
936 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
938 ("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
939 tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
940 tmp_arp_data->eth_addr.addr_bytes[1],
941 tmp_arp_data->eth_addr.addr_bytes[2],
942 tmp_arp_data->eth_addr.addr_bytes[3],
943 tmp_arp_data->eth_addr.addr_bytes[4],
944 tmp_arp_data->eth_addr.addr_bytes[5],
945 arp_status[tmp_arp_data->status],
946 (tmp_arp_data->ip >> 24),
947 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
948 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
949 ((tmp_arp_data->ip & 0x000000ff)));
953 printf("\nARP routing table has %d entries\n", p_arp_data->lib_arp_route_ent_cnt);
954 printf("\nIP_Address Mask Port NH_IP_Address\n");
955 for (i = 0; i < p_arp_data->lib_arp_route_ent_cnt; i++) {
956 printf("0x%x 0x%x %d 0x%x\n",
957 p_arp_data->lib_arp_route_table[i].ip,
958 p_arp_data->lib_arp_route_table[i].mask,
959 p_arp_data->lib_arp_route_table[i].port, p_arp_data->lib_arp_route_table[i].nh);
963 ("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
964 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
965 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
966 lib_arp_populate_called, lib_arp_delete_called,
967 lib_arp_duplicate_found);
969 printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
973 void print_nd_table(void)
975 const void *next_key;
978 uint8_t ii = 0, j = 0, k = 0;
980 ("------------------------------------------------------------------------------------------------------\n");
981 printf("\tport hw addr status ip addr\n");
984 ("------------------------------------------------------------------------------------------------------\n");
985 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
988 struct nd_entry_data *tmp_nd_data =
989 (struct nd_entry_data *)next_data;
990 struct nd_key_ipv6 tmp_nd_key;
991 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
992 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s\n",
994 tmp_nd_data->eth_addr.addr_bytes[0],
995 tmp_nd_data->eth_addr.addr_bytes[1],
996 tmp_nd_data->eth_addr.addr_bytes[2],
997 tmp_nd_data->eth_addr.addr_bytes[3],
998 tmp_nd_data->eth_addr.addr_bytes[4],
999 tmp_nd_data->eth_addr.addr_bytes[5],
1000 tmp_nd_data->status ==
1001 COMPLETE ? "COMPLETE" : "INCOMPLETE");
1002 printf("\t\t\t\t\t\t");
1003 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
1004 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
1005 tmp_nd_data->ipv6[ii + 1]);
1011 printf("\n\nND IPV6 routing table has %d entries\n",
1012 nd_route_tbl_index);
1014 ("\nIP_Address Depth Port NH_IP_Address\n");
1015 for (i = 0; i < nd_route_tbl_index; i++) {
1018 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
1019 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1020 lib_nd_route_table[i].ipv6[j],
1021 lib_nd_route_table[i].ipv6[j + 1]);
1025 ("\n\t\t\t %d %d \n",
1026 lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
1027 printf("\t\t\t\t\t\t\t\t\t");
1028 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
1029 printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
1030 lib_nd_route_table[i].ipv6[k + 1]);
1034 ("\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",
1035 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
1036 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
1037 lib_nd_populate_called, lib_nd_delete_called,
1038 lib_nd_duplicate_found);
1039 printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
1042 void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
1045 struct arp_timer_key *arp_key = (struct arp_timer_key *)arg;
1046 lib_arp_delete_called++;
1048 rte_timer_stop(ret_arp_data->timer);
1049 rte_free(ret_arp_data->timer_key);
1050 rte_free(ret_arp_data->buf_pkts);
1051 ret_arp_data->buf_pkts = NULL;
1052 if (ARPICMP_DEBUG) {
1053 RTE_LOG(INFO, LIBARP,
1054 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
1055 (arp_key->ip >> 24),
1056 ((arp_key->ip & 0x00ff0000) >>
1058 ((arp_key->ip & 0x0000ff00) >>
1060 ((arp_key->ip & 0x000000ff)),
1063 rte_hash_del_key(arp_hash_handle, arp_key);
1068 void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
1071 struct nd_entry_data *ret_nd_data = NULL;
1072 struct nd_key_ipv6 nd_key;
1073 nd_key.port_id = portid;
1075 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1076 nd_key.ipv6[i] = ipv6addr[i];
1083 lib_nd_delete_called++;
1086 RTE_LOG(INFO, LIBARP,
1087 "Deletes rte hash table nd entry for port %d ipv6=",
1089 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1090 RTE_LOG(INFO, LIBARP, "%02X%02X ", nd_key.ipv6[i],
1091 nd_key.ipv6[i + 1]);
1094 struct nd_timer_key callback_key;
1095 callback_key.port_id = portid;
1097 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1098 callback_key.ipv6[i] = ipv6addr[i];
1101 int ret = rte_hash_lookup_data(arp_hash_handle, &callback_key,
1102 (void **)&ret_nd_data);
1104 // RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
1106 if (ret_nd_data->mode == DYNAMIC_ND) {
1107 rte_timer_stop(ret_nd_data->timer);
1108 rte_free(ret_nd_data->timer);
1111 rte_hash_del_key(nd_hash_handle, &nd_key);
1115 arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
1117 if (ret_arp_data->num_pkts == NUM_DESC) {
1120 ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
1125 arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,struct ether_addr *hw_addr, uint8_t port_id)
1127 l2_phy_interface_t *port = ifm_get_port(port_id);
1128 struct rte_mbuf *pkt, *tmp;
1129 uint8_t *eth_dest, *eth_src;
1133 if (!hw_addr || !ret_arp_data)
1136 for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
1137 pkt = ret_arp_data->buf_pkts[i];
1138 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1139 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1141 memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
1142 memcpy(eth_src, get_link_hw_addr(port_id),
1143 sizeof(struct ether_addr));
1144 port->transmit_single_pkt(port, pkt);
1146 rte_pktmbuf_free(tmp);
1148 ret_arp_data->num_pkts = 0;
1149 ret_arp_data->buffered_pkt_list_head = NULL;
1154 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1155 uint8_t portid, uint8_t mode)
1157 struct arp_key_ipv4 arp_key;
1158 struct arp_entry_data *new_arp_data;
1159 arp_key.port_id = portid;
1160 arp_key.ip = ipaddr;
1161 arp_key.filler1 = 0;
1162 arp_key.filler2 = 0;
1163 arp_key.filler3 = 0;
1165 lib_arp_populate_called++;
1166 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip, arp_key.port_id);
1169 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1170 arp_key.ip, arp_key.port_id);
1172 new_arp_data = retrieve_arp_entry(arp_key, mode);
1173 if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1174 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1175 && mode == STATIC_ARP))) {
1177 RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry already exists(%d %d)\n",
1178 new_arp_data->mode, mode);
1183 if (mode == DYNAMIC_ARP) {
1186 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1187 printf("entry exists\n");
1189 if (ARPICMP_DEBUG) {
1190 RTE_LOG(INFO, LIBARP,
1191 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1193 ((arp_key.ip & 0x00ff0000) >> 16),
1194 ((arp_key.ip & 0x0000ff00) >> 8),
1195 ((arp_key.ip & 0x000000ff)),
1198 lib_arp_duplicate_found++;
1199 new_arp_data->retry_count = 0; // Reset
1200 if (new_arp_data->status == STALE) {
1201 new_arp_data->status = PROBE;
1202 if (ifm_chk_port_ipv4_enabled
1203 (new_arp_data->port)) {
1204 request_arp(new_arp_data->port,
1208 RTE_LOG(INFO, LIBARP,
1209 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1211 new_arp_data->port);
1215 if (rte_timer_reset(new_arp_data->timer,
1216 (arp_timeout * rte_get_tsc_hz()),
1217 SINGLE, timer_lcore,
1219 new_arp_data->timer_key) < 0) {
1221 RTE_LOG(INFO, LIBARP,
1222 "Err : Timer already running\n");
1226 ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
1227 if ((new_arp_data->status == INCOMPLETE) ||
1228 (new_arp_data->status == PROBE)) {
1229 new_arp_data->status = COMPLETE;
1230 new_arp_data->mode = mode;
1231 new_arp_data->n_confirmed = time(NULL);
1232 //end_tsc[new_arp_data->port] = rte_rdtsc();
1233 //printf("confirmed val is %x %dms\n",new_arp_data->ip, (end_tsc[new_arp_data->port] - start_tsc[new_arp_data->port] + ticks_per_ms/2)/ticks_per_ms);
1234 new_arp_data->retry_count = 0;
1235 if (rte_timer_reset(new_arp_data->timer,
1236 (arp_timeout * rte_get_tsc_hz()),
1237 SINGLE, timer_lcore,
1239 new_arp_data->timer_key) < 0) {
1241 RTE_LOG(INFO, LIBARP,
1242 "Err : Timer already running\n");
1249 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1251 if (ARPICMP_DEBUG) {
1252 RTE_LOG(INFO, LIBARP,
1253 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1255 ((arp_key.ip & 0x00ff0000) >> 16),
1256 ((arp_key.ip & 0x0000ff00) >> 8),
1257 ((arp_key.ip & 0x000000ff)),
1260 lib_arp_duplicate_found++;
1263 RTE_CACHE_LINE_ROUNDUP(sizeof
1264 (struct arp_entry_data));
1266 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1267 new_arp_data->eth_addr = *hw_addr;
1268 new_arp_data->status = COMPLETE;
1269 new_arp_data->port = portid;
1270 new_arp_data->ip = ipaddr;
1271 new_arp_data->mode = mode;
1272 new_arp_data->buffered_pkt_list_head = NULL;
1273 new_arp_data->buffered_pkt_list_tail = NULL;
1274 new_arp_data->num_pkts = 0;
1276 rte_hash_add_key_data(arp_hash_handle, &arp_key,
1278 if (ARPICMP_DEBUG) {
1279 RTE_LOG(INFO, LIBARP,
1280 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1282 ((arp_key.ip & 0x00ff0000) >> 16),
1283 ((arp_key.ip & 0x0000ff00) >> 8),
1284 ((arp_key.ip & 0x000000ff)),
1287 #ifdef L3_STACK_SUPPORT
1288 // Call l3fwd module for resolving 2_adj structure.
1289 resolve_l2_adj(ipaddr, portid, hw_addr);
1294 if (ARPICMP_DEBUG) {
1295 /* print entire hash table */
1296 RTE_LOG(INFO, LIBARP,
1297 "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d on port=%d\n",
1298 new_arp_data->eth_addr.addr_bytes[0],
1299 new_arp_data->eth_addr.addr_bytes[1],
1300 new_arp_data->eth_addr.addr_bytes[2],
1301 new_arp_data->eth_addr.addr_bytes[3],
1302 new_arp_data->eth_addr.addr_bytes[4],
1303 new_arp_data->eth_addr.addr_bytes[5],
1304 (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1305 ((arp_key.ip & 0x0000ff00) >> 8),
1306 ((arp_key.ip & 0x000000ff)), portid);
1314 * Install key - data pair in Hash table - From Pipeline Configuration
1318 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1319 uint8_t portid, uint8_t mode)
1322 /* need to lock here if multi-threaded */
1323 /* rte_hash_add_key_data is not thread safe */
1325 struct nd_key_ipv6 nd_key;
1326 nd_key.port_id = portid;
1328 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
1329 nd_key.ipv6[i] = ipv6[i];
1331 // RTE_LOG(INFO, LIBARP,"\n");
1336 lib_nd_populate_called++;
1338 /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1339 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
1341 if (mode == DYNAMIC_ND) {
1343 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1346 RTE_LOG(INFO, LIBARP,
1347 "nd_entry exists port %d ipv6 = ",
1349 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1351 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1353 nd_key.ipv6[i + 1]);
1357 lib_nd_duplicate_found++;
1358 RTE_LOG(INFO, LIBARP, "nd_entry exists\n");
1362 RTE_CACHE_LINE_ROUNDUP(sizeof(struct nd_entry_data));
1363 new_nd_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1365 //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
1366 new_nd_data->eth_addr = *hw_addr;
1367 new_nd_data->status = COMPLETE;
1368 new_nd_data->port = portid;
1369 new_nd_data->mode = mode;
1371 (timer_mempool_arp, (void **)&(new_nd_data->timer)) < 0) {
1372 RTE_LOG(INFO, LIBARP,
1373 "TIMER - Error in getting timer alloc buffer\n");
1378 RTE_LOG(INFO, LIBARP, "populate_nd_entry ipv6=");
1380 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1381 new_nd_data->ipv6[i] = ipv6[i];
1385 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1387 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1388 new_nd_data->ipv6[i],
1389 new_nd_data->ipv6[i + 1]);
1393 /*Add a key-data pair at hash table for ND IPv6 static routing */
1394 rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
1395 /* need to check the return value of the hash add */
1397 /* after the hash is created then time is started */
1398 rte_timer_init(new_nd_data->timer);
1399 struct nd_timer_key *callback_key =
1400 (struct nd_timer_key *)rte_malloc(NULL,
1401 sizeof(struct nd_timer_key
1403 RTE_CACHE_LINE_SIZE);
1404 callback_key->port_id = portid;
1406 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1407 callback_key->ipv6[i] = ipv6[i];
1410 (new_nd_data->timer, (arp_timeout * rte_get_tsc_hz()),
1411 SINGLE, timer_lcore, nd_timer_callback, callback_key) < 0)
1412 RTE_LOG(INFO, LIBARP, "Err : Timer already running\n");
1415 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1417 RTE_LOG(INFO, LIBARP,
1418 "nd_entry exists port %d ipv6 = ",
1420 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1422 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1424 nd_key.ipv6[i + 1]);
1428 lib_nd_duplicate_found++;
1431 RTE_CACHE_LINE_ROUNDUP(sizeof
1432 (struct nd_entry_data));
1434 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1436 //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
1437 new_nd_data->eth_addr = *hw_addr;
1438 new_nd_data->status = COMPLETE;
1439 new_nd_data->port = portid;
1440 new_nd_data->mode = mode;
1441 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1442 new_nd_data->ipv6[i] = ipv6[i];
1445 /*Add a key-data pair at hash table for ND IPv6 static routing */
1446 rte_hash_add_key_data(nd_hash_handle, &nd_key,
1448 /* need to check the return value of the hash add */
1453 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1456 /* print entire hash table */
1458 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1459 new_nd_data->eth_addr.addr_bytes[0],
1460 new_nd_data->eth_addr.addr_bytes[1],
1461 new_nd_data->eth_addr.addr_bytes[2],
1462 new_nd_data->eth_addr.addr_bytes[3],
1463 new_nd_data->eth_addr.addr_bytes[4],
1464 new_nd_data->eth_addr.addr_bytes[5], portid);
1465 RTE_LOG(INFO, LIBARP, "\tipv6=");
1466 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1467 new_nd_data->ipv6[i] = ipv6[i];
1468 RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1469 new_nd_data->ipv6[i + 1]);
1472 RTE_LOG(INFO, LIBARP, "\n");
1478 void print_pkt1(struct rte_mbuf *pkt)
1480 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1482 RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1483 for (i = 0; i < 20; i++) {
1484 for (j = 0; j < 20; j++)
1485 printf("%02x ", rd[(20 * i) + j]);
1486 RTE_LOG(INFO, LIBARP, "\n");
1490 #define MAX_NUM_MAC_ADDRESS 16
1491 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1492 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1493 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1494 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1495 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1496 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1497 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1498 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1499 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1500 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1501 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1502 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1503 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1504 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1505 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1506 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1507 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1510 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1512 return &p_arp_data->link_hw_addr[out_port];
1515 void request_arp(uint8_t port_id, uint32_t ip)
1518 struct ether_hdr *eth_h;
1519 struct arp_hdr *arp_h;
1521 l2_phy_interface_t *link;
1522 link = ifm_get_port(port_id);
1523 struct rte_mbuf *arp_pkt = lib_arp_pkt[port_id];
1525 if (arp_pkt == NULL) {
1527 RTE_LOG(INFO, LIBARP,
1528 "Error allocating arp_pkt rte_mbuf\n");
1531 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1533 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1534 ether_addr_copy((struct ether_addr *)
1535 &link->macaddr[0], ð_h->s_addr);
1536 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1538 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1539 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1540 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1541 arp_h->arp_hln = ETHER_ADDR_LEN;
1542 arp_h->arp_pln = sizeof(uint32_t);
1543 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1545 if (link && link->ipv4_list) {
1546 arp_h->arp_data.arp_sip =
1547 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1549 ether_addr_copy((struct ether_addr *)
1550 &link->macaddr[0], &arp_h->arp_data.arp_sha);
1551 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1552 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1554 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1555 arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1556 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1557 arp_pkt->pkt_len = 42;
1558 arp_pkt->data_len = 42;
1560 if (ARPICMP_DEBUG) {
1561 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1562 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1565 link->transmit_single_pkt(link, arp_pkt);
1566 // start_tsc[port_id] = rte_rdtsc();
1567 printf("Sent ARP Request %x \n", arp_h->arp_data.arp_tip);
1570 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1572 struct ether_hdr *eth_h;
1573 struct ipv4_hdr *ip_h;
1574 struct icmp_hdr *icmp_h;
1575 l2_phy_interface_t *port = ifm_get_port(port_id);
1577 struct rte_mbuf *icmp_pkt = lib_arp_pkt[port_id];
1578 if (icmp_pkt == NULL) {
1580 RTE_LOG(INFO, LIBARP,
1581 "Error allocating icmp_pkt rte_mbuf\n");
1585 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1587 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1588 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1590 ip_h->version_ihl = IP_VHL_DEF;
1591 ip_h->type_of_service = 0;
1592 ip_h->total_length =
1593 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1594 ip_h->packet_id = 0xaabb;
1595 ip_h->fragment_offset = 0x0000;
1596 ip_h->time_to_live = 64;
1597 ip_h->next_proto_id = IPPROTO_ICMP;
1598 if (port && port->ipv4_list)
1600 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1601 ip_h->dst_addr = rte_cpu_to_be_32(ip);
1603 ip_h->hdr_checksum = 0;
1604 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1606 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1607 icmp_h->icmp_code = 0;
1608 icmp_h->icmp_ident = 0xdead;
1609 icmp_h->icmp_seq_nb = 0xbeef;
1611 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1614 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1615 sizeof(struct icmp_hdr);
1616 icmp_pkt->data_len = icmp_pkt->pkt_len;
1618 print_mbuf("TX", 0, icmp_pkt, __LINE__);
1624 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1625 uint64_t pkt_mask, l2_phy_interface_t *port)
1627 RTE_SET_USED(pkt_num);
1629 RTE_LOG(INFO, LIBARP,
1630 "============ARP ENTRY================\n");
1633 RTE_LOG(INFO, LIBARP,
1634 "============ARP PROCESS================\n");
1637 uint64_t pkts_for_process = pkt_mask;
1638 for (; pkts_for_process;) {
1639 /**< process only valid packets. */
1640 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1641 uint64_t pkts_mask = 1LLU << pos; /** <bitmask representing only this packet. */
1642 pkts_for_process &= ~pkts_mask; /** <remove this packet from the mask. */
1643 process_arpicmp_pkt(pkt[pos], port);
1648 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1650 uint8_t in_port_id = pkt->port;
1651 struct ether_hdr *eth_h;
1652 struct arp_hdr *arp_h;
1653 struct ipv4_hdr *ip_h;
1654 struct icmp_hdr *icmp_h;
1660 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1662 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1664 RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1665 __FUNCTION__, port->pmdid, __LINE__);
1667 (struct arp_hdr *)((char *)eth_h +
1668 sizeof(struct ether_hdr));
1669 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1670 RTE_LOG(INFO, LIBARP,
1671 "Invalid hardware format of hardware address - not processing ARP req\n");
1672 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1673 RTE_LOG(INFO, LIBARP,
1674 "Invalid protocol address format - not processing ARP req\n");
1675 else if (arp_h->arp_hln != 6)
1676 RTE_LOG(INFO, LIBARP,
1677 "Invalid hardware address length - not processing ARP req\n");
1678 else if (arp_h->arp_pln != 4)
1679 RTE_LOG(INFO, LIBARP,
1680 "Invalid protocol address length - not processing ARP req\n");
1682 if (port->ipv4_list == NULL) {
1683 RTE_LOG(INFO, LIBARP,
1684 "Ports IPV4 List is NULL.. Unable to Process\n");
1688 if (arp_h->arp_data.arp_tip !=
1689 ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1690 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1691 printf("gratuitous arp received\n");
1693 (struct ether_addr *)&arp_h->arp_data.arp_sha,
1694 rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1699 RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1702 /// revise conditionals to allow processing of requests with target ip = this ip and
1703 // processing of replies to destination ip = this ip
1704 else if (arp_h->arp_op ==
1705 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1706 if (ARPICMP_DEBUG) {
1707 RTE_LOG(INFO, LIBARP,
1708 "%s, portid %u. Line %d\n\r",
1709 __FUNCTION__, port->pmdid,
1712 RTE_LOG(INFO, LIBARP,
1713 "arp_op %d, ARP_OP_REQUEST %d\n",
1717 print_mbuf("RX", in_port_id, pkt,
1720 populate_arp_entry((struct ether_addr *)
1721 &arp_h->arp_data.arp_sha,
1723 (arp_h->arp_data.arp_sip),
1724 in_port_id, DYNAMIC_ARP);
1727 req_tip = arp_h->arp_data.arp_tip;
1728 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1729 ether_addr_copy((struct ether_addr *)&port->macaddr[0], ð_h->s_addr); /**< set sender mac address*/
1730 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1731 ether_addr_copy(ð_h->s_addr,
1732 &arp_h->arp_data.arp_sha);
1733 arp_h->arp_data.arp_tip =
1734 arp_h->arp_data.arp_sip;
1735 arp_h->arp_data.arp_sip = req_tip;
1736 ether_addr_copy(ð_h->d_addr,
1737 &arp_h->arp_data.arp_tha);
1739 print_mbuf("TX ARP REPLY PKT",
1740 port->pmdid, pkt, __LINE__);
1741 port->transmit_bulk_pkts(port, &pkt, 1);
1743 print_mbuf("TX", port->pmdid, pkt,
1745 printf("replying arp pkt done\n");
1746 //rte_pktmbuf_free(pkt);
1748 } else if (arp_h->arp_op ==
1749 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1750 if (ARPICMP_DEBUG) {
1751 RTE_LOG(INFO, LIBARP,
1752 "ARP_OP_REPLY received");
1753 print_mbuf("RX", port->pmdid, pkt,
1756 populate_arp_entry((struct ether_addr *)
1757 &arp_h->arp_data.arp_sha,
1760 in_port_id, DYNAMIC_ARP);
1762 //rte_pktmbuf_free(pkt);
1766 RTE_LOG(INFO, LIBARP,
1767 "Invalid ARP opcode - not processing ARP req %x\n",
1772 rte_pktmbuf_free(pkt);
1775 (struct ipv4_hdr *)((char *)eth_h +
1776 sizeof(struct ether_hdr));
1778 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1780 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1782 if (ip_h->next_proto_id != IPPROTO_ICMP) {
1783 if (ARPICMP_DEBUG) {
1784 RTE_LOG(INFO, LIBARP,
1785 "IP protocol ID is not set to ICMP - discarding\n");
1787 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1788 if (ARPICMP_DEBUG) {
1789 RTE_LOG(INFO, LIBARP,
1790 "IP version other than 4 - discarding\n");
1792 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1793 if (ARPICMP_DEBUG) {
1794 RTE_LOG(INFO, LIBARP,
1795 "Unknown IHL - discarding\n");
1798 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1799 && icmp_h->icmp_code == 0) {
1801 print_mbuf("RX", in_port_id,
1804 ip_addr = ip_h->src_addr;
1805 ether_addr_copy(ð_h->s_addr,
1807 ether_addr_copy((struct ether_addr *)
1811 RTE_LOG(INFO, LIBARP,
1812 "%s, portid %u. Line %d\n\r",
1814 port->pmdid, __LINE__);
1816 if (is_multicast_ipv4_addr
1821 rte_be_to_cpu_32(ip_addr);
1822 if ((ip_src & 0x00000003) == 1)
1833 rte_cpu_to_be_32(ip_src);
1834 ip_h->dst_addr = ip_addr;
1836 ip_h->hdr_checksum = 0;
1837 ip_h->hdr_checksum =
1838 ~rte_raw_cksum(ip_h,
1843 RTE_LOG(INFO, LIBARP,
1844 "%s, portid %u. Line %d\n\r",
1848 ip_h->src_addr = ip_h->dst_addr;
1849 ip_h->dst_addr = ip_addr;
1852 icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1853 cksum = ~icmp_h->icmp_cksum & 0xffff;
1855 ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1857 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1859 (cksum & 0xffff) + (cksum >> 16);
1861 (cksum & 0xffff) + (cksum >> 16);
1862 icmp_h->icmp_cksum = ~cksum;
1866 ("TX ICMP ECHO REPLY PKT",
1867 in_port_id, pkt, __LINE__);
1868 port->transmit_bulk_pkts(port, &pkt, 1);
1870 print_mbuf("TX", port->pmdid,
1874 } else if (icmp_h->icmp_type ==
1876 && icmp_h->icmp_code == 0) {
1878 print_mbuf("RX", in_port_id,
1881 struct arp_key_ipv4 arp_key;
1882 arp_key.port_id = in_port_id;
1884 rte_bswap32(ip_h->src_addr);
1885 arp_key.filler1 = 0;
1886 arp_key.filler2 = 0;
1887 arp_key.filler3 = 0;
1889 struct arp_entry_data *arp_entry =
1890 retrieve_arp_entry(arp_key, DYNAMIC_ARP);
1891 if (arp_entry == NULL) {
1893 RTE_LOG(INFO, LIBARP,
1894 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1899 arp_entry->status = COMPLETE;
1904 rte_pktmbuf_free(pkt);
1906 printf("reached end of process_arpicmp\n");
1910 * inet_pton(af, src, dst)
1911 * convert from presentation format (which usually means ASCII printable)
1912 * to network format (which is usually some kind of binary format).
1914 * 1 if the address was valid for the specified address family
1915 * 0 if the address wasn't valid (`dst' is untouched in this case)
1916 * -1 if some other error occurred (`dst' is untouched in this case, too)
1920 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
1924 return inet_pton_ipv4(src, dst);
1926 return inet_pton_ipv6(src, dst);
1928 errno = EAFNOSUPPORT;
1935 * inet_pton_ipv4(src, dst)
1936 * like inet_aton() but without all the hexadecimal and shorthand.
1938 * 1 if `src' is a valid dotted quad, else 0.
1940 * does not touch `dst' unless it's returning 1.
1944 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1946 static const char digits[] = "0123456789";
1947 int saw_digit, octets, ch;
1948 unsigned char tmp[INADDRSZ], *tp;
1953 while ((ch = *src++) != '\0') {
1956 pch = strchr(digits, ch);
1958 unsigned int new = *tp * 10 + (pch - digits);
1967 *tp = (unsigned char)new;
1968 } else if (ch == '.' && saw_digit) {
1979 memcpy(dst, tmp, INADDRSZ);
1984 * inet_pton_ipv6(src, dst)
1985 * convert presentation level address to network order binary form.
1987 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1989 * (1) does not touch `dst' unless it's returning 1.
1990 * (2) :: in a full address is silently ignored.
1992 * inspired by Mark Andrews.
1996 static int inet_pton_ipv6(const char *src, unsigned char *dst)
1998 static const char xdigits_l[] = "0123456789abcdef",
1999 xdigits_u[] = "0123456789ABCDEF";
2000 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2001 const char *xdigits = 0, *curtok = 0;
2002 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2003 unsigned int val = 0;
2004 unsigned int dbloct_count = 0;
2006 memset((tp = tmp), '\0', IN6ADDRSZ);
2007 endp = tp + IN6ADDRSZ;
2009 /* Leading :: requires some special handling. */
2014 saw_xdigit = count_xdigit = 0;
2017 while ((ch = *src++) != '\0') {
2020 pch = strchr((xdigits = xdigits_l), ch);
2022 pch = strchr((xdigits = xdigits_u), ch);
2024 if (count_xdigit >= 4)
2027 val |= (pch - xdigits);
2041 } else if (*src == '\0') {
2044 if (tp + sizeof(int16_t) > endp)
2046 *tp++ = (unsigned char)((val >> 8) & 0xff);
2047 *tp++ = (unsigned char)(val & 0xff);
2054 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2055 inet_pton_ipv4(curtok, tp) > 0) {
2059 break; /* '\0' was seen by inet_pton4(). */
2064 if (tp + sizeof(int16_t) > endp)
2066 *tp++ = (unsigned char)((val >> 8) & 0xff);
2067 *tp++ = (unsigned char)(val & 0xff);
2070 if (colonp != NULL) {
2071 /* if we already have 8 double octets, having a colon means error */
2072 if (dbloct_count == 8)
2076 * Since some memmove()'s erroneously fail to handle
2077 * overlapping regions, we'll do the shift by hand.
2079 const int n = tp - colonp;
2082 for (i = 1; i <= n; i++) {
2083 endp[-i] = colonp[n - i];
2090 memcpy(dst, tmp, IN6ADDRSZ);
2094 static int arp_parse_args(struct pipeline_params *params)
2096 uint32_t arp_route_tbl_present = 0;
2097 uint32_t nd_route_tbl_present = 0;
2098 uint32_t ports_mac_list_present = 0;
2100 uint32_t n_vnf_threads_present = 0;
2102 uint32_t pktq_in_prv_present = 0;
2103 uint32_t prv_to_pub_map_present = 0;
2105 uint8_t n_prv_in_port = 0;
2107 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2108 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2109 prv_to_pub_map[i] = 0xff;
2110 pub_to_prv_map[i] = 0xff;
2113 RTE_SET_USED(ports_mac_list_present);
2114 RTE_SET_USED(nd_route_tbl_present);
2115 RTE_SET_USED(arp_route_tbl_present);
2116 for (numArg = 0; numArg < params->n_args; numArg++) {
2117 char *arg_name = params->args_name[numArg];
2118 char *arg_value = params->args_value[numArg];
2120 /* arp timer expiry */
2121 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2122 arp_timeout = atoi(arg_value);
2126 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2127 if (pktq_in_prv_present) {
2129 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2132 pktq_in_prv_present = 1;
2134 int rxport = 0, j = 0;
2135 char phy_port_num[5];
2136 char *token = strtok(arg_value, "RXQ");
2139 while ((j < 4) && (token[j] != '.')) {
2140 phy_port_num[j] = token[j];
2143 phy_port_num[j] = '\0';
2144 rxport = atoi(phy_port_num);
2145 prv_in_port_a[n_prv_in_port++] = rxport;
2149 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2150 token, phy_port_num, rxport);
2151 prv_in_port_a[n_prv_in_port++] = rxport;
2152 if(rxport < PIPELINE_MAX_PORT_IN)
2153 in_port_dir_a[rxport] = 1; // set rxport egress
2154 token = strtok(NULL, "RXQ");
2157 if (n_prv_in_port == 0) {
2159 ("VNF common parse error - no prv RX phy port\n");
2165 if (strcmp(arg_name, "arp_buf") == 0) {
2166 arp_buffer = atoi(arg_value);
2169 /* prv_to_pub_map */
2170 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2171 if (prv_to_pub_map_present) {
2173 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2176 prv_to_pub_map_present = 1;
2178 int rxport = 0, txport = 0, j = 0, k = 0;
2179 char rx_phy_port_num[5];
2180 char tx_phy_port_num[5];
2181 char *token = strtok(arg_value, "(");
2184 while ((j < 4) && (token[j] != ',')) {
2185 rx_phy_port_num[j] = token[j];
2188 rx_phy_port_num[j] = '\0';
2189 rxport = atoi(rx_phy_port_num);
2195 while ((k < 4) && (token[j + k] != ')')) {
2196 tx_phy_port_num[k] = token[j + k];
2199 tx_phy_port_num[k] = '\0';
2200 txport = atoi(tx_phy_port_num);
2204 RTE_LOG(INFO, LIBARP, "token: %s,"
2205 "rx_phy_port_str: %s, phy_port_num %d,"
2206 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2207 token, rx_phy_port_num, rxport,
2208 tx_phy_port_num, txport);
2210 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2211 (txport >= PIPELINE_MAX_PORT_IN) ||
2212 (in_port_dir_a[rxport] != 1)) {
2214 ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2216 in_port_dir_a[rxport]);
2220 prv_to_pub_map[rxport] = txport;
2221 pub_to_prv_map[txport] = rxport;
2222 token = strtok(NULL, "(");
2228 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2229 if (n_vnf_threads_present)
2231 n_vnf_threads_present = 1;
2233 num_vnf_threads = atoi(arg_value);
2234 if (num_vnf_threads <= 0) {
2235 RTE_LOG(INFO, LIBARP,
2236 "n_vnf_threads is invalid\n");
2239 RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2244 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2245 ARPICMP_DEBUG = atoi(arg_value);
2250 /* ports_mac_list */
2251 if (strcmp(arg_name, "ports_mac_list") == 0) {
2252 ports_mac_list_present = 1;
2254 uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
2256 char byteStr[MAC_NUM_BYTES][3];
2257 uint32_t byte[MAC_NUM_BYTES];
2259 char *token = strtok(arg_value, " ");
2262 for (i = 0; i < MAC_NUM_BYTES; i++) {
2263 for (j = 0; j < 2; j++) {
2264 byteStr[i][j] = token[k++];
2266 byteStr[i][j] = '\0';
2270 for (i = 0; i < MAC_NUM_BYTES; i++) {
2271 byte[i] = strtoul(byteStr[i], NULL, 16);
2274 if (ARPICMP_DEBUG) {
2275 RTE_LOG(INFO, LIBARP, "token: %s",
2277 for (i = 0; i < MAC_NUM_BYTES; i++)
2278 RTE_LOG(INFO, LIBARP,
2281 RTE_LOG(INFO, LIBARP, "\n");
2283 //Populate the static arp_route_table
2284 for (i = 0; i < MAC_NUM_BYTES; i++)
2285 p_arp_data->link_hw_addr[p_arp_data->link_hw_addr_array_idx].addr_bytes[i] = byte[i];
2287 p_arp_data->link_hw_addr_array_idx++;
2288 token = strtok(NULL, " ");
2295 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2296 arp_route_tbl_present = 1;
2298 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2299 0, i = 0, j = 0, k = 0, l = 0;
2300 uint32_t arp_route_tbl_str_max_len = 10;
2301 char dest_ip_str[arp_route_tbl_str_max_len];
2302 char mask_str[arp_route_tbl_str_max_len];
2303 char tx_port_str[arp_route_tbl_str_max_len];
2304 char nh_ip_str[arp_route_tbl_str_max_len];
2305 char *token = strtok(arg_value, "(");
2308 while ((i < (arp_route_tbl_str_max_len - 1))
2309 && (token[i] != ',')) {
2310 dest_ip_str[i] = token[i];
2313 dest_ip_str[i] = '\0';
2314 dest_ip = strtoul(dest_ip_str, NULL, 16);
2318 while ((j < (arp_route_tbl_str_max_len - 1))
2319 && (token[i + j] != ',')) {
2320 mask_str[j] = token[i + j];
2324 mask = strtoul(mask_str, NULL, 16);
2328 while ((k < (arp_route_tbl_str_max_len - 1))
2329 && (token[i + j + k] != ',')) {
2330 tx_port_str[k] = token[i + j + k];
2333 tx_port_str[k] = '\0';
2334 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2338 while ((l < (arp_route_tbl_str_max_len - 1))
2339 && (token[i + j + k + l] != ')')) {
2340 nh_ip_str[l] = token[i + j + k + l];
2343 nh_ip_str[l] = '\0';
2344 nh_ip = strtoul(nh_ip_str, NULL, 16); //atoi(nh_ip_str);
2347 RTE_LOG(INFO, LIBARP, "token: %s, "
2348 "dest_ip_str: %s, dest_ip %u, "
2349 "mask_str: %s, mask %u, "
2350 "tx_port_str: %s, tx_port %u, "
2351 "nh_ip_str: %s, nh_ip %u\n",
2352 token, dest_ip_str, dest_ip,
2353 mask_str, mask, tx_port_str,
2354 tx_port, nh_ip_str, nh_ip);
2357 /* if (tx_port >= params->n_ports_out)
2359 RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2360 tx_port, params->n_ports_out);
2364 //Populate the static arp_route_table
2365 struct lib_arp_route_table_entry *lentry =
2366 &p_arp_data->lib_arp_route_table
2367 [p_arp_data->lib_arp_route_ent_cnt];
2368 lentry->ip = dest_ip;
2369 lentry->mask = mask;
2370 lentry->port = tx_port;
2372 lentry->nh_mask = nh_ip & mask;
2373 p_arp_data->lib_arp_route_ent_cnt++;
2374 token = strtok(NULL, "(");
2381 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2382 nd_route_tbl_present = 1;
2384 uint8_t dest_ipv6[16], depth = 0, tx_port =
2385 0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2386 uint8_t nd_route_tbl_str_max_len = 128; //64;
2387 char dest_ipv6_str[nd_route_tbl_str_max_len];
2388 char depth_str[nd_route_tbl_str_max_len];
2389 char tx_port_str[nd_route_tbl_str_max_len];
2390 char nh_ipv6_str[nd_route_tbl_str_max_len];
2391 char *token = strtok(arg_value, "(");
2394 while ((i < (nd_route_tbl_str_max_len - 1))
2395 && (token[i] != ',')) {
2396 dest_ipv6_str[i] = token[i];
2399 dest_ipv6_str[i] = '\0';
2400 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2405 while ((j < (nd_route_tbl_str_max_len - 1))
2406 && (token[i + j] != ',')) {
2407 depth_str[j] = token[i + j];
2410 depth_str[j] = '\0';
2411 //converting string char to integer
2413 for (s = 0; depth_str[s] != '\0'; ++s)
2414 depth = depth * 10 + depth_str[s] - '0';
2418 while ((k < (nd_route_tbl_str_max_len - 1))
2419 && (token[i + j + k] != ',')) {
2420 tx_port_str[k] = token[i + j + k];
2423 tx_port_str[k] = '\0';
2424 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2428 while ((l < (nd_route_tbl_str_max_len - 1))
2429 && (token[i + j + k + l] != ')')) {
2430 nh_ipv6_str[l] = token[i + j + k + l];
2433 nh_ipv6_str[l] = '\0';
2434 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2437 //Populate the static arp_route_table
2438 for (i = 0; i < 16; i++) {
2440 [nd_route_tbl_index].ipv6[i] =
2443 [nd_route_tbl_index].nhipv6[i] =
2446 lib_nd_route_table[nd_route_tbl_index].depth =
2448 lib_nd_route_table[nd_route_tbl_index].port =
2451 nd_route_tbl_index++;
2452 token = strtok(NULL, "(");
2460 /* Check that mandatory arguments are present */
2462 if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2463 RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2464 RTE_LOG(INFO, LIBARP,"%d, %d \n",
2465 arp_route_tbl_present, ports_mac_list_present);
2473 static void local_arp_cache_init(void)
2476 for (i=0; i<MAX_PORTS;i++) {
2477 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2478 p_arp_data->arp_local_cache[i].nhip[j] = 0;
2480 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2481 p_arp_data->arp_local_cache[i].num_nhip = 0;
2486 struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip)
2490 struct ether_addr *x = NULL;
2491 limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2492 for (i=0; i < limit; i++) {
2493 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2495 x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2502 void lib_arp_init(struct pipeline_params *params,
2503 __rte_unused struct app_params *app)
2508 struct pipeline_cgnapt *p;
2510 RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2512 /* create arp data for table entries */
2513 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2514 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2515 p_arp_data = (struct arp_data *)p;
2517 /* Parse arguments */
2518 if (arp_parse_args(params)) {
2519 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2523 /* create the arp_icmp mbuf rx pool */
2524 lib_arp_pktmbuf_tx_pool =
2525 rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2526 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2529 if (lib_arp_pktmbuf_tx_pool == NULL) {
2530 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2534 for (i=0; i<MAX_PORTS; i++) {
2535 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2536 if (lib_arp_pkt[i] == NULL) {
2537 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2541 /* create the arp_icmp mbuf rx pool */
2542 arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2543 NB_ARPICMP_MBUF, 32, 0,
2544 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2546 if (arp_icmp_pktmbuf_tx_pool == NULL) {
2547 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2551 arp_hash_params.socket_id = rte_socket_id();
2552 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2553 arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2554 arp_hash_handle = rte_hash_create(&arp_hash_params);
2556 if (arp_hash_handle == NULL) {
2557 RTE_LOG(INFO, LIBARP,
2558 "ARP rte_hash_create failed. socket %d ... \n",
2559 arp_hash_params.socket_id);
2561 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2562 (void *)arp_hash_handle);
2565 /* Create port alloc buffer */
2567 timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2568 timer_objs_mempool_count,
2569 sizeof(struct rte_timer),
2572 NULL, NULL, rte_socket_id(), 0);
2573 if (timer_mempool_arp == NULL) {
2574 rte_panic("timer_mempool create error\n");
2576 rte_timer_subsystem_init();
2577 list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2580 nd_hash_params.socket_id = rte_socket_id();
2581 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2582 nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2583 nd_hash_handle = rte_hash_create(&nd_hash_params);
2584 if (nd_hash_handle == NULL) {
2585 RTE_LOG(INFO, LIBARP,
2586 "ND rte_hash_create failed. socket %d ... \n",
2587 nd_hash_params.socket_id);
2589 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2590 (void *)nd_hash_handle);
2593 /* Initialize the local arp cache */
2594 local_arp_cache_init();
2599 void arp_timer_callback(struct rte_timer *timer, void *arg)
2601 struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2602 struct arp_key_ipv4 arp_key;
2603 arp_key.port_id = timer_key->port_id;
2604 arp_key.ip = timer_key->ip;
2605 arp_key.filler1 = 0;
2606 arp_key.filler2 = 0;
2607 arp_key.filler3 = 0;
2609 struct arp_entry_data *ret_arp_data = NULL;
2611 if (ARPICMP_DEBUG) {
2612 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2613 arp_key.ip, arp_key.port_id);
2616 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2617 (void **)&ret_arp_data);
2621 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2622 (int)timer->expire, now);
2624 printf("Should not have come here\n");
2627 if (ret_arp_data->mode == DYNAMIC_ARP) {
2628 if (ret_arp_data->status == PROBE ||
2629 ret_arp_data->status == INCOMPLETE) {
2630 if (ret_arp_data->retry_count == 3) {
2631 remove_arp_entry(ret_arp_data, arg);
2633 ret_arp_data->retry_count++;
2635 if (ARPICMP_DEBUG) {
2636 RTE_LOG(INFO, LIBARP,
2637 "RETRY ARP..retry count : %u\n",
2638 ret_arp_data->retry_count);
2640 RTE_LOG(INFO, LIBARP,
2641 "TIMER STARTED FOR %u seconds\n",
2645 if (ifm_chk_port_ipv4_enabled
2646 (ret_arp_data->port)) {
2647 //printf("inside arp timer callback numpkts:%d\n", ret_arp_data->num_pkts);
2648 request_arp(ret_arp_data->port,
2652 RTE_LOG(INFO, LIBARP,
2653 "%s: IP is not enabled on port %u, not sending GARP\n\r",
2655 ret_arp_data->port);
2658 if (rte_timer_reset(ret_arp_data->timer,
2660 rte_get_tsc_hz()/ 1000),
2666 RTE_LOG(INFO, LIBARP,
2667 "Err : Timer already running\n");
2670 } else if (ret_arp_data->status == COMPLETE) {
2671 if (now <= (ret_arp_data->n_confirmed + arp_timeout)) {
2672 if (rte_timer_reset(ret_arp_data->timer,
2674 rte_get_tsc_hz()), SINGLE,
2679 RTE_LOG(INFO, LIBARP,
2680 "Err : Timer already running\n");
2681 } else if (now <= (ret_arp_data->n_last_update + USED_TIME)) {
2682 if (rte_timer_reset(ret_arp_data->timer,
2684 rte_get_tsc_hz()), SINGLE,
2689 RTE_LOG(INFO, LIBARP,
2690 "Err : Timer already running\n");
2692 ret_arp_data->status = STALE;
2693 p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2697 rte_hash_del_key(arp_hash_handle, &arp_key);
2703 void nd_timer_callback(struct rte_timer *timer, void *arg)
2705 struct nd_timer_key *remove_key = (struct nd_timer_key *)arg;
2707 RTE_LOG(INFO, LIBARP, "nd time callback : expire :%d\n",
2708 (int)timer->expire);
2709 remove_nd_entry_ipv6(remove_key->ipv6, remove_key->port_id);
2713 void create_arp_table(void)
2717 for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2718 populate_arp_entry((const struct ether_addr *)
2719 &arp_entry_data_table[i].eth_addr,
2720 arp_entry_data_table[i].ip,
2721 (uint8_t) arp_entry_data_table[i].port,
2729 void create_nd_table(void)
2733 for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2734 populate_nd_entry((const struct ether_addr *)
2735 nd_entry_data_table[i].eth_addr,
2736 nd_entry_data_table[i].ipv6,
2737 (uint8_t) nd_entry_data_table[i].port,
2744 void send_gratuitous_arp(l2_phy_interface_t *port)
2746 struct ether_hdr *eth_h;
2747 struct arp_hdr *arp_h;
2749 struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
2752 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2757 if (arp_pkt == NULL) {
2759 RTE_LOG(INFO, LIBARP,
2760 "Error allocating arp_pkt rte_mbuf\n");
2764 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2766 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
2767 ether_addr_copy((struct ether_addr *)
2768 &port->macaddr[0], ð_h->s_addr);
2769 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2771 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2772 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2773 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2774 arp_h->arp_hln = ETHER_ADDR_LEN;
2775 arp_h->arp_pln = sizeof(uint32_t);
2776 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2778 ether_addr_copy((struct ether_addr *)
2779 &port->macaddr[0], &arp_h->arp_data.arp_sha);
2780 if (port->ipv4_list == NULL) {
2782 RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2786 arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2787 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2788 //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2789 arp_h->arp_data.arp_tip = 0; //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2790 // RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2791 //arp_h->arp_data.arp_sip);
2792 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2793 arp_pkt->pkt_len = 42;
2794 arp_pkt->data_len = 42;
2796 if (ARPICMP_DEBUG) {
2797 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2798 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2800 port->transmit_single_pkt(port, arp_pkt);
2803 void set_arpdebug(int flag)
2806 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2811 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2817 void set_arptimeout(uint32_t timeout_val)
2819 if (timeout_val == 0) {
2820 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2824 RTE_LOG(INFO, LIBARP,
2825 "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2826 arp_timeout, timeout_val);
2827 arp_timeout = timeout_val;
2829 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",