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 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;
297 struct ether_addr *x;
300 /* as part of optimization we store mac address in cache
301 * & thus can be sent without having to retrieve
303 if (likely(arp_cache_dest_mac_present(phy_port))) {
304 x = get_local_cache_hw_addr(phy_port, nhip);
306 printf("local copy of address not stored\n");
310 ether_addr_copy(x, hw_addr);
311 return &arp_entry_data_default;
314 struct arp_key_ipv4 tmp_arp_key;
315 tmp_arp_key.port_id = phy_port; /* Changed for Multi Port */
316 tmp_arp_key.ip = nhip;
319 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
322 ret_arp_data = retrieve_arp_entry(tmp_arp_key, DYNAMIC_ARP);
323 if (ret_arp_data == NULL) {
324 if (ARPICMP_DEBUG && nhip)
326 RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x,"
327 " port %u\n", nhip, phy_port);
330 lib_arp_no_arp_entry_found++;
331 } else if (ret_arp_data->status == COMPLETE) {
332 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
333 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
334 p_arp_data->arp_cache_hw_laddr_valid[phy_port] = 1;
335 index = p_arp_data->arp_local_cache[phy_port].num_nhip;
336 p_arp_data->arp_local_cache[phy_port].nhip[index] = nhip;
337 ether_addr_copy(hw_addr,
338 &p_arp_data->arp_local_cache[phy_port].link_hw_laddr[index]);
339 p_arp_data->arp_local_cache[phy_port].num_nhip++;
340 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
341 lib_arp_arp_entry_found++;
343 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
347 p_arp_data->update_tsc[phy_port] = rte_rdtsc();
353 struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[],
354 uint32_t phy_port, struct ether_addr *hw_addr)
358 lib_nd_get_mac_req++;
360 struct nd_entry_data *ret_nd_data = NULL;
361 struct nd_key_ipv6 tmp_nd_key;
362 struct ether_addr *addr;
363 tmp_nd_key.port_id = phy_port;
365 if (nd_cache_dest_mac_present(phy_port)) {
366 addr = get_nd_local_link_hw_addr((uint8_t)phy_port, nhipv6);
368 printf("local copy not stored\n");
372 ether_addr_copy(addr, hw_addr);
373 return &nd_entry_data_default;
377 for (i = 0; i < 16; i++)
378 tmp_nd_key.ipv6[i] = nhipv6[i];
380 ret_nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND);
381 if (ret_nd_data == NULL) {
383 printf("NDIPV6 no entry found for ip %x, port %d\n",
384 nhipv6[0], phy_port);
386 lib_nd_no_arp_entry_found++;
388 } else if (ret_nd_data->status == COMPLETE) {
389 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
390 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
391 p_arp_data->nd_cache_hw_laddr_valid[phy_port] = 1;
392 index = p_arp_data->nd_local_cache[phy_port].num_nhip;
393 for (i=0; i<16; i++) {
394 p_arp_data->nd_local_cache[phy_port].nhip[index][i] = nhipv6[i];
396 ether_addr_copy(hw_addr,
397 &p_arp_data->nd_local_cache[phy_port].link_hw_laddr[index]);
398 p_arp_data->nd_local_cache[phy_port].num_nhip++;
400 lib_nd_nd_entry_found++;
401 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
405 p_arp_data->update_tsc[phy_port] = rte_rdtsc();
411 * A structure for arp entries in Arp table
414 struct lib_arp_arp_table_entry {
415 struct rte_pipeline_table_entry head;
416 uint64_t macaddr; /**< Mac address */
419 static const char *arp_op_name(uint16_t arp_op)
421 switch (CHECK_ENDIAN_16(arp_op)) {
422 case (ARP_OP_REQUEST):
423 return "ARP Request";
426 case (ARP_OP_REVREQUEST):
427 return "Reverse ARP Request";
428 case (ARP_OP_REVREPLY):
429 return "Reverse ARP Reply";
430 case (ARP_OP_INVREQUEST):
431 return "Peer Identify Request";
432 case (ARP_OP_INVREPLY):
433 return "Peer Identify Reply";
437 return "Unkwown ARP op";
440 static void print_icmp_packet(struct icmp_hdr *icmp_h)
442 RTE_LOG(INFO, LIBARP, " ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
444 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
445 (icmp_h->icmp_type ==
446 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
447 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
448 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
451 static void print_ipv4_h(struct ipv4_hdr *ip_h)
453 struct icmp_hdr *icmp_h =
454 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
455 RTE_LOG(INFO, LIBARP, " IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
456 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
457 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
458 if (ip_h->next_proto_id == IPPROTO_ICMP) {
459 print_icmp_packet(icmp_h);
463 static void print_arp_packet(struct arp_hdr *arp_h)
465 RTE_LOG(INFO, LIBARP, " ARP: hrd=%d proto=0x%04x hln=%d "
466 "pln=%d op=%u (%s)\n",
467 CHECK_ENDIAN_16(arp_h->arp_hrd),
468 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
469 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
470 arp_op_name(arp_h->arp_op));
472 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
473 RTE_LOG(INFO, LIBARP,
474 "incorrect arp_hrd format for IPv4 ARP (%d)\n",
476 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
477 RTE_LOG(INFO, LIBARP,
478 "incorrect arp_pro format for IPv4 ARP (%d)\n",
480 } else if (arp_h->arp_hln != 6) {
481 RTE_LOG(INFO, LIBARP,
482 "incorrect arp_hln format for IPv4 ARP (%d)\n",
484 } else if (arp_h->arp_pln != 4) {
485 RTE_LOG(INFO, LIBARP,
486 "incorrect arp_pln format for IPv4 ARP (%d)\n",
489 RTE_LOG(INFO, LIBARP,
490 " sha=%02X:%02X:%02X:%02X:%02X:%02X",
491 arp_h->arp_data.arp_sha.addr_bytes[0],
492 arp_h->arp_data.arp_sha.addr_bytes[1],
493 arp_h->arp_data.arp_sha.addr_bytes[2],
494 arp_h->arp_data.arp_sha.addr_bytes[3],
495 arp_h->arp_data.arp_sha.addr_bytes[4],
496 arp_h->arp_data.arp_sha.addr_bytes[5]);
497 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
498 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
499 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
500 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
501 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
502 RTE_LOG(INFO, LIBARP,
503 " tha=%02X:%02X:%02X:%02X:%02X:%02X",
504 arp_h->arp_data.arp_tha.addr_bytes[0],
505 arp_h->arp_data.arp_tha.addr_bytes[1],
506 arp_h->arp_data.arp_tha.addr_bytes[2],
507 arp_h->arp_data.arp_tha.addr_bytes[3],
508 arp_h->arp_data.arp_tha.addr_bytes[4],
509 arp_h->arp_data.arp_tha.addr_bytes[5]);
510 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
511 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
512 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
513 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
514 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
518 static void print_eth(struct ether_hdr *eth_h)
520 RTE_LOG(INFO, LIBARP, " ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
521 eth_h->s_addr.addr_bytes[0],
522 eth_h->s_addr.addr_bytes[1],
523 eth_h->s_addr.addr_bytes[2],
524 eth_h->s_addr.addr_bytes[3],
525 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
526 RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
527 eth_h->d_addr.addr_bytes[0],
528 eth_h->d_addr.addr_bytes[1],
529 eth_h->d_addr.addr_bytes[2],
530 eth_h->d_addr.addr_bytes[3],
531 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
536 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
539 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
540 struct arp_hdr *arp_h =
541 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
542 struct ipv4_hdr *ipv4_h =
543 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
545 RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
546 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
548 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
549 case ETHER_TYPE_IPv4:
550 print_ipv4_h(ipv4_h);
553 print_arp_packet(arp_h);
556 RTE_LOG(INFO, LIBARP, " unknown packet type\n");
563 * Add entry in ND table.
568 * return nd entry from table.
571 static int add_nd_data(struct nd_key_ipv6 *nd_key,
572 struct nd_entry_data *ret_nd_data)
575 struct nd_entry_data *tmp_nd_data = NULL;
576 rte_rwlock_write_lock(&nd_hash_handle_lock);
577 /* Check for value while locked */
578 ret = rte_hash_lookup_data(nd_hash_handle, nd_key, (void **)&tmp_nd_data);
580 if (ret == -ENOENT) {
581 /* entry not yet added, do so now */
582 ret = rte_hash_add_key_data(nd_hash_handle, nd_key, ret_nd_data);
584 /* We panic here because either:
585 * ret == -EINVAL and a parameter got messed up, or
586 * ret == -ENOSPC and the hash table isn't big enough
588 rte_panic("ND: Error on entry add for %s", rte_strerror(abs(ret)));
590 } else if (ret < 0) {
591 /* We panic here because ret == -EINVAL and a parameter got
592 * messed up, or dpdk hash lib changed and this needs corrected */
593 rte_panic("ARP: Error on entry add for %s", rte_strerror(abs(ret)));
595 /* entry already exists */
599 rte_rwlock_write_unlock(&nd_hash_handle_lock);
604 * Add entry in ARP table.
608 * @param ret_arp_data
609 * return arp entry from table.
612 static int add_arp_data(struct arp_key_ipv4 *arp_key,
613 struct arp_entry_data *ret_arp_data) {
615 struct arp_entry_data *tmp_arp_data = NULL;
616 rte_rwlock_write_lock(&arp_hash_handle_lock);
617 /* Check for value while locked */
618 ret = rte_hash_lookup_data(arp_hash_handle, arp_key, (void **)&tmp_arp_data);
620 if (ret == -ENOENT) {
621 /* entry not yet added, do so now */
622 ret = rte_hash_add_key_data(arp_hash_handle, arp_key, ret_arp_data);
624 /* We panic here because either:
625 * ret == -EINVAL and a parameter got messed up, or
626 * ret == -ENOSPC and the hash table isn't big enough
628 rte_panic("ARP: Error on entry add for %s - %s",
629 inet_ntoa(*(struct in_addr *)&arp_key->ip),
630 rte_strerror(abs(ret)));
632 } else if (ret < 0) {
633 /* We panic here because ret == -EINVAL and a parameter got
634 * messed up, or dpdk hash lib changed and this needs corrected */
635 rte_panic("ARP: Error on entry add for %s - %s",
636 inet_ntoa(*(struct in_addr *)&arp_key->ip),
637 rte_strerror(abs(ret)));
639 /* entry already exists */
643 rte_rwlock_write_unlock(&arp_hash_handle_lock);
647 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t mode)
649 struct arp_entry_data *ret_arp_data = NULL;
654 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
655 (void **)&ret_arp_data);
656 if (ret < 0 && (mode == DYNAMIC_ARP)) {
658 RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",arp_key.ip);
660 /* add INCOMPLETE arp entry */
661 ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data),
662 RTE_CACHE_LINE_SIZE, rte_socket_id());
663 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
664 ret_arp_data->status = INCOMPLETE;
665 ret_arp_data->port = arp_key.port_id;
666 ret_arp_data->ip = arp_key.ip;
667 ret_arp_data->mode = mode;
668 ret_arp_data->num_pkts = 0;
669 rte_rwlock_init(&ret_arp_data->queue_lock);
670 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
672 /* attempt to add arp_entry to hash */
673 ret = add_arp_data(&arp_key, ret_arp_data);
676 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
677 rte_free(ret_arp_data);
678 /* Some other thread has 'beat' this thread in
679 creation of arp_data, try again */
683 if (rte_mempool_get(timer_mempool_arp,
684 (void **) &(ret_arp_data->timer) ) < 0) {
685 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
686 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
690 ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
691 NULL, sizeof(struct rte_mbuf *) * arp_buffer,
692 RTE_CACHE_LINE_SIZE, rte_socket_id());
694 if (ret_arp_data->buf_pkts == NULL) {
695 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
696 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
700 rte_timer_init(ret_arp_data->timer);
701 struct arp_timer_key * callback_key =
702 (struct arp_timer_key*) rte_malloc(NULL,
703 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
704 callback_key->port_id = arp_key.port_id;
705 callback_key->ip = arp_key.ip;
707 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
709 if(rte_timer_reset(ret_arp_data->timer,
710 (PROBE_TIME * rte_get_tsc_hz() / 1000),
715 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
717 ret_arp_data->timer_key = callback_key;
719 /* send arp request */
720 request_arp(arp_key.port_id, arp_key.ip);
721 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
724 ret_arp_data->mode == DYNAMIC_ARP && ret_arp_data->status == STALE) {
725 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
726 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
727 ret_arp_data->status = PROBE;
728 struct arp_timer_key * callback_key =
729 (struct arp_timer_key*) rte_malloc(NULL,
730 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
731 callback_key->port_id = arp_key.port_id;
732 callback_key->ip = arp_key.ip;
734 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u"
735 " seconds\n",ARP_TIMER_EXPIRY);
736 if(rte_timer_reset(ret_arp_data->timer,
737 (arp_timeout * rte_get_tsc_hz()),
742 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
744 ret_arp_data->timer_key = callback_key;
746 /* send arp request */
747 request_arp(arp_key.port_id, arp_key.ip);
748 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
756 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
758 struct nd_entry_data *ret_nd_data = NULL;
759 l2_phy_interface_t *port;
765 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
766 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
767 (void **)&ret_nd_data);
768 if (ret < 0 && (mode == DYNAMIC_ND)) {
770 RTE_LOG(INFO, LIBARP, "ND entry not found for ip \n");
772 /* add INCOMPLETE arp entry */
773 ret_nd_data = rte_malloc_socket(NULL, sizeof(struct nd_entry_data),
774 RTE_CACHE_LINE_SIZE, rte_socket_id());
775 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
776 ret_nd_data->status = INCOMPLETE;
777 ret_nd_data->port = nd_key.port_id;
779 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
780 ret_nd_data->ipv6[i] = nd_key.ipv6[i];
781 ret_nd_data->mode = mode;
782 ret_nd_data->num_pkts = 0;
783 rte_rwlock_init(&ret_nd_data->queue_lock);
784 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
786 /* attempt to add arp_entry to hash */
787 ret = add_nd_data(&nd_key, ret_nd_data);
790 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
791 rte_free(ret_nd_data);
792 /* Some other thread has 'beat' this thread in
793 creation of arp_data, try again */
798 if (rte_mempool_get(timer_mempool_arp,
799 (void **) &(ret_nd_data->timer) ) < 0) {
800 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
801 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
805 ret_nd_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
806 NULL, sizeof(struct rte_mbuf *) * nd_buffer,
807 RTE_CACHE_LINE_SIZE, rte_socket_id());
809 if (ret_nd_data->buf_pkts == NULL) {
810 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
811 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
815 rte_timer_init(ret_nd_data->timer);
816 struct nd_timer_key * callback_key =
817 (struct nd_timer_key*) rte_malloc(NULL,
818 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
819 callback_key->port_id = nd_key.port_id;
820 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
821 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
825 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
829 if(rte_timer_reset(ret_nd_data->timer,
830 (PROBE_TIME * rte_get_tsc_hz() / 1000),
835 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
837 ret_nd_data->timer_key = callback_key;
838 /* send nd request */
839 port = ifm_get_port(callback_key->port_id);
841 printf("port returned is NULL inside retrieve_nd_entry\n");
842 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
846 request_nd(callback_key->ipv6, port);
847 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
850 ret_nd_data->mode == DYNAMIC_ND && ret_nd_data->status == STALE) {
851 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
852 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
853 ret_nd_data->status = PROBE;
854 struct nd_timer_key * callback_key =
855 (struct nd_timer_key*) rte_malloc(NULL,
856 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
858 callback_key->port_id = nd_key.port_id;
859 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
860 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
865 (arp_timeout * rte_get_tsc_hz()), SINGLE,
866 timer_lcore, nd_timer_callback, callback_key) < 0)
868 RTE_LOG(INFO, LIBARP,
869 "Err : Timer already running\n");
870 ret_nd_data->timer_key = callback_key;
872 /* send nd request */
873 port = ifm_get_port(callback_key->port_id);
875 printf("port returned is NULL inside retrieve_nd_entry\n");
876 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
880 request_nd(callback_key->ipv6, port);
881 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
887 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
889 void print_arp_table(void)
891 const void *next_key;
895 printf ("------------------------ ARP CACHE -----------------------------------------\n");
896 printf ("----------------------------------------------------------------------------\n");
897 printf("\tport hw addr status ip addr\n");
898 printf ("----------------------------------------------------------------------------\n");
900 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
903 struct arp_entry_data *tmp_arp_data =
904 (struct arp_entry_data *)next_data;
905 struct arp_key_ipv4 tmp_arp_key;
906 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
907 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
909 tmp_arp_data->eth_addr.addr_bytes[0],
910 tmp_arp_data->eth_addr.addr_bytes[1],
911 tmp_arp_data->eth_addr.addr_bytes[2],
912 tmp_arp_data->eth_addr.addr_bytes[3],
913 tmp_arp_data->eth_addr.addr_bytes[4],
914 tmp_arp_data->eth_addr.addr_bytes[5],
915 arp_status[tmp_arp_data->status],
916 (tmp_arp_data->ip >> 24),
917 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
918 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
919 ((tmp_arp_data->ip & 0x000000ff)));
925 printf("\nARP routing table...\n");
926 printf("\nIP_Address \t Mask \t\t Port\n");
927 for (j = 0; j < gw_get_num_ports(); j++) {
928 for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
929 printf("0x%08x \t 0x%08x \t %d\n",
930 p_route_data[j]->route_table[i].nh,
931 p_route_data[j]->route_table[i].mask,
932 p_route_data[j]->route_table[i].port);
935 printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, "
936 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
937 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
938 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
939 lib_arp_populate_called, lib_arp_delete_called,
940 lib_arp_duplicate_found);
942 printf("ARP table key len is %d\n", (uint32_t) sizeof(struct arp_key_ipv4));
946 void print_nd_table(void)
948 const void *next_key;
951 uint8_t ii = 0, k = 0;
953 ("------------------------------------------------------------------------------------------------------\n");
954 printf("\tport hw addr status ip addr\n");
957 ("------------------------------------------------------------------------------------------------------\n");
958 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
961 struct nd_entry_data *tmp_nd_data =
962 (struct nd_entry_data *)next_data;
963 struct nd_key_ipv6 tmp_nd_key;
964 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
965 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s",
967 tmp_nd_data->eth_addr.addr_bytes[0],
968 tmp_nd_data->eth_addr.addr_bytes[1],
969 tmp_nd_data->eth_addr.addr_bytes[2],
970 tmp_nd_data->eth_addr.addr_bytes[3],
971 tmp_nd_data->eth_addr.addr_bytes[4],
972 tmp_nd_data->eth_addr.addr_bytes[5],
973 arp_status[tmp_nd_data->status]);
975 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
976 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
977 tmp_nd_data->ipv6[ii + 1]);
982 uint32_t i = 0, p = 0;
983 printf("\n\nND IPV6 routing table ...\n");
984 printf ("\nNH_IP_Address Depth Port \n");
985 for(p = 0; p < gw_get_num_ports(); p++ ) {
986 for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) {
989 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
990 printf("%02X%02X ", p_nd_route_data[p]->nd_route_table[i].nhipv6[k],
991 p_nd_route_data[p]->nd_route_table[i].nhipv6[k + 1]);
995 p_nd_route_data[p]->nd_route_table[i].depth,
996 p_nd_route_data[p]->nd_route_table[i].port);
999 printf ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, "
1000 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
1001 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
1002 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
1003 lib_nd_populate_called, lib_nd_delete_called,
1004 lib_nd_duplicate_found);
1005 printf("ND table key len is %d\n\n", (uint32_t) sizeof(struct nd_key_ipv6));
1008 void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
1011 struct arp_timer_key *arp_key = (struct arp_timer_key *)arg;
1012 lib_arp_delete_called++;
1014 if (ret_arp_data->timer) {
1015 rte_timer_stop(ret_arp_data->timer);
1016 rte_free(ret_arp_data->timer_key);
1017 rte_free(ret_arp_data->buf_pkts);
1018 ret_arp_data->buf_pkts = NULL;
1021 if (ARPICMP_DEBUG) {
1022 RTE_LOG(INFO, LIBARP,
1023 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
1024 (arp_key->ip >> 24),
1025 ((arp_key->ip & 0x00ff0000) >> 16),
1026 ((arp_key->ip & 0x0000ff00) >> 8),
1027 ((arp_key->ip & 0x000000ff)),
1030 rte_hash_del_key(arp_hash_handle, arp_key);
1035 void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg)
1038 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
1040 lib_nd_delete_called++;
1042 rte_timer_stop(ret_nd_data->timer);
1043 rte_free(ret_nd_data->timer_key);
1044 rte_free(ret_nd_data->buf_pkts);
1045 ret_nd_data->buf_pkts = NULL;
1048 RTE_LOG(INFO, LIBARP,
1049 "Deletes rte hash table nd entry for port %d ipv6=",
1050 timer_key->port_id);
1051 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1052 RTE_LOG(INFO, LIBARP, "%02X%02X ", timer_key->ipv6[i],
1053 timer_key->ipv6[i + 1]);
1056 rte_hash_del_key(nd_hash_handle, timer_key);
1060 arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
1062 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1063 if (ret_arp_data->num_pkts == NUM_DESC) {
1064 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1068 ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
1069 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1074 arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
1075 struct ether_addr *hw_addr, uint8_t port_id)
1077 l2_phy_interface_t *port = ifm_get_port(port_id);
1078 struct rte_mbuf *pkt, *tmp;
1079 uint8_t *eth_dest, *eth_src;
1083 if (!hw_addr || !ret_arp_data || !port)
1086 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1087 for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
1088 pkt = ret_arp_data->buf_pkts[i];
1090 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1091 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1093 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1094 memcpy(eth_src, get_link_hw_addr(port_id),
1095 sizeof(struct ether_addr));
1096 port->transmit_single_pkt(port, pkt);
1098 rte_pktmbuf_free(tmp);
1100 printf("arp send buffered pkts = %d\n",ret_arp_data->num_pkts);
1101 ret_arp_data->num_pkts = 0;
1102 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1106 nd_queue_unresolved_packet(struct nd_entry_data *ret_nd_data, struct rte_mbuf *pkt)
1108 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1109 if (ret_nd_data->num_pkts == get_nd_buf()) {
1110 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1114 ret_nd_data->buf_pkts[ret_nd_data->num_pkts++] = pkt;
1115 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1120 nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
1121 struct ether_addr *hw_addr, uint8_t port_id)
1123 l2_phy_interface_t *port = ifm_get_port(port_id);
1124 struct rte_mbuf *pkt, *tmp;
1125 uint8_t *eth_dest, *eth_src;
1128 if (!hw_addr || !ret_nd_data || !port)
1131 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1132 for (i=0;i<(int)ret_nd_data->num_pkts;i++) {
1133 pkt = ret_nd_data->buf_pkts[i];
1134 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1135 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1137 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1138 memcpy(eth_src, get_link_hw_addr(port_id),
1139 sizeof(struct ether_addr));
1140 port->transmit_single_pkt(port, pkt);
1142 rte_pktmbuf_free(tmp);
1144 ret_nd_data->num_pkts = 0;
1145 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1149 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1150 uint8_t portid, uint8_t mode)
1152 struct arp_key_ipv4 arp_key;
1153 struct arp_entry_data *new_arp_data;
1154 arp_key.port_id = portid;
1155 arp_key.ip = ipaddr;
1156 arp_key.filler1 = 0;
1157 arp_key.filler2 = 0;
1158 arp_key.filler3 = 0;
1160 lib_arp_populate_called++;
1161 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip, arp_key.port_id);
1164 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1165 arp_key.ip, arp_key.port_id);
1167 new_arp_data = retrieve_arp_entry(arp_key, mode);
1168 if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1169 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1170 && mode == STATIC_ARP))) {
1172 RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry "
1173 "already exists(%d %d)\n", new_arp_data->mode, mode);
1177 if (mode == DYNAMIC_ARP) {
1180 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1181 printf("entry exists\n");
1183 if (ARPICMP_DEBUG) {
1184 RTE_LOG(INFO, LIBARP,
1185 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1187 ((arp_key.ip & 0x00ff0000) >> 16),
1188 ((arp_key.ip & 0x0000ff00) >> 8),
1189 ((arp_key.ip & 0x000000ff)),
1192 lib_arp_duplicate_found++;
1193 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1194 new_arp_data->retry_count = 0; // Reset
1195 if (new_arp_data->status == STALE) {
1196 new_arp_data->status = PROBE;
1197 if (ifm_chk_port_ipv4_enabled
1198 (new_arp_data->port) != IFM_FAILURE) {
1199 request_arp(new_arp_data->port,
1203 RTE_LOG(INFO, LIBARP,
1204 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1206 new_arp_data->port);
1210 if (rte_timer_reset(new_arp_data->timer,
1211 (arp_timeout * rte_get_tsc_hz()),
1212 SINGLE, timer_lcore,
1214 new_arp_data->timer_key) < 0) {
1216 RTE_LOG(INFO, LIBARP,
1217 "Err : Timer already running\n");
1219 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1222 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1223 ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
1224 if (new_arp_data && ((new_arp_data->status == INCOMPLETE) ||
1225 (new_arp_data->status == PROBE))) {
1226 new_arp_data->status = COMPLETE;
1227 new_arp_data->mode = mode;
1228 new_arp_data->n_confirmed = rte_rdtsc();
1229 new_arp_data->retry_count = 0;
1230 if (rte_timer_reset(new_arp_data->timer,
1231 (arp_timeout * rte_get_tsc_hz()),
1232 SINGLE, timer_lcore,
1234 new_arp_data->timer_key) < 0) {
1236 RTE_LOG(INFO, LIBARP,
1237 "Err : Timer already running\n");
1240 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1245 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
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 lib_arp_duplicate_found++;
1259 RTE_CACHE_LINE_ROUNDUP(sizeof
1260 (struct arp_entry_data));
1262 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1263 new_arp_data->eth_addr = *hw_addr;
1264 new_arp_data->status = COMPLETE;
1265 new_arp_data->port = portid;
1266 new_arp_data->ip = ipaddr;
1267 new_arp_data->mode = mode;
1268 new_arp_data->num_pkts = 0;
1270 /* attempt to add arp_entry to hash */
1272 ret = add_arp_data(&arp_key, new_arp_data);
1274 /* Some other thread created an entry for this ip */
1275 rte_free(new_arp_data);
1278 if (ARPICMP_DEBUG) {
1279 RTE_LOG(INFO, LIBARP,
1280 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1282 ((arp_key.ip & 0x00ff0000) >> 16),
1283 ((arp_key.ip & 0x0000ff00) >> 8),
1284 ((arp_key.ip & 0x000000ff)),
1287 #ifdef L3_STACK_SUPPORT
1288 // Call l3fwd module for resolving 2_adj structure.
1289 resolve_l2_adj(ipaddr, portid, hw_addr);
1294 if (ARPICMP_DEBUG) {
1295 /* print entire hash table */
1296 RTE_LOG(INFO, LIBARP,
1297 "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d on port=%d\n",
1298 new_arp_data->eth_addr.addr_bytes[0],
1299 new_arp_data->eth_addr.addr_bytes[1],
1300 new_arp_data->eth_addr.addr_bytes[2],
1301 new_arp_data->eth_addr.addr_bytes[3],
1302 new_arp_data->eth_addr.addr_bytes[4],
1303 new_arp_data->eth_addr.addr_bytes[5],
1304 (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1305 ((arp_key.ip & 0x0000ff00) >> 8),
1306 ((arp_key.ip & 0x000000ff)), portid);
1314 * Install key - data pair in Hash table - From Pipeline Configuration
1317 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1318 uint8_t portid, uint8_t mode)
1321 /* need to lock here if multi-threaded */
1322 /* rte_hash_add_key_data is not thread safe */
1324 struct nd_key_ipv6 nd_key;
1325 nd_key.port_id = portid;
1326 l2_phy_interface_t *port;
1328 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1329 nd_key.ipv6[i] = ipv6[i];
1340 lib_nd_populate_called++;
1342 /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1343 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, mode);
1344 if (new_nd_data && ((new_nd_data->mode == STATIC_ND
1345 && mode == DYNAMIC_ND) || (new_nd_data->mode == DYNAMIC_ND
1346 && mode == STATIC_ND))) {
1348 RTE_LOG(INFO, LIBARP, "populate_arp_entry: ND entry already"
1349 " exists(%d %d)\n", new_nd_data->mode, mode);
1353 if (mode == DYNAMIC_ND) {
1355 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1358 RTE_LOG(INFO, LIBARP,
1359 "nd_entry exists port %d ipv6 = ",
1361 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1363 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1365 nd_key.ipv6[i + 1]);
1369 lib_nd_duplicate_found++;
1370 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1371 if (new_nd_data->status == STALE) {
1372 new_nd_data->retry_count = 0; // Reset
1373 new_nd_data->status = PROBE;
1374 port = ifm_get_port(new_nd_data->port);
1377 request_nd(new_nd_data->ipv6, port);
1379 if (rte_timer_reset(new_nd_data->timer,
1380 (arp_timeout * rte_get_tsc_hz()),
1381 SINGLE, timer_lcore,
1383 new_nd_data->timer_key) < 0) {
1385 RTE_LOG(INFO, LIBARP,
1386 "Err : Timer already running\n");
1389 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1392 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1393 ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
1394 if (new_nd_data && ((new_nd_data->status == INCOMPLETE) ||
1395 (new_nd_data->status == PROBE))) {
1396 new_nd_data->status = COMPLETE;
1397 new_nd_data->mode = mode;
1398 new_nd_data->n_confirmed = rte_rdtsc();
1399 new_nd_data->retry_count = 0;
1400 if (rte_timer_reset(new_nd_data->timer,
1401 (arp_timeout * rte_get_tsc_hz()),
1402 SINGLE, timer_lcore,
1404 new_nd_data->timer_key) < 0) {
1406 RTE_LOG(INFO, LIBARP,
1407 "Err : Timer already running\n");
1410 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1416 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1418 RTE_LOG(INFO, LIBARP,
1419 "nd_entry exists port %d ipv6 = ",
1421 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1423 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1425 nd_key.ipv6[i + 1]);
1429 lib_nd_duplicate_found++;
1432 RTE_CACHE_LINE_ROUNDUP(sizeof
1433 (struct nd_entry_data));
1435 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1437 new_nd_data->eth_addr = *hw_addr;
1438 new_nd_data->status = COMPLETE;
1439 new_nd_data->port = portid;
1440 new_nd_data->mode = mode;
1441 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1442 new_nd_data->ipv6[i] = ipv6[i];
1444 new_nd_data->mode = mode;
1445 new_nd_data->num_pkts = 0;
1447 /*Add a key-data pair at hash table for ND IPv6 static routing */
1448 /* attempt to add arp_entry to hash */
1450 ret = add_nd_data(&nd_key, new_nd_data);
1452 rte_free(new_nd_data);
1455 /* need to check the return value of the hash add */
1456 #ifdef L3_STACK_SUPPORT
1457 // Call l3fwd module for resolving 2_adj structure.
1458 resolve_l2_adj(ipaddr, portid, hw_addr);
1465 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1468 /* print entire hash table */
1470 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1471 new_nd_data->eth_addr.addr_bytes[0],
1472 new_nd_data->eth_addr.addr_bytes[1],
1473 new_nd_data->eth_addr.addr_bytes[2],
1474 new_nd_data->eth_addr.addr_bytes[3],
1475 new_nd_data->eth_addr.addr_bytes[4],
1476 new_nd_data->eth_addr.addr_bytes[5], portid);
1477 RTE_LOG(INFO, LIBARP, "\tipv6=");
1478 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1479 new_nd_data->ipv6[i] = ipv6[i];
1480 RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1481 new_nd_data->ipv6[i + 1]);
1484 RTE_LOG(INFO, LIBARP, "\n");
1490 void print_pkt1(struct rte_mbuf *pkt)
1492 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1494 RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1495 for (i = 0; i < 20; i++) {
1496 for (j = 0; j < 20; j++)
1497 printf("%02x ", rd[(20 * i) + j]);
1498 RTE_LOG(INFO, LIBARP, "\n");
1502 #define MAX_NUM_MAC_ADDRESS 16
1503 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1504 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1505 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1506 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1507 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1508 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1509 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1510 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1511 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1512 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1513 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1514 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1515 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1516 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1517 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1518 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1519 {.addr_bytes = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1522 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1524 return &p_arp_data->link_hw_addr[out_port];
1527 void request_arp(uint8_t port_id, uint32_t ip)
1530 struct ether_hdr *eth_h;
1531 struct arp_hdr *arp_h;
1533 l2_phy_interface_t *link;
1534 link = ifm_get_port(port_id);
1535 struct rte_mbuf *arp_pkt = lib_arp_pkt[port_id];
1537 if (arp_pkt == NULL) {
1539 RTE_LOG(INFO, LIBARP,
1540 "Error allocating arp_pkt rte_mbuf\n");
1543 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1545 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1546 ether_addr_copy((struct ether_addr *)
1547 &link->macaddr[0], ð_h->s_addr);
1548 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1550 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1551 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1552 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1553 arp_h->arp_hln = ETHER_ADDR_LEN;
1554 arp_h->arp_pln = sizeof(uint32_t);
1555 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1557 if (link && link->ipv4_list) {
1558 arp_h->arp_data.arp_sip =
1559 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1561 ether_addr_copy((struct ether_addr *)
1562 &link->macaddr[0], &arp_h->arp_data.arp_sha);
1563 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1564 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1566 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1567 arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1568 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1569 arp_pkt->pkt_len = 42;
1570 arp_pkt->data_len = 42;
1572 if (ARPICMP_DEBUG) {
1573 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1574 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1577 link->transmit_single_pkt(link, arp_pkt);
1578 // start_tsc[port_id] = rte_rdtsc();
1579 printf("Sent ARP Request %x \n", arp_h->arp_data.arp_tip);
1582 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1584 struct ether_hdr *eth_h;
1585 struct ipv4_hdr *ip_h;
1586 struct icmp_hdr *icmp_h;
1587 l2_phy_interface_t *port = ifm_get_port(port_id);
1589 struct rte_mbuf *icmp_pkt = lib_arp_pkt[port_id];
1590 if (icmp_pkt == NULL) {
1592 RTE_LOG(INFO, LIBARP,
1593 "Error allocating icmp_pkt rte_mbuf\n");
1597 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1599 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1600 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1602 ip_h->version_ihl = IP_VHL_DEF;
1603 ip_h->type_of_service = 0;
1604 ip_h->total_length =
1605 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1606 ip_h->packet_id = 0xaabb;
1607 ip_h->fragment_offset = 0x0000;
1608 ip_h->time_to_live = 64;
1609 ip_h->next_proto_id = IPPROTO_ICMP;
1610 if (port && port->ipv4_list)
1612 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1613 ip_h->dst_addr = rte_cpu_to_be_32(ip);
1615 ip_h->hdr_checksum = 0;
1616 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1618 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1619 icmp_h->icmp_code = 0;
1620 icmp_h->icmp_ident = 0xdead;
1621 icmp_h->icmp_seq_nb = 0xbeef;
1623 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1626 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1627 sizeof(struct icmp_hdr);
1628 icmp_pkt->data_len = icmp_pkt->pkt_len;
1630 print_mbuf("TX", 0, icmp_pkt, __LINE__);
1636 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1637 uint64_t pkt_mask, l2_phy_interface_t *port)
1639 RTE_SET_USED(pkt_num);
1641 RTE_LOG(INFO, LIBARP,
1642 "============ARP ENTRY================\n");
1645 RTE_LOG(INFO, LIBARP,
1646 "============ARP PROCESS================\n");
1649 uint64_t pkts_for_process = pkt_mask;
1650 for (; pkts_for_process;) {
1651 /**< process only valid packets. */
1652 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1653 uint64_t pkts_mask = 1LLU << pos; /** <bitmask representing only this packet. */
1654 pkts_for_process &= ~pkts_mask; /** <remove this packet from the mask. */
1655 process_arpicmp_pkt(pkt[pos], port);
1660 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1662 uint8_t in_port_id = pkt->port;
1663 struct ether_hdr *eth_h;
1664 struct arp_hdr *arp_h;
1665 struct ipv4_hdr *ip_h;
1666 struct icmp_hdr *icmp_h;
1672 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1674 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1676 RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1677 __FUNCTION__, port->pmdid, __LINE__);
1679 (struct arp_hdr *)((char *)eth_h +
1680 sizeof(struct ether_hdr));
1681 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1682 RTE_LOG(INFO, LIBARP,
1683 "Invalid hardware format of hardware address - not processing ARP req\n");
1684 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1685 RTE_LOG(INFO, LIBARP,
1686 "Invalid protocol address format - not processing ARP req\n");
1687 else if (arp_h->arp_hln != 6)
1688 RTE_LOG(INFO, LIBARP,
1689 "Invalid hardware address length - not processing ARP req\n");
1690 else if (arp_h->arp_pln != 4)
1691 RTE_LOG(INFO, LIBARP,
1692 "Invalid protocol address length - not processing ARP req\n");
1694 if (port->ipv4_list == NULL) {
1695 RTE_LOG(INFO, LIBARP,
1696 "Ports IPV4 List is NULL.. Unable to Process\n");
1700 if (arp_h->arp_data.arp_tip !=
1701 ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1702 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1703 printf("gratuitous arp received\n");
1705 (struct ether_addr *)&arp_h->arp_data.arp_sha,
1706 rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1712 RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1715 /// revise conditionals to allow processing of requests with target ip = this ip and
1716 // processing of replies to destination ip = this ip
1717 else if (arp_h->arp_op ==
1718 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1719 if (ARPICMP_DEBUG) {
1720 RTE_LOG(INFO, LIBARP,
1721 "%s, portid %u. Line %d\n\r",
1722 __FUNCTION__, port->pmdid,
1725 RTE_LOG(INFO, LIBARP,
1726 "arp_op %d, ARP_OP_REQUEST %d\n",
1730 print_mbuf("RX", in_port_id, pkt,
1733 populate_arp_entry((struct ether_addr *)
1734 &arp_h->arp_data.arp_sha,
1736 (arp_h->arp_data.arp_sip),
1737 in_port_id, DYNAMIC_ARP);
1740 req_tip = arp_h->arp_data.arp_tip;
1741 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1742 ether_addr_copy((struct ether_addr *)&port->macaddr[0], ð_h->s_addr); /**< set sender mac address*/
1743 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1744 ether_addr_copy(ð_h->s_addr,
1745 &arp_h->arp_data.arp_sha);
1746 arp_h->arp_data.arp_tip =
1747 arp_h->arp_data.arp_sip;
1748 arp_h->arp_data.arp_sip = req_tip;
1749 ether_addr_copy(ð_h->d_addr,
1750 &arp_h->arp_data.arp_tha);
1752 print_mbuf("TX ARP REPLY PKT",
1753 port->pmdid, pkt, __LINE__);
1754 port->transmit_bulk_pkts(port, &pkt, 1);
1756 print_mbuf("TX", port->pmdid, pkt,
1758 printf("replying arp pkt done\n");
1760 } else if (arp_h->arp_op ==
1761 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1762 if (ARPICMP_DEBUG) {
1763 RTE_LOG(INFO, LIBARP,
1764 "ARP_OP_REPLY received");
1765 print_mbuf("RX", port->pmdid, pkt,
1768 populate_arp_entry((struct ether_addr *)
1769 &arp_h->arp_data.arp_sha,
1772 in_port_id, DYNAMIC_ARP);
1777 RTE_LOG(INFO, LIBARP,
1778 "Invalid ARP opcode - not processing ARP req %x\n",
1783 rte_pktmbuf_free(pkt);
1786 (struct ipv4_hdr *)((char *)eth_h +
1787 sizeof(struct ether_hdr));
1789 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1791 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1793 if (ip_h->next_proto_id != IPPROTO_ICMP) {
1794 if (ARPICMP_DEBUG) {
1795 RTE_LOG(INFO, LIBARP,
1796 "IP protocol ID is not set to ICMP - discarding\n");
1798 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1799 if (ARPICMP_DEBUG) {
1800 RTE_LOG(INFO, LIBARP,
1801 "IP version other than 4 - discarding\n");
1803 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1804 if (ARPICMP_DEBUG) {
1805 RTE_LOG(INFO, LIBARP,
1806 "Unknown IHL - discarding\n");
1809 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1810 && icmp_h->icmp_code == 0) {
1812 print_mbuf("RX", in_port_id,
1815 ip_addr = ip_h->src_addr;
1816 ether_addr_copy(ð_h->s_addr,
1818 ether_addr_copy((struct ether_addr *)
1822 RTE_LOG(INFO, LIBARP,
1823 "%s, portid %u. Line %d\n\r",
1825 port->pmdid, __LINE__);
1827 if (is_multicast_ipv4_addr
1832 rte_be_to_cpu_32(ip_addr);
1833 if ((ip_src & 0x00000003) == 1)
1844 rte_cpu_to_be_32(ip_src);
1845 ip_h->dst_addr = ip_addr;
1847 ip_h->hdr_checksum = 0;
1848 ip_h->hdr_checksum =
1849 ~rte_raw_cksum(ip_h,
1854 RTE_LOG(INFO, LIBARP,
1855 "%s, portid %u. Line %d\n\r",
1859 ip_h->src_addr = ip_h->dst_addr;
1860 ip_h->dst_addr = ip_addr;
1863 icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1864 cksum = ~icmp_h->icmp_cksum & 0xffff;
1866 ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1868 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1870 (cksum & 0xffff) + (cksum >> 16);
1872 (cksum & 0xffff) + (cksum >> 16);
1873 icmp_h->icmp_cksum = ~cksum;
1877 ("TX ICMP ECHO REPLY PKT",
1878 in_port_id, pkt, __LINE__);
1879 port->transmit_bulk_pkts(port, &pkt, 1);
1881 print_mbuf("TX", port->pmdid,
1885 } else if (icmp_h->icmp_type ==
1887 && icmp_h->icmp_code == 0) {
1889 print_mbuf("RX", in_port_id,
1892 struct arp_key_ipv4 arp_key;
1893 arp_key.port_id = in_port_id;
1895 rte_bswap32(ip_h->src_addr);
1896 arp_key.filler1 = 0;
1897 arp_key.filler2 = 0;
1898 arp_key.filler3 = 0;
1900 struct arp_entry_data *arp_entry =
1901 retrieve_arp_entry(arp_key,
1903 if (arp_entry == NULL) {
1905 RTE_LOG(INFO, LIBARP,
1906 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1911 arp_entry->status = COMPLETE;
1916 rte_pktmbuf_free(pkt);
1921 * inet_pton(af, src, dst)
1922 * convert from presentation format (which usually means ASCII printable)
1923 * to network format (which is usually some kind of binary format).
1925 * 1 if the address was valid for the specified address family
1926 * 0 if the address wasn't valid (`dst' is untouched in this case)
1927 * -1 if some other error occurred (`dst' is untouched in this case, too)
1931 int my_inet_pton_ipv6(int af, const char *src, void *dst)
1935 return inet_pton_ipv4(src, dst);
1937 return inet_pton_ipv6(src, dst);
1939 errno = EAFNOSUPPORT;
1946 * inet_pton_ipv4(src, dst)
1947 * like inet_aton() but without all the hexadecimal and shorthand.
1949 * 1 if `src' is a valid dotted quad, else 0.
1951 * does not touch `dst' unless it's returning 1.
1955 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1957 static const char digits[] = "0123456789";
1958 int saw_digit, octets, ch;
1959 unsigned char tmp[INADDRSZ], *tp;
1964 while ((ch = *src++) != '\0') {
1967 pch = strchr(digits, ch);
1969 unsigned int new = *tp * 10 + (pch - digits);
1978 *tp = (unsigned char)new;
1979 } else if (ch == '.' && saw_digit) {
1990 memcpy(dst, tmp, INADDRSZ);
1995 * inet_pton_ipv6(src, dst)
1996 * convert presentation level address to network order binary form.
1998 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
2000 * (1) does not touch `dst' unless it's returning 1.
2001 * (2) :: in a full address is silently ignored.
2003 * inspired by Mark Andrews.
2007 static int inet_pton_ipv6(const char *src, unsigned char *dst)
2009 static const char xdigits_l[] = "0123456789abcdef",
2010 xdigits_u[] = "0123456789ABCDEF";
2011 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2012 const char *xdigits = 0, *curtok = 0;
2013 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2014 unsigned int val = 0;
2015 unsigned int dbloct_count = 0;
2017 memset((tp = tmp), '\0', IN6ADDRSZ);
2018 endp = tp + IN6ADDRSZ;
2020 /* Leading :: requires some special handling. */
2025 saw_xdigit = count_xdigit = 0;
2028 while ((ch = *src++) != '\0') {
2031 pch = strchr((xdigits = xdigits_l), ch);
2033 pch = strchr((xdigits = xdigits_u), ch);
2035 if (count_xdigit >= 4)
2038 val |= (pch - xdigits);
2052 } else if (*src == '\0') {
2055 if (tp + sizeof(int16_t) > endp)
2057 *tp++ = (unsigned char)((val >> 8) & 0xff);
2058 *tp++ = (unsigned char)(val & 0xff);
2065 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2066 inet_pton_ipv4(curtok, tp) > 0) {
2070 break; /* '\0' was seen by inet_pton4(). */
2075 if (tp + sizeof(int16_t) > endp)
2077 *tp++ = (unsigned char)((val >> 8) & 0xff);
2078 *tp++ = (unsigned char)(val & 0xff);
2081 if (colonp != NULL) {
2082 /* if we already have 8 double octets, having a colon means error */
2083 if (dbloct_count == 8)
2087 * Since some memmove()'s erroneously fail to handle
2088 * overlapping regions, we'll do the shift by hand.
2090 const int n = tp - colonp;
2093 for (i = 1; i <= n; i++) {
2094 endp[-i] = colonp[n - i];
2101 memcpy(dst, tmp, IN6ADDRSZ);
2105 static int arp_parse_args(struct pipeline_params *params)
2107 uint32_t arp_route_tbl_present = 0;
2108 uint32_t nd_route_tbl_present = 0;
2110 uint32_t n_vnf_threads_present = 0;
2112 uint32_t pktq_in_prv_present = 0;
2113 uint32_t prv_to_pub_map_present = 0;
2115 uint8_t n_prv_in_port = 0;
2117 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2118 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2119 prv_to_pub_map[i] = 0xff;
2120 pub_to_prv_map[i] = 0xff;
2123 RTE_SET_USED(nd_route_tbl_present);
2124 RTE_SET_USED(arp_route_tbl_present);
2125 for (numArg = 0; numArg < params->n_args; numArg++) {
2127 char *arg_name = params->args_name[numArg];
2128 char *arg_value = params->args_value[numArg];
2130 /* arp timer expiry */
2131 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2132 arp_timeout = atoi(arg_value);
2136 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2137 if (pktq_in_prv_present) {
2139 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2142 pktq_in_prv_present = 1;
2144 int rxport = 0, j = 0;
2145 char phy_port_num[5];
2146 char *token = strtok(arg_value, "RXQ");
2149 while ((j < 4) && (token[j] != '.')) {
2150 phy_port_num[j] = token[j];
2153 phy_port_num[j] = '\0';
2154 rxport = atoi(phy_port_num);
2155 prv_in_port_a[n_prv_in_port++] = rxport;
2159 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2160 token, phy_port_num, rxport);
2161 prv_in_port_a[n_prv_in_port++] = rxport;
2162 if(rxport < PIPELINE_MAX_PORT_IN)
2163 in_port_dir_a[rxport] = 1; // set rxport egress
2164 token = strtok(NULL, "RXQ");
2167 if (n_prv_in_port == 0) {
2169 ("VNF common parse error - no prv RX phy port\n");
2175 if (strcmp(arg_name, "arp_buf") == 0) {
2176 arp_buffer = atoi(arg_value);
2180 if (strcmp(arg_name, "nd_buf") == 0) {
2181 nd_buffer = atoi(arg_value);
2185 /* prv_to_pub_map */
2186 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2187 if (prv_to_pub_map_present) {
2189 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2192 prv_to_pub_map_present = 1;
2194 int rxport = 0, txport = 0, j = 0, k = 0;
2195 char rx_phy_port_num[5];
2196 char tx_phy_port_num[5];
2197 char *token = strtok(arg_value, "(");
2200 while ((j < 4) && (token[j] != ',')) {
2201 rx_phy_port_num[j] = token[j];
2204 rx_phy_port_num[j] = '\0';
2205 rxport = atoi(rx_phy_port_num);
2211 while ((k < 4) && (token[j + k] != ')')) {
2212 tx_phy_port_num[k] = token[j + k];
2215 tx_phy_port_num[k] = '\0';
2216 txport = atoi(tx_phy_port_num);
2220 RTE_LOG(INFO, LIBARP, "token: %s,"
2221 "rx_phy_port_str: %s, phy_port_num %d,"
2222 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2223 token, rx_phy_port_num, rxport,
2224 tx_phy_port_num, txport);
2226 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2227 (txport >= PIPELINE_MAX_PORT_IN)) {
2229 ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d\n",
2234 if (in_port_dir_a[rxport] != 1) {
2235 printf("CG-NAPT parse error - incorrect rx_port supplied\n");
2239 prv_to_pub_map[rxport] = txport;
2240 pub_to_prv_map[txport] = rxport;
2241 token = strtok(NULL, "(");
2247 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2248 if (n_vnf_threads_present)
2250 n_vnf_threads_present = 1;
2252 num_vnf_threads = atoi(arg_value);
2253 if (num_vnf_threads <= 0) {
2254 RTE_LOG(INFO, LIBARP,
2255 "n_vnf_threads is invalid\n");
2258 RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2263 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2264 ARPICMP_DEBUG = atoi(arg_value);
2270 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2271 arp_route_tbl_present = 1;
2272 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip = 0,
2273 i = 0, j = 0, k = 0, l = 0;
2274 uint32_t arp_route_tbl_str_max_len = 10;
2275 char dest_ip_str[arp_route_tbl_str_max_len];
2276 char mask_str[arp_route_tbl_str_max_len];
2277 char tx_port_str[arp_route_tbl_str_max_len];
2278 char nh_ip_str[arp_route_tbl_str_max_len];
2279 char *token = strtok(arg_value, "(");
2282 while ((i < (arp_route_tbl_str_max_len - 1))
2283 && (token[i] != ',')) {
2284 dest_ip_str[i] = token[i];
2287 dest_ip_str[i] = '\0';
2288 dest_ip = strtoul(dest_ip_str, NULL, 16);
2292 while ((j < (arp_route_tbl_str_max_len - 1))
2293 && (token[i + j] != ',')) {
2294 mask_str[j] = token[i + j];
2298 mask = strtoul(mask_str, NULL, 16);
2302 while ((k < (arp_route_tbl_str_max_len - 1))
2303 && (token[i + j + k] != ',')) {
2304 tx_port_str[k] = token[i + j + k];
2307 tx_port_str[k] = '\0';
2308 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2309 if (tx_port > MAX_ROUTE_ENTRY_SIZE) {
2310 printf("tx_port is greater than route entry max size\n");
2316 while ((l < (arp_route_tbl_str_max_len - 1))
2317 && (token[i + j + k + l] != ')')) {
2318 nh_ip_str[l] = token[i + j + k + l];
2321 nh_ip_str[l] = '\0';
2322 nh_ip = strtoul(nh_ip_str, NULL, 16); //atoi(nh_ip_str);
2325 RTE_LOG(INFO, LIBARP, "token: %s, "
2326 "dest_ip_str: %s, dest_ip %u, "
2327 "mask_str: %s, mask %x, "
2328 "tx_port_str: %s, tx_port %u, "
2329 "nh_ip_str: %s, nh_ip %u\n",
2330 token, dest_ip_str, dest_ip,
2331 mask_str, mask, tx_port_str,
2332 tx_port, nh_ip_str, nh_ip);
2335 /* if (tx_port >= params->n_ports_out)
2337 RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2338 tx_port, params->n_ports_out);
2342 //Populate the static arp_route_table
2344 struct route_table_entry *lentry =
2345 &p_route_data[tx_port]->route_table
2346 [p_route_data[tx_port]->route_ent_cnt];
2347 lentry->mask = mask;
2348 lentry->port = tx_port;
2350 lentry->nh_mask = nh_ip & mask;
2351 printf("*********lentry_mask:%x lentry_port:%d lentry_nh:%x mask:%x\n", lentry->mask, lentry->port, lentry->nh, lentry->nh_mask);
2352 p_route_data[tx_port]->route_ent_cnt++;
2354 token = strtok(NULL, "(");
2361 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2362 nd_route_tbl_present = 1;
2363 uint8_t dest_ipv6[16];
2364 char dest_ipv6_str[128];
2365 uint8_t depth = 0, tx_port = 0, nh_ipv6[16];
2366 uint8_t i = 0, j = 0, k = 0, l = 0;
2367 uint8_t nd_route_tbl_str_max_len = 128; //64;
2368 // char dest_ipv6_str[nd_route_tbl_str_max_len];
2369 char depth_str[nd_route_tbl_str_max_len];
2370 char tx_port_str[nd_route_tbl_str_max_len];
2371 char nh_ipv6_str[nd_route_tbl_str_max_len];
2372 char *token = strtok(arg_value, "(");
2375 while ((i < (nd_route_tbl_str_max_len - 1))
2376 && (token[i] != ',')) {
2377 dest_ipv6_str[i] = token[i];
2380 dest_ipv6_str[i] = '\0';
2381 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2386 while ((j < (nd_route_tbl_str_max_len - 1))
2387 && (token[i + j] != ',')) {
2388 depth_str[j] = token[i + j];
2391 depth_str[j] = '\0';
2392 //converting string char to integer
2394 for (s = 0; depth_str[s] != '\0'; ++s)
2395 depth = depth * 10 + depth_str[s] - '0';
2399 while ((k < (nd_route_tbl_str_max_len - 1))
2400 && (token[i + j + k] != ',')) {
2401 tx_port_str[k] = token[i + j + k];
2404 tx_port_str[k] = '\0';
2405 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2409 while ((l < (nd_route_tbl_str_max_len - 1))
2410 && (token[i + j + k + l] != ')')) {
2411 nh_ipv6_str[l] = token[i + j + k + l];
2414 nh_ipv6_str[l] = '\0';
2415 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2418 struct nd_route_table_entry *lentry =
2419 &p_nd_route_data[tx_port]->nd_route_table
2420 [p_nd_route_data[tx_port]->nd_route_ent_cnt];
2422 //Populate the static arp_route_table
2423 for (i = 0; i < 16; i++)
2424 lentry->nhipv6[i] = nh_ipv6[i];
2426 lentry->depth = depth;
2427 lentry->port = tx_port;
2429 p_nd_route_data[tx_port]->nd_route_ent_cnt++;
2432 token = strtok(NULL, "(");
2440 /* Check that mandatory arguments are present */
2442 if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2443 RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2444 RTE_LOG(INFO, LIBARP,"%d, %d \n",
2445 arp_route_tbl_present, ports_mac_list_present);
2453 static void local_arp_cache_init(void)
2456 for (i=0; i<MAX_PORTS;i++) {
2457 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2458 p_arp_data->arp_local_cache[i].nhip[j] = 0;
2460 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2461 p_arp_data->arp_local_cache[i].num_nhip = 0;
2466 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
2469 struct ether_addr *x = NULL;
2470 limit = p_arp_data->nd_local_cache[out_port].num_nhip;
2472 for (i=0; i < limit; i++) {
2473 for (j=0;j<16;j++) {
2474 if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
2478 x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
2481 for (j = 0; j < 6; j++)
2482 printf("%d %d", x->addr_bytes[j],
2483 p_arp_data->nd_local_cache[out_port].link_hw_laddr[i].addr_bytes[j]);
2491 struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip)
2495 struct ether_addr *x = NULL;
2496 limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2497 for (i=0; i < limit; i++) {
2498 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2499 if (likely(tmp == nhip)) {
2500 x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2507 void lib_arp_init(struct pipeline_params *params,
2508 __rte_unused struct app_params *app)
2515 RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2517 /* create arp data for table entries */
2518 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2519 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2520 p_arp_data = (struct arp_data *)p;
2522 /* Parse arguments */
2523 if (arp_parse_args(params)) {
2524 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2528 /* acquire the mac addresses */
2529 struct ether_addr hw_addr;
2530 uint8_t nb_ports = rte_eth_dev_count();
2532 for (i = 0; i < nb_ports; i++) {
2533 rte_eth_macaddr_get(i, &hw_addr);
2534 ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
2535 p_arp_data->link_hw_addr_array_idx++;
2538 /* create a lock for arp/nd hash */
2539 rte_rwlock_init(&arp_hash_handle_lock);
2540 rte_rwlock_init(&nd_hash_handle_lock);
2542 /* create the arp_icmp mbuf rx pool */
2543 lib_arp_pktmbuf_tx_pool =
2544 rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2545 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2548 if (lib_arp_pktmbuf_tx_pool == NULL) {
2549 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2553 for (i=0; i<MAX_PORTS; i++) {
2554 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2555 if (lib_arp_pkt[i] == NULL) {
2556 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2561 /* create the nd icmp mbuf rx pool */
2562 lib_nd_pktmbuf_tx_pool =
2563 rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2564 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2567 if (lib_nd_pktmbuf_tx_pool == NULL) {
2568 RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
2572 for (i=0; i<MAX_PORTS; i++) {
2573 lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
2574 if (lib_nd_pkt[i] == NULL) {
2575 RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
2580 /* create the arp_icmp mbuf rx pool */
2581 arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2582 NB_ARPICMP_MBUF, MAX_POOL, 0,
2583 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2585 if (arp_icmp_pktmbuf_tx_pool == NULL) {
2586 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2590 arp_hash_params.socket_id = rte_socket_id();
2591 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2592 arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2593 arp_hash_handle = rte_hash_create(&arp_hash_params);
2595 if (arp_hash_handle == NULL) {
2596 RTE_LOG(INFO, LIBARP,
2597 "ARP rte_hash_create failed. socket %d ... \n",
2598 arp_hash_params.socket_id);
2600 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2601 (void *)arp_hash_handle);
2604 /* Create port alloc buffer */
2606 timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2607 timer_objs_mempool_count,
2608 sizeof(struct rte_timer),
2611 NULL, NULL, rte_socket_id(), 0);
2612 if (timer_mempool_arp == NULL) {
2613 rte_panic("timer_mempool create error\n");
2615 rte_timer_subsystem_init();
2616 list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2619 nd_hash_params.socket_id = rte_socket_id();
2620 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2621 nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2622 nd_hash_handle = rte_hash_create(&nd_hash_params);
2623 if (nd_hash_handle == NULL) {
2624 RTE_LOG(INFO, LIBARP,
2625 "ND rte_hash_create failed. socket %d ... \n",
2626 nd_hash_params.socket_id);
2628 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2629 (void *)nd_hash_handle);
2632 /* Initialize the local arp cache */
2633 local_arp_cache_init();
2638 void arp_timer_callback(struct rte_timer *timer, void *arg)
2640 struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2641 struct arp_key_ipv4 arp_key;
2642 arp_key.port_id = timer_key->port_id;
2643 arp_key.ip = timer_key->ip;
2644 arp_key.filler1 = 0;
2645 arp_key.filler2 = 0;
2646 arp_key.filler3 = 0;
2648 struct arp_entry_data *ret_arp_data = NULL;
2650 if (ARPICMP_DEBUG) {
2651 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2652 arp_key.ip, arp_key.port_id);
2655 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2656 (void **)&ret_arp_data);
2660 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2661 (int)timer->expire, now);
2663 printf("Should not have come here\n");
2666 if (ret_arp_data->mode == DYNAMIC_ARP) {
2667 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
2668 if (ret_arp_data->status == PROBE ||
2669 ret_arp_data->status == INCOMPLETE) {
2670 if (ret_arp_data->retry_count == ARP_RETRY_COUNT) {
2671 remove_arp_entry(ret_arp_data, arg);
2673 ret_arp_data->retry_count++;
2675 if (ARPICMP_DEBUG) {
2676 RTE_LOG(INFO, LIBARP,
2677 "RETRY ARP..retry count : %u\n",
2678 ret_arp_data->retry_count);
2680 RTE_LOG(INFO, LIBARP,
2681 "TIMER STARTED FOR %u seconds\n",
2685 if (ifm_chk_port_ipv4_enabled
2686 (ret_arp_data->port) != IFM_FAILURE) {
2687 request_arp(ret_arp_data->port,
2691 RTE_LOG(INFO, LIBARP,
2692 "%s: IP is not enabled on port %u"
2693 ", not sending GARP\n\r",
2695 ret_arp_data->port);
2698 if (rte_timer_reset(ret_arp_data->timer,
2700 rte_get_tsc_hz()/ 1000),
2706 RTE_LOG(INFO, LIBARP,
2707 "Err : Timer already running\n");
2710 } else if (ret_arp_data->status == COMPLETE) {
2711 if (now <= (ret_arp_data->n_confirmed +
2712 (arp_timeout * rte_get_tsc_hz()))) {
2713 if (rte_timer_reset(ret_arp_data->timer,
2715 rte_get_tsc_hz()), SINGLE,
2720 RTE_LOG(INFO, LIBARP,
2721 "Err : Timer already running\n");
2722 } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2723 if (rte_timer_reset(ret_arp_data->timer,
2725 rte_get_tsc_hz()), SINGLE,
2730 RTE_LOG(INFO, LIBARP,
2731 "Err : Timer already running\n");
2733 ret_arp_data->status = STALE;
2734 p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2737 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
2739 rte_hash_del_key(arp_hash_handle, &arp_key);
2745 void nd_timer_callback(struct rte_timer *timer, void *arg)
2747 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
2748 struct nd_key_ipv6 nd_key;
2750 struct nd_entry_data *ret_nd_data = NULL;
2752 l2_phy_interface_t *port;
2754 nd_key.port_id = timer_key->port_id;
2759 rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
2761 if (ARPICMP_DEBUG) {
2762 RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
2766 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
2767 (void **)&ret_nd_data);
2771 RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
2772 (int)timer->expire, now);
2774 printf("Should not have come here \n");
2775 for (j = 0; j < 16; j++)
2776 printf("*%d ", nd_key.ipv6[j]);
2777 printf("*%d ", nd_key.port_id);
2780 if (ret_nd_data->mode == DYNAMIC_ARP) {
2781 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
2782 if (ret_nd_data->status == PROBE ||
2783 ret_nd_data->status == INCOMPLETE) {
2784 if (ret_nd_data->retry_count == ARP_RETRY_COUNT) {
2785 remove_nd_entry_ipv6(ret_nd_data, arg);
2787 ret_nd_data->retry_count++;
2789 if (ARPICMP_DEBUG) {
2790 RTE_LOG(INFO, LIBARP,
2791 "RETRY ND..retry count : %u\n",
2792 ret_nd_data->retry_count);
2794 RTE_LOG(INFO, LIBARP,
2795 "TIMER STARTED FOR %u seconds\n",
2798 port = ifm_get_port(ret_nd_data->port);
2800 printf("port is NULL in nd_timer_callback\n");
2804 request_nd(ret_nd_data->ipv6, port);
2805 if (rte_timer_reset(ret_nd_data->timer,
2807 rte_get_tsc_hz()/ 1000),
2813 RTE_LOG(INFO, LIBARP,
2814 "Err : Timer already running\n");
2817 } else if (ret_nd_data->status == COMPLETE) {
2818 if (now <= (ret_nd_data->n_confirmed +
2819 (arp_timeout * rte_get_tsc_hz()))) {
2820 if (rte_timer_reset(ret_nd_data->timer,
2822 rte_get_tsc_hz()), SINGLE,
2827 RTE_LOG(INFO, LIBARP,
2828 "Err : Timer already running\n");
2829 } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2830 if (rte_timer_reset(ret_nd_data->timer,
2832 rte_get_tsc_hz()), SINGLE,
2837 RTE_LOG(INFO, LIBARP,
2838 "Err : Timer already running\n");
2840 printf("making it stale\n");
2841 ret_nd_data->status = STALE;
2842 p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
2845 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
2847 rte_hash_del_key(nd_hash_handle, &nd_key);
2853 void create_arp_table(void)
2857 for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2858 populate_arp_entry((const struct ether_addr *)
2859 &arp_entry_data_table[i].eth_addr,
2860 arp_entry_data_table[i].ip,
2861 (uint8_t) arp_entry_data_table[i].port,
2869 void create_nd_table(void)
2873 for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2874 populate_nd_entry((const struct ether_addr *)
2875 nd_entry_data_table[i].eth_addr,
2876 nd_entry_data_table[i].ipv6,
2877 (uint8_t) nd_entry_data_table[i].port,
2884 void send_gratuitous_arp(l2_phy_interface_t *port)
2886 struct ether_hdr *eth_h;
2887 struct arp_hdr *arp_h;
2889 struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
2892 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2897 if (arp_pkt == NULL) {
2899 RTE_LOG(INFO, LIBARP,
2900 "Error allocating arp_pkt rte_mbuf\n");
2904 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2906 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
2907 ether_addr_copy((struct ether_addr *)
2908 &port->macaddr[0], ð_h->s_addr);
2909 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2911 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2912 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2913 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2914 arp_h->arp_hln = ETHER_ADDR_LEN;
2915 arp_h->arp_pln = sizeof(uint32_t);
2916 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2918 ether_addr_copy((struct ether_addr *)
2919 &port->macaddr[0], &arp_h->arp_data.arp_sha);
2920 if (port->ipv4_list == NULL) {
2922 RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2926 arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2927 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2928 //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2929 arp_h->arp_data.arp_tip = 0; //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2930 // RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2931 //arp_h->arp_data.arp_sip);
2932 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2933 arp_pkt->pkt_len = 42;
2934 arp_pkt->data_len = 42;
2936 if (ARPICMP_DEBUG) {
2937 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2938 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2940 port->transmit_single_pkt(port, arp_pkt);
2943 void set_arpdebug(int flag)
2946 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2951 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2957 void set_arptimeout(uint32_t timeout_val)
2959 if (timeout_val == 0) {
2960 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2964 RTE_LOG(INFO, LIBARP,
2965 "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2966 arp_timeout, timeout_val);
2967 arp_timeout = timeout_val;
2969 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",