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;
66 uint32_t nd_buffer = ARP_BUF_DEFAULT;
73 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
74 static int inet_pton_ipv6(const char *src, unsigned char *dst);
75 static int inet_pton_ipv4(const char *src, unsigned char *dst);
76 static void local_arp_cache_init(void);
77 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]);
78 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
79 uint8_t netmask_ipv6[]);
81 uint8_t vnf_common_arp_lib_init;
82 uint8_t vnf_common_nd_lib_init;
83 uint8_t loadb_pipeline_count;
85 uint32_t ARPICMP_DEBUG;
86 uint32_t NDIPV6_DEBUG;
88 uint32_t arp_route_tbl_index;
89 uint32_t nd_route_tbl_index;
90 uint32_t link_hw_addr_array_idx;
92 uint32_t lib_arp_get_mac_req;
93 uint32_t lib_arp_nh_found;
94 uint32_t lib_arp_no_nh_found;
95 uint32_t lib_arp_arp_entry_found;
96 uint32_t lib_arp_no_arp_entry_found;
97 uint32_t lib_arp_populate_called;
98 uint32_t lib_arp_delete_called;
99 uint32_t lib_arp_duplicate_found;
101 uint32_t lib_nd_get_mac_req;
102 uint32_t lib_nd_nh_found;
103 uint32_t lib_nd_no_nh_found;
104 uint32_t lib_nd_nd_entry_found;
105 uint32_t lib_nd_no_arp_entry_found;
106 uint32_t lib_nd_populate_called;
107 uint32_t lib_nd_delete_called;
108 uint32_t lib_nd_duplicate_found;
109 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
110 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
112 struct rte_mbuf *lib_arp_pkt[MAX_PORTS];
113 struct rte_mbuf *lib_nd_pkt[MAX_PORTS];
115 uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
116 uint8_t default_ip[4] = { 0, 0, 1, 1 };
118 uint64_t start_tsc[4];
120 #define ticks_per_ms (rte_get_tsc_hz()/1000)
122 #define MAX_NUM_ARP_CACHE_MAC_ADDRESS 16
124 /***** ARP local cache *****/
125 struct arp_data *p_arp_data;
126 //struct arp_cache arp_local_cache[MAX_PORTS];
127 uint8_t arp_cache_hw_laddr_valid[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
128 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0
135 rte_rwlock_t arp_hash_handle_lock;
136 rte_rwlock_t nd_hash_handle_lock;
138 void update_nhip_access(uint8_t dest_if)
140 p_arp_data->update_tsc[dest_if] = rte_rdtsc();
144 * A structure defining the mbuf meta data for VFW.
146 struct mbuf_arp_meta_data {
147 /* output port stored for RTE_PIPELINE_ACTION_PORT_META */
148 uint32_t output_port;
149 struct rte_mbuf *next; /* next pointer for chained buffers */
150 } __rte_cache_aligned;
152 static struct arp_entry_data arp_entry_data_default = {
157 static struct nd_entry_data nd_entry_data_default = {
163 * memory pool for queued up user pkts.
165 struct rte_mempool *arp_icmp_pktmbuf_tx_pool;
167 static struct rte_hash_parameters arp_hash_params = {
171 .key_len = sizeof(struct arp_key_ipv4),
172 .hash_func = rte_jhash,
173 .hash_func_init_val = 0,
176 static struct rte_hash_parameters nd_hash_params = {
180 .key_len = sizeof(struct nd_key_ipv6),
181 .hash_func = rte_jhash,
182 .hash_func_init_val = 0,
185 struct ether_addr broadcast_ether_addr = {
186 .addr_bytes[0] = 0xFF,
187 .addr_bytes[1] = 0xFF,
188 .addr_bytes[2] = 0xFF,
189 .addr_bytes[3] = 0xFF,
190 .addr_bytes[4] = 0xFF,
191 .addr_bytes[5] = 0xFF,
194 static const struct ether_addr null_ether_addr = {
195 .addr_bytes[0] = 0x00,
196 .addr_bytes[1] = 0x00,
197 .addr_bytes[2] = 0x00,
198 .addr_bytes[3] = 0x00,
199 .addr_bytes[4] = 0x00,
200 .addr_bytes[5] = 0x00,
203 struct rte_hash *arp_hash_handle;
204 struct rte_hash *nd_hash_handle;
206 void print_pkt1(struct rte_mbuf *pkt);
208 struct app_params *myApp;
209 struct rte_pipeline *myP;
210 uint8_t num_vnf_threads;
213 * A structure for Arp port address
215 struct arp_port_address {
216 uint32_t ip; /**< Ip address */
217 uint8_t mac_addr[6]; /**< Mac address */
220 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
221 struct rte_mempool *timer_mempool_arp;
223 int timer_objs_mempool_count = 70000;
225 #define MAX_NUM_ARP_ENTRIES 64
226 #define MAX_NUM_ND_ENTRIES 64
228 inline uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr);
229 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[],
230 struct ether_addr *hw_addr);
232 #define MAX_ARP_DATA_ENTRY_TABLE 7
234 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = {
235 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 1)},
236 {{0, 0, 0, 0, 0, 2}, 0, INCOMPLETE, IPv4(1, 1, 1, 2)},
237 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 3)},
238 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 4)},
239 {{0, 0, 0, 0, 0, 4}, 1, INCOMPLETE, IPv4(1, 1, 1, 5)},
240 {{0, 0, 0, 0, 0, 5}, 0, INCOMPLETE, IPv4(1, 1, 1, 6)},
241 {{0, 0, 0, 0, 0, 6}, 1, INCOMPLETE, IPv4(1, 1, 1, 7)},
244 #define MAX_ND_DATA_ENTRY_TABLE 7
245 struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = {
246 {{0, 0, 0, 0, 0, 8}, 1, INCOMPLETE,
247 {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, 0},
249 {{0, 0, 0, 0, 0, 9}, 1, INCOMPLETE,
250 {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, 0},
251 {{0, 0, 0, 0, 0, 10}, 2, INCOMPLETE,
252 {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
253 {{0, 0, 0, 0, 0, 11}, 3, INCOMPLETE,
254 {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
255 {{0, 0, 0, 0, 0, 12}, 4, INCOMPLETE,
256 {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
257 {{0, 0, 0, 0, 0, 13}, 5, INCOMPLETE,
258 {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
259 {{0, 0, 0, 0, 0, 14}, 6, INCOMPLETE,
260 {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
263 struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
264 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
265 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
266 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
267 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
268 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
269 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
270 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0,
271 {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}, 0, 0,
273 {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}, 0, 0,
275 {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}, 0, 0,
277 {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}, 0, 0,
279 {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}, 0, 0,
281 {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}, 0, 0,
283 {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}, 0, 0,
285 {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}, 0, 0,
287 {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}, 0, 0,
289 {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}, 0, 0,
291 {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}, 0, 0,
293 {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}, 0, 0,
295 {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}, 0, 0,
297 {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}, 0, 0,
299 {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}, 0, 0,
301 {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}, 0, 0,
303 {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}, 0, 0,
305 {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}, 0, 0,
307 {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}, 0, 0,
309 {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}, 0, 0,
311 {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}, 0, 0,
313 {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}, 0, 0,
315 {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}, 0, 0,
317 {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}, 0, 0,
319 {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}, 0, 0,
321 {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}, 0, 0,
323 {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}, 0, 0,
325 {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}, 0, 0,
327 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
330 void print_trace(void);
332 uint32_t get_arp_buf(void)
337 uint32_t get_nd_buf(void)
342 uint8_t arp_cache_dest_mac_present(uint32_t out_port)
344 return p_arp_data->arp_cache_hw_laddr_valid[out_port];
347 uint8_t nd_cache_dest_mac_present(uint32_t out_port)
349 return p_arp_data->nd_cache_hw_laddr_valid[out_port];
352 /* Obtain a backtrace and print it to stdout. */
353 void print_trace(void)
360 size = backtrace(array, 10);
361 strings = backtrace_symbols(array, size);
363 RTE_LOG(INFO, LIBARP, "Obtained %zd stack frames.\n", size);
365 for (i = 0; i < size; i++)
366 RTE_LOG(INFO, LIBARP, "%s\n", strings[i]);
371 uint32_t get_nh(uint32_t ip, uint32_t *port, struct ether_addr *addr)
374 for (i = 0; i < p_arp_data->lib_arp_route_ent_cnt; i++) {
375 if ((p_arp_data->lib_arp_route_table[i].nh_mask) ==
376 (ip & p_arp_data->lib_arp_route_table[i].mask)) {
378 *port = p_arp_data->lib_arp_route_table[i].port;
379 if (arp_cache_dest_mac_present(*port))
381 get_local_link_hw_addr(*port,
382 p_arp_data->lib_arp_route_table[i].nh), addr);
383 return p_arp_data->lib_arp_route_table[i].nh;
386 lib_arp_no_nh_found++;
391 void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[],
392 struct ether_addr *hw_addr)
395 uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
396 uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0;
397 memset(netmask_ipv6, 0, sizeof(netmask_ipv6));
398 memset(netip_nd, 0, sizeof(netip_nd));
399 memset(netip_in, 0, sizeof(netip_in));
402 for (i = 0; i < MAX_ARP_RT_ENTRY; i++) {
404 convert_prefixlen_to_netmask_ipv6(lib_nd_route_table[i].depth,
407 for (k = 0; k < 16; k++) {
408 if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) {
410 netip_nd[k] = lib_nd_route_table[i].ipv6[k];
414 for (l = 0; l < 16; l++) {
415 if (ipv6[l] & netmask_ipv6[l]) {
417 netip_in[l] = ipv6[l];
421 if ((depthflags == depthflags1)
422 && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) {
423 //&& (lib_nd_route_table[i].port == port))
424 *port = lib_nd_route_table[i].port;
427 for (j = 0; j < 16; j++)
428 nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
430 if (nd_cache_dest_mac_present(*port)) {
432 get_nd_local_link_hw_addr(*port, nhipv6),
433 (struct ether_addr *)hw_addr);
439 printf("No nh match\n");
444 printf("No NH - ip 0x%x, \n", ipv6[0]);
445 lib_nd_no_nh_found++;
448 /* Added for Multiport changes*/
449 struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
450 uint32_t *phy_port, struct ether_addr *hw_addr)
452 struct arp_entry_data *ret_arp_data = NULL;
456 nhip = get_nh(ipaddr, phy_port, hw_addr);
457 if (unlikely(nhip == 0)) {
459 printf("ARPICMP no nh found for ip %x, port %d\n",
464 /* as part of optimization we store mac address in cache
465 * & thus can be sent without having to retrieve
467 if (arp_cache_dest_mac_present(*phy_port)) {
468 return &arp_entry_data_default;
471 struct arp_key_ipv4 tmp_arp_key;
472 tmp_arp_key.port_id = *phy_port; /* Changed for Multi Port */
473 tmp_arp_key.ip = nhip;
476 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
479 ret_arp_data = retrieve_arp_entry(tmp_arp_key, DYNAMIC_ARP);
480 if (ret_arp_data == NULL) {
481 if (ARPICMP_DEBUG && ipaddr)
483 RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x,"
484 " port %u\n", ipaddr, *phy_port);
487 lib_arp_no_arp_entry_found++;
488 } else if (ret_arp_data->status == COMPLETE) {
489 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
490 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
491 p_arp_data->arp_cache_hw_laddr_valid[*phy_port] = 1;
492 index = p_arp_data->arp_local_cache[*phy_port].num_nhip;
493 p_arp_data->arp_local_cache[*phy_port].nhip[index] = nhip;
494 ether_addr_copy(hw_addr,
495 &p_arp_data->arp_local_cache[*phy_port].link_hw_laddr[index]);
496 p_arp_data->arp_local_cache[*phy_port].num_nhip++;
497 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
498 lib_arp_arp_entry_found++;
500 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
504 p_arp_data->update_tsc[*phy_port] = rte_rdtsc();
509 struct nd_entry_data *get_dest_mac_address_ipv6_port(uint8_t ipv6addr[],
510 uint32_t *phy_port, struct ether_addr *hw_addr, uint8_t nhipv6[])
512 int i = 0, j = 0, flag = 0;
514 lib_nd_get_mac_req++;
516 get_nh_ipv6(ipv6addr, phy_port, nhipv6, hw_addr);
517 for (j = 0; j < 16; j++) {
524 printf("NDIPV6 no nh found for ipv6 "
525 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
526 "%02x%02x%02x%02x%02x%02x, port %d\n",
527 ipv6addr[0], ipv6addr[1], ipv6addr[2],
528 ipv6addr[3], ipv6addr[4], ipv6addr[5],
529 ipv6addr[6], ipv6addr[7], ipv6addr[8],
530 ipv6addr[9], ipv6addr[10], ipv6addr[11],
531 ipv6addr[12], ipv6addr[13], ipv6addr[14],
532 ipv6addr[15], *phy_port);
536 struct nd_entry_data *ret_nd_data = NULL;
537 struct nd_key_ipv6 tmp_nd_key;
538 tmp_nd_key.port_id = *phy_port;
540 if (nd_cache_dest_mac_present(*phy_port)) {
541 return &nd_entry_data_default;
545 for (i = 0; i < 16; i++)
546 tmp_nd_key.ipv6[i] = nhipv6[i];
548 ret_nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND);
549 if (ret_nd_data == NULL) {
551 printf("NDIPV6 no nd entry found for ip %x, port %d\n",
552 ipv6addr[0], *phy_port);
554 lib_nd_no_arp_entry_found++;
556 } else if (ret_nd_data->status == COMPLETE) {
557 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
558 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
559 p_arp_data->nd_cache_hw_laddr_valid[*phy_port] = 1;
560 index = p_arp_data->nd_local_cache[*phy_port].num_nhip;
561 rte_mov16(&p_arp_data->nd_local_cache[*phy_port].nhip[index][0],
563 ether_addr_copy(hw_addr,
564 &p_arp_data->nd_local_cache[*phy_port].link_hw_laddr[index]);
565 p_arp_data->nd_local_cache[*phy_port].num_nhip++;
567 lib_nd_nd_entry_found++;
568 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
572 p_arp_data->update_tsc[*phy_port] = rte_rdtsc();
578 * A structure for arp entries in Arp table
581 struct lib_arp_arp_table_entry {
582 struct rte_pipeline_table_entry head;
583 uint64_t macaddr; /**< Mac address */
586 static const char *arp_op_name(uint16_t arp_op)
588 switch (CHECK_ENDIAN_16(arp_op)) {
589 case (ARP_OP_REQUEST):
590 return "ARP Request";
593 case (ARP_OP_REVREQUEST):
594 return "Reverse ARP Request";
595 case (ARP_OP_REVREPLY):
596 return "Reverse ARP Reply";
597 case (ARP_OP_INVREQUEST):
598 return "Peer Identify Request";
599 case (ARP_OP_INVREPLY):
600 return "Peer Identify Reply";
604 return "Unkwown ARP op";
607 static void print_icmp_packet(struct icmp_hdr *icmp_h)
609 RTE_LOG(INFO, LIBARP, " ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
611 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
612 (icmp_h->icmp_type ==
613 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
614 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
615 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
618 static void print_ipv4_h(struct ipv4_hdr *ip_h)
620 struct icmp_hdr *icmp_h =
621 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
622 RTE_LOG(INFO, LIBARP, " IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
623 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
624 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
625 if (ip_h->next_proto_id == IPPROTO_ICMP) {
626 print_icmp_packet(icmp_h);
630 static void print_arp_packet(struct arp_hdr *arp_h)
632 RTE_LOG(INFO, LIBARP, " ARP: hrd=%d proto=0x%04x hln=%d "
633 "pln=%d op=%u (%s)\n",
634 CHECK_ENDIAN_16(arp_h->arp_hrd),
635 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
636 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
637 arp_op_name(arp_h->arp_op));
639 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
640 RTE_LOG(INFO, LIBARP,
641 "incorrect arp_hrd format for IPv4 ARP (%d)\n",
643 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
644 RTE_LOG(INFO, LIBARP,
645 "incorrect arp_pro format for IPv4 ARP (%d)\n",
647 } else if (arp_h->arp_hln != 6) {
648 RTE_LOG(INFO, LIBARP,
649 "incorrect arp_hln format for IPv4 ARP (%d)\n",
651 } else if (arp_h->arp_pln != 4) {
652 RTE_LOG(INFO, LIBARP,
653 "incorrect arp_pln format for IPv4 ARP (%d)\n",
656 RTE_LOG(INFO, LIBARP,
657 " sha=%02X:%02X:%02X:%02X:%02X:%02X",
658 arp_h->arp_data.arp_sha.addr_bytes[0],
659 arp_h->arp_data.arp_sha.addr_bytes[1],
660 arp_h->arp_data.arp_sha.addr_bytes[2],
661 arp_h->arp_data.arp_sha.addr_bytes[3],
662 arp_h->arp_data.arp_sha.addr_bytes[4],
663 arp_h->arp_data.arp_sha.addr_bytes[5]);
664 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
665 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
666 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
667 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
668 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
669 RTE_LOG(INFO, LIBARP,
670 " tha=%02X:%02X:%02X:%02X:%02X:%02X",
671 arp_h->arp_data.arp_tha.addr_bytes[0],
672 arp_h->arp_data.arp_tha.addr_bytes[1],
673 arp_h->arp_data.arp_tha.addr_bytes[2],
674 arp_h->arp_data.arp_tha.addr_bytes[3],
675 arp_h->arp_data.arp_tha.addr_bytes[4],
676 arp_h->arp_data.arp_tha.addr_bytes[5]);
677 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
678 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
679 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
680 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
681 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
685 static void print_eth(struct ether_hdr *eth_h)
687 RTE_LOG(INFO, LIBARP, " ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
688 eth_h->s_addr.addr_bytes[0],
689 eth_h->s_addr.addr_bytes[1],
690 eth_h->s_addr.addr_bytes[2],
691 eth_h->s_addr.addr_bytes[3],
692 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
693 RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
694 eth_h->d_addr.addr_bytes[0],
695 eth_h->d_addr.addr_bytes[1],
696 eth_h->d_addr.addr_bytes[2],
697 eth_h->d_addr.addr_bytes[3],
698 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
703 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
706 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
707 struct arp_hdr *arp_h =
708 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
709 struct ipv4_hdr *ipv4_h =
710 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
712 RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
713 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
715 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
716 case ETHER_TYPE_IPv4:
717 print_ipv4_h(ipv4_h);
720 print_arp_packet(arp_h);
723 RTE_LOG(INFO, LIBARP, " unknown packet type\n");
730 * Add entry in ND table.
735 * return nd entry from table.
738 static int add_nd_data(struct nd_key_ipv6 *nd_key,
739 struct nd_entry_data *ret_nd_data)
742 struct nd_entry_data *tmp_nd_data = NULL;
743 rte_rwlock_write_lock(&nd_hash_handle_lock);
744 /* Check for value while locked */
745 ret = rte_hash_lookup_data(nd_hash_handle, nd_key, (void **)&tmp_nd_data);
747 if (ret == -ENOENT) {
748 /* entry not yet added, do so now */
749 ret = rte_hash_add_key_data(nd_hash_handle, nd_key, ret_nd_data);
751 /* We panic here because either:
752 * ret == -EINVAL and a parameter got messed up, or
753 * ret == -ENOSPC and the hash table isn't big enough
755 rte_panic("ND: Error on entry add for %s", rte_strerror(abs(ret)));
757 } else if (ret < 0) {
758 /* We panic here because ret == -EINVAL and a parameter got
759 * messed up, or dpdk hash lib changed and this needs corrected */
760 rte_panic("ARP: Error on entry add for %s", rte_strerror(abs(ret)));
762 /* entry already exists */
766 rte_rwlock_write_unlock(&nd_hash_handle_lock);
771 * Add entry in ARP table.
775 * @param ret_arp_data
776 * return arp entry from table.
779 static int add_arp_data(struct arp_key_ipv4 *arp_key,
780 struct arp_entry_data *ret_arp_data) {
782 struct arp_entry_data *tmp_arp_data = NULL;
783 rte_rwlock_write_lock(&arp_hash_handle_lock);
784 /* Check for value while locked */
785 ret = rte_hash_lookup_data(arp_hash_handle, arp_key, (void **)&tmp_arp_data);
787 if (ret == -ENOENT) {
788 /* entry not yet added, do so now */
789 ret = rte_hash_add_key_data(arp_hash_handle, arp_key, ret_arp_data);
791 /* We panic here because either:
792 * ret == -EINVAL and a parameter got messed up, or
793 * ret == -ENOSPC and the hash table isn't big enough
795 rte_panic("ARP: Error on entry add for %s - %s",
796 inet_ntoa(*(struct in_addr *)&arp_key->ip),
797 rte_strerror(abs(ret)));
799 } else if (ret < 0) {
800 /* We panic here because ret == -EINVAL and a parameter got
801 * messed up, or dpdk hash lib changed and this needs corrected */
802 rte_panic("ARP: Error on entry add for %s - %s",
803 inet_ntoa(*(struct in_addr *)&arp_key->ip),
804 rte_strerror(abs(ret)));
806 /* entry already exists */
810 rte_rwlock_write_unlock(&arp_hash_handle_lock);
814 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t mode)
816 struct arp_entry_data *ret_arp_data = NULL;
821 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
822 (void **)&ret_arp_data);
823 if (ret < 0 && (mode == DYNAMIC_ARP)) {
825 RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",
828 /* add INCOMPLETE arp entry */
829 ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data),
830 RTE_CACHE_LINE_SIZE, rte_socket_id());
831 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
832 ret_arp_data->status = INCOMPLETE;
833 ret_arp_data->port = arp_key.port_id;
834 ret_arp_data->ip = arp_key.ip;
835 ret_arp_data->mode = mode;
836 ret_arp_data->num_pkts = 0;
837 rte_rwlock_init(&ret_arp_data->queue_lock);
838 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
840 /* attempt to add arp_entry to hash */
841 ret = add_arp_data(&arp_key, ret_arp_data);
844 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
845 rte_free(ret_arp_data);
846 /* Some other thread has 'beat' this thread in
847 creation of arp_data, try again */
851 if (rte_mempool_get(timer_mempool_arp,
852 (void **) &(ret_arp_data->timer) ) < 0) {
853 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
854 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
858 ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
859 NULL, sizeof(struct rte_mbuf *) * arp_buffer,
860 RTE_CACHE_LINE_SIZE, rte_socket_id());
862 if (ret_arp_data->buf_pkts == NULL) {
863 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
864 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
868 rte_timer_init(ret_arp_data->timer);
869 struct arp_timer_key * callback_key =
870 (struct arp_timer_key*) rte_malloc(NULL,
871 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
872 callback_key->port_id = arp_key.port_id;
873 callback_key->ip = arp_key.ip;
875 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
877 if(rte_timer_reset(ret_arp_data->timer,
878 (PROBE_TIME * rte_get_tsc_hz() / 1000),
883 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
885 ret_arp_data->timer_key = callback_key;
887 /* send arp request */
888 request_arp(arp_key.port_id, arp_key.ip);
889 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
892 ret_arp_data->mode == DYNAMIC_ARP && ret_arp_data->status == STALE) {
893 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
894 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
895 ret_arp_data->status = PROBE;
896 struct arp_timer_key * callback_key =
897 (struct arp_timer_key*) rte_malloc(NULL,
898 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
899 callback_key->port_id = arp_key.port_id;
900 callback_key->ip = arp_key.ip;
902 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u"
903 " seconds\n",ARP_TIMER_EXPIRY);
904 if(rte_timer_reset(ret_arp_data->timer,
905 (arp_timeout * rte_get_tsc_hz()),
910 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
912 ret_arp_data->timer_key = callback_key;
914 /* send arp request */
915 request_arp(arp_key.port_id, arp_key.ip);
916 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
924 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
926 struct nd_entry_data *ret_nd_data = NULL;
932 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
933 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
934 (void **)&ret_nd_data);
935 if (ret < 0 && (mode == DYNAMIC_ND)) {
937 RTE_LOG(INFO, LIBARP, "ND entry not found for ip \n");
939 /* add INCOMPLETE arp entry */
940 ret_nd_data = rte_malloc_socket(NULL, sizeof(struct nd_entry_data),
941 RTE_CACHE_LINE_SIZE, rte_socket_id());
942 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
943 ret_nd_data->status = INCOMPLETE;
944 ret_nd_data->port = nd_key.port_id;
946 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
947 ret_nd_data->ipv6[i] = nd_key.ipv6[i];
948 ret_nd_data->mode = mode;
949 ret_nd_data->num_pkts = 0;
950 rte_rwlock_init(&ret_nd_data->queue_lock);
951 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
953 /* attempt to add arp_entry to hash */
954 ret = add_nd_data(&nd_key, ret_nd_data);
957 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
958 rte_free(ret_nd_data);
959 /* Some other thread has 'beat' this thread in
960 creation of arp_data, try again */
965 if (rte_mempool_get(timer_mempool_arp,
966 (void **) &(ret_nd_data->timer) ) < 0) {
967 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
968 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
972 ret_nd_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
973 NULL, sizeof(struct rte_mbuf *) * nd_buffer,
974 RTE_CACHE_LINE_SIZE, rte_socket_id());
976 if (ret_nd_data->buf_pkts == NULL) {
977 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
978 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
982 rte_timer_init(ret_nd_data->timer);
983 struct nd_timer_key * callback_key =
984 (struct nd_timer_key*) rte_malloc(NULL,
985 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
986 callback_key->port_id = nd_key.port_id;
987 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
988 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
992 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
996 if(rte_timer_reset(ret_nd_data->timer,
997 (PROBE_TIME * rte_get_tsc_hz() / 1000),
1002 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
1004 ret_nd_data->timer_key = callback_key;
1005 /* send nd request */
1006 request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
1007 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1010 ret_nd_data->mode == DYNAMIC_ND && ret_nd_data->status == STALE) {
1011 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1012 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
1013 ret_nd_data->status = PROBE;
1014 struct nd_timer_key * callback_key =
1015 (struct nd_timer_key*) rte_malloc(NULL,
1016 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
1018 callback_key->port_id = nd_key.port_id;
1019 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1020 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
1024 (ret_nd_data->timer,
1025 (arp_timeout * rte_get_tsc_hz()), SINGLE,
1026 timer_lcore, nd_timer_callback, callback_key) < 0)
1028 RTE_LOG(INFO, LIBARP,
1029 "Err : Timer already running\n");
1030 ret_nd_data->timer_key = callback_key;
1032 /* send nd request */
1033 request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
1034 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1040 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
1042 void print_arp_table(void)
1044 const void *next_key;
1048 printf("------------------------ ARP CACHE ------------------------------------\n");
1049 printf("-----------------------------------------------------------------------\n");
1050 printf("\tport hw addr status ip addr\n");
1051 printf("-----------------------------------------------------------------------\n");
1053 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
1056 struct arp_entry_data *tmp_arp_data =
1057 (struct arp_entry_data *)next_data;
1058 struct arp_key_ipv4 tmp_arp_key;
1059 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
1060 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X"
1061 " %10s %d.%d.%d.%d\n",
1062 tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
1063 tmp_arp_data->eth_addr.addr_bytes[1],
1064 tmp_arp_data->eth_addr.addr_bytes[2],
1065 tmp_arp_data->eth_addr.addr_bytes[3],
1066 tmp_arp_data->eth_addr.addr_bytes[4],
1067 tmp_arp_data->eth_addr.addr_bytes[5],
1068 arp_status[tmp_arp_data->status],
1069 (tmp_arp_data->ip >> 24),
1070 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
1071 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
1072 ((tmp_arp_data->ip & 0x000000ff)));
1076 printf("\nARP routing table has %d entries\n", p_arp_data->lib_arp_route_ent_cnt);
1077 printf("\nIP_Address Mask Port NH_IP_Address\n");
1078 for (i = 0; i < p_arp_data->lib_arp_route_ent_cnt; i++) {
1079 printf("0x%x 0x%x %d 0x%x\n",
1080 p_arp_data->lib_arp_route_table[i].ip,
1081 p_arp_data->lib_arp_route_table[i].mask,
1082 p_arp_data->lib_arp_route_table[i].port,
1083 p_arp_data->lib_arp_route_table[i].nh);
1086 printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u,"
1087 " no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1088 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
1089 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
1090 lib_arp_populate_called, lib_arp_delete_called,
1091 lib_arp_duplicate_found);
1093 printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
1097 void print_nd_table(void)
1099 const void *next_key;
1102 uint8_t ii = 0, j = 0, k = 0;
1103 printf("-----------------------------------------------------------------------\n");
1104 printf("\tport hw addr status ip addr\n");
1106 printf("-----------------------------------------------------------------------\n");
1107 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
1110 struct nd_entry_data *tmp_nd_data =
1111 (struct nd_entry_data *)next_data;
1112 struct nd_key_ipv6 tmp_nd_key;
1113 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
1114 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s\n",
1116 tmp_nd_data->eth_addr.addr_bytes[0],
1117 tmp_nd_data->eth_addr.addr_bytes[1],
1118 tmp_nd_data->eth_addr.addr_bytes[2],
1119 tmp_nd_data->eth_addr.addr_bytes[3],
1120 tmp_nd_data->eth_addr.addr_bytes[4],
1121 tmp_nd_data->eth_addr.addr_bytes[5],
1122 arp_status[tmp_nd_data->status]);
1123 printf("\t\t\t\t\t\t");
1124 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
1125 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
1126 tmp_nd_data->ipv6[ii + 1]);
1132 printf("\n\nND IPV6 routing table has %d entries\n",
1133 nd_route_tbl_index);
1134 printf("\nIP_Address Depth");
1135 printf(" Port NH_IP_Address\n");
1136 for (i = 0; i < nd_route_tbl_index; i++) {
1139 for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) {
1140 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1141 lib_nd_route_table[i].ipv6[j],
1142 lib_nd_route_table[i].ipv6[j + 1]);
1146 ("\n\t\t\t %d %d \n",
1147 lib_nd_route_table[i].depth, lib_nd_route_table[i].port);
1148 printf("\t\t\t\t\t\t\t\t\t");
1149 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
1150 printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k],
1151 lib_nd_route_table[i].ipv6[k + 1]);
1154 printf("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u,"
1155 " no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1156 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
1157 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
1158 lib_nd_populate_called, lib_nd_delete_called,
1159 lib_nd_duplicate_found);
1160 printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
1163 void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
1166 struct arp_timer_key *arp_key = (struct arp_timer_key *)arg;
1167 lib_arp_delete_called++;
1169 rte_timer_stop(ret_arp_data->timer);
1170 rte_free(ret_arp_data->timer_key);
1171 rte_free(ret_arp_data->buf_pkts);
1172 ret_arp_data->buf_pkts = NULL;
1173 if (ARPICMP_DEBUG) {
1174 RTE_LOG(INFO, LIBARP,
1175 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
1176 (arp_key->ip >> 24),
1177 ((arp_key->ip & 0x00ff0000) >> 16),
1178 ((arp_key->ip & 0x0000ff00) >> 8),
1179 ((arp_key->ip & 0x000000ff)),
1182 rte_hash_del_key(arp_hash_handle, arp_key);
1187 void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg)
1190 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
1192 lib_nd_delete_called++;
1194 rte_timer_stop(ret_nd_data->timer);
1195 rte_free(ret_nd_data->timer_key);
1196 rte_free(ret_nd_data->buf_pkts);
1197 ret_nd_data->buf_pkts = NULL;
1200 RTE_LOG(INFO, LIBARP,
1201 "Deletes rte hash table nd entry for port %d ipv6=",
1202 timer_key->port_id);
1203 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1204 RTE_LOG(INFO, LIBARP, "%02X%02X ", timer_key->ipv6[i],
1205 timer_key->ipv6[i + 1]);
1208 rte_hash_del_key(nd_hash_handle, timer_key);
1212 arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
1214 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1215 if (ret_arp_data->num_pkts == NUM_DESC) {
1216 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1220 ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
1221 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1226 arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
1227 struct ether_addr *hw_addr, uint8_t port_id)
1229 l2_phy_interface_t *port = ifm_get_port(port_id);
1230 struct rte_mbuf *pkt, *tmp;
1231 uint8_t *eth_dest, *eth_src;
1235 if (!hw_addr || !ret_arp_data)
1238 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1239 for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
1240 pkt = ret_arp_data->buf_pkts[i];
1242 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1243 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1245 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1246 memcpy(eth_src, get_link_hw_addr(port_id),
1247 sizeof(struct ether_addr));
1248 port->transmit_single_pkt(port, pkt);
1250 rte_pktmbuf_free(tmp);
1252 ret_arp_data->num_pkts = 0;
1253 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1257 nd_queue_unresolved_packet(struct nd_entry_data *ret_nd_data, struct rte_mbuf *pkt)
1259 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1260 if (ret_nd_data->num_pkts == get_nd_buf()) {
1261 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1265 ret_nd_data->buf_pkts[ret_nd_data->num_pkts++] = pkt;
1266 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1271 nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
1272 struct ether_addr *hw_addr, uint8_t port_id)
1274 l2_phy_interface_t *port = ifm_get_port(port_id);
1275 struct rte_mbuf *pkt, *tmp;
1276 uint8_t *eth_dest, *eth_src;
1279 if (!hw_addr || !ret_nd_data)
1282 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1283 for (i=0;i<(int)ret_nd_data->num_pkts;i++) {
1284 pkt = ret_nd_data->buf_pkts[i];
1285 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1286 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1288 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1289 memcpy(eth_src, get_link_hw_addr(port_id),
1290 sizeof(struct ether_addr));
1291 port->transmit_single_pkt(port, pkt);
1293 rte_pktmbuf_free(tmp);
1295 ret_nd_data->num_pkts = 0;
1296 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1300 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1301 uint8_t portid, uint8_t mode)
1303 struct arp_key_ipv4 arp_key;
1304 struct arp_entry_data *new_arp_data;
1305 arp_key.port_id = portid;
1306 arp_key.ip = ipaddr;
1307 arp_key.filler1 = 0;
1308 arp_key.filler2 = 0;
1309 arp_key.filler3 = 0;
1311 lib_arp_populate_called++;
1312 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip, arp_key.port_id);
1315 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1316 arp_key.ip, arp_key.port_id);
1318 new_arp_data = retrieve_arp_entry(arp_key, mode);
1319 if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1320 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1321 && mode == STATIC_ARP))) {
1323 RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry "
1324 "already exists(%d %d)\n", new_arp_data->mode, mode);
1328 if (mode == DYNAMIC_ARP) {
1331 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1332 printf("entry exists\n");
1334 if (ARPICMP_DEBUG) {
1335 RTE_LOG(INFO, LIBARP,
1336 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1338 ((arp_key.ip & 0x00ff0000) >> 16),
1339 ((arp_key.ip & 0x0000ff00) >> 8),
1340 ((arp_key.ip & 0x000000ff)),
1343 lib_arp_duplicate_found++;
1344 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1345 new_arp_data->retry_count = 0; // Reset
1346 if (new_arp_data->status == STALE) {
1347 new_arp_data->status = PROBE;
1348 if (ifm_chk_port_ipv4_enabled
1349 (new_arp_data->port)) {
1350 request_arp(new_arp_data->port,
1354 RTE_LOG(INFO, LIBARP,
1355 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1357 new_arp_data->port);
1361 if (rte_timer_reset(new_arp_data->timer,
1362 (arp_timeout * rte_get_tsc_hz()),
1363 SINGLE, timer_lcore,
1365 new_arp_data->timer_key) < 0) {
1367 RTE_LOG(INFO, LIBARP,
1368 "Err : Timer already running\n");
1370 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1373 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1374 ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
1375 if ((new_arp_data->status == INCOMPLETE) ||
1376 (new_arp_data->status == PROBE)) {
1377 new_arp_data->status = COMPLETE;
1378 new_arp_data->mode = mode;
1379 new_arp_data->n_confirmed = rte_rdtsc();
1380 new_arp_data->retry_count = 0;
1381 if (rte_timer_reset(new_arp_data->timer,
1382 (arp_timeout * rte_get_tsc_hz()),
1383 SINGLE, timer_lcore,
1385 new_arp_data->timer_key) < 0) {
1387 RTE_LOG(INFO, LIBARP,
1388 "Err : Timer already running\n");
1391 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1396 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1398 if (ARPICMP_DEBUG) {
1399 RTE_LOG(INFO, LIBARP,
1400 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1402 ((arp_key.ip & 0x00ff0000) >> 16),
1403 ((arp_key.ip & 0x0000ff00) >> 8),
1404 ((arp_key.ip & 0x000000ff)),
1407 lib_arp_duplicate_found++;
1410 RTE_CACHE_LINE_ROUNDUP(sizeof
1411 (struct arp_entry_data));
1413 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1414 new_arp_data->eth_addr = *hw_addr;
1415 new_arp_data->status = COMPLETE;
1416 new_arp_data->port = portid;
1417 new_arp_data->ip = ipaddr;
1418 new_arp_data->mode = mode;
1419 new_arp_data->num_pkts = 0;
1421 /* attempt to add arp_entry to hash */
1423 ret = add_arp_data(&arp_key, new_arp_data);
1425 /* Some other thread created an entry for this ip */
1426 rte_free(new_arp_data);
1429 if (ARPICMP_DEBUG) {
1430 RTE_LOG(INFO, LIBARP,
1431 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1433 ((arp_key.ip & 0x00ff0000) >> 16),
1434 ((arp_key.ip & 0x0000ff00) >> 8),
1435 ((arp_key.ip & 0x000000ff)),
1438 #ifdef L3_STACK_SUPPORT
1439 // Call l3fwd module for resolving 2_adj structure.
1440 resolve_l2_adj(ipaddr, portid, hw_addr);
1445 if (ARPICMP_DEBUG) {
1446 /* print entire hash table */
1447 RTE_LOG(INFO, LIBARP,
1448 "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d on port=%d\n",
1449 new_arp_data->eth_addr.addr_bytes[0],
1450 new_arp_data->eth_addr.addr_bytes[1],
1451 new_arp_data->eth_addr.addr_bytes[2],
1452 new_arp_data->eth_addr.addr_bytes[3],
1453 new_arp_data->eth_addr.addr_bytes[4],
1454 new_arp_data->eth_addr.addr_bytes[5],
1455 (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1456 ((arp_key.ip & 0x0000ff00) >> 8),
1457 ((arp_key.ip & 0x000000ff)), portid);
1465 * Install key - data pair in Hash table - From Pipeline Configuration
1468 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1469 uint8_t portid, uint8_t mode)
1472 /* need to lock here if multi-threaded */
1473 /* rte_hash_add_key_data is not thread safe */
1475 struct nd_key_ipv6 nd_key;
1476 nd_key.port_id = portid;
1478 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1479 nd_key.ipv6[i] = ipv6[i];
1490 lib_nd_populate_called++;
1492 /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1493 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, mode);
1494 if (new_nd_data && ((new_nd_data->mode == STATIC_ND
1495 && mode == DYNAMIC_ND) || (new_nd_data->mode == DYNAMIC_ND
1496 && mode == STATIC_ND))) {
1498 RTE_LOG(INFO, LIBARP, "populate_arp_entry: ND entry already"
1499 " exists(%d %d)\n", new_nd_data->mode, mode);
1503 if (mode == DYNAMIC_ND) {
1504 if (new_nd_data && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1507 RTE_LOG(INFO, LIBARP,
1508 "nd_entry exists port %d ipv6 = ",
1510 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1512 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1514 nd_key.ipv6[i + 1]);
1518 lib_nd_duplicate_found++;
1519 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1520 if (new_nd_data->status == STALE) {
1521 new_nd_data->retry_count = 0; // Reset
1522 new_nd_data->status = PROBE;
1523 request_nd(new_nd_data->ipv6,
1524 ifm_get_port(new_nd_data->port));
1526 if (rte_timer_reset(new_nd_data->timer,
1527 (arp_timeout * rte_get_tsc_hz()),
1528 SINGLE, timer_lcore,
1530 new_nd_data->timer_key) < 0) {
1532 RTE_LOG(INFO, LIBARP,
1533 "Err : Timer already running\n");
1536 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1539 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1540 ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
1541 if ((new_nd_data->status == INCOMPLETE) ||
1542 (new_nd_data->status == PROBE)) {
1543 new_nd_data->status = COMPLETE;
1544 new_nd_data->mode = mode;
1545 new_nd_data->n_confirmed = rte_rdtsc();
1546 new_nd_data->retry_count = 0;
1547 if (rte_timer_reset(new_nd_data->timer,
1548 (arp_timeout * rte_get_tsc_hz()),
1549 SINGLE, timer_lcore,
1551 new_nd_data->timer_key) < 0) {
1553 RTE_LOG(INFO, LIBARP,
1554 "Err : Timer already running\n");
1557 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1563 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1565 RTE_LOG(INFO, LIBARP,
1566 "nd_entry exists port %d ipv6 = ",
1568 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1570 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1572 nd_key.ipv6[i + 1]);
1576 lib_nd_duplicate_found++;
1579 RTE_CACHE_LINE_ROUNDUP(sizeof
1580 (struct nd_entry_data));
1582 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1584 new_nd_data->eth_addr = *hw_addr;
1585 new_nd_data->status = COMPLETE;
1586 new_nd_data->port = portid;
1587 new_nd_data->mode = mode;
1588 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1589 new_nd_data->ipv6[i] = ipv6[i];
1591 new_nd_data->mode = mode;
1592 new_nd_data->num_pkts = 0;
1594 /*Add a key-data pair at hash table for ND IPv6 static routing */
1595 /* attempt to add arp_entry to hash */
1597 ret = add_nd_data(&nd_key, new_nd_data);
1599 rte_free(new_nd_data);
1602 /* need to check the return value of the hash add */
1603 #ifdef L3_STACK_SUPPORT
1604 // Call l3fwd module for resolving 2_adj structure.
1605 resolve_l2_adj(ipaddr, portid, hw_addr);
1612 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1615 /* print entire hash table */
1617 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1618 new_nd_data->eth_addr.addr_bytes[0],
1619 new_nd_data->eth_addr.addr_bytes[1],
1620 new_nd_data->eth_addr.addr_bytes[2],
1621 new_nd_data->eth_addr.addr_bytes[3],
1622 new_nd_data->eth_addr.addr_bytes[4],
1623 new_nd_data->eth_addr.addr_bytes[5], portid);
1624 RTE_LOG(INFO, LIBARP, "\tipv6=");
1625 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1626 new_nd_data->ipv6[i] = ipv6[i];
1627 RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1628 new_nd_data->ipv6[i + 1]);
1631 RTE_LOG(INFO, LIBARP, "\n");
1637 void print_pkt1(struct rte_mbuf *pkt)
1639 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1641 RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1642 for (i = 0; i < 20; i++) {
1643 for (j = 0; j < 20; j++)
1644 printf("%02x ", rd[(20 * i) + j]);
1645 RTE_LOG(INFO, LIBARP, "\n");
1649 #define MAX_NUM_MAC_ADDRESS 16
1650 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1651 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1652 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1653 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1654 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1655 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1656 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1657 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1658 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1659 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1660 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1661 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1662 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1663 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1664 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1665 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1666 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1669 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1671 return &p_arp_data->link_hw_addr[out_port];
1674 void request_arp(uint8_t port_id, uint32_t ip)
1677 struct ether_hdr *eth_h;
1678 struct arp_hdr *arp_h;
1680 l2_phy_interface_t *link;
1681 link = ifm_get_port(port_id);
1682 struct rte_mbuf *arp_pkt = lib_arp_pkt[port_id];
1684 if (arp_pkt == NULL) {
1686 RTE_LOG(INFO, LIBARP,
1687 "Error allocating arp_pkt rte_mbuf\n");
1690 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1692 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1693 ether_addr_copy((struct ether_addr *)
1694 &link->macaddr[0], ð_h->s_addr);
1695 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1697 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1698 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1699 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1700 arp_h->arp_hln = ETHER_ADDR_LEN;
1701 arp_h->arp_pln = sizeof(uint32_t);
1702 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1704 if (link && link->ipv4_list) {
1705 arp_h->arp_data.arp_sip =
1706 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1708 ether_addr_copy((struct ether_addr *)
1709 &link->macaddr[0], &arp_h->arp_data.arp_sha);
1710 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1711 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1713 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1714 arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1715 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1716 arp_pkt->pkt_len = 42;
1717 arp_pkt->data_len = 42;
1719 if (ARPICMP_DEBUG) {
1720 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1721 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1724 link->transmit_single_pkt(link, arp_pkt);
1725 // start_tsc[port_id] = rte_rdtsc();
1726 printf("Sent ARP Request %x \n", arp_h->arp_data.arp_tip);
1729 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1731 struct ether_hdr *eth_h;
1732 struct ipv4_hdr *ip_h;
1733 struct icmp_hdr *icmp_h;
1734 l2_phy_interface_t *port = ifm_get_port(port_id);
1736 struct rte_mbuf *icmp_pkt = lib_arp_pkt[port_id];
1737 if (icmp_pkt == NULL) {
1739 RTE_LOG(INFO, LIBARP,
1740 "Error allocating icmp_pkt rte_mbuf\n");
1744 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1746 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1747 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1749 ip_h->version_ihl = IP_VHL_DEF;
1750 ip_h->type_of_service = 0;
1751 ip_h->total_length =
1752 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1753 ip_h->packet_id = 0xaabb;
1754 ip_h->fragment_offset = 0x0000;
1755 ip_h->time_to_live = 64;
1756 ip_h->next_proto_id = IPPROTO_ICMP;
1757 if (port && port->ipv4_list)
1759 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1760 ip_h->dst_addr = rte_cpu_to_be_32(ip);
1762 ip_h->hdr_checksum = 0;
1763 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1765 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1766 icmp_h->icmp_code = 0;
1767 icmp_h->icmp_ident = 0xdead;
1768 icmp_h->icmp_seq_nb = 0xbeef;
1770 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1773 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1774 sizeof(struct icmp_hdr);
1775 icmp_pkt->data_len = icmp_pkt->pkt_len;
1777 print_mbuf("TX", 0, icmp_pkt, __LINE__);
1783 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1784 uint64_t pkt_mask, l2_phy_interface_t *port)
1786 RTE_SET_USED(pkt_num);
1788 RTE_LOG(INFO, LIBARP,
1789 "============ARP ENTRY================\n");
1792 RTE_LOG(INFO, LIBARP,
1793 "============ARP PROCESS================\n");
1796 uint64_t pkts_for_process = pkt_mask;
1797 for (; pkts_for_process;) {
1798 /**< process only valid packets. */
1799 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1800 uint64_t pkts_mask = 1LLU << pos; /** <bitmask representing only this packet. */
1801 pkts_for_process &= ~pkts_mask; /** <remove this packet from the mask. */
1802 process_arpicmp_pkt(pkt[pos], port);
1807 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1809 uint8_t in_port_id = pkt->port;
1810 struct ether_hdr *eth_h;
1811 struct arp_hdr *arp_h;
1812 struct ipv4_hdr *ip_h;
1813 struct icmp_hdr *icmp_h;
1819 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1821 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1823 RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1824 __FUNCTION__, port->pmdid, __LINE__);
1826 (struct arp_hdr *)((char *)eth_h +
1827 sizeof(struct ether_hdr));
1828 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1829 RTE_LOG(INFO, LIBARP,
1830 "Invalid hardware format of hardware address - not processing ARP req\n");
1831 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1832 RTE_LOG(INFO, LIBARP,
1833 "Invalid protocol address format - not processing ARP req\n");
1834 else if (arp_h->arp_hln != 6)
1835 RTE_LOG(INFO, LIBARP,
1836 "Invalid hardware address length - not processing ARP req\n");
1837 else if (arp_h->arp_pln != 4)
1838 RTE_LOG(INFO, LIBARP,
1839 "Invalid protocol address length - not processing ARP req\n");
1841 if (port->ipv4_list == NULL) {
1842 RTE_LOG(INFO, LIBARP,
1843 "Ports IPV4 List is NULL.. Unable to Process\n");
1847 if (arp_h->arp_data.arp_tip !=
1848 ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1849 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1850 printf("gratuitous arp received\n");
1852 (struct ether_addr *)&arp_h->arp_data.arp_sha,
1853 rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1858 RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1861 /// revise conditionals to allow processing of requests with target ip = this ip and
1862 // processing of replies to destination ip = this ip
1863 else if (arp_h->arp_op ==
1864 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1865 if (ARPICMP_DEBUG) {
1866 RTE_LOG(INFO, LIBARP,
1867 "%s, portid %u. Line %d\n\r",
1868 __FUNCTION__, port->pmdid,
1871 RTE_LOG(INFO, LIBARP,
1872 "arp_op %d, ARP_OP_REQUEST %d\n",
1876 print_mbuf("RX", in_port_id, pkt,
1879 populate_arp_entry((struct ether_addr *)
1880 &arp_h->arp_data.arp_sha,
1882 (arp_h->arp_data.arp_sip),
1883 in_port_id, DYNAMIC_ARP);
1886 req_tip = arp_h->arp_data.arp_tip;
1887 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1888 ether_addr_copy((struct ether_addr *)&port->macaddr[0], ð_h->s_addr); /**< set sender mac address*/
1889 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1890 ether_addr_copy(ð_h->s_addr,
1891 &arp_h->arp_data.arp_sha);
1892 arp_h->arp_data.arp_tip =
1893 arp_h->arp_data.arp_sip;
1894 arp_h->arp_data.arp_sip = req_tip;
1895 ether_addr_copy(ð_h->d_addr,
1896 &arp_h->arp_data.arp_tha);
1898 print_mbuf("TX ARP REPLY PKT",
1899 port->pmdid, pkt, __LINE__);
1900 port->transmit_bulk_pkts(port, &pkt, 1);
1902 print_mbuf("TX", port->pmdid, pkt,
1904 printf("replying arp pkt done\n");
1906 } else if (arp_h->arp_op ==
1907 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1908 if (ARPICMP_DEBUG) {
1909 RTE_LOG(INFO, LIBARP,
1910 "ARP_OP_REPLY received");
1911 print_mbuf("RX", port->pmdid, pkt,
1914 populate_arp_entry((struct ether_addr *)
1915 &arp_h->arp_data.arp_sha,
1918 in_port_id, DYNAMIC_ARP);
1923 RTE_LOG(INFO, LIBARP,
1924 "Invalid ARP opcode - not processing ARP req %x\n",
1929 rte_pktmbuf_free(pkt);
1932 (struct ipv4_hdr *)((char *)eth_h +
1933 sizeof(struct ether_hdr));
1935 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1937 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1939 if (ip_h->next_proto_id != IPPROTO_ICMP) {
1940 if (ARPICMP_DEBUG) {
1941 RTE_LOG(INFO, LIBARP,
1942 "IP protocol ID is not set to ICMP - discarding\n");
1944 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1945 if (ARPICMP_DEBUG) {
1946 RTE_LOG(INFO, LIBARP,
1947 "IP version other than 4 - discarding\n");
1949 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1950 if (ARPICMP_DEBUG) {
1951 RTE_LOG(INFO, LIBARP,
1952 "Unknown IHL - discarding\n");
1955 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1956 && icmp_h->icmp_code == 0) {
1958 print_mbuf("RX", in_port_id,
1961 ip_addr = ip_h->src_addr;
1962 ether_addr_copy(ð_h->s_addr,
1964 ether_addr_copy((struct ether_addr *)
1968 RTE_LOG(INFO, LIBARP,
1969 "%s, portid %u. Line %d\n\r",
1971 port->pmdid, __LINE__);
1973 if (is_multicast_ipv4_addr
1978 rte_be_to_cpu_32(ip_addr);
1979 if ((ip_src & 0x00000003) == 1)
1990 rte_cpu_to_be_32(ip_src);
1991 ip_h->dst_addr = ip_addr;
1993 ip_h->hdr_checksum = 0;
1994 ip_h->hdr_checksum =
1995 ~rte_raw_cksum(ip_h,
2000 RTE_LOG(INFO, LIBARP,
2001 "%s, portid %u. Line %d\n\r",
2005 ip_h->src_addr = ip_h->dst_addr;
2006 ip_h->dst_addr = ip_addr;
2009 icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
2010 cksum = ~icmp_h->icmp_cksum & 0xffff;
2012 ~htons(IP_ICMP_ECHO_REQUEST << 8) &
2014 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
2016 (cksum & 0xffff) + (cksum >> 16);
2018 (cksum & 0xffff) + (cksum >> 16);
2019 icmp_h->icmp_cksum = ~cksum;
2023 ("TX ICMP ECHO REPLY PKT",
2024 in_port_id, pkt, __LINE__);
2025 port->transmit_bulk_pkts(port, &pkt, 1);
2027 print_mbuf("TX", port->pmdid,
2031 } else if (icmp_h->icmp_type ==
2033 && icmp_h->icmp_code == 0) {
2035 print_mbuf("RX", in_port_id,
2038 struct arp_key_ipv4 arp_key;
2039 arp_key.port_id = in_port_id;
2041 rte_bswap32(ip_h->src_addr);
2042 arp_key.filler1 = 0;
2043 arp_key.filler2 = 0;
2044 arp_key.filler3 = 0;
2046 struct arp_entry_data *arp_entry =
2047 retrieve_arp_entry(arp_key,
2049 if (arp_entry == NULL) {
2051 RTE_LOG(INFO, LIBARP,
2052 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
2057 arp_entry->status = COMPLETE;
2062 rte_pktmbuf_free(pkt);
2067 * inet_pton(af, src, dst)
2068 * convert from presentation format (which usually means ASCII printable)
2069 * to network format (which is usually some kind of binary format).
2071 * 1 if the address was valid for the specified address family
2072 * 0 if the address wasn't valid (`dst' is untouched in this case)
2073 * -1 if some other error occurred (`dst' is untouched in this case, too)
2077 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
2081 return inet_pton_ipv4(src, dst);
2083 return inet_pton_ipv6(src, dst);
2085 errno = EAFNOSUPPORT;
2092 * inet_pton_ipv4(src, dst)
2093 * like inet_aton() but without all the hexadecimal and shorthand.
2095 * 1 if `src' is a valid dotted quad, else 0.
2097 * does not touch `dst' unless it's returning 1.
2101 static int inet_pton_ipv4(const char *src, unsigned char *dst)
2103 static const char digits[] = "0123456789";
2104 int saw_digit, octets, ch;
2105 unsigned char tmp[INADDRSZ], *tp;
2110 while ((ch = *src++) != '\0') {
2113 pch = strchr(digits, ch);
2115 unsigned int new = *tp * 10 + (pch - digits);
2124 *tp = (unsigned char)new;
2125 } else if (ch == '.' && saw_digit) {
2136 memcpy(dst, tmp, INADDRSZ);
2141 * inet_pton_ipv6(src, dst)
2142 * convert presentation level address to network order binary form.
2144 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
2146 * (1) does not touch `dst' unless it's returning 1.
2147 * (2) :: in a full address is silently ignored.
2149 * inspired by Mark Andrews.
2153 static int inet_pton_ipv6(const char *src, unsigned char *dst)
2155 static const char xdigits_l[] = "0123456789abcdef",
2156 xdigits_u[] = "0123456789ABCDEF";
2157 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2158 const char *xdigits = 0, *curtok = 0;
2159 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2160 unsigned int val = 0;
2161 unsigned int dbloct_count = 0;
2163 memset((tp = tmp), '\0', IN6ADDRSZ);
2164 endp = tp + IN6ADDRSZ;
2166 /* Leading :: requires some special handling. */
2171 saw_xdigit = count_xdigit = 0;
2174 while ((ch = *src++) != '\0') {
2177 pch = strchr((xdigits = xdigits_l), ch);
2179 pch = strchr((xdigits = xdigits_u), ch);
2181 if (count_xdigit >= 4)
2184 val |= (pch - xdigits);
2198 } else if (*src == '\0') {
2201 if (tp + sizeof(int16_t) > endp)
2203 *tp++ = (unsigned char)((val >> 8) & 0xff);
2204 *tp++ = (unsigned char)(val & 0xff);
2211 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2212 inet_pton_ipv4(curtok, tp) > 0) {
2216 break; /* '\0' was seen by inet_pton4(). */
2221 if (tp + sizeof(int16_t) > endp)
2223 *tp++ = (unsigned char)((val >> 8) & 0xff);
2224 *tp++ = (unsigned char)(val & 0xff);
2227 if (colonp != NULL) {
2228 /* if we already have 8 double octets, having a colon means error */
2229 if (dbloct_count == 8)
2233 * Since some memmove()'s erroneously fail to handle
2234 * overlapping regions, we'll do the shift by hand.
2236 const int n = tp - colonp;
2239 for (i = 1; i <= n; i++) {
2240 endp[-i] = colonp[n - i];
2247 memcpy(dst, tmp, IN6ADDRSZ);
2251 static int arp_parse_args(struct pipeline_params *params)
2253 uint32_t arp_route_tbl_present = 0;
2254 uint32_t nd_route_tbl_present = 0;
2256 uint32_t n_vnf_threads_present = 0;
2258 uint32_t pktq_in_prv_present = 0;
2259 uint32_t prv_to_pub_map_present = 0;
2261 uint8_t n_prv_in_port = 0;
2263 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2264 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2265 prv_to_pub_map[i] = 0xff;
2266 pub_to_prv_map[i] = 0xff;
2269 RTE_SET_USED(nd_route_tbl_present);
2270 RTE_SET_USED(arp_route_tbl_present);
2271 for (numArg = 0; numArg < params->n_args; numArg++) {
2272 char *arg_name = params->args_name[numArg];
2273 char *arg_value = params->args_value[numArg];
2275 /* arp timer expiry */
2276 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2277 arp_timeout = atoi(arg_value);
2281 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2282 if (pktq_in_prv_present) {
2284 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2287 pktq_in_prv_present = 1;
2289 int rxport = 0, j = 0;
2290 char phy_port_num[5];
2291 char *token = strtok(arg_value, "RXQ");
2294 while ((j < 4) && (token[j] != '.')) {
2295 phy_port_num[j] = token[j];
2298 phy_port_num[j] = '\0';
2299 rxport = atoi(phy_port_num);
2300 prv_in_port_a[n_prv_in_port++] = rxport;
2304 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2305 token, phy_port_num, rxport);
2306 prv_in_port_a[n_prv_in_port++] = rxport;
2307 if(rxport < PIPELINE_MAX_PORT_IN)
2308 in_port_dir_a[rxport] = 1; // set rxport egress
2309 token = strtok(NULL, "RXQ");
2312 if (n_prv_in_port == 0) {
2314 ("VNF common parse error - no prv RX phy port\n");
2320 if (strcmp(arg_name, "arp_buf") == 0) {
2321 arp_buffer = atoi(arg_value);
2325 if (strcmp(arg_name, "nd_buf") == 0) {
2326 nd_buffer = atoi(arg_value);
2330 /* prv_to_pub_map */
2331 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2332 if (prv_to_pub_map_present) {
2334 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2337 prv_to_pub_map_present = 1;
2339 int rxport = 0, txport = 0, j = 0, k = 0;
2340 char rx_phy_port_num[5];
2341 char tx_phy_port_num[5];
2342 char *token = strtok(arg_value, "(");
2345 while ((j < 4) && (token[j] != ',')) {
2346 rx_phy_port_num[j] = token[j];
2349 rx_phy_port_num[j] = '\0';
2350 rxport = atoi(rx_phy_port_num);
2356 while ((k < 4) && (token[j + k] != ')')) {
2357 tx_phy_port_num[k] = token[j + k];
2360 tx_phy_port_num[k] = '\0';
2361 txport = atoi(tx_phy_port_num);
2365 RTE_LOG(INFO, LIBARP, "token: %s,"
2366 "rx_phy_port_str: %s, phy_port_num %d,"
2367 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2368 token, rx_phy_port_num, rxport,
2369 tx_phy_port_num, txport);
2371 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2372 (txport >= PIPELINE_MAX_PORT_IN) ||
2373 (in_port_dir_a[rxport] != 1)) {
2375 ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2377 in_port_dir_a[rxport]);
2381 prv_to_pub_map[rxport] = txport;
2382 pub_to_prv_map[txport] = rxport;
2383 token = strtok(NULL, "(");
2389 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2390 if (n_vnf_threads_present)
2392 n_vnf_threads_present = 1;
2394 num_vnf_threads = atoi(arg_value);
2395 if (num_vnf_threads <= 0) {
2396 RTE_LOG(INFO, LIBARP,
2397 "n_vnf_threads is invalid\n");
2400 RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2405 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2406 ARPICMP_DEBUG = atoi(arg_value);
2412 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2413 arp_route_tbl_present = 1;
2415 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip =
2416 0, i = 0, j = 0, k = 0, l = 0;
2417 uint32_t arp_route_tbl_str_max_len = 10;
2418 char dest_ip_str[arp_route_tbl_str_max_len];
2419 char mask_str[arp_route_tbl_str_max_len];
2420 char tx_port_str[arp_route_tbl_str_max_len];
2421 char nh_ip_str[arp_route_tbl_str_max_len];
2422 char *token = strtok(arg_value, "(");
2425 while ((i < (arp_route_tbl_str_max_len - 1))
2426 && (token[i] != ',')) {
2427 dest_ip_str[i] = token[i];
2430 dest_ip_str[i] = '\0';
2431 dest_ip = strtoul(dest_ip_str, NULL, 16);
2435 while ((j < (arp_route_tbl_str_max_len - 1))
2436 && (token[i + j] != ',')) {
2437 mask_str[j] = token[i + j];
2441 mask = strtoul(mask_str, NULL, 16);
2445 while ((k < (arp_route_tbl_str_max_len - 1))
2446 && (token[i + j + k] != ',')) {
2447 tx_port_str[k] = token[i + j + k];
2450 tx_port_str[k] = '\0';
2451 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2455 while ((l < (arp_route_tbl_str_max_len - 1))
2456 && (token[i + j + k + l] != ')')) {
2457 nh_ip_str[l] = token[i + j + k + l];
2460 nh_ip_str[l] = '\0';
2461 nh_ip = strtoul(nh_ip_str, NULL, 16); //atoi(nh_ip_str);
2464 RTE_LOG(INFO, LIBARP, "token: %s, "
2465 "dest_ip_str: %s, dest_ip %u, "
2466 "mask_str: %s, mask %u, "
2467 "tx_port_str: %s, tx_port %u, "
2468 "nh_ip_str: %s, nh_ip %u\n",
2469 token, dest_ip_str, dest_ip,
2470 mask_str, mask, tx_port_str,
2471 tx_port, nh_ip_str, nh_ip);
2474 /* if (tx_port >= params->n_ports_out)
2476 RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2477 tx_port, params->n_ports_out);
2481 //Populate the static arp_route_table
2482 struct lib_arp_route_table_entry *lentry =
2483 &p_arp_data->lib_arp_route_table
2484 [p_arp_data->lib_arp_route_ent_cnt];
2485 lentry->ip = dest_ip;
2486 lentry->mask = mask;
2487 lentry->port = tx_port;
2489 lentry->nh_mask = nh_ip & mask;
2490 p_arp_data->lib_arp_route_ent_cnt++;
2491 token = strtok(NULL, "(");
2498 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2499 nd_route_tbl_present = 1;
2501 uint8_t dest_ipv6[16], depth = 0, tx_port =
2502 0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0;
2503 uint8_t nd_route_tbl_str_max_len = 128; //64;
2504 char dest_ipv6_str[nd_route_tbl_str_max_len];
2505 char depth_str[nd_route_tbl_str_max_len];
2506 char tx_port_str[nd_route_tbl_str_max_len];
2507 char nh_ipv6_str[nd_route_tbl_str_max_len];
2508 char *token = strtok(arg_value, "(");
2511 while ((i < (nd_route_tbl_str_max_len - 1))
2512 && (token[i] != ',')) {
2513 dest_ipv6_str[i] = token[i];
2516 dest_ipv6_str[i] = '\0';
2517 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2522 while ((j < (nd_route_tbl_str_max_len - 1))
2523 && (token[i + j] != ',')) {
2524 depth_str[j] = token[i + j];
2527 depth_str[j] = '\0';
2528 //converting string char to integer
2530 for (s = 0; depth_str[s] != '\0'; ++s)
2531 depth = depth * 10 + depth_str[s] - '0';
2535 while ((k < (nd_route_tbl_str_max_len - 1))
2536 && (token[i + j + k] != ',')) {
2537 tx_port_str[k] = token[i + j + k];
2540 tx_port_str[k] = '\0';
2541 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2545 while ((l < (nd_route_tbl_str_max_len - 1))
2546 && (token[i + j + k + l] != ')')) {
2547 nh_ipv6_str[l] = token[i + j + k + l];
2550 nh_ipv6_str[l] = '\0';
2551 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2554 //Populate the static arp_route_table
2555 for (i = 0; i < 16; i++) {
2557 [nd_route_tbl_index].ipv6[i] =
2560 [nd_route_tbl_index].nhipv6[i] =
2563 lib_nd_route_table[nd_route_tbl_index].depth =
2565 lib_nd_route_table[nd_route_tbl_index].port =
2568 nd_route_tbl_index++;
2569 token = strtok(NULL, "(");
2577 /* Check that mandatory arguments are present */
2579 if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2580 RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2581 RTE_LOG(INFO, LIBARP,"%d, %d \n",
2582 arp_route_tbl_present, ports_mac_list_present);
2590 static void local_arp_cache_init(void)
2593 for (i=0; i<MAX_PORTS;i++) {
2594 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2595 p_arp_data->arp_local_cache[i].nhip[j] = 0;
2597 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2598 p_arp_data->arp_local_cache[i].num_nhip = 0;
2603 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
2606 struct ether_addr *x = NULL;
2607 limit = p_arp_data->nd_local_cache[out_port].num_nhip;
2609 for (i=0; i < limit; i++) {
2610 for (j=0;j<16;j++) {
2611 if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
2615 x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
2622 struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip)
2626 struct ether_addr *x = NULL;
2627 limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2628 for (i=0; i < limit; i++) {
2629 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2631 x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2638 void lib_arp_init(struct pipeline_params *params,
2639 __rte_unused struct app_params *app)
2644 struct pipeline_cgnapt *p;
2646 RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2648 /* create arp data for table entries */
2649 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2650 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2651 p_arp_data = (struct arp_data *)p;
2653 /* Parse arguments */
2654 if (arp_parse_args(params)) {
2655 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2659 /* acquire the mac addresses */
2660 struct ether_addr hw_addr;
2661 uint8_t nb_ports = rte_eth_dev_count();
2663 for (i = 0; i < nb_ports; i++) {
2664 rte_eth_macaddr_get(i, &hw_addr);
2665 ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
2666 p_arp_data->link_hw_addr_array_idx++;
2669 /* create a lock for arp/nd hash */
2670 rte_rwlock_init(&arp_hash_handle_lock);
2671 rte_rwlock_init(&nd_hash_handle_lock);
2673 /* create the arp_icmp mbuf rx pool */
2674 lib_arp_pktmbuf_tx_pool =
2675 rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2676 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2679 if (lib_arp_pktmbuf_tx_pool == NULL) {
2680 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2684 for (i=0; i<MAX_PORTS; i++) {
2685 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2686 if (lib_arp_pkt[i] == NULL) {
2687 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2692 /* create the nd icmp mbuf rx pool */
2693 lib_nd_pktmbuf_tx_pool =
2694 rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2695 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2698 if (lib_nd_pktmbuf_tx_pool == NULL) {
2699 RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
2703 for (i=0; i<MAX_PORTS; i++) {
2704 lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
2705 if (lib_nd_pkt[i] == NULL) {
2706 RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
2711 /* create the arp_icmp mbuf rx pool */
2712 arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2713 NB_ARPICMP_MBUF, MAX_POOL, 0,
2714 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2716 if (arp_icmp_pktmbuf_tx_pool == NULL) {
2717 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2721 arp_hash_params.socket_id = rte_socket_id();
2722 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2723 arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2724 arp_hash_handle = rte_hash_create(&arp_hash_params);
2726 if (arp_hash_handle == NULL) {
2727 RTE_LOG(INFO, LIBARP,
2728 "ARP rte_hash_create failed. socket %d ... \n",
2729 arp_hash_params.socket_id);
2731 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2732 (void *)arp_hash_handle);
2735 /* Create port alloc buffer */
2737 timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2738 timer_objs_mempool_count,
2739 sizeof(struct rte_timer),
2742 NULL, NULL, rte_socket_id(), 0);
2743 if (timer_mempool_arp == NULL) {
2744 rte_panic("timer_mempool create error\n");
2746 rte_timer_subsystem_init();
2747 list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2750 nd_hash_params.socket_id = rte_socket_id();
2751 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2752 nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2753 nd_hash_handle = rte_hash_create(&nd_hash_params);
2754 if (nd_hash_handle == NULL) {
2755 RTE_LOG(INFO, LIBARP,
2756 "ND rte_hash_create failed. socket %d ... \n",
2757 nd_hash_params.socket_id);
2759 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2760 (void *)nd_hash_handle);
2763 /* Initialize the local arp cache */
2764 local_arp_cache_init();
2769 void arp_timer_callback(struct rte_timer *timer, void *arg)
2771 struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2772 struct arp_key_ipv4 arp_key;
2773 arp_key.port_id = timer_key->port_id;
2774 arp_key.ip = timer_key->ip;
2775 arp_key.filler1 = 0;
2776 arp_key.filler2 = 0;
2777 arp_key.filler3 = 0;
2779 struct arp_entry_data *ret_arp_data = NULL;
2781 if (ARPICMP_DEBUG) {
2782 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2783 arp_key.ip, arp_key.port_id);
2786 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2787 (void **)&ret_arp_data);
2791 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2792 (int)timer->expire, now);
2794 printf("Should not have come here\n");
2797 if (ret_arp_data->mode == DYNAMIC_ARP) {
2798 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
2799 if (ret_arp_data->status == PROBE ||
2800 ret_arp_data->status == INCOMPLETE) {
2801 if (ret_arp_data->retry_count == 3) {
2802 remove_arp_entry(ret_arp_data, arg);
2804 ret_arp_data->retry_count++;
2806 if (ARPICMP_DEBUG) {
2807 RTE_LOG(INFO, LIBARP,
2808 "RETRY ARP..retry count : %u\n",
2809 ret_arp_data->retry_count);
2811 RTE_LOG(INFO, LIBARP,
2812 "TIMER STARTED FOR %u seconds\n",
2816 if (ifm_chk_port_ipv4_enabled
2817 (ret_arp_data->port)) {
2818 request_arp(ret_arp_data->port,
2822 RTE_LOG(INFO, LIBARP,
2823 "%s: IP is not enabled on port %u"
2824 ", not sending GARP\n\r",
2826 ret_arp_data->port);
2829 if (rte_timer_reset(ret_arp_data->timer,
2831 rte_get_tsc_hz()/ 1000),
2837 RTE_LOG(INFO, LIBARP,
2838 "Err : Timer already running\n");
2841 } else if (ret_arp_data->status == COMPLETE) {
2842 if (now <= (ret_arp_data->n_confirmed +
2843 (arp_timeout * rte_get_tsc_hz()))) {
2844 if (rte_timer_reset(ret_arp_data->timer,
2846 rte_get_tsc_hz()), SINGLE,
2851 RTE_LOG(INFO, LIBARP,
2852 "Err : Timer already running\n");
2853 } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2854 if (rte_timer_reset(ret_arp_data->timer,
2856 rte_get_tsc_hz()), SINGLE,
2861 RTE_LOG(INFO, LIBARP,
2862 "Err : Timer already running\n");
2864 ret_arp_data->status = STALE;
2865 p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2868 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
2870 rte_hash_del_key(arp_hash_handle, &arp_key);
2876 void nd_timer_callback(struct rte_timer *timer, void *arg)
2878 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
2879 struct nd_key_ipv6 nd_key;
2881 struct nd_entry_data *ret_nd_data = NULL;
2884 nd_key.port_id = timer_key->port_id;
2889 rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
2891 if (ARPICMP_DEBUG) {
2892 RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
2896 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
2897 (void **)&ret_nd_data);
2901 RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
2902 (int)timer->expire, now);
2904 printf("Should not have come here \n");
2905 for (j = 0; j < 16; j++)
2906 printf("*%d ", nd_key.ipv6[j]);
2907 printf("*%d ", nd_key.port_id);
2910 if (ret_nd_data->mode == DYNAMIC_ARP) {
2911 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
2912 if (ret_nd_data->status == PROBE ||
2913 ret_nd_data->status == INCOMPLETE) {
2914 if (ret_nd_data->retry_count == 3) {
2915 remove_nd_entry_ipv6(ret_nd_data, arg);
2917 ret_nd_data->retry_count++;
2919 if (ARPICMP_DEBUG) {
2920 RTE_LOG(INFO, LIBARP,
2921 "RETRY ND..retry count : %u\n",
2922 ret_nd_data->retry_count);
2924 RTE_LOG(INFO, LIBARP,
2925 "TIMER STARTED FOR %u seconds\n",
2929 request_nd(ret_nd_data->ipv6,
2930 ifm_get_port(ret_nd_data->port));
2931 if (rte_timer_reset(ret_nd_data->timer,
2933 rte_get_tsc_hz()/ 1000),
2939 RTE_LOG(INFO, LIBARP,
2940 "Err : Timer already running\n");
2943 } else if (ret_nd_data->status == COMPLETE) {
2944 if (now <= (ret_nd_data->n_confirmed +
2945 (arp_timeout * rte_get_tsc_hz()))) {
2946 if (rte_timer_reset(ret_nd_data->timer,
2948 rte_get_tsc_hz()), SINGLE,
2953 RTE_LOG(INFO, LIBARP,
2954 "Err : Timer already running\n");
2955 } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2956 if (rte_timer_reset(ret_nd_data->timer,
2958 rte_get_tsc_hz()), SINGLE,
2963 RTE_LOG(INFO, LIBARP,
2964 "Err : Timer already running\n");
2966 printf("making it stale\n");
2967 ret_nd_data->status = STALE;
2968 p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
2971 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
2973 rte_hash_del_key(nd_hash_handle, &nd_key);
2979 void create_arp_table(void)
2983 for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2984 populate_arp_entry((const struct ether_addr *)
2985 &arp_entry_data_table[i].eth_addr,
2986 arp_entry_data_table[i].ip,
2987 (uint8_t) arp_entry_data_table[i].port,
2995 void create_nd_table(void)
2999 for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
3000 populate_nd_entry((const struct ether_addr *)
3001 nd_entry_data_table[i].eth_addr,
3002 nd_entry_data_table[i].ipv6,
3003 (uint8_t) nd_entry_data_table[i].port,
3010 void send_gratuitous_arp(l2_phy_interface_t *port)
3012 struct ether_hdr *eth_h;
3013 struct arp_hdr *arp_h;
3015 struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
3018 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
3023 if (arp_pkt == NULL) {
3025 RTE_LOG(INFO, LIBARP,
3026 "Error allocating arp_pkt rte_mbuf\n");
3030 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
3032 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
3033 ether_addr_copy((struct ether_addr *)
3034 &port->macaddr[0], ð_h->s_addr);
3035 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
3037 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
3038 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
3039 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
3040 arp_h->arp_hln = ETHER_ADDR_LEN;
3041 arp_h->arp_pln = sizeof(uint32_t);
3042 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
3044 ether_addr_copy((struct ether_addr *)
3045 &port->macaddr[0], &arp_h->arp_data.arp_sha);
3046 if (port->ipv4_list == NULL) {
3048 RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
3052 arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
3053 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
3054 //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
3055 arp_h->arp_data.arp_tip = 0; //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
3056 // RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
3057 //arp_h->arp_data.arp_sip);
3058 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
3059 arp_pkt->pkt_len = 42;
3060 arp_pkt->data_len = 42;
3062 if (ARPICMP_DEBUG) {
3063 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
3064 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
3066 port->transmit_single_pkt(port, arp_pkt);
3069 void set_arpdebug(int flag)
3072 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
3077 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
3083 void set_arptimeout(uint32_t timeout_val)
3085 if (timeout_val == 0) {
3086 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
3090 RTE_LOG(INFO, LIBARP,
3091 "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
3092 arp_timeout, timeout_val);
3093 arp_timeout = timeout_val;
3095 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",