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"
45 #if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN)
46 #define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x)
47 #define CHECK_ENDIAN_32(x) rte_be_to_cpu_32(x)
49 #define CHECK_ENDIAN_16(x) (x)
50 #define CHECK_ENDIAN_32(x) (x)
53 #define NB_ARPICMP_MBUF 64
54 #define NB_NDICMP_MBUF 64
55 #define IP_VERSION_4 0x40
56 #define IP_HDRLEN 0x05 /**< default IP header length == five 32-bits words. */
57 #define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
59 #define is_multicast_ipv4_addr(ipv4_addr) \
60 (((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
62 extern uint8_t prv_in_port_a[PIPELINE_MAX_PORT_IN];
63 extern uint32_t timer_lcore;
64 extern int USE_RTM_LOCKS;
65 uint32_t arp_timeout = ARP_TIMER_EXPIRY;
66 uint32_t arp_buffer = ARP_BUF_DEFAULT;
67 uint32_t nd_buffer = ARP_BUF_DEFAULT;
74 static int my_inet_pton_ipv6(int af, const char *src, void *dst);
75 static int inet_pton_ipv6(const char *src, unsigned char *dst);
76 static int inet_pton_ipv4(const char *src, unsigned char *dst);
77 static void local_arp_cache_init(void);
78 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]);
79 extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
80 uint8_t netmask_ipv6[]);
82 uint8_t vnf_common_arp_lib_init;
83 uint8_t vnf_common_nd_lib_init;
84 uint8_t loadb_pipeline_count;
86 uint32_t ARPICMP_DEBUG;
87 uint32_t NDIPV6_DEBUG;
89 uint32_t arp_route_tbl_index;
90 uint32_t nd_route_tbl_index;
91 uint32_t link_hw_addr_array_idx;
93 uint32_t lib_arp_get_mac_req;
94 uint32_t lib_arp_nh_found;
95 uint32_t lib_arp_no_nh_found;
96 uint32_t lib_arp_arp_entry_found;
97 uint32_t lib_arp_no_arp_entry_found;
98 uint32_t lib_arp_populate_called;
99 uint32_t lib_arp_delete_called;
100 uint32_t lib_arp_duplicate_found;
102 uint32_t lib_nd_get_mac_req;
103 uint32_t lib_nd_nh_found;
104 uint32_t lib_nd_no_nh_found;
105 uint32_t lib_nd_nd_entry_found;
106 uint32_t lib_nd_no_arp_entry_found;
107 uint32_t lib_nd_populate_called;
108 uint32_t lib_nd_delete_called;
109 uint32_t lib_nd_duplicate_found;
110 struct rte_mempool *lib_arp_pktmbuf_tx_pool;
111 struct rte_mempool *lib_nd_pktmbuf_tx_pool;
113 struct rte_mbuf *lib_arp_pkt[MAX_PORTS];
114 struct rte_mbuf *lib_nd_pkt[MAX_PORTS];
116 uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
117 uint8_t default_ip[4] = { 0, 0, 1, 1 };
119 uint64_t start_tsc[4];
121 #define ticks_per_ms (rte_get_tsc_hz()/1000)
123 #define MAX_NUM_ARP_CACHE_MAC_ADDRESS 16
125 /***** ARP local cache *****/
126 struct arp_data *p_arp_data;
127 //struct arp_cache arp_local_cache[MAX_PORTS];
128 uint8_t arp_cache_hw_laddr_valid[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
129 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0
136 rte_rwlock_t arp_hash_handle_lock;
137 rte_rwlock_t nd_hash_handle_lock;
139 void update_nhip_access(uint8_t dest_if)
141 p_arp_data->update_tsc[dest_if] = rte_rdtsc();
144 static struct arp_entry_data arp_entry_data_default = {
149 static struct nd_entry_data nd_entry_data_default = {
155 * memory pool for queued up user pkts.
157 struct rte_mempool *arp_icmp_pktmbuf_tx_pool;
159 static struct rte_hash_parameters arp_hash_params = {
163 .key_len = sizeof(struct arp_key_ipv4),
164 .hash_func = rte_jhash,
165 .hash_func_init_val = 0,
168 static struct rte_hash_parameters nd_hash_params = {
172 .key_len = sizeof(struct nd_key_ipv6),
173 .hash_func = rte_jhash,
174 .hash_func_init_val = 0,
177 struct ether_addr broadcast_ether_addr = {
178 .addr_bytes[0] = 0xFF,
179 .addr_bytes[1] = 0xFF,
180 .addr_bytes[2] = 0xFF,
181 .addr_bytes[3] = 0xFF,
182 .addr_bytes[4] = 0xFF,
183 .addr_bytes[5] = 0xFF,
186 static const struct ether_addr null_ether_addr = {
187 .addr_bytes[0] = 0x00,
188 .addr_bytes[1] = 0x00,
189 .addr_bytes[2] = 0x00,
190 .addr_bytes[3] = 0x00,
191 .addr_bytes[4] = 0x00,
192 .addr_bytes[5] = 0x00,
195 struct rte_hash *arp_hash_handle;
196 struct rte_hash *nd_hash_handle;
198 void print_pkt1(struct rte_mbuf *pkt);
200 struct app_params *myApp;
201 struct rte_pipeline *myP;
202 uint8_t num_vnf_threads;
205 * A structure for Arp port address
207 struct arp_port_address {
208 uint32_t ip; /**< Ip address */
209 uint8_t mac_addr[6]; /**< Mac address */
212 struct arp_port_address arp_port_addresses[RTE_MAX_ETHPORTS];
213 struct rte_mempool *timer_mempool_arp;
215 int timer_objs_mempool_count = 70000;
217 #define MAX_NUM_ARP_ENTRIES 64
218 #define MAX_NUM_ND_ENTRIES 64
219 #define MAX_ARP_DATA_ENTRY_TABLE 7
221 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = {
222 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 1)},
223 {{0, 0, 0, 0, 0, 2}, 0, INCOMPLETE, IPv4(1, 1, 1, 2)},
224 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 3)},
225 {{0, 0, 0, 0, 0, 1}, 1, INCOMPLETE, IPv4(1, 1, 1, 4)},
226 {{0, 0, 0, 0, 0, 4}, 1, INCOMPLETE, IPv4(1, 1, 1, 5)},
227 {{0, 0, 0, 0, 0, 5}, 0, INCOMPLETE, IPv4(1, 1, 1, 6)},
228 {{0, 0, 0, 0, 0, 6}, 1, INCOMPLETE, IPv4(1, 1, 1, 7)},
231 #define MAX_ND_DATA_ENTRY_TABLE 7
232 struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = {
233 {{0, 0, 0, 0, 0, 8}, 1, INCOMPLETE,
234 {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, 0},
236 {{0, 0, 0, 0, 0, 9}, 1, INCOMPLETE,
237 {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, 0},
238 {{0, 0, 0, 0, 0, 10}, 2, INCOMPLETE,
239 {3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
240 {{0, 0, 0, 0, 0, 11}, 3, INCOMPLETE,
241 {4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
242 {{0, 0, 0, 0, 0, 12}, 4, INCOMPLETE,
243 {5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
244 {{0, 0, 0, 0, 0, 13}, 5, INCOMPLETE,
245 {6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
246 {{0, 0, 0, 0, 0, 14}, 6, INCOMPLETE,
247 {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0},
250 void print_trace(void);
252 uint32_t get_arp_buf(void)
257 uint32_t get_nd_buf(void)
262 uint8_t arp_cache_dest_mac_present(uint32_t out_port)
264 return p_arp_data->arp_cache_hw_laddr_valid[out_port];
267 uint8_t nd_cache_dest_mac_present(uint32_t out_port)
269 return p_arp_data->nd_cache_hw_laddr_valid[out_port];
272 /* Obtain a backtrace and print it to stdout. */
273 void print_trace(void)
280 size = backtrace(array, 10);
281 strings = backtrace_symbols(array, size);
283 RTE_LOG(INFO, LIBARP, "Obtained %zd stack frames.\n", size);
285 for (i = 0; i < size; i++)
286 RTE_LOG(INFO, LIBARP, "%s\n", strings[i]);
292 /* Added for Multiport changes*/
293 struct arp_entry_data *get_dest_mac_addr_ipv4(const uint32_t nhip,
294 uint32_t phy_port, struct ether_addr *hw_addr)
296 struct arp_entry_data *ret_arp_data = NULL;
299 /* as part of optimization we store mac address in cache
300 * & thus can be sent without having to retrieve
302 if (arp_cache_dest_mac_present(phy_port)) {
303 ether_addr_copy(get_local_cache_hw_addr(phy_port, nhip), hw_addr);
304 return &arp_entry_data_default;
307 struct arp_key_ipv4 tmp_arp_key;
308 tmp_arp_key.port_id = phy_port; /* Changed for Multi Port */
309 tmp_arp_key.ip = nhip;
312 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
315 ret_arp_data = retrieve_arp_entry(tmp_arp_key, DYNAMIC_ARP);
316 if (ret_arp_data == NULL) {
317 if (ARPICMP_DEBUG && nhip)
319 RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x,"
320 " port %u\n", nhip, phy_port);
323 lib_arp_no_arp_entry_found++;
324 } else if (ret_arp_data->status == COMPLETE) {
325 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
326 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
327 p_arp_data->arp_cache_hw_laddr_valid[phy_port] = 1;
328 index = p_arp_data->arp_local_cache[phy_port].num_nhip;
329 p_arp_data->arp_local_cache[phy_port].nhip[index] = nhip;
330 ether_addr_copy(hw_addr,
331 &p_arp_data->arp_local_cache[phy_port].link_hw_laddr[index]);
332 p_arp_data->arp_local_cache[phy_port].num_nhip++;
333 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
334 lib_arp_arp_entry_found++;
336 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
340 p_arp_data->update_tsc[phy_port] = rte_rdtsc();
346 struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[],
347 uint32_t phy_port, struct ether_addr *hw_addr)
351 lib_nd_get_mac_req++;
353 struct nd_entry_data *ret_nd_data = NULL;
354 struct nd_key_ipv6 tmp_nd_key;
355 tmp_nd_key.port_id = phy_port;
357 if (nd_cache_dest_mac_present(phy_port)) {
358 ether_addr_copy(get_nd_local_link_hw_addr(
359 (uint8_t)phy_port, nhipv6), hw_addr);
360 return &nd_entry_data_default;
364 for (i = 0; i < 16; i++)
365 tmp_nd_key.ipv6[i] = nhipv6[i];
367 ret_nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND);
368 if (ret_nd_data == NULL) {
370 printf("NDIPV6 no entry found for ip %x, port %d\n",
371 nhipv6[0], phy_port);
373 lib_nd_no_arp_entry_found++;
375 } else if (ret_nd_data->status == COMPLETE) {
376 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
377 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
378 p_arp_data->nd_cache_hw_laddr_valid[phy_port] = 1;
379 index = p_arp_data->nd_local_cache[phy_port].num_nhip;
380 for (i=0; i<16; i++) {
381 p_arp_data->nd_local_cache[phy_port].nhip[index][i] = nhipv6[i];
383 ether_addr_copy(hw_addr,
384 &p_arp_data->nd_local_cache[phy_port].link_hw_laddr[index]);
385 p_arp_data->nd_local_cache[phy_port].num_nhip++;
387 lib_nd_nd_entry_found++;
388 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
392 p_arp_data->update_tsc[phy_port] = rte_rdtsc();
398 * A structure for arp entries in Arp table
401 struct lib_arp_arp_table_entry {
402 struct rte_pipeline_table_entry head;
403 uint64_t macaddr; /**< Mac address */
406 static const char *arp_op_name(uint16_t arp_op)
408 switch (CHECK_ENDIAN_16(arp_op)) {
409 case (ARP_OP_REQUEST):
410 return "ARP Request";
413 case (ARP_OP_REVREQUEST):
414 return "Reverse ARP Request";
415 case (ARP_OP_REVREPLY):
416 return "Reverse ARP Reply";
417 case (ARP_OP_INVREQUEST):
418 return "Peer Identify Request";
419 case (ARP_OP_INVREPLY):
420 return "Peer Identify Reply";
424 return "Unkwown ARP op";
427 static void print_icmp_packet(struct icmp_hdr *icmp_h)
429 RTE_LOG(INFO, LIBARP, " ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
431 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
432 (icmp_h->icmp_type ==
433 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
434 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
435 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
438 static void print_ipv4_h(struct ipv4_hdr *ip_h)
440 struct icmp_hdr *icmp_h =
441 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
442 RTE_LOG(INFO, LIBARP, " IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
443 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
444 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
445 if (ip_h->next_proto_id == IPPROTO_ICMP) {
446 print_icmp_packet(icmp_h);
450 static void print_arp_packet(struct arp_hdr *arp_h)
452 RTE_LOG(INFO, LIBARP, " ARP: hrd=%d proto=0x%04x hln=%d "
453 "pln=%d op=%u (%s)\n",
454 CHECK_ENDIAN_16(arp_h->arp_hrd),
455 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
456 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
457 arp_op_name(arp_h->arp_op));
459 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
460 RTE_LOG(INFO, LIBARP,
461 "incorrect arp_hrd format for IPv4 ARP (%d)\n",
463 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
464 RTE_LOG(INFO, LIBARP,
465 "incorrect arp_pro format for IPv4 ARP (%d)\n",
467 } else if (arp_h->arp_hln != 6) {
468 RTE_LOG(INFO, LIBARP,
469 "incorrect arp_hln format for IPv4 ARP (%d)\n",
471 } else if (arp_h->arp_pln != 4) {
472 RTE_LOG(INFO, LIBARP,
473 "incorrect arp_pln format for IPv4 ARP (%d)\n",
476 RTE_LOG(INFO, LIBARP,
477 " sha=%02X:%02X:%02X:%02X:%02X:%02X",
478 arp_h->arp_data.arp_sha.addr_bytes[0],
479 arp_h->arp_data.arp_sha.addr_bytes[1],
480 arp_h->arp_data.arp_sha.addr_bytes[2],
481 arp_h->arp_data.arp_sha.addr_bytes[3],
482 arp_h->arp_data.arp_sha.addr_bytes[4],
483 arp_h->arp_data.arp_sha.addr_bytes[5]);
484 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
485 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
486 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
487 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
488 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
489 RTE_LOG(INFO, LIBARP,
490 " tha=%02X:%02X:%02X:%02X:%02X:%02X",
491 arp_h->arp_data.arp_tha.addr_bytes[0],
492 arp_h->arp_data.arp_tha.addr_bytes[1],
493 arp_h->arp_data.arp_tha.addr_bytes[2],
494 arp_h->arp_data.arp_tha.addr_bytes[3],
495 arp_h->arp_data.arp_tha.addr_bytes[4],
496 arp_h->arp_data.arp_tha.addr_bytes[5]);
497 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
498 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
499 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
500 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
501 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
505 static void print_eth(struct ether_hdr *eth_h)
507 RTE_LOG(INFO, LIBARP, " ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
508 eth_h->s_addr.addr_bytes[0],
509 eth_h->s_addr.addr_bytes[1],
510 eth_h->s_addr.addr_bytes[2],
511 eth_h->s_addr.addr_bytes[3],
512 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
513 RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
514 eth_h->d_addr.addr_bytes[0],
515 eth_h->d_addr.addr_bytes[1],
516 eth_h->d_addr.addr_bytes[2],
517 eth_h->d_addr.addr_bytes[3],
518 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
523 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
526 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
527 struct arp_hdr *arp_h =
528 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
529 struct ipv4_hdr *ipv4_h =
530 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
532 RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
533 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
535 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
536 case ETHER_TYPE_IPv4:
537 print_ipv4_h(ipv4_h);
540 print_arp_packet(arp_h);
543 RTE_LOG(INFO, LIBARP, " unknown packet type\n");
550 * Add entry in ND table.
555 * return nd entry from table.
558 static int add_nd_data(struct nd_key_ipv6 *nd_key,
559 struct nd_entry_data *ret_nd_data)
562 struct nd_entry_data *tmp_nd_data = NULL;
563 rte_rwlock_write_lock(&nd_hash_handle_lock);
564 /* Check for value while locked */
565 ret = rte_hash_lookup_data(nd_hash_handle, nd_key, (void **)&tmp_nd_data);
567 if (ret == -ENOENT) {
568 /* entry not yet added, do so now */
569 ret = rte_hash_add_key_data(nd_hash_handle, nd_key, ret_nd_data);
571 /* We panic here because either:
572 * ret == -EINVAL and a parameter got messed up, or
573 * ret == -ENOSPC and the hash table isn't big enough
575 rte_panic("ND: Error on entry add for %s", rte_strerror(abs(ret)));
577 } else if (ret < 0) {
578 /* We panic here because ret == -EINVAL and a parameter got
579 * messed up, or dpdk hash lib changed and this needs corrected */
580 rte_panic("ARP: Error on entry add for %s", rte_strerror(abs(ret)));
582 /* entry already exists */
586 rte_rwlock_write_unlock(&nd_hash_handle_lock);
591 * Add entry in ARP table.
595 * @param ret_arp_data
596 * return arp entry from table.
599 static int add_arp_data(struct arp_key_ipv4 *arp_key,
600 struct arp_entry_data *ret_arp_data) {
602 struct arp_entry_data *tmp_arp_data = NULL;
603 rte_rwlock_write_lock(&arp_hash_handle_lock);
604 /* Check for value while locked */
605 ret = rte_hash_lookup_data(arp_hash_handle, arp_key, (void **)&tmp_arp_data);
607 if (ret == -ENOENT) {
608 /* entry not yet added, do so now */
609 ret = rte_hash_add_key_data(arp_hash_handle, arp_key, ret_arp_data);
611 /* We panic here because either:
612 * ret == -EINVAL and a parameter got messed up, or
613 * ret == -ENOSPC and the hash table isn't big enough
615 rte_panic("ARP: Error on entry add for %s - %s",
616 inet_ntoa(*(struct in_addr *)&arp_key->ip),
617 rte_strerror(abs(ret)));
619 } else if (ret < 0) {
620 /* We panic here because ret == -EINVAL and a parameter got
621 * messed up, or dpdk hash lib changed and this needs corrected */
622 rte_panic("ARP: Error on entry add for %s - %s",
623 inet_ntoa(*(struct in_addr *)&arp_key->ip),
624 rte_strerror(abs(ret)));
626 /* entry already exists */
630 rte_rwlock_write_unlock(&arp_hash_handle_lock);
634 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t mode)
636 struct arp_entry_data *ret_arp_data = NULL;
641 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
642 (void **)&ret_arp_data);
643 if (ret < 0 && (mode == DYNAMIC_ARP)) {
645 RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",arp_key.ip);
647 /* add INCOMPLETE arp entry */
648 ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data),
649 RTE_CACHE_LINE_SIZE, rte_socket_id());
650 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
651 ret_arp_data->status = INCOMPLETE;
652 ret_arp_data->port = arp_key.port_id;
653 ret_arp_data->ip = arp_key.ip;
654 ret_arp_data->mode = mode;
655 ret_arp_data->num_pkts = 0;
656 rte_rwlock_init(&ret_arp_data->queue_lock);
657 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
659 /* attempt to add arp_entry to hash */
660 ret = add_arp_data(&arp_key, ret_arp_data);
663 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
664 rte_free(ret_arp_data);
665 /* Some other thread has 'beat' this thread in
666 creation of arp_data, try again */
670 if (rte_mempool_get(timer_mempool_arp,
671 (void **) &(ret_arp_data->timer) ) < 0) {
672 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
673 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
677 ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
678 NULL, sizeof(struct rte_mbuf *) * arp_buffer,
679 RTE_CACHE_LINE_SIZE, rte_socket_id());
681 if (ret_arp_data->buf_pkts == NULL) {
682 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
683 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
687 rte_timer_init(ret_arp_data->timer);
688 struct arp_timer_key * callback_key =
689 (struct arp_timer_key*) rte_malloc(NULL,
690 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
691 callback_key->port_id = arp_key.port_id;
692 callback_key->ip = arp_key.ip;
694 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
696 if(rte_timer_reset(ret_arp_data->timer,
697 (PROBE_TIME * rte_get_tsc_hz() / 1000),
702 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
704 ret_arp_data->timer_key = callback_key;
706 /* send arp request */
707 request_arp(arp_key.port_id, arp_key.ip);
708 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
711 ret_arp_data->mode == DYNAMIC_ARP && ret_arp_data->status == STALE) {
712 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
713 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
714 ret_arp_data->status = PROBE;
715 struct arp_timer_key * callback_key =
716 (struct arp_timer_key*) rte_malloc(NULL,
717 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
718 callback_key->port_id = arp_key.port_id;
719 callback_key->ip = arp_key.ip;
721 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u"
722 " seconds\n",ARP_TIMER_EXPIRY);
723 if(rte_timer_reset(ret_arp_data->timer,
724 (arp_timeout * rte_get_tsc_hz()),
729 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
731 ret_arp_data->timer_key = callback_key;
733 /* send arp request */
734 request_arp(arp_key.port_id, arp_key.ip);
735 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
743 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
745 struct nd_entry_data *ret_nd_data = NULL;
751 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
752 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
753 (void **)&ret_nd_data);
754 if (ret < 0 && (mode == DYNAMIC_ND)) {
756 RTE_LOG(INFO, LIBARP, "ND entry not found for ip \n");
758 /* add INCOMPLETE arp entry */
759 ret_nd_data = rte_malloc_socket(NULL, sizeof(struct nd_entry_data),
760 RTE_CACHE_LINE_SIZE, rte_socket_id());
761 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
762 ret_nd_data->status = INCOMPLETE;
763 ret_nd_data->port = nd_key.port_id;
765 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
766 ret_nd_data->ipv6[i] = nd_key.ipv6[i];
767 ret_nd_data->mode = mode;
768 ret_nd_data->num_pkts = 0;
769 rte_rwlock_init(&ret_nd_data->queue_lock);
770 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
772 /* attempt to add arp_entry to hash */
773 ret = add_nd_data(&nd_key, ret_nd_data);
776 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
777 rte_free(ret_nd_data);
778 /* Some other thread has 'beat' this thread in
779 creation of arp_data, try again */
784 if (rte_mempool_get(timer_mempool_arp,
785 (void **) &(ret_nd_data->timer) ) < 0) {
786 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
787 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
791 ret_nd_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
792 NULL, sizeof(struct rte_mbuf *) * nd_buffer,
793 RTE_CACHE_LINE_SIZE, rte_socket_id());
795 if (ret_nd_data->buf_pkts == NULL) {
796 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
797 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
801 rte_timer_init(ret_nd_data->timer);
802 struct nd_timer_key * callback_key =
803 (struct nd_timer_key*) rte_malloc(NULL,
804 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
805 callback_key->port_id = nd_key.port_id;
806 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
807 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
811 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
815 if(rte_timer_reset(ret_nd_data->timer,
816 (PROBE_TIME * rte_get_tsc_hz() / 1000),
821 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
823 ret_nd_data->timer_key = callback_key;
824 /* send nd request */
825 request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
826 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
829 ret_nd_data->mode == DYNAMIC_ND && ret_nd_data->status == STALE) {
830 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
831 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
832 ret_nd_data->status = PROBE;
833 struct nd_timer_key * callback_key =
834 (struct nd_timer_key*) rte_malloc(NULL,
835 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
837 callback_key->port_id = nd_key.port_id;
838 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
839 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
844 (arp_timeout * rte_get_tsc_hz()), SINGLE,
845 timer_lcore, nd_timer_callback, callback_key) < 0)
847 RTE_LOG(INFO, LIBARP,
848 "Err : Timer already running\n");
849 ret_nd_data->timer_key = callback_key;
851 /* send nd request */
852 request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
853 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
859 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
861 void print_arp_table(void)
863 const void *next_key;
867 printf ("------------------------ ARP CACHE -----------------------------------------\n");
868 printf ("----------------------------------------------------------------------------\n");
869 printf("\tport hw addr status ip addr\n");
870 printf ("----------------------------------------------------------------------------\n");
872 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
875 struct arp_entry_data *tmp_arp_data =
876 (struct arp_entry_data *)next_data;
877 struct arp_key_ipv4 tmp_arp_key;
878 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
879 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
881 tmp_arp_data->eth_addr.addr_bytes[0],
882 tmp_arp_data->eth_addr.addr_bytes[1],
883 tmp_arp_data->eth_addr.addr_bytes[2],
884 tmp_arp_data->eth_addr.addr_bytes[3],
885 tmp_arp_data->eth_addr.addr_bytes[4],
886 tmp_arp_data->eth_addr.addr_bytes[5],
887 arp_status[tmp_arp_data->status],
888 (tmp_arp_data->ip >> 24),
889 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
890 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
891 ((tmp_arp_data->ip & 0x000000ff)));
897 printf("\nARP routing table...\n");
898 printf("\nIP_Address \t Mask \t\t Port\n");
899 for (j = 0; j < gw_get_num_ports(); j++) {
900 for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
901 printf("0x%08x \t 0x%08x \t %d\n",
902 p_route_data[j]->route_table[i].nh,
903 p_route_data[j]->route_table[i].mask,
904 p_route_data[j]->route_table[i].port);
907 printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, "
908 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
909 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
910 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
911 lib_arp_populate_called, lib_arp_delete_called,
912 lib_arp_duplicate_found);
914 printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4));
918 void print_nd_table(void)
920 const void *next_key;
923 uint8_t ii = 0, k = 0;
925 ("------------------------------------------------------------------------------------------------------\n");
926 printf("\tport hw addr status ip addr\n");
929 ("------------------------------------------------------------------------------------------------------\n");
930 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
933 struct nd_entry_data *tmp_nd_data =
934 (struct nd_entry_data *)next_data;
935 struct nd_key_ipv6 tmp_nd_key;
936 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
937 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s",
939 tmp_nd_data->eth_addr.addr_bytes[0],
940 tmp_nd_data->eth_addr.addr_bytes[1],
941 tmp_nd_data->eth_addr.addr_bytes[2],
942 tmp_nd_data->eth_addr.addr_bytes[3],
943 tmp_nd_data->eth_addr.addr_bytes[4],
944 tmp_nd_data->eth_addr.addr_bytes[5],
945 arp_status[tmp_nd_data->status]);
947 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
948 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
949 tmp_nd_data->ipv6[ii + 1]);
955 printf("\n\nND IPV6 routing table ...\n");
956 printf ("\nNH_IP_Address Depth Port \n");
957 for(uint32_t p = 0; p < gw_get_num_ports(); p++ ) {
958 for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) {
961 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
962 printf("%02X%02X ", p_nd_route_data[p]->nd_route_table[i].nhipv6[k],
963 p_nd_route_data[p]->nd_route_table[i].nhipv6[k + 1]);
967 p_nd_route_data[p]->nd_route_table[i].depth,
968 p_nd_route_data[p]->nd_route_table[i].port);
971 printf ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, "
972 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
973 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
974 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
975 lib_nd_populate_called, lib_nd_delete_called,
976 lib_nd_duplicate_found);
977 printf("ND table key len is %lu\n\n", sizeof(struct nd_key_ipv6));
980 void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
983 struct arp_timer_key *arp_key = (struct arp_timer_key *)arg;
984 lib_arp_delete_called++;
986 rte_timer_stop(ret_arp_data->timer);
987 rte_free(ret_arp_data->timer_key);
988 rte_free(ret_arp_data->buf_pkts);
989 ret_arp_data->buf_pkts = NULL;
991 RTE_LOG(INFO, LIBARP,
992 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
994 ((arp_key->ip & 0x00ff0000) >> 16),
995 ((arp_key->ip & 0x0000ff00) >> 8),
996 ((arp_key->ip & 0x000000ff)),
999 rte_hash_del_key(arp_hash_handle, arp_key);
1004 void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg)
1007 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
1009 lib_nd_delete_called++;
1011 rte_timer_stop(ret_nd_data->timer);
1012 rte_free(ret_nd_data->timer_key);
1013 rte_free(ret_nd_data->buf_pkts);
1014 ret_nd_data->buf_pkts = NULL;
1017 RTE_LOG(INFO, LIBARP,
1018 "Deletes rte hash table nd entry for port %d ipv6=",
1019 timer_key->port_id);
1020 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1021 RTE_LOG(INFO, LIBARP, "%02X%02X ", timer_key->ipv6[i],
1022 timer_key->ipv6[i + 1]);
1025 rte_hash_del_key(nd_hash_handle, timer_key);
1029 arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
1031 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1032 if (ret_arp_data->num_pkts == NUM_DESC) {
1033 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1037 ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
1038 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1043 arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
1044 struct ether_addr *hw_addr, uint8_t port_id)
1046 l2_phy_interface_t *port = ifm_get_port(port_id);
1047 struct rte_mbuf *pkt, *tmp;
1048 uint8_t *eth_dest, *eth_src;
1052 if (!hw_addr || !ret_arp_data)
1055 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1056 for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
1057 pkt = ret_arp_data->buf_pkts[i];
1059 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1060 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1062 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1063 memcpy(eth_src, get_link_hw_addr(port_id),
1064 sizeof(struct ether_addr));
1065 port->transmit_single_pkt(port, pkt);
1067 rte_pktmbuf_free(tmp);
1069 printf("arp send buffered pkts = %d\n",ret_arp_data->num_pkts);
1070 ret_arp_data->num_pkts = 0;
1071 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1075 nd_queue_unresolved_packet(struct nd_entry_data *ret_nd_data, struct rte_mbuf *pkt)
1077 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1078 if (ret_nd_data->num_pkts == get_nd_buf()) {
1079 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1083 ret_nd_data->buf_pkts[ret_nd_data->num_pkts++] = pkt;
1084 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1089 nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
1090 struct ether_addr *hw_addr, uint8_t port_id)
1092 l2_phy_interface_t *port = ifm_get_port(port_id);
1093 struct rte_mbuf *pkt, *tmp;
1094 uint8_t *eth_dest, *eth_src;
1097 if (!hw_addr || !ret_nd_data)
1100 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1101 for (i=0;i<(int)ret_nd_data->num_pkts;i++) {
1102 pkt = ret_nd_data->buf_pkts[i];
1103 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1104 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1106 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1107 memcpy(eth_src, get_link_hw_addr(port_id),
1108 sizeof(struct ether_addr));
1109 port->transmit_single_pkt(port, pkt);
1111 rte_pktmbuf_free(tmp);
1113 ret_nd_data->num_pkts = 0;
1114 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1118 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1119 uint8_t portid, uint8_t mode)
1121 struct arp_key_ipv4 arp_key;
1122 struct arp_entry_data *new_arp_data;
1123 arp_key.port_id = portid;
1124 arp_key.ip = ipaddr;
1125 arp_key.filler1 = 0;
1126 arp_key.filler2 = 0;
1127 arp_key.filler3 = 0;
1129 lib_arp_populate_called++;
1130 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip, arp_key.port_id);
1133 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1134 arp_key.ip, arp_key.port_id);
1136 new_arp_data = retrieve_arp_entry(arp_key, mode);
1137 if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1138 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1139 && mode == STATIC_ARP))) {
1141 RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry "
1142 "already exists(%d %d)\n", new_arp_data->mode, mode);
1146 if (mode == DYNAMIC_ARP) {
1149 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1150 printf("entry exists\n");
1152 if (ARPICMP_DEBUG) {
1153 RTE_LOG(INFO, LIBARP,
1154 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1156 ((arp_key.ip & 0x00ff0000) >> 16),
1157 ((arp_key.ip & 0x0000ff00) >> 8),
1158 ((arp_key.ip & 0x000000ff)),
1161 lib_arp_duplicate_found++;
1162 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1163 new_arp_data->retry_count = 0; // Reset
1164 if (new_arp_data->status == STALE) {
1165 new_arp_data->status = PROBE;
1166 if (ifm_chk_port_ipv4_enabled
1167 (new_arp_data->port)) {
1168 request_arp(new_arp_data->port,
1172 RTE_LOG(INFO, LIBARP,
1173 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1175 new_arp_data->port);
1179 if (rte_timer_reset(new_arp_data->timer,
1180 (arp_timeout * rte_get_tsc_hz()),
1181 SINGLE, timer_lcore,
1183 new_arp_data->timer_key) < 0) {
1185 RTE_LOG(INFO, LIBARP,
1186 "Err : Timer already running\n");
1188 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1191 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1192 ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
1193 if ((new_arp_data->status == INCOMPLETE) ||
1194 (new_arp_data->status == PROBE)) {
1195 new_arp_data->status = COMPLETE;
1196 new_arp_data->mode = mode;
1197 new_arp_data->n_confirmed = rte_rdtsc();
1198 new_arp_data->retry_count = 0;
1199 if (rte_timer_reset(new_arp_data->timer,
1200 (arp_timeout * rte_get_tsc_hz()),
1201 SINGLE, timer_lcore,
1203 new_arp_data->timer_key) < 0) {
1205 RTE_LOG(INFO, LIBARP,
1206 "Err : Timer already running\n");
1209 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1214 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1216 if (ARPICMP_DEBUG) {
1217 RTE_LOG(INFO, LIBARP,
1218 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1220 ((arp_key.ip & 0x00ff0000) >> 16),
1221 ((arp_key.ip & 0x0000ff00) >> 8),
1222 ((arp_key.ip & 0x000000ff)),
1225 lib_arp_duplicate_found++;
1228 RTE_CACHE_LINE_ROUNDUP(sizeof
1229 (struct arp_entry_data));
1231 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1232 new_arp_data->eth_addr = *hw_addr;
1233 new_arp_data->status = COMPLETE;
1234 new_arp_data->port = portid;
1235 new_arp_data->ip = ipaddr;
1236 new_arp_data->mode = mode;
1237 new_arp_data->num_pkts = 0;
1239 /* attempt to add arp_entry to hash */
1241 ret = add_arp_data(&arp_key, new_arp_data);
1243 /* Some other thread created an entry for this ip */
1244 rte_free(new_arp_data);
1247 if (ARPICMP_DEBUG) {
1248 RTE_LOG(INFO, LIBARP,
1249 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1251 ((arp_key.ip & 0x00ff0000) >> 16),
1252 ((arp_key.ip & 0x0000ff00) >> 8),
1253 ((arp_key.ip & 0x000000ff)),
1256 #ifdef L3_STACK_SUPPORT
1257 // Call l3fwd module for resolving 2_adj structure.
1258 resolve_l2_adj(ipaddr, portid, hw_addr);
1263 if (ARPICMP_DEBUG) {
1264 /* print entire hash table */
1265 RTE_LOG(INFO, LIBARP,
1266 "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d on port=%d\n",
1267 new_arp_data->eth_addr.addr_bytes[0],
1268 new_arp_data->eth_addr.addr_bytes[1],
1269 new_arp_data->eth_addr.addr_bytes[2],
1270 new_arp_data->eth_addr.addr_bytes[3],
1271 new_arp_data->eth_addr.addr_bytes[4],
1272 new_arp_data->eth_addr.addr_bytes[5],
1273 (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1274 ((arp_key.ip & 0x0000ff00) >> 8),
1275 ((arp_key.ip & 0x000000ff)), portid);
1283 * Install key - data pair in Hash table - From Pipeline Configuration
1286 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1287 uint8_t portid, uint8_t mode)
1290 /* need to lock here if multi-threaded */
1291 /* rte_hash_add_key_data is not thread safe */
1293 struct nd_key_ipv6 nd_key;
1294 nd_key.port_id = portid;
1296 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1297 nd_key.ipv6[i] = ipv6[i];
1308 lib_nd_populate_called++;
1310 /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1311 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, mode);
1312 if (new_nd_data && ((new_nd_data->mode == STATIC_ND
1313 && mode == DYNAMIC_ND) || (new_nd_data->mode == DYNAMIC_ND
1314 && mode == STATIC_ND))) {
1316 RTE_LOG(INFO, LIBARP, "populate_arp_entry: ND entry already"
1317 " exists(%d %d)\n", new_nd_data->mode, mode);
1321 if (mode == DYNAMIC_ND) {
1323 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1326 RTE_LOG(INFO, LIBARP,
1327 "nd_entry exists port %d ipv6 = ",
1329 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1331 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1333 nd_key.ipv6[i + 1]);
1337 lib_nd_duplicate_found++;
1338 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1339 if (new_nd_data->status == STALE) {
1340 new_nd_data->retry_count = 0; // Reset
1341 new_nd_data->status = PROBE;
1342 request_nd(new_nd_data->ipv6,
1343 ifm_get_port(new_nd_data->port));
1345 if (rte_timer_reset(new_nd_data->timer,
1346 (arp_timeout * rte_get_tsc_hz()),
1347 SINGLE, timer_lcore,
1349 new_nd_data->timer_key) < 0) {
1351 RTE_LOG(INFO, LIBARP,
1352 "Err : Timer already running\n");
1355 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1358 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1359 ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
1360 if ((new_nd_data->status == INCOMPLETE) ||
1361 (new_nd_data->status == PROBE)) {
1362 new_nd_data->status = COMPLETE;
1363 new_nd_data->mode = mode;
1364 new_nd_data->n_confirmed = rte_rdtsc();
1365 new_nd_data->retry_count = 0;
1366 if (rte_timer_reset(new_nd_data->timer,
1367 (arp_timeout * rte_get_tsc_hz()),
1368 SINGLE, timer_lcore,
1370 new_nd_data->timer_key) < 0) {
1372 RTE_LOG(INFO, LIBARP,
1373 "Err : Timer already running\n");
1376 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1382 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1384 RTE_LOG(INFO, LIBARP,
1385 "nd_entry exists port %d ipv6 = ",
1387 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1389 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1391 nd_key.ipv6[i + 1]);
1395 lib_nd_duplicate_found++;
1398 RTE_CACHE_LINE_ROUNDUP(sizeof
1399 (struct nd_entry_data));
1401 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1403 new_nd_data->eth_addr = *hw_addr;
1404 new_nd_data->status = COMPLETE;
1405 new_nd_data->port = portid;
1406 new_nd_data->mode = mode;
1407 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1408 new_nd_data->ipv6[i] = ipv6[i];
1410 new_nd_data->mode = mode;
1411 new_nd_data->num_pkts = 0;
1413 /*Add a key-data pair at hash table for ND IPv6 static routing */
1414 /* attempt to add arp_entry to hash */
1416 ret = add_nd_data(&nd_key, new_nd_data);
1418 rte_free(new_nd_data);
1421 /* need to check the return value of the hash add */
1422 #ifdef L3_STACK_SUPPORT
1423 // Call l3fwd module for resolving 2_adj structure.
1424 resolve_l2_adj(ipaddr, portid, hw_addr);
1431 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1434 /* print entire hash table */
1436 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1437 new_nd_data->eth_addr.addr_bytes[0],
1438 new_nd_data->eth_addr.addr_bytes[1],
1439 new_nd_data->eth_addr.addr_bytes[2],
1440 new_nd_data->eth_addr.addr_bytes[3],
1441 new_nd_data->eth_addr.addr_bytes[4],
1442 new_nd_data->eth_addr.addr_bytes[5], portid);
1443 RTE_LOG(INFO, LIBARP, "\tipv6=");
1444 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1445 new_nd_data->ipv6[i] = ipv6[i];
1446 RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1447 new_nd_data->ipv6[i + 1]);
1450 RTE_LOG(INFO, LIBARP, "\n");
1456 void print_pkt1(struct rte_mbuf *pkt)
1458 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1460 RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1461 for (i = 0; i < 20; i++) {
1462 for (j = 0; j < 20; j++)
1463 printf("%02x ", rd[(20 * i) + j]);
1464 RTE_LOG(INFO, LIBARP, "\n");
1468 #define MAX_NUM_MAC_ADDRESS 16
1469 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1470 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1471 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1472 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1473 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1474 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1475 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1476 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1477 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1478 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1479 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1480 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1481 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1482 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1483 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1484 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1485 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1488 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1490 return &p_arp_data->link_hw_addr[out_port];
1493 void request_arp(uint8_t port_id, uint32_t ip)
1496 struct ether_hdr *eth_h;
1497 struct arp_hdr *arp_h;
1499 l2_phy_interface_t *link;
1500 link = ifm_get_port(port_id);
1501 struct rte_mbuf *arp_pkt = lib_arp_pkt[port_id];
1503 if (arp_pkt == NULL) {
1505 RTE_LOG(INFO, LIBARP,
1506 "Error allocating arp_pkt rte_mbuf\n");
1509 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1511 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1512 ether_addr_copy((struct ether_addr *)
1513 &link->macaddr[0], ð_h->s_addr);
1514 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1516 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1517 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1518 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1519 arp_h->arp_hln = ETHER_ADDR_LEN;
1520 arp_h->arp_pln = sizeof(uint32_t);
1521 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1523 if (link && link->ipv4_list) {
1524 arp_h->arp_data.arp_sip =
1525 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1527 ether_addr_copy((struct ether_addr *)
1528 &link->macaddr[0], &arp_h->arp_data.arp_sha);
1529 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1530 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1532 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1533 arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1534 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1535 arp_pkt->pkt_len = 42;
1536 arp_pkt->data_len = 42;
1538 if (ARPICMP_DEBUG) {
1539 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1540 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1543 link->transmit_single_pkt(link, arp_pkt);
1544 // start_tsc[port_id] = rte_rdtsc();
1545 printf("Sent ARP Request %x \n", arp_h->arp_data.arp_tip);
1548 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1550 struct ether_hdr *eth_h;
1551 struct ipv4_hdr *ip_h;
1552 struct icmp_hdr *icmp_h;
1553 l2_phy_interface_t *port = ifm_get_port(port_id);
1555 struct rte_mbuf *icmp_pkt = lib_arp_pkt[port_id];
1556 if (icmp_pkt == NULL) {
1558 RTE_LOG(INFO, LIBARP,
1559 "Error allocating icmp_pkt rte_mbuf\n");
1563 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1565 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1566 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1568 ip_h->version_ihl = IP_VHL_DEF;
1569 ip_h->type_of_service = 0;
1570 ip_h->total_length =
1571 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1572 ip_h->packet_id = 0xaabb;
1573 ip_h->fragment_offset = 0x0000;
1574 ip_h->time_to_live = 64;
1575 ip_h->next_proto_id = IPPROTO_ICMP;
1576 if (port && port->ipv4_list)
1578 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1579 ip_h->dst_addr = rte_cpu_to_be_32(ip);
1581 ip_h->hdr_checksum = 0;
1582 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1584 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1585 icmp_h->icmp_code = 0;
1586 icmp_h->icmp_ident = 0xdead;
1587 icmp_h->icmp_seq_nb = 0xbeef;
1589 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1592 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1593 sizeof(struct icmp_hdr);
1594 icmp_pkt->data_len = icmp_pkt->pkt_len;
1596 print_mbuf("TX", 0, icmp_pkt, __LINE__);
1602 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1603 uint64_t pkt_mask, l2_phy_interface_t *port)
1605 RTE_SET_USED(pkt_num);
1607 RTE_LOG(INFO, LIBARP,
1608 "============ARP ENTRY================\n");
1611 RTE_LOG(INFO, LIBARP,
1612 "============ARP PROCESS================\n");
1615 uint64_t pkts_for_process = pkt_mask;
1616 for (; pkts_for_process;) {
1617 /**< process only valid packets. */
1618 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1619 uint64_t pkts_mask = 1LLU << pos; /** <bitmask representing only this packet. */
1620 pkts_for_process &= ~pkts_mask; /** <remove this packet from the mask. */
1621 process_arpicmp_pkt(pkt[pos], port);
1626 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1628 uint8_t in_port_id = pkt->port;
1629 struct ether_hdr *eth_h;
1630 struct arp_hdr *arp_h;
1631 struct ipv4_hdr *ip_h;
1632 struct icmp_hdr *icmp_h;
1638 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1640 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1642 RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1643 __FUNCTION__, port->pmdid, __LINE__);
1645 (struct arp_hdr *)((char *)eth_h +
1646 sizeof(struct ether_hdr));
1647 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1648 RTE_LOG(INFO, LIBARP,
1649 "Invalid hardware format of hardware address - not processing ARP req\n");
1650 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1651 RTE_LOG(INFO, LIBARP,
1652 "Invalid protocol address format - not processing ARP req\n");
1653 else if (arp_h->arp_hln != 6)
1654 RTE_LOG(INFO, LIBARP,
1655 "Invalid hardware address length - not processing ARP req\n");
1656 else if (arp_h->arp_pln != 4)
1657 RTE_LOG(INFO, LIBARP,
1658 "Invalid protocol address length - not processing ARP req\n");
1660 if (port->ipv4_list == NULL) {
1661 RTE_LOG(INFO, LIBARP,
1662 "Ports IPV4 List is NULL.. Unable to Process\n");
1666 if (arp_h->arp_data.arp_tip !=
1667 ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1668 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1669 printf("gratuitous arp received\n");
1671 (struct ether_addr *)&arp_h->arp_data.arp_sha,
1672 rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1678 RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1681 /// revise conditionals to allow processing of requests with target ip = this ip and
1682 // processing of replies to destination ip = this ip
1683 else if (arp_h->arp_op ==
1684 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1685 if (ARPICMP_DEBUG) {
1686 RTE_LOG(INFO, LIBARP,
1687 "%s, portid %u. Line %d\n\r",
1688 __FUNCTION__, port->pmdid,
1691 RTE_LOG(INFO, LIBARP,
1692 "arp_op %d, ARP_OP_REQUEST %d\n",
1696 print_mbuf("RX", in_port_id, pkt,
1699 populate_arp_entry((struct ether_addr *)
1700 &arp_h->arp_data.arp_sha,
1702 (arp_h->arp_data.arp_sip),
1703 in_port_id, DYNAMIC_ARP);
1706 req_tip = arp_h->arp_data.arp_tip;
1707 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1708 ether_addr_copy((struct ether_addr *)&port->macaddr[0], ð_h->s_addr); /**< set sender mac address*/
1709 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1710 ether_addr_copy(ð_h->s_addr,
1711 &arp_h->arp_data.arp_sha);
1712 arp_h->arp_data.arp_tip =
1713 arp_h->arp_data.arp_sip;
1714 arp_h->arp_data.arp_sip = req_tip;
1715 ether_addr_copy(ð_h->d_addr,
1716 &arp_h->arp_data.arp_tha);
1718 print_mbuf("TX ARP REPLY PKT",
1719 port->pmdid, pkt, __LINE__);
1720 port->transmit_bulk_pkts(port, &pkt, 1);
1722 print_mbuf("TX", port->pmdid, pkt,
1724 printf("replying arp pkt done\n");
1726 } else if (arp_h->arp_op ==
1727 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1728 if (ARPICMP_DEBUG) {
1729 RTE_LOG(INFO, LIBARP,
1730 "ARP_OP_REPLY received");
1731 print_mbuf("RX", port->pmdid, pkt,
1734 populate_arp_entry((struct ether_addr *)
1735 &arp_h->arp_data.arp_sha,
1738 in_port_id, DYNAMIC_ARP);
1743 RTE_LOG(INFO, LIBARP,
1744 "Invalid ARP opcode - not processing ARP req %x\n",
1749 rte_pktmbuf_free(pkt);
1752 (struct ipv4_hdr *)((char *)eth_h +
1753 sizeof(struct ether_hdr));
1755 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1757 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1759 if (ip_h->next_proto_id != IPPROTO_ICMP) {
1760 if (ARPICMP_DEBUG) {
1761 RTE_LOG(INFO, LIBARP,
1762 "IP protocol ID is not set to ICMP - discarding\n");
1764 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1765 if (ARPICMP_DEBUG) {
1766 RTE_LOG(INFO, LIBARP,
1767 "IP version other than 4 - discarding\n");
1769 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1770 if (ARPICMP_DEBUG) {
1771 RTE_LOG(INFO, LIBARP,
1772 "Unknown IHL - discarding\n");
1775 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1776 && icmp_h->icmp_code == 0) {
1778 print_mbuf("RX", in_port_id,
1781 ip_addr = ip_h->src_addr;
1782 ether_addr_copy(ð_h->s_addr,
1784 ether_addr_copy((struct ether_addr *)
1788 RTE_LOG(INFO, LIBARP,
1789 "%s, portid %u. Line %d\n\r",
1791 port->pmdid, __LINE__);
1793 if (is_multicast_ipv4_addr
1798 rte_be_to_cpu_32(ip_addr);
1799 if ((ip_src & 0x00000003) == 1)
1810 rte_cpu_to_be_32(ip_src);
1811 ip_h->dst_addr = ip_addr;
1813 ip_h->hdr_checksum = 0;
1814 ip_h->hdr_checksum =
1815 ~rte_raw_cksum(ip_h,
1820 RTE_LOG(INFO, LIBARP,
1821 "%s, portid %u. Line %d\n\r",
1825 ip_h->src_addr = ip_h->dst_addr;
1826 ip_h->dst_addr = ip_addr;
1829 icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1830 cksum = ~icmp_h->icmp_cksum & 0xffff;
1832 ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1834 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1836 (cksum & 0xffff) + (cksum >> 16);
1838 (cksum & 0xffff) + (cksum >> 16);
1839 icmp_h->icmp_cksum = ~cksum;
1843 ("TX ICMP ECHO REPLY PKT",
1844 in_port_id, pkt, __LINE__);
1845 port->transmit_bulk_pkts(port, &pkt, 1);
1847 print_mbuf("TX", port->pmdid,
1851 } else if (icmp_h->icmp_type ==
1853 && icmp_h->icmp_code == 0) {
1855 print_mbuf("RX", in_port_id,
1858 struct arp_key_ipv4 arp_key;
1859 arp_key.port_id = in_port_id;
1861 rte_bswap32(ip_h->src_addr);
1862 arp_key.filler1 = 0;
1863 arp_key.filler2 = 0;
1864 arp_key.filler3 = 0;
1866 struct arp_entry_data *arp_entry =
1867 retrieve_arp_entry(arp_key,
1869 if (arp_entry == NULL) {
1871 RTE_LOG(INFO, LIBARP,
1872 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1877 arp_entry->status = COMPLETE;
1882 rte_pktmbuf_free(pkt);
1887 * inet_pton(af, src, dst)
1888 * convert from presentation format (which usually means ASCII printable)
1889 * to network format (which is usually some kind of binary format).
1891 * 1 if the address was valid for the specified address family
1892 * 0 if the address wasn't valid (`dst' is untouched in this case)
1893 * -1 if some other error occurred (`dst' is untouched in this case, too)
1897 static int my_inet_pton_ipv6(int af, const char *src, void *dst)
1901 return inet_pton_ipv4(src, dst);
1903 return inet_pton_ipv6(src, dst);
1905 errno = EAFNOSUPPORT;
1912 * inet_pton_ipv4(src, dst)
1913 * like inet_aton() but without all the hexadecimal and shorthand.
1915 * 1 if `src' is a valid dotted quad, else 0.
1917 * does not touch `dst' unless it's returning 1.
1921 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1923 static const char digits[] = "0123456789";
1924 int saw_digit, octets, ch;
1925 unsigned char tmp[INADDRSZ], *tp;
1930 while ((ch = *src++) != '\0') {
1933 pch = strchr(digits, ch);
1935 unsigned int new = *tp * 10 + (pch - digits);
1944 *tp = (unsigned char)new;
1945 } else if (ch == '.' && saw_digit) {
1956 memcpy(dst, tmp, INADDRSZ);
1961 * inet_pton_ipv6(src, dst)
1962 * convert presentation level address to network order binary form.
1964 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1966 * (1) does not touch `dst' unless it's returning 1.
1967 * (2) :: in a full address is silently ignored.
1969 * inspired by Mark Andrews.
1973 static int inet_pton_ipv6(const char *src, unsigned char *dst)
1975 static const char xdigits_l[] = "0123456789abcdef",
1976 xdigits_u[] = "0123456789ABCDEF";
1977 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
1978 const char *xdigits = 0, *curtok = 0;
1979 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
1980 unsigned int val = 0;
1981 unsigned int dbloct_count = 0;
1983 memset((tp = tmp), '\0', IN6ADDRSZ);
1984 endp = tp + IN6ADDRSZ;
1986 /* Leading :: requires some special handling. */
1991 saw_xdigit = count_xdigit = 0;
1994 while ((ch = *src++) != '\0') {
1997 pch = strchr((xdigits = xdigits_l), ch);
1999 pch = strchr((xdigits = xdigits_u), ch);
2001 if (count_xdigit >= 4)
2004 val |= (pch - xdigits);
2018 } else if (*src == '\0') {
2021 if (tp + sizeof(int16_t) > endp)
2023 *tp++ = (unsigned char)((val >> 8) & 0xff);
2024 *tp++ = (unsigned char)(val & 0xff);
2031 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2032 inet_pton_ipv4(curtok, tp) > 0) {
2036 break; /* '\0' was seen by inet_pton4(). */
2041 if (tp + sizeof(int16_t) > endp)
2043 *tp++ = (unsigned char)((val >> 8) & 0xff);
2044 *tp++ = (unsigned char)(val & 0xff);
2047 if (colonp != NULL) {
2048 /* if we already have 8 double octets, having a colon means error */
2049 if (dbloct_count == 8)
2053 * Since some memmove()'s erroneously fail to handle
2054 * overlapping regions, we'll do the shift by hand.
2056 const int n = tp - colonp;
2059 for (i = 1; i <= n; i++) {
2060 endp[-i] = colonp[n - i];
2067 memcpy(dst, tmp, IN6ADDRSZ);
2071 static int arp_parse_args(struct pipeline_params *params)
2073 uint32_t arp_route_tbl_present = 0;
2074 uint32_t nd_route_tbl_present = 0;
2076 uint32_t n_vnf_threads_present = 0;
2078 uint32_t pktq_in_prv_present = 0;
2079 uint32_t prv_to_pub_map_present = 0;
2081 uint8_t n_prv_in_port = 0;
2083 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2084 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2085 prv_to_pub_map[i] = 0xff;
2086 pub_to_prv_map[i] = 0xff;
2089 RTE_SET_USED(nd_route_tbl_present);
2090 RTE_SET_USED(arp_route_tbl_present);
2091 for (numArg = 0; numArg < params->n_args; numArg++) {
2092 char *arg_name = params->args_name[numArg];
2093 char *arg_value = params->args_value[numArg];
2095 /* arp timer expiry */
2096 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2097 arp_timeout = atoi(arg_value);
2101 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2102 if (pktq_in_prv_present) {
2104 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2107 pktq_in_prv_present = 1;
2109 int rxport = 0, j = 0;
2110 char phy_port_num[5];
2111 char *token = strtok(arg_value, "RXQ");
2114 while ((j < 4) && (token[j] != '.')) {
2115 phy_port_num[j] = token[j];
2118 phy_port_num[j] = '\0';
2119 rxport = atoi(phy_port_num);
2120 prv_in_port_a[n_prv_in_port++] = rxport;
2124 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2125 token, phy_port_num, rxport);
2126 prv_in_port_a[n_prv_in_port++] = rxport;
2127 if(rxport < PIPELINE_MAX_PORT_IN)
2128 in_port_dir_a[rxport] = 1; // set rxport egress
2129 token = strtok(NULL, "RXQ");
2132 if (n_prv_in_port == 0) {
2134 ("VNF common parse error - no prv RX phy port\n");
2140 if (strcmp(arg_name, "arp_buf") == 0) {
2141 arp_buffer = atoi(arg_value);
2145 if (strcmp(arg_name, "nd_buf") == 0) {
2146 nd_buffer = atoi(arg_value);
2150 /* prv_to_pub_map */
2151 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2152 if (prv_to_pub_map_present) {
2154 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2157 prv_to_pub_map_present = 1;
2159 int rxport = 0, txport = 0, j = 0, k = 0;
2160 char rx_phy_port_num[5];
2161 char tx_phy_port_num[5];
2162 char *token = strtok(arg_value, "(");
2165 while ((j < 4) && (token[j] != ',')) {
2166 rx_phy_port_num[j] = token[j];
2169 rx_phy_port_num[j] = '\0';
2170 rxport = atoi(rx_phy_port_num);
2176 while ((k < 4) && (token[j + k] != ')')) {
2177 tx_phy_port_num[k] = token[j + k];
2180 tx_phy_port_num[k] = '\0';
2181 txport = atoi(tx_phy_port_num);
2185 RTE_LOG(INFO, LIBARP, "token: %s,"
2186 "rx_phy_port_str: %s, phy_port_num %d,"
2187 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2188 token, rx_phy_port_num, rxport,
2189 tx_phy_port_num, txport);
2191 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2192 (txport >= PIPELINE_MAX_PORT_IN) ||
2193 (in_port_dir_a[rxport] != 1)) {
2195 ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d, Rx Dir %d\n",
2197 in_port_dir_a[rxport]);
2201 prv_to_pub_map[rxport] = txport;
2202 pub_to_prv_map[txport] = rxport;
2203 token = strtok(NULL, "(");
2209 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2210 if (n_vnf_threads_present)
2212 n_vnf_threads_present = 1;
2214 num_vnf_threads = atoi(arg_value);
2215 if (num_vnf_threads <= 0) {
2216 RTE_LOG(INFO, LIBARP,
2217 "n_vnf_threads is invalid\n");
2220 RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2225 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2226 ARPICMP_DEBUG = atoi(arg_value);
2232 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2233 arp_route_tbl_present = 1;
2234 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip = 0,
2235 i = 0, j = 0, k = 0;
2236 uint32_t arp_route_tbl_str_max_len = 10;
2237 char dest_ip_str[arp_route_tbl_str_max_len];
2238 char mask_str[arp_route_tbl_str_max_len];
2239 char tx_port_str[arp_route_tbl_str_max_len];
2240 char nh_ip_str[arp_route_tbl_str_max_len];
2241 char *token = strtok(arg_value, "(");
2244 while ((i < (arp_route_tbl_str_max_len - 1))
2245 && (token[i] != ',')) {
2246 nh_ip_str[i] = token[i];
2249 nh_ip_str[i] = '\0';
2250 nh_ip = strtoul(nh_ip_str, NULL, 16);
2254 while ((j < (arp_route_tbl_str_max_len - 1))
2255 && (token[i + j] != ',')) {
2256 mask_str[j] = token[i + j];
2260 mask = strtoul(mask_str, NULL, 16);
2264 while ((k < (arp_route_tbl_str_max_len - 1))
2265 && (token[i + j + k] != ',')) {
2266 tx_port_str[k] = token[i + j + k];
2269 tx_port_str[k] = '\0';
2270 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2275 RTE_LOG(INFO, LIBARP, "token: %s, "
2276 "dest_ip_str: %s, dest_ip %u, "
2277 "mask_str: %s, mask %x, "
2278 "tx_port_str: %s, tx_port %u, "
2279 "nh_ip_str: %s, nh_ip %u\n",
2280 token, dest_ip_str, dest_ip,
2281 mask_str, mask, tx_port_str,
2282 tx_port, nh_ip_str, nh_ip);
2285 /* if (tx_port >= params->n_ports_out)
2287 RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2288 tx_port, params->n_ports_out);
2292 //Populate the static arp_route_table
2294 struct route_table_entry *lentry =
2295 &p_route_data[tx_port]->route_table
2296 [p_route_data[tx_port]->route_ent_cnt];
2297 lentry->mask = mask;
2298 lentry->port = tx_port;
2300 lentry->nh_mask = nh_ip & mask;
2301 p_route_data[tx_port]->route_ent_cnt++;
2302 token = strtok(NULL, "(");
2309 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2310 nd_route_tbl_present = 1;
2312 uint8_t depth = 0, tx_port = 0, nh_ipv6[16];
2313 uint8_t i = 0, j = 0, k = 0;
2314 uint8_t nd_route_tbl_str_max_len = 128; //64;
2315 // char dest_ipv6_str[nd_route_tbl_str_max_len];
2316 char depth_str[nd_route_tbl_str_max_len];
2317 char tx_port_str[nd_route_tbl_str_max_len];
2318 char nh_ipv6_str[nd_route_tbl_str_max_len];
2319 char *token = strtok(arg_value, "(");
2322 while ((i < (nd_route_tbl_str_max_len - 1))
2323 && (token[i] != ',')) {
2324 nh_ipv6_str[i] = token[i];
2327 nh_ipv6_str[i] = '\0';
2328 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2332 while ((j < (nd_route_tbl_str_max_len - 1))
2333 && (token[i + j] != ',')) {
2334 depth_str[j] = token[i + j];
2337 depth_str[j] = '\0';
2338 //converting string char to integer
2340 for (s = 0; depth_str[s] != '\0'; ++s)
2341 depth = depth * 10 + depth_str[s] - '0';
2345 while ((k < (nd_route_tbl_str_max_len - 1))
2346 && (token[i + j + k] != ',')) {
2347 tx_port_str[k] = token[i + j + k];
2350 tx_port_str[k] = '\0';
2351 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2354 struct nd_route_table_entry *lentry =
2355 &p_nd_route_data[tx_port]->nd_route_table
2356 [p_nd_route_data[tx_port]->nd_route_ent_cnt];
2358 //Populate the static arp_route_table
2359 for (i = 0; i < 16; i++)
2360 lentry->nhipv6[i] = nh_ipv6[i];
2362 lentry->depth = depth;
2363 lentry->port = tx_port;
2365 p_nd_route_data[tx_port]->nd_route_ent_cnt++;
2367 token = strtok(NULL, "(");
2375 /* Check that mandatory arguments are present */
2377 if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2378 RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2379 RTE_LOG(INFO, LIBARP,"%d, %d \n",
2380 arp_route_tbl_present, ports_mac_list_present);
2388 static void local_arp_cache_init(void)
2391 for (i=0; i<MAX_PORTS;i++) {
2392 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2393 p_arp_data->arp_local_cache[i].nhip[j] = 0;
2395 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2396 p_arp_data->arp_local_cache[i].num_nhip = 0;
2401 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
2404 struct ether_addr *x = NULL;
2405 limit = p_arp_data->nd_local_cache[out_port].num_nhip;
2407 for (i=0; i < limit; i++) {
2408 for (j=0;j<16;j++) {
2409 if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
2413 x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
2416 for (j = 0; j < 6; j++)
2417 printf("%d %d", x->addr_bytes[j],
2418 p_arp_data->nd_local_cache[out_port].link_hw_laddr[i].addr_bytes[j]);
2426 struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip)
2430 struct ether_addr *x = NULL;
2431 limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2432 for (i=0; i < limit; i++) {
2433 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2435 x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2442 void lib_arp_init(struct pipeline_params *params,
2443 __rte_unused struct app_params *app)
2450 RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2452 /* create arp data for table entries */
2453 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2454 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2455 p_arp_data = (struct arp_data *)p;
2457 /* Parse arguments */
2458 if (arp_parse_args(params)) {
2459 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2463 /* acquire the mac addresses */
2464 struct ether_addr hw_addr;
2465 uint8_t nb_ports = rte_eth_dev_count();
2467 for (i = 0; i < nb_ports; i++) {
2468 rte_eth_macaddr_get(i, &hw_addr);
2469 ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
2470 p_arp_data->link_hw_addr_array_idx++;
2473 /* create a lock for arp/nd hash */
2474 rte_rwlock_init(&arp_hash_handle_lock);
2475 rte_rwlock_init(&nd_hash_handle_lock);
2477 /* create the arp_icmp mbuf rx pool */
2478 lib_arp_pktmbuf_tx_pool =
2479 rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2480 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2483 if (lib_arp_pktmbuf_tx_pool == NULL) {
2484 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2488 for (i=0; i<MAX_PORTS; i++) {
2489 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2490 if (lib_arp_pkt[i] == NULL) {
2491 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2496 /* create the nd icmp mbuf rx pool */
2497 lib_nd_pktmbuf_tx_pool =
2498 rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2499 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2502 if (lib_nd_pktmbuf_tx_pool == NULL) {
2503 RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
2507 for (i=0; i<MAX_PORTS; i++) {
2508 lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
2509 if (lib_nd_pkt[i] == NULL) {
2510 RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
2515 /* create the arp_icmp mbuf rx pool */
2516 arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2517 NB_ARPICMP_MBUF, MAX_POOL, 0,
2518 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2520 if (arp_icmp_pktmbuf_tx_pool == NULL) {
2521 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2525 arp_hash_params.socket_id = rte_socket_id();
2526 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2527 arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2528 arp_hash_handle = rte_hash_create(&arp_hash_params);
2530 if (arp_hash_handle == NULL) {
2531 RTE_LOG(INFO, LIBARP,
2532 "ARP rte_hash_create failed. socket %d ... \n",
2533 arp_hash_params.socket_id);
2535 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2536 (void *)arp_hash_handle);
2539 /* Create port alloc buffer */
2541 timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2542 timer_objs_mempool_count,
2543 sizeof(struct rte_timer),
2546 NULL, NULL, rte_socket_id(), 0);
2547 if (timer_mempool_arp == NULL) {
2548 rte_panic("timer_mempool create error\n");
2550 rte_timer_subsystem_init();
2551 list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2554 nd_hash_params.socket_id = rte_socket_id();
2555 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2556 nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2557 nd_hash_handle = rte_hash_create(&nd_hash_params);
2558 if (nd_hash_handle == NULL) {
2559 RTE_LOG(INFO, LIBARP,
2560 "ND rte_hash_create failed. socket %d ... \n",
2561 nd_hash_params.socket_id);
2563 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2564 (void *)nd_hash_handle);
2567 /* Initialize the local arp cache */
2568 local_arp_cache_init();
2573 void arp_timer_callback(struct rte_timer *timer, void *arg)
2575 struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2576 struct arp_key_ipv4 arp_key;
2577 arp_key.port_id = timer_key->port_id;
2578 arp_key.ip = timer_key->ip;
2579 arp_key.filler1 = 0;
2580 arp_key.filler2 = 0;
2581 arp_key.filler3 = 0;
2583 struct arp_entry_data *ret_arp_data = NULL;
2585 if (ARPICMP_DEBUG) {
2586 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2587 arp_key.ip, arp_key.port_id);
2590 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2591 (void **)&ret_arp_data);
2595 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2596 (int)timer->expire, now);
2598 printf("Should not have come here\n");
2601 if (ret_arp_data->mode == DYNAMIC_ARP) {
2602 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
2603 if (ret_arp_data->status == PROBE ||
2604 ret_arp_data->status == INCOMPLETE) {
2605 if (ret_arp_data->retry_count == ARP_RETRY_COUNT) {
2606 remove_arp_entry(ret_arp_data, arg);
2608 ret_arp_data->retry_count++;
2610 if (ARPICMP_DEBUG) {
2611 RTE_LOG(INFO, LIBARP,
2612 "RETRY ARP..retry count : %u\n",
2613 ret_arp_data->retry_count);
2615 RTE_LOG(INFO, LIBARP,
2616 "TIMER STARTED FOR %u seconds\n",
2620 if (ifm_chk_port_ipv4_enabled
2621 (ret_arp_data->port)) {
2622 request_arp(ret_arp_data->port,
2626 RTE_LOG(INFO, LIBARP,
2627 "%s: IP is not enabled on port %u"
2628 ", not sending GARP\n\r",
2630 ret_arp_data->port);
2633 if (rte_timer_reset(ret_arp_data->timer,
2635 rte_get_tsc_hz()/ 1000),
2641 RTE_LOG(INFO, LIBARP,
2642 "Err : Timer already running\n");
2645 } else if (ret_arp_data->status == COMPLETE) {
2646 if (now <= (ret_arp_data->n_confirmed +
2647 (arp_timeout * rte_get_tsc_hz()))) {
2648 if (rte_timer_reset(ret_arp_data->timer,
2650 rte_get_tsc_hz()), SINGLE,
2655 RTE_LOG(INFO, LIBARP,
2656 "Err : Timer already running\n");
2657 } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2658 if (rte_timer_reset(ret_arp_data->timer,
2660 rte_get_tsc_hz()), SINGLE,
2665 RTE_LOG(INFO, LIBARP,
2666 "Err : Timer already running\n");
2668 ret_arp_data->status = STALE;
2669 p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2672 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
2674 rte_hash_del_key(arp_hash_handle, &arp_key);
2680 void nd_timer_callback(struct rte_timer *timer, void *arg)
2682 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
2683 struct nd_key_ipv6 nd_key;
2685 struct nd_entry_data *ret_nd_data = NULL;
2688 nd_key.port_id = timer_key->port_id;
2693 rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
2695 if (ARPICMP_DEBUG) {
2696 RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
2700 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
2701 (void **)&ret_nd_data);
2705 RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
2706 (int)timer->expire, now);
2708 printf("Should not have come here \n");
2709 for (j = 0; j < 16; j++)
2710 printf("*%d ", nd_key.ipv6[j]);
2711 printf("*%d ", nd_key.port_id);
2714 if (ret_nd_data->mode == DYNAMIC_ARP) {
2715 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
2716 if (ret_nd_data->status == PROBE ||
2717 ret_nd_data->status == INCOMPLETE) {
2718 if (ret_nd_data->retry_count == ARP_RETRY_COUNT) {
2719 remove_nd_entry_ipv6(ret_nd_data, arg);
2721 ret_nd_data->retry_count++;
2723 if (ARPICMP_DEBUG) {
2724 RTE_LOG(INFO, LIBARP,
2725 "RETRY ND..retry count : %u\n",
2726 ret_nd_data->retry_count);
2728 RTE_LOG(INFO, LIBARP,
2729 "TIMER STARTED FOR %u seconds\n",
2733 request_nd(ret_nd_data->ipv6,
2734 ifm_get_port(ret_nd_data->port));
2735 if (rte_timer_reset(ret_nd_data->timer,
2737 rte_get_tsc_hz()/ 1000),
2743 RTE_LOG(INFO, LIBARP,
2744 "Err : Timer already running\n");
2747 } else if (ret_nd_data->status == COMPLETE) {
2748 if (now <= (ret_nd_data->n_confirmed +
2749 (arp_timeout * rte_get_tsc_hz()))) {
2750 if (rte_timer_reset(ret_nd_data->timer,
2752 rte_get_tsc_hz()), SINGLE,
2757 RTE_LOG(INFO, LIBARP,
2758 "Err : Timer already running\n");
2759 } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2760 if (rte_timer_reset(ret_nd_data->timer,
2762 rte_get_tsc_hz()), SINGLE,
2767 RTE_LOG(INFO, LIBARP,
2768 "Err : Timer already running\n");
2770 printf("making it stale\n");
2771 ret_nd_data->status = STALE;
2772 p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
2775 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
2777 rte_hash_del_key(nd_hash_handle, &nd_key);
2783 void create_arp_table(void)
2787 for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2788 populate_arp_entry((const struct ether_addr *)
2789 &arp_entry_data_table[i].eth_addr,
2790 arp_entry_data_table[i].ip,
2791 (uint8_t) arp_entry_data_table[i].port,
2799 void create_nd_table(void)
2803 for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2804 populate_nd_entry((const struct ether_addr *)
2805 nd_entry_data_table[i].eth_addr,
2806 nd_entry_data_table[i].ipv6,
2807 (uint8_t) nd_entry_data_table[i].port,
2814 void send_gratuitous_arp(l2_phy_interface_t *port)
2816 struct ether_hdr *eth_h;
2817 struct arp_hdr *arp_h;
2819 struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
2822 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2827 if (arp_pkt == NULL) {
2829 RTE_LOG(INFO, LIBARP,
2830 "Error allocating arp_pkt rte_mbuf\n");
2834 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2836 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
2837 ether_addr_copy((struct ether_addr *)
2838 &port->macaddr[0], ð_h->s_addr);
2839 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2841 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2842 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2843 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2844 arp_h->arp_hln = ETHER_ADDR_LEN;
2845 arp_h->arp_pln = sizeof(uint32_t);
2846 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2848 ether_addr_copy((struct ether_addr *)
2849 &port->macaddr[0], &arp_h->arp_data.arp_sha);
2850 if (port->ipv4_list == NULL) {
2852 RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2856 arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2857 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2858 //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2859 arp_h->arp_data.arp_tip = 0; //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2860 // RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2861 //arp_h->arp_data.arp_sip);
2862 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2863 arp_pkt->pkt_len = 42;
2864 arp_pkt->data_len = 42;
2866 if (ARPICMP_DEBUG) {
2867 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2868 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2870 port->transmit_single_pkt(port, arp_pkt);
2873 void set_arpdebug(int flag)
2876 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2881 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2887 void set_arptimeout(uint32_t timeout_val)
2889 if (timeout_val == 0) {
2890 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2894 RTE_LOG(INFO, LIBARP,
2895 "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2896 arp_timeout, timeout_val);
2897 arp_timeout = timeout_val;
2899 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",