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;
299 /* as part of optimization we store mac address in cache
300 * & thus can be sent without having to retrieve
302 if (likely(arp_cache_dest_mac_present(phy_port))) {
303 return &arp_entry_data_default;
306 struct arp_key_ipv4 tmp_arp_key;
307 tmp_arp_key.port_id = phy_port; /* Changed for Multi Port */
308 tmp_arp_key.ip = nhip;
311 printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip,
314 ret_arp_data = retrieve_arp_entry(tmp_arp_key, DYNAMIC_ARP);
315 if (ret_arp_data == NULL) {
316 if (ARPICMP_DEBUG && nhip)
318 RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x,"
319 " port %u\n", nhip, phy_port);
322 lib_arp_no_arp_entry_found++;
323 } else if (ret_arp_data->status == COMPLETE) {
324 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
325 ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
326 p_arp_data->arp_cache_hw_laddr_valid[phy_port] = 1;
327 index = p_arp_data->arp_local_cache[phy_port].num_nhip;
328 p_arp_data->arp_local_cache[phy_port].nhip[index] = nhip;
329 ether_addr_copy(hw_addr,
330 &p_arp_data->arp_local_cache[phy_port].link_hw_laddr[index]);
331 p_arp_data->arp_local_cache[phy_port].num_nhip++;
332 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
333 lib_arp_arp_entry_found++;
335 printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
339 p_arp_data->update_tsc[phy_port] = rte_rdtsc();
345 struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[],
346 uint32_t phy_port, struct ether_addr *hw_addr)
350 lib_nd_get_mac_req++;
352 struct nd_entry_data *ret_nd_data = NULL;
353 struct nd_key_ipv6 tmp_nd_key;
354 struct ether_addr *addr;
355 tmp_nd_key.port_id = phy_port;
357 if (nd_cache_dest_mac_present(phy_port)) {
358 addr = get_nd_local_link_hw_addr((uint8_t)phy_port, nhipv6);
360 printf("local copy not stored\n");
364 ether_addr_copy(addr, hw_addr);
365 return &nd_entry_data_default;
369 for (i = 0; i < 16; i++)
370 tmp_nd_key.ipv6[i] = nhipv6[i];
372 ret_nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND);
373 if (ret_nd_data == NULL) {
375 printf("NDIPV6 no entry found for ip %x, port %d\n",
376 nhipv6[0], phy_port);
378 lib_nd_no_arp_entry_found++;
380 } else if (ret_nd_data->status == COMPLETE) {
381 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
382 ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
383 p_arp_data->nd_cache_hw_laddr_valid[phy_port] = 1;
384 index = p_arp_data->nd_local_cache[phy_port].num_nhip;
385 for (i=0; i<16; i++) {
386 p_arp_data->nd_local_cache[phy_port].nhip[index][i] = nhipv6[i];
388 ether_addr_copy(hw_addr,
389 &p_arp_data->nd_local_cache[phy_port].link_hw_laddr[index]);
390 p_arp_data->nd_local_cache[phy_port].num_nhip++;
392 lib_nd_nd_entry_found++;
393 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
397 p_arp_data->update_tsc[phy_port] = rte_rdtsc();
403 * A structure for arp entries in Arp table
406 struct lib_arp_arp_table_entry {
407 struct rte_pipeline_table_entry head;
408 uint64_t macaddr; /**< Mac address */
411 static const char *arp_op_name(uint16_t arp_op)
413 switch (CHECK_ENDIAN_16(arp_op)) {
414 case (ARP_OP_REQUEST):
415 return "ARP Request";
418 case (ARP_OP_REVREQUEST):
419 return "Reverse ARP Request";
420 case (ARP_OP_REVREPLY):
421 return "Reverse ARP Reply";
422 case (ARP_OP_INVREQUEST):
423 return "Peer Identify Request";
424 case (ARP_OP_INVREPLY):
425 return "Peer Identify Reply";
429 return "Unkwown ARP op";
432 static void print_icmp_packet(struct icmp_hdr *icmp_h)
434 RTE_LOG(INFO, LIBARP, " ICMP: type=%d (%s) code=%d id=%d seqnum=%d\n",
436 (icmp_h->icmp_type == IP_ICMP_ECHO_REPLY ? "Reply" :
437 (icmp_h->icmp_type ==
438 IP_ICMP_ECHO_REQUEST ? "Reqest" : "Undef")),
439 icmp_h->icmp_code, CHECK_ENDIAN_16(icmp_h->icmp_ident),
440 CHECK_ENDIAN_16(icmp_h->icmp_seq_nb));
443 static void print_ipv4_h(struct ipv4_hdr *ip_h)
445 struct icmp_hdr *icmp_h =
446 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
447 RTE_LOG(INFO, LIBARP, " IPv4: Version=%d HLEN=%d Type=%d Length=%d\n",
448 (ip_h->version_ihl & 0xf0) >> 4, (ip_h->version_ihl & 0x0f),
449 ip_h->type_of_service, rte_cpu_to_be_16(ip_h->total_length));
450 if (ip_h->next_proto_id == IPPROTO_ICMP) {
451 print_icmp_packet(icmp_h);
455 static void print_arp_packet(struct arp_hdr *arp_h)
457 RTE_LOG(INFO, LIBARP, " ARP: hrd=%d proto=0x%04x hln=%d "
458 "pln=%d op=%u (%s)\n",
459 CHECK_ENDIAN_16(arp_h->arp_hrd),
460 CHECK_ENDIAN_16(arp_h->arp_pro), arp_h->arp_hln,
461 arp_h->arp_pln, CHECK_ENDIAN_16(arp_h->arp_op),
462 arp_op_name(arp_h->arp_op));
464 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER) {
465 RTE_LOG(INFO, LIBARP,
466 "incorrect arp_hrd format for IPv4 ARP (%d)\n",
468 } else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4) {
469 RTE_LOG(INFO, LIBARP,
470 "incorrect arp_pro format for IPv4 ARP (%d)\n",
472 } else if (arp_h->arp_hln != 6) {
473 RTE_LOG(INFO, LIBARP,
474 "incorrect arp_hln format for IPv4 ARP (%d)\n",
476 } else if (arp_h->arp_pln != 4) {
477 RTE_LOG(INFO, LIBARP,
478 "incorrect arp_pln format for IPv4 ARP (%d)\n",
481 RTE_LOG(INFO, LIBARP,
482 " sha=%02X:%02X:%02X:%02X:%02X:%02X",
483 arp_h->arp_data.arp_sha.addr_bytes[0],
484 arp_h->arp_data.arp_sha.addr_bytes[1],
485 arp_h->arp_data.arp_sha.addr_bytes[2],
486 arp_h->arp_data.arp_sha.addr_bytes[3],
487 arp_h->arp_data.arp_sha.addr_bytes[4],
488 arp_h->arp_data.arp_sha.addr_bytes[5]);
489 RTE_LOG(INFO, LIBARP, " sip=%d.%d.%d.%d\n",
490 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 24) & 0xFF,
491 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 16) & 0xFF,
492 (CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) >> 8) & 0xFF,
493 CHECK_ENDIAN_32(arp_h->arp_data.arp_sip) & 0xFF);
494 RTE_LOG(INFO, LIBARP,
495 " tha=%02X:%02X:%02X:%02X:%02X:%02X",
496 arp_h->arp_data.arp_tha.addr_bytes[0],
497 arp_h->arp_data.arp_tha.addr_bytes[1],
498 arp_h->arp_data.arp_tha.addr_bytes[2],
499 arp_h->arp_data.arp_tha.addr_bytes[3],
500 arp_h->arp_data.arp_tha.addr_bytes[4],
501 arp_h->arp_data.arp_tha.addr_bytes[5]);
502 RTE_LOG(INFO, LIBARP, " tip=%d.%d.%d.%d\n",
503 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 24) & 0xFF,
504 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 16) & 0xFF,
505 (CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) >> 8) & 0xFF,
506 CHECK_ENDIAN_32(arp_h->arp_data.arp_tip) & 0xFF);
510 static void print_eth(struct ether_hdr *eth_h)
512 RTE_LOG(INFO, LIBARP, " ETH: src=%02X:%02X:%02X:%02X:%02X:%02X",
513 eth_h->s_addr.addr_bytes[0],
514 eth_h->s_addr.addr_bytes[1],
515 eth_h->s_addr.addr_bytes[2],
516 eth_h->s_addr.addr_bytes[3],
517 eth_h->s_addr.addr_bytes[4], eth_h->s_addr.addr_bytes[5]);
518 RTE_LOG(INFO, LIBARP, " dst=%02X:%02X:%02X:%02X:%02X:%02X\n",
519 eth_h->d_addr.addr_bytes[0],
520 eth_h->d_addr.addr_bytes[1],
521 eth_h->d_addr.addr_bytes[2],
522 eth_h->d_addr.addr_bytes[3],
523 eth_h->d_addr.addr_bytes[4], eth_h->d_addr.addr_bytes[5]);
528 print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
531 struct ether_hdr *eth_h = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
532 struct arp_hdr *arp_h =
533 (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
534 struct ipv4_hdr *ipv4_h =
535 (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
537 RTE_LOG(INFO, LIBARP, "%s(%d): on port %d pkt-len=%u nb-segs=%u\n",
538 rx_tx, line, portid, mbuf->pkt_len, mbuf->nb_segs);
540 switch (rte_cpu_to_be_16(eth_h->ether_type)) {
541 case ETHER_TYPE_IPv4:
542 print_ipv4_h(ipv4_h);
545 print_arp_packet(arp_h);
548 RTE_LOG(INFO, LIBARP, " unknown packet type\n");
555 * Add entry in ND table.
560 * return nd entry from table.
563 static int add_nd_data(struct nd_key_ipv6 *nd_key,
564 struct nd_entry_data *ret_nd_data)
567 struct nd_entry_data *tmp_nd_data = NULL;
568 rte_rwlock_write_lock(&nd_hash_handle_lock);
569 /* Check for value while locked */
570 ret = rte_hash_lookup_data(nd_hash_handle, nd_key, (void **)&tmp_nd_data);
572 if (ret == -ENOENT) {
573 /* entry not yet added, do so now */
574 ret = rte_hash_add_key_data(nd_hash_handle, nd_key, ret_nd_data);
576 /* We panic here because either:
577 * ret == -EINVAL and a parameter got messed up, or
578 * ret == -ENOSPC and the hash table isn't big enough
580 rte_panic("ND: Error on entry add for %s", rte_strerror(abs(ret)));
582 } else if (ret < 0) {
583 /* We panic here because ret == -EINVAL and a parameter got
584 * messed up, or dpdk hash lib changed and this needs corrected */
585 rte_panic("ARP: Error on entry add for %s", rte_strerror(abs(ret)));
587 /* entry already exists */
591 rte_rwlock_write_unlock(&nd_hash_handle_lock);
596 * Add entry in ARP table.
600 * @param ret_arp_data
601 * return arp entry from table.
604 static int add_arp_data(struct arp_key_ipv4 *arp_key,
605 struct arp_entry_data *ret_arp_data) {
607 struct arp_entry_data *tmp_arp_data = NULL;
608 rte_rwlock_write_lock(&arp_hash_handle_lock);
609 /* Check for value while locked */
610 ret = rte_hash_lookup_data(arp_hash_handle, arp_key, (void **)&tmp_arp_data);
612 if (ret == -ENOENT) {
613 /* entry not yet added, do so now */
614 ret = rte_hash_add_key_data(arp_hash_handle, arp_key, ret_arp_data);
616 /* We panic here because either:
617 * ret == -EINVAL and a parameter got messed up, or
618 * ret == -ENOSPC and the hash table isn't big enough
620 rte_panic("ARP: Error on entry add for %s - %s",
621 inet_ntoa(*(struct in_addr *)&arp_key->ip),
622 rte_strerror(abs(ret)));
624 } else if (ret < 0) {
625 /* We panic here because ret == -EINVAL and a parameter got
626 * messed up, or dpdk hash lib changed and this needs corrected */
627 rte_panic("ARP: Error on entry add for %s - %s",
628 inet_ntoa(*(struct in_addr *)&arp_key->ip),
629 rte_strerror(abs(ret)));
631 /* entry already exists */
635 rte_rwlock_write_unlock(&arp_hash_handle_lock);
639 struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t mode)
641 struct arp_entry_data *ret_arp_data = NULL;
646 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
647 (void **)&ret_arp_data);
648 if (ret < 0 && (mode == DYNAMIC_ARP)) {
650 RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",arp_key.ip);
652 /* add INCOMPLETE arp entry */
653 ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data),
654 RTE_CACHE_LINE_SIZE, rte_socket_id());
655 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
656 ret_arp_data->status = INCOMPLETE;
657 ret_arp_data->port = arp_key.port_id;
658 ret_arp_data->ip = arp_key.ip;
659 ret_arp_data->mode = mode;
660 ret_arp_data->num_pkts = 0;
661 rte_rwlock_init(&ret_arp_data->queue_lock);
662 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
664 /* attempt to add arp_entry to hash */
665 ret = add_arp_data(&arp_key, ret_arp_data);
668 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
669 rte_free(ret_arp_data);
670 /* Some other thread has 'beat' this thread in
671 creation of arp_data, try again */
675 if (rte_mempool_get(timer_mempool_arp,
676 (void **) &(ret_arp_data->timer) ) < 0) {
677 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
678 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
682 ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
683 NULL, sizeof(struct rte_mbuf *) * arp_buffer,
684 RTE_CACHE_LINE_SIZE, rte_socket_id());
686 if (ret_arp_data->buf_pkts == NULL) {
687 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
688 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
692 rte_timer_init(ret_arp_data->timer);
693 struct arp_timer_key * callback_key =
694 (struct arp_timer_key*) rte_malloc(NULL,
695 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
696 callback_key->port_id = arp_key.port_id;
697 callback_key->ip = arp_key.ip;
699 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
701 if(rte_timer_reset(ret_arp_data->timer,
702 (PROBE_TIME * rte_get_tsc_hz() / 1000),
707 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
709 ret_arp_data->timer_key = callback_key;
711 /* send arp request */
712 request_arp(arp_key.port_id, arp_key.ip);
713 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
716 ret_arp_data->mode == DYNAMIC_ARP && ret_arp_data->status == STALE) {
717 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
718 ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
719 ret_arp_data->status = PROBE;
720 struct arp_timer_key * callback_key =
721 (struct arp_timer_key*) rte_malloc(NULL,
722 sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
723 callback_key->port_id = arp_key.port_id;
724 callback_key->ip = arp_key.ip;
726 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u"
727 " seconds\n",ARP_TIMER_EXPIRY);
728 if(rte_timer_reset(ret_arp_data->timer,
729 (arp_timeout * rte_get_tsc_hz()),
734 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
736 ret_arp_data->timer_key = callback_key;
738 /* send arp request */
739 request_arp(arp_key.port_id, arp_key.ip);
740 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
748 struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
750 struct nd_entry_data *ret_nd_data = NULL;
751 l2_phy_interface_t *port;
757 /*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
758 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
759 (void **)&ret_nd_data);
760 if (ret < 0 && (mode == DYNAMIC_ND)) {
762 RTE_LOG(INFO, LIBARP, "ND entry not found for ip \n");
764 /* add INCOMPLETE arp entry */
765 ret_nd_data = rte_malloc_socket(NULL, sizeof(struct nd_entry_data),
766 RTE_CACHE_LINE_SIZE, rte_socket_id());
767 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
768 ret_nd_data->status = INCOMPLETE;
769 ret_nd_data->port = nd_key.port_id;
771 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
772 ret_nd_data->ipv6[i] = nd_key.ipv6[i];
773 ret_nd_data->mode = mode;
774 ret_nd_data->num_pkts = 0;
775 rte_rwlock_init(&ret_nd_data->queue_lock);
776 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
778 /* attempt to add arp_entry to hash */
779 ret = add_nd_data(&nd_key, ret_nd_data);
782 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
783 rte_free(ret_nd_data);
784 /* Some other thread has 'beat' this thread in
785 creation of arp_data, try again */
790 if (rte_mempool_get(timer_mempool_arp,
791 (void **) &(ret_nd_data->timer) ) < 0) {
792 RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
793 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
797 ret_nd_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
798 NULL, sizeof(struct rte_mbuf *) * nd_buffer,
799 RTE_CACHE_LINE_SIZE, rte_socket_id());
801 if (ret_nd_data->buf_pkts == NULL) {
802 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
803 RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
807 rte_timer_init(ret_nd_data->timer);
808 struct nd_timer_key * callback_key =
809 (struct nd_timer_key*) rte_malloc(NULL,
810 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
811 callback_key->port_id = nd_key.port_id;
812 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
813 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
817 RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
821 if(rte_timer_reset(ret_nd_data->timer,
822 (PROBE_TIME * rte_get_tsc_hz() / 1000),
827 RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
829 ret_nd_data->timer_key = callback_key;
830 /* send nd request */
831 port = ifm_get_port(callback_key->port_id);
833 printf("port returned is NULL inside retrieve_nd_entry\n");
834 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
838 request_nd(callback_key->ipv6, port);
839 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
842 ret_nd_data->mode == DYNAMIC_ND && ret_nd_data->status == STALE) {
843 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
844 ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
845 ret_nd_data->status = PROBE;
846 struct nd_timer_key * callback_key =
847 (struct nd_timer_key*) rte_malloc(NULL,
848 sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
850 callback_key->port_id = nd_key.port_id;
851 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
852 callback_key->ipv6[i] = ret_nd_data->ipv6[i];
857 (arp_timeout * rte_get_tsc_hz()), SINGLE,
858 timer_lcore, nd_timer_callback, callback_key) < 0)
860 RTE_LOG(INFO, LIBARP,
861 "Err : Timer already running\n");
862 ret_nd_data->timer_key = callback_key;
864 /* send nd request */
865 port = ifm_get_port(callback_key->port_id);
867 printf("port returned is NULL inside retrieve_nd_entry\n");
868 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
872 request_nd(callback_key->ipv6, port);
873 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
879 static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
881 void print_arp_table(void)
883 const void *next_key;
887 printf ("------------------------ ARP CACHE -----------------------------------------\n");
888 printf ("----------------------------------------------------------------------------\n");
889 printf("\tport hw addr status ip addr\n");
890 printf ("----------------------------------------------------------------------------\n");
892 while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
895 struct arp_entry_data *tmp_arp_data =
896 (struct arp_entry_data *)next_data;
897 struct arp_key_ipv4 tmp_arp_key;
898 memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
899 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
901 tmp_arp_data->eth_addr.addr_bytes[0],
902 tmp_arp_data->eth_addr.addr_bytes[1],
903 tmp_arp_data->eth_addr.addr_bytes[2],
904 tmp_arp_data->eth_addr.addr_bytes[3],
905 tmp_arp_data->eth_addr.addr_bytes[4],
906 tmp_arp_data->eth_addr.addr_bytes[5],
907 arp_status[tmp_arp_data->status],
908 (tmp_arp_data->ip >> 24),
909 ((tmp_arp_data->ip & 0x00ff0000) >> 16),
910 ((tmp_arp_data->ip & 0x0000ff00) >> 8),
911 ((tmp_arp_data->ip & 0x000000ff)));
917 printf("\nARP routing table...\n");
918 printf("\nIP_Address \t Mask \t\t Port\n");
919 for (j = 0; j < gw_get_num_ports(); j++) {
920 for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) {
921 printf("0x%08x \t 0x%08x \t %d\n",
922 p_route_data[j]->route_table[i].nh,
923 p_route_data[j]->route_table[i].mask,
924 p_route_data[j]->route_table[i].port);
927 printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, "
928 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
929 lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
930 lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
931 lib_arp_populate_called, lib_arp_delete_called,
932 lib_arp_duplicate_found);
934 printf("ARP table key len is %d\n", (uint32_t) sizeof(struct arp_key_ipv4));
938 void print_nd_table(void)
940 const void *next_key;
943 uint8_t ii = 0, k = 0;
945 ("------------------------------------------------------------------------------------------------------\n");
946 printf("\tport hw addr status ip addr\n");
949 ("------------------------------------------------------------------------------------------------------\n");
950 while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
953 struct nd_entry_data *tmp_nd_data =
954 (struct nd_entry_data *)next_data;
955 struct nd_key_ipv6 tmp_nd_key;
956 memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6));
957 printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s",
959 tmp_nd_data->eth_addr.addr_bytes[0],
960 tmp_nd_data->eth_addr.addr_bytes[1],
961 tmp_nd_data->eth_addr.addr_bytes[2],
962 tmp_nd_data->eth_addr.addr_bytes[3],
963 tmp_nd_data->eth_addr.addr_bytes[4],
964 tmp_nd_data->eth_addr.addr_bytes[5],
965 arp_status[tmp_nd_data->status]);
967 for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
968 printf("%02X%02X ", tmp_nd_data->ipv6[ii],
969 tmp_nd_data->ipv6[ii + 1]);
974 uint32_t i = 0, p = 0;
975 printf("\n\nND IPV6 routing table ...\n");
976 printf ("\nNH_IP_Address Depth Port \n");
977 for(p = 0; p < gw_get_num_ports(); p++ ) {
978 for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) {
981 for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) {
982 printf("%02X%02X ", p_nd_route_data[p]->nd_route_table[i].nhipv6[k],
983 p_nd_route_data[p]->nd_route_table[i].nhipv6[k + 1]);
987 p_nd_route_data[p]->nd_route_table[i].depth,
988 p_nd_route_data[p]->nd_route_table[i].port);
991 printf ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, "
992 "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
993 lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
994 lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
995 lib_nd_populate_called, lib_nd_delete_called,
996 lib_nd_duplicate_found);
997 printf("ND table key len is %d\n\n", (uint32_t) sizeof(struct nd_key_ipv6));
1000 void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
1003 struct arp_timer_key *arp_key = (struct arp_timer_key *)arg;
1004 lib_arp_delete_called++;
1006 if (ret_arp_data->timer) {
1007 rte_timer_stop(ret_arp_data->timer);
1008 rte_free(ret_arp_data->timer_key);
1009 rte_free(ret_arp_data->buf_pkts);
1010 ret_arp_data->buf_pkts = NULL;
1013 if (ARPICMP_DEBUG) {
1014 RTE_LOG(INFO, LIBARP,
1015 "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
1016 (arp_key->ip >> 24),
1017 ((arp_key->ip & 0x00ff0000) >> 16),
1018 ((arp_key->ip & 0x0000ff00) >> 8),
1019 ((arp_key->ip & 0x000000ff)),
1022 rte_hash_del_key(arp_hash_handle, arp_key);
1027 void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg)
1030 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
1032 lib_nd_delete_called++;
1034 rte_timer_stop(ret_nd_data->timer);
1035 rte_free(ret_nd_data->timer_key);
1036 rte_free(ret_nd_data->buf_pkts);
1037 ret_nd_data->buf_pkts = NULL;
1040 RTE_LOG(INFO, LIBARP,
1041 "Deletes rte hash table nd entry for port %d ipv6=",
1042 timer_key->port_id);
1043 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1044 RTE_LOG(INFO, LIBARP, "%02X%02X ", timer_key->ipv6[i],
1045 timer_key->ipv6[i + 1]);
1048 rte_hash_del_key(nd_hash_handle, timer_key);
1052 arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
1054 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1055 if (ret_arp_data->num_pkts == NUM_DESC) {
1056 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1060 ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
1061 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1066 arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
1067 struct ether_addr *hw_addr, uint8_t port_id)
1069 l2_phy_interface_t *port = ifm_get_port(port_id);
1070 struct rte_mbuf *pkt, *tmp;
1071 uint8_t *eth_dest, *eth_src;
1075 if (!hw_addr || !ret_arp_data || !port)
1078 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
1079 for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
1080 pkt = ret_arp_data->buf_pkts[i];
1082 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1083 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1085 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1086 memcpy(eth_src, get_link_hw_addr(port_id),
1087 sizeof(struct ether_addr));
1088 port->transmit_single_pkt(port, pkt);
1090 rte_pktmbuf_free(tmp);
1092 printf("arp send buffered pkts = %d\n",ret_arp_data->num_pkts);
1093 ret_arp_data->num_pkts = 0;
1094 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
1098 nd_queue_unresolved_packet(struct nd_entry_data *ret_nd_data, struct rte_mbuf *pkt)
1100 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1101 if (ret_nd_data->num_pkts == get_nd_buf()) {
1102 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1106 ret_nd_data->buf_pkts[ret_nd_data->num_pkts++] = pkt;
1107 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1112 nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
1113 struct ether_addr *hw_addr, uint8_t port_id)
1115 l2_phy_interface_t *port = ifm_get_port(port_id);
1116 struct rte_mbuf *pkt, *tmp;
1117 uint8_t *eth_dest, *eth_src;
1120 if (!hw_addr || !ret_nd_data || !port)
1123 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
1124 for (i=0;i<(int)ret_nd_data->num_pkts;i++) {
1125 pkt = ret_nd_data->buf_pkts[i];
1126 eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
1127 eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
1129 memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
1130 memcpy(eth_src, get_link_hw_addr(port_id),
1131 sizeof(struct ether_addr));
1132 port->transmit_single_pkt(port, pkt);
1134 rte_pktmbuf_free(tmp);
1136 ret_nd_data->num_pkts = 0;
1137 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
1141 populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
1142 uint8_t portid, uint8_t mode)
1144 struct arp_key_ipv4 arp_key;
1145 struct arp_entry_data *new_arp_data;
1146 arp_key.port_id = portid;
1147 arp_key.ip = ipaddr;
1148 arp_key.filler1 = 0;
1149 arp_key.filler2 = 0;
1150 arp_key.filler3 = 0;
1152 lib_arp_populate_called++;
1153 printf("populate_arp_entry ip %x, port %d\n", arp_key.ip, arp_key.port_id);
1156 RTE_LOG(INFO, LIBARP, "populate_arp_entry ip %x, port %d\n",
1157 arp_key.ip, arp_key.port_id);
1159 new_arp_data = retrieve_arp_entry(arp_key, mode);
1160 if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
1161 && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
1162 && mode == STATIC_ARP))) {
1164 RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry "
1165 "already exists(%d %d)\n", new_arp_data->mode, mode);
1169 if (mode == DYNAMIC_ARP) {
1172 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1173 printf("entry exists\n");
1175 if (ARPICMP_DEBUG) {
1176 RTE_LOG(INFO, LIBARP,
1177 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1179 ((arp_key.ip & 0x00ff0000) >> 16),
1180 ((arp_key.ip & 0x0000ff00) >> 8),
1181 ((arp_key.ip & 0x000000ff)),
1184 lib_arp_duplicate_found++;
1185 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1186 new_arp_data->retry_count = 0; // Reset
1187 if (new_arp_data->status == STALE) {
1188 new_arp_data->status = PROBE;
1189 if (ifm_chk_port_ipv4_enabled
1190 (new_arp_data->port) != IFM_FAILURE) {
1191 request_arp(new_arp_data->port,
1195 RTE_LOG(INFO, LIBARP,
1196 "%s: IP is not enabled on port %u, not sending GARP\n\r",
1198 new_arp_data->port);
1202 if (rte_timer_reset(new_arp_data->timer,
1203 (arp_timeout * rte_get_tsc_hz()),
1204 SINGLE, timer_lcore,
1206 new_arp_data->timer_key) < 0) {
1208 RTE_LOG(INFO, LIBARP,
1209 "Err : Timer already running\n");
1211 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1214 rte_rwlock_write_lock(&new_arp_data->queue_lock);
1215 ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
1216 if (new_arp_data && ((new_arp_data->status == INCOMPLETE) ||
1217 (new_arp_data->status == PROBE))) {
1218 new_arp_data->status = COMPLETE;
1219 new_arp_data->mode = mode;
1220 new_arp_data->n_confirmed = rte_rdtsc();
1221 new_arp_data->retry_count = 0;
1222 if (rte_timer_reset(new_arp_data->timer,
1223 (arp_timeout * rte_get_tsc_hz()),
1224 SINGLE, timer_lcore,
1226 new_arp_data->timer_key) < 0) {
1228 RTE_LOG(INFO, LIBARP,
1229 "Err : Timer already running\n");
1232 rte_rwlock_write_unlock(&new_arp_data->queue_lock);
1237 && is_same_ether_addr(&new_arp_data->eth_addr, hw_addr)) {
1239 if (ARPICMP_DEBUG) {
1240 RTE_LOG(INFO, LIBARP,
1241 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1243 ((arp_key.ip & 0x00ff0000) >> 16),
1244 ((arp_key.ip & 0x0000ff00) >> 8),
1245 ((arp_key.ip & 0x000000ff)),
1248 lib_arp_duplicate_found++;
1251 RTE_CACHE_LINE_ROUNDUP(sizeof
1252 (struct arp_entry_data));
1254 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1255 new_arp_data->eth_addr = *hw_addr;
1256 new_arp_data->status = COMPLETE;
1257 new_arp_data->port = portid;
1258 new_arp_data->ip = ipaddr;
1259 new_arp_data->mode = mode;
1260 new_arp_data->num_pkts = 0;
1262 /* attempt to add arp_entry to hash */
1264 ret = add_arp_data(&arp_key, new_arp_data);
1266 /* Some other thread created an entry for this ip */
1267 rte_free(new_arp_data);
1270 if (ARPICMP_DEBUG) {
1271 RTE_LOG(INFO, LIBARP,
1272 "arp_entry exists ip :%d.%d.%d.%d , port %d\n",
1274 ((arp_key.ip & 0x00ff0000) >> 16),
1275 ((arp_key.ip & 0x0000ff00) >> 8),
1276 ((arp_key.ip & 0x000000ff)),
1279 #ifdef L3_STACK_SUPPORT
1280 // Call l3fwd module for resolving 2_adj structure.
1281 resolve_l2_adj(ipaddr, portid, hw_addr);
1286 if (ARPICMP_DEBUG) {
1287 /* print entire hash table */
1288 RTE_LOG(INFO, LIBARP,
1289 "\tARP: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x ip=%d.%d.%d.%d on port=%d\n",
1290 new_arp_data->eth_addr.addr_bytes[0],
1291 new_arp_data->eth_addr.addr_bytes[1],
1292 new_arp_data->eth_addr.addr_bytes[2],
1293 new_arp_data->eth_addr.addr_bytes[3],
1294 new_arp_data->eth_addr.addr_bytes[4],
1295 new_arp_data->eth_addr.addr_bytes[5],
1296 (arp_key.ip >> 24), ((arp_key.ip & 0x00ff0000) >> 16),
1297 ((arp_key.ip & 0x0000ff00) >> 8),
1298 ((arp_key.ip & 0x000000ff)), portid);
1306 * Install key - data pair in Hash table - From Pipeline Configuration
1309 void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
1310 uint8_t portid, uint8_t mode)
1313 /* need to lock here if multi-threaded */
1314 /* rte_hash_add_key_data is not thread safe */
1316 struct nd_key_ipv6 nd_key;
1317 nd_key.port_id = portid;
1318 l2_phy_interface_t *port;
1320 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1321 nd_key.ipv6[i] = ipv6[i];
1332 lib_nd_populate_called++;
1334 /* Validate if key-value pair already exists in the hash table for ND IPv6 */
1335 struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, mode);
1336 if (new_nd_data && ((new_nd_data->mode == STATIC_ND
1337 && mode == DYNAMIC_ND) || (new_nd_data->mode == DYNAMIC_ND
1338 && mode == STATIC_ND))) {
1340 RTE_LOG(INFO, LIBARP, "populate_arp_entry: ND entry already"
1341 " exists(%d %d)\n", new_nd_data->mode, mode);
1345 if (mode == DYNAMIC_ND) {
1347 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1350 RTE_LOG(INFO, LIBARP,
1351 "nd_entry exists port %d ipv6 = ",
1353 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1355 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1357 nd_key.ipv6[i + 1]);
1361 lib_nd_duplicate_found++;
1362 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1363 if (new_nd_data->status == STALE) {
1364 new_nd_data->retry_count = 0; // Reset
1365 new_nd_data->status = PROBE;
1366 port = ifm_get_port(new_nd_data->port);
1369 request_nd(new_nd_data->ipv6, port);
1371 if (rte_timer_reset(new_nd_data->timer,
1372 (arp_timeout * rte_get_tsc_hz()),
1373 SINGLE, timer_lcore,
1375 new_nd_data->timer_key) < 0) {
1377 RTE_LOG(INFO, LIBARP,
1378 "Err : Timer already running\n");
1381 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1384 rte_rwlock_write_lock(&new_nd_data->queue_lock);
1385 ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
1386 if (new_nd_data && ((new_nd_data->status == INCOMPLETE) ||
1387 (new_nd_data->status == PROBE))) {
1388 new_nd_data->status = COMPLETE;
1389 new_nd_data->mode = mode;
1390 new_nd_data->n_confirmed = rte_rdtsc();
1391 new_nd_data->retry_count = 0;
1392 if (rte_timer_reset(new_nd_data->timer,
1393 (arp_timeout * rte_get_tsc_hz()),
1394 SINGLE, timer_lcore,
1396 new_nd_data->timer_key) < 0) {
1398 RTE_LOG(INFO, LIBARP,
1399 "Err : Timer already running\n");
1402 rte_rwlock_write_unlock(&new_nd_data->queue_lock);
1408 && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
1410 RTE_LOG(INFO, LIBARP,
1411 "nd_entry exists port %d ipv6 = ",
1413 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1415 RTE_LOG(INFO, LIBARP, "%02X%02X ",
1417 nd_key.ipv6[i + 1]);
1421 lib_nd_duplicate_found++;
1424 RTE_CACHE_LINE_ROUNDUP(sizeof
1425 (struct nd_entry_data));
1427 rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
1429 new_nd_data->eth_addr = *hw_addr;
1430 new_nd_data->status = COMPLETE;
1431 new_nd_data->port = portid;
1432 new_nd_data->mode = mode;
1433 for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
1434 new_nd_data->ipv6[i] = ipv6[i];
1436 new_nd_data->mode = mode;
1437 new_nd_data->num_pkts = 0;
1439 /*Add a key-data pair at hash table for ND IPv6 static routing */
1440 /* attempt to add arp_entry to hash */
1442 ret = add_nd_data(&nd_key, new_nd_data);
1444 rte_free(new_nd_data);
1447 /* need to check the return value of the hash add */
1448 #ifdef L3_STACK_SUPPORT
1449 // Call l3fwd module for resolving 2_adj structure.
1450 resolve_l2_adj(ipaddr, portid, hw_addr);
1457 ("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
1460 /* print entire hash table */
1462 ("\tND: table update - hwaddr=%02x:%02x:%02x:%02x:%02x:%02x on port=%d\n",
1463 new_nd_data->eth_addr.addr_bytes[0],
1464 new_nd_data->eth_addr.addr_bytes[1],
1465 new_nd_data->eth_addr.addr_bytes[2],
1466 new_nd_data->eth_addr.addr_bytes[3],
1467 new_nd_data->eth_addr.addr_bytes[4],
1468 new_nd_data->eth_addr.addr_bytes[5], portid);
1469 RTE_LOG(INFO, LIBARP, "\tipv6=");
1470 for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
1471 new_nd_data->ipv6[i] = ipv6[i];
1472 RTE_LOG(INFO, LIBARP, "%02X%02X ", new_nd_data->ipv6[i],
1473 new_nd_data->ipv6[i + 1]);
1476 RTE_LOG(INFO, LIBARP, "\n");
1482 void print_pkt1(struct rte_mbuf *pkt)
1484 uint8_t *rd = RTE_MBUF_METADATA_UINT8_PTR(pkt, 0);
1486 RTE_LOG(INFO, LIBARP, "\nPacket Contents...\n");
1487 for (i = 0; i < 20; i++) {
1488 for (j = 0; j < 20; j++)
1489 printf("%02x ", rd[(20 * i) + j]);
1490 RTE_LOG(INFO, LIBARP, "\n");
1494 #define MAX_NUM_MAC_ADDRESS 16
1495 struct ether_addr link_hw_addr[MAX_NUM_MAC_ADDRESS] = {
1496 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc8} },
1497 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1498 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1499 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1500 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1501 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1502 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
1503 {.addr_bytes = {0x90, 0xe2, 0xba, 0x54, 0x67, 0xc9} },
1504 {.addr_bytes = {0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11} },
1505 {.addr_bytes = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17} },
1506 {.addr_bytes = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77} },
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 = {0x18, 0x19, 0x1a, 0x1b, 0xcd, 0xef} }
1514 struct ether_addr *get_link_hw_addr(uint8_t out_port)
1516 return &p_arp_data->link_hw_addr[out_port];
1519 void request_arp(uint8_t port_id, uint32_t ip)
1522 struct ether_hdr *eth_h;
1523 struct arp_hdr *arp_h;
1525 l2_phy_interface_t *link;
1526 link = ifm_get_port(port_id);
1527 struct rte_mbuf *arp_pkt = lib_arp_pkt[port_id];
1529 if (arp_pkt == NULL) {
1531 RTE_LOG(INFO, LIBARP,
1532 "Error allocating arp_pkt rte_mbuf\n");
1535 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
1537 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
1538 ether_addr_copy((struct ether_addr *)
1539 &link->macaddr[0], ð_h->s_addr);
1540 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
1542 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1543 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
1544 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
1545 arp_h->arp_hln = ETHER_ADDR_LEN;
1546 arp_h->arp_pln = sizeof(uint32_t);
1547 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
1549 if (link && link->ipv4_list) {
1550 arp_h->arp_data.arp_sip =
1551 (((ipv4list_t *) (link->ipv4_list))->ipaddr);
1553 ether_addr_copy((struct ether_addr *)
1554 &link->macaddr[0], &arp_h->arp_data.arp_sha);
1555 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
1556 arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
1558 RTE_LOG(INFO, LIBARP, "arp tip:%x arp sip :%x\n",
1559 arp_h->arp_data.arp_tip, arp_h->arp_data.arp_sip);
1560 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
1561 arp_pkt->pkt_len = 42;
1562 arp_pkt->data_len = 42;
1564 if (ARPICMP_DEBUG) {
1565 RTE_LOG(INFO, LIBARP, "Sending arp request\n");
1566 print_mbuf("TX", port_id, arp_pkt, __LINE__);
1569 link->transmit_single_pkt(link, arp_pkt);
1570 // start_tsc[port_id] = rte_rdtsc();
1571 printf("Sent ARP Request %x \n", arp_h->arp_data.arp_tip);
1574 struct rte_mbuf *request_echo(uint32_t port_id, uint32_t ip)
1576 struct ether_hdr *eth_h;
1577 struct ipv4_hdr *ip_h;
1578 struct icmp_hdr *icmp_h;
1579 l2_phy_interface_t *port = ifm_get_port(port_id);
1581 struct rte_mbuf *icmp_pkt = lib_arp_pkt[port_id];
1582 if (icmp_pkt == NULL) {
1584 RTE_LOG(INFO, LIBARP,
1585 "Error allocating icmp_pkt rte_mbuf\n");
1589 eth_h = rte_pktmbuf_mtod(icmp_pkt, struct ether_hdr *);
1591 ip_h = (struct ipv4_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
1592 icmp_h = (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1594 ip_h->version_ihl = IP_VHL_DEF;
1595 ip_h->type_of_service = 0;
1596 ip_h->total_length =
1597 rte_cpu_to_be_16(sizeof(struct ipv4_hdr) + sizeof(struct icmp_hdr));
1598 ip_h->packet_id = 0xaabb;
1599 ip_h->fragment_offset = 0x0000;
1600 ip_h->time_to_live = 64;
1601 ip_h->next_proto_id = IPPROTO_ICMP;
1602 if (port && port->ipv4_list)
1604 rte_cpu_to_be_32(((ipv4list_t *) port->ipv4_list)->ipaddr);
1605 ip_h->dst_addr = rte_cpu_to_be_32(ip);
1607 ip_h->hdr_checksum = 0;
1608 ip_h->hdr_checksum = rte_ipv4_cksum(ip_h);
1610 icmp_h->icmp_type = IP_ICMP_ECHO_REQUEST;
1611 icmp_h->icmp_code = 0;
1612 icmp_h->icmp_ident = 0xdead;
1613 icmp_h->icmp_seq_nb = 0xbeef;
1615 icmp_h->icmp_cksum = ~rte_raw_cksum(icmp_h, sizeof(struct icmp_hdr));
1618 sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
1619 sizeof(struct icmp_hdr);
1620 icmp_pkt->data_len = icmp_pkt->pkt_len;
1622 print_mbuf("TX", 0, icmp_pkt, __LINE__);
1628 process_arpicmp_pkt_parse(struct rte_mbuf **pkt, uint16_t pkt_num,
1629 uint64_t pkt_mask, l2_phy_interface_t *port)
1631 RTE_SET_USED(pkt_num);
1633 RTE_LOG(INFO, LIBARP,
1634 "============ARP ENTRY================\n");
1637 RTE_LOG(INFO, LIBARP,
1638 "============ARP PROCESS================\n");
1641 uint64_t pkts_for_process = pkt_mask;
1642 for (; pkts_for_process;) {
1643 /**< process only valid packets. */
1644 uint8_t pos = (uint8_t) __builtin_ctzll(pkts_for_process);
1645 uint64_t pkts_mask = 1LLU << pos; /** <bitmask representing only this packet. */
1646 pkts_for_process &= ~pkts_mask; /** <remove this packet from the mask. */
1647 process_arpicmp_pkt(pkt[pos], port);
1652 void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
1654 uint8_t in_port_id = pkt->port;
1655 struct ether_hdr *eth_h;
1656 struct arp_hdr *arp_h;
1657 struct ipv4_hdr *ip_h;
1658 struct icmp_hdr *icmp_h;
1664 eth_h = rte_pktmbuf_mtod(pkt, struct ether_hdr *);
1666 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_ARP)) {
1668 RTE_LOG(INFO, LIBARP, "%s, portid %u. Line %d\n\r",
1669 __FUNCTION__, port->pmdid, __LINE__);
1671 (struct arp_hdr *)((char *)eth_h +
1672 sizeof(struct ether_hdr));
1673 if (CHECK_ENDIAN_16(arp_h->arp_hrd) != ARP_HRD_ETHER)
1674 RTE_LOG(INFO, LIBARP,
1675 "Invalid hardware format of hardware address - not processing ARP req\n");
1676 else if (CHECK_ENDIAN_16(arp_h->arp_pro) != ETHER_TYPE_IPv4)
1677 RTE_LOG(INFO, LIBARP,
1678 "Invalid protocol address format - not processing ARP req\n");
1679 else if (arp_h->arp_hln != 6)
1680 RTE_LOG(INFO, LIBARP,
1681 "Invalid hardware address length - not processing ARP req\n");
1682 else if (arp_h->arp_pln != 4)
1683 RTE_LOG(INFO, LIBARP,
1684 "Invalid protocol address length - not processing ARP req\n");
1686 if (port->ipv4_list == NULL) {
1687 RTE_LOG(INFO, LIBARP,
1688 "Ports IPV4 List is NULL.. Unable to Process\n");
1692 if (arp_h->arp_data.arp_tip !=
1693 ((ipv4list_t *) (port->ipv4_list))->ipaddr) {
1694 if (arp_h->arp_data.arp_tip == arp_h->arp_data.arp_sip) {
1695 printf("gratuitous arp received\n");
1697 (struct ether_addr *)&arp_h->arp_data.arp_sha,
1698 rte_cpu_to_be_32(arp_h->arp_data.arp_sip),
1704 RTE_LOG(INFO, LIBARP,"ARP requested IP address mismatches interface IP - discarding\n");
1707 /// revise conditionals to allow processing of requests with target ip = this ip and
1708 // processing of replies to destination ip = this ip
1709 else if (arp_h->arp_op ==
1710 rte_cpu_to_be_16(ARP_OP_REQUEST)) {
1711 if (ARPICMP_DEBUG) {
1712 RTE_LOG(INFO, LIBARP,
1713 "%s, portid %u. Line %d\n\r",
1714 __FUNCTION__, port->pmdid,
1717 RTE_LOG(INFO, LIBARP,
1718 "arp_op %d, ARP_OP_REQUEST %d\n",
1722 print_mbuf("RX", in_port_id, pkt,
1725 populate_arp_entry((struct ether_addr *)
1726 &arp_h->arp_data.arp_sha,
1728 (arp_h->arp_data.arp_sip),
1729 in_port_id, DYNAMIC_ARP);
1732 req_tip = arp_h->arp_data.arp_tip;
1733 ether_addr_copy(ð_h->s_addr, ð_h->d_addr);
1734 ether_addr_copy((struct ether_addr *)&port->macaddr[0], ð_h->s_addr); /**< set sender mac address*/
1735 arp_h->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY);
1736 ether_addr_copy(ð_h->s_addr,
1737 &arp_h->arp_data.arp_sha);
1738 arp_h->arp_data.arp_tip =
1739 arp_h->arp_data.arp_sip;
1740 arp_h->arp_data.arp_sip = req_tip;
1741 ether_addr_copy(ð_h->d_addr,
1742 &arp_h->arp_data.arp_tha);
1744 print_mbuf("TX ARP REPLY PKT",
1745 port->pmdid, pkt, __LINE__);
1746 port->transmit_bulk_pkts(port, &pkt, 1);
1748 print_mbuf("TX", port->pmdid, pkt,
1750 printf("replying arp pkt done\n");
1752 } else if (arp_h->arp_op ==
1753 rte_cpu_to_be_16(ARP_OP_REPLY)) {
1754 if (ARPICMP_DEBUG) {
1755 RTE_LOG(INFO, LIBARP,
1756 "ARP_OP_REPLY received");
1757 print_mbuf("RX", port->pmdid, pkt,
1760 populate_arp_entry((struct ether_addr *)
1761 &arp_h->arp_data.arp_sha,
1764 in_port_id, DYNAMIC_ARP);
1769 RTE_LOG(INFO, LIBARP,
1770 "Invalid ARP opcode - not processing ARP req %x\n",
1775 rte_pktmbuf_free(pkt);
1778 (struct ipv4_hdr *)((char *)eth_h +
1779 sizeof(struct ether_hdr));
1781 (struct icmp_hdr *)((char *)ip_h + sizeof(struct ipv4_hdr));
1783 if (eth_h->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
1785 if (ip_h->next_proto_id != IPPROTO_ICMP) {
1786 if (ARPICMP_DEBUG) {
1787 RTE_LOG(INFO, LIBARP,
1788 "IP protocol ID is not set to ICMP - discarding\n");
1790 } else if ((ip_h->version_ihl & 0xf0) != IP_VERSION_4) {
1791 if (ARPICMP_DEBUG) {
1792 RTE_LOG(INFO, LIBARP,
1793 "IP version other than 4 - discarding\n");
1795 } else if ((ip_h->version_ihl & 0x0f) != IP_HDRLEN) {
1796 if (ARPICMP_DEBUG) {
1797 RTE_LOG(INFO, LIBARP,
1798 "Unknown IHL - discarding\n");
1801 if (icmp_h->icmp_type == IP_ICMP_ECHO_REQUEST
1802 && icmp_h->icmp_code == 0) {
1804 print_mbuf("RX", in_port_id,
1807 ip_addr = ip_h->src_addr;
1808 ether_addr_copy(ð_h->s_addr,
1810 ether_addr_copy((struct ether_addr *)
1814 RTE_LOG(INFO, LIBARP,
1815 "%s, portid %u. Line %d\n\r",
1817 port->pmdid, __LINE__);
1819 if (is_multicast_ipv4_addr
1824 rte_be_to_cpu_32(ip_addr);
1825 if ((ip_src & 0x00000003) == 1)
1836 rte_cpu_to_be_32(ip_src);
1837 ip_h->dst_addr = ip_addr;
1839 ip_h->hdr_checksum = 0;
1840 ip_h->hdr_checksum =
1841 ~rte_raw_cksum(ip_h,
1846 RTE_LOG(INFO, LIBARP,
1847 "%s, portid %u. Line %d\n\r",
1851 ip_h->src_addr = ip_h->dst_addr;
1852 ip_h->dst_addr = ip_addr;
1855 icmp_h->icmp_type = IP_ICMP_ECHO_REPLY;
1856 cksum = ~icmp_h->icmp_cksum & 0xffff;
1858 ~htons(IP_ICMP_ECHO_REQUEST << 8) &
1860 cksum += htons(IP_ICMP_ECHO_REPLY << 8);
1862 (cksum & 0xffff) + (cksum >> 16);
1864 (cksum & 0xffff) + (cksum >> 16);
1865 icmp_h->icmp_cksum = ~cksum;
1869 ("TX ICMP ECHO REPLY PKT",
1870 in_port_id, pkt, __LINE__);
1871 port->transmit_bulk_pkts(port, &pkt, 1);
1873 print_mbuf("TX", port->pmdid,
1877 } else if (icmp_h->icmp_type ==
1879 && icmp_h->icmp_code == 0) {
1881 print_mbuf("RX", in_port_id,
1884 struct arp_key_ipv4 arp_key;
1885 arp_key.port_id = in_port_id;
1887 rte_bswap32(ip_h->src_addr);
1888 arp_key.filler1 = 0;
1889 arp_key.filler2 = 0;
1890 arp_key.filler3 = 0;
1892 struct arp_entry_data *arp_entry =
1893 retrieve_arp_entry(arp_key,
1895 if (arp_entry == NULL) {
1897 RTE_LOG(INFO, LIBARP,
1898 "Received unsolicited ICMP echo reply from ip%x, port %d\n",
1903 arp_entry->status = COMPLETE;
1908 rte_pktmbuf_free(pkt);
1913 * inet_pton(af, src, dst)
1914 * convert from presentation format (which usually means ASCII printable)
1915 * to network format (which is usually some kind of binary format).
1917 * 1 if the address was valid for the specified address family
1918 * 0 if the address wasn't valid (`dst' is untouched in this case)
1919 * -1 if some other error occurred (`dst' is untouched in this case, too)
1923 int my_inet_pton_ipv6(int af, const char *src, void *dst)
1927 return inet_pton_ipv4(src, dst);
1929 return inet_pton_ipv6(src, dst);
1931 errno = EAFNOSUPPORT;
1938 * inet_pton_ipv4(src, dst)
1939 * like inet_aton() but without all the hexadecimal and shorthand.
1941 * 1 if `src' is a valid dotted quad, else 0.
1943 * does not touch `dst' unless it's returning 1.
1947 static int inet_pton_ipv4(const char *src, unsigned char *dst)
1949 static const char digits[] = "0123456789";
1950 int saw_digit, octets, ch;
1951 unsigned char tmp[INADDRSZ], *tp;
1956 while ((ch = *src++) != '\0') {
1959 pch = strchr(digits, ch);
1961 unsigned int new = *tp * 10 + (pch - digits);
1970 *tp = (unsigned char)new;
1971 } else if (ch == '.' && saw_digit) {
1982 memcpy(dst, tmp, INADDRSZ);
1987 * inet_pton_ipv6(src, dst)
1988 * convert presentation level address to network order binary form.
1990 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1992 * (1) does not touch `dst' unless it's returning 1.
1993 * (2) :: in a full address is silently ignored.
1995 * inspired by Mark Andrews.
1999 static int inet_pton_ipv6(const char *src, unsigned char *dst)
2001 static const char xdigits_l[] = "0123456789abcdef",
2002 xdigits_u[] = "0123456789ABCDEF";
2003 unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2004 const char *xdigits = 0, *curtok = 0;
2005 int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2006 unsigned int val = 0;
2007 unsigned int dbloct_count = 0;
2009 memset((tp = tmp), '\0', IN6ADDRSZ);
2010 endp = tp + IN6ADDRSZ;
2012 /* Leading :: requires some special handling. */
2017 saw_xdigit = count_xdigit = 0;
2020 while ((ch = *src++) != '\0') {
2023 pch = strchr((xdigits = xdigits_l), ch);
2025 pch = strchr((xdigits = xdigits_u), ch);
2027 if (count_xdigit >= 4)
2030 val |= (pch - xdigits);
2044 } else if (*src == '\0') {
2047 if (tp + sizeof(int16_t) > endp)
2049 *tp++ = (unsigned char)((val >> 8) & 0xff);
2050 *tp++ = (unsigned char)(val & 0xff);
2057 if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2058 inet_pton_ipv4(curtok, tp) > 0) {
2062 break; /* '\0' was seen by inet_pton4(). */
2067 if (tp + sizeof(int16_t) > endp)
2069 *tp++ = (unsigned char)((val >> 8) & 0xff);
2070 *tp++ = (unsigned char)(val & 0xff);
2073 if (colonp != NULL) {
2074 /* if we already have 8 double octets, having a colon means error */
2075 if (dbloct_count == 8)
2079 * Since some memmove()'s erroneously fail to handle
2080 * overlapping regions, we'll do the shift by hand.
2082 const int n = tp - colonp;
2085 for (i = 1; i <= n; i++) {
2086 endp[-i] = colonp[n - i];
2093 memcpy(dst, tmp, IN6ADDRSZ);
2097 static int arp_parse_args(struct pipeline_params *params)
2099 uint32_t arp_route_tbl_present = 0;
2100 uint32_t nd_route_tbl_present = 0;
2102 uint32_t n_vnf_threads_present = 0;
2104 uint32_t pktq_in_prv_present = 0;
2105 uint32_t prv_to_pub_map_present = 0;
2107 uint8_t n_prv_in_port = 0;
2109 for (i = 0; i < PIPELINE_MAX_PORT_IN; i++) {
2110 in_port_dir_a[i] = 0; //make all RX ports ingress initially
2111 prv_to_pub_map[i] = 0xff;
2112 pub_to_prv_map[i] = 0xff;
2115 RTE_SET_USED(nd_route_tbl_present);
2116 RTE_SET_USED(arp_route_tbl_present);
2117 for (numArg = 0; numArg < params->n_args; numArg++) {
2119 char *arg_name = params->args_name[numArg];
2120 char *arg_value = params->args_value[numArg];
2122 /* arp timer expiry */
2123 if (strcmp(arg_name, "arp_timer_expiry") == 0) {
2124 arp_timeout = atoi(arg_value);
2128 if (strcmp(arg_name, "pktq_in_prv") == 0) {
2129 if (pktq_in_prv_present) {
2131 ("Duplicate pktq_in_prv ... parse failed..\n\n");
2134 pktq_in_prv_present = 1;
2136 int rxport = 0, j = 0;
2137 char phy_port_num[5];
2138 char *token = strtok(arg_value, "RXQ");
2141 while ((j < 4) && (token[j] != '.')) {
2142 phy_port_num[j] = token[j];
2145 phy_port_num[j] = '\0';
2146 rxport = atoi(phy_port_num);
2147 prv_in_port_a[n_prv_in_port++] = rxport;
2151 ("token: %s, phy_port_str: %s, phy_port_num %d\n",
2152 token, phy_port_num, rxport);
2153 prv_in_port_a[n_prv_in_port++] = rxport;
2154 if(rxport < PIPELINE_MAX_PORT_IN)
2155 in_port_dir_a[rxport] = 1; // set rxport egress
2156 token = strtok(NULL, "RXQ");
2159 if (n_prv_in_port == 0) {
2161 ("VNF common parse error - no prv RX phy port\n");
2167 if (strcmp(arg_name, "arp_buf") == 0) {
2168 arp_buffer = atoi(arg_value);
2172 if (strcmp(arg_name, "nd_buf") == 0) {
2173 nd_buffer = atoi(arg_value);
2177 /* prv_to_pub_map */
2178 if (strcmp(arg_name, "prv_to_pub_map") == 0) {
2179 if (prv_to_pub_map_present) {
2181 ("Duplicated prv_to_pub_map ... parse failed ...\n");
2184 prv_to_pub_map_present = 1;
2186 int rxport = 0, txport = 0, j = 0, k = 0;
2187 char rx_phy_port_num[5];
2188 char tx_phy_port_num[5];
2189 char *token = strtok(arg_value, "(");
2192 while ((j < 4) && (token[j] != ',')) {
2193 rx_phy_port_num[j] = token[j];
2196 rx_phy_port_num[j] = '\0';
2197 rxport = atoi(rx_phy_port_num);
2203 while ((k < 4) && (token[j + k] != ')')) {
2204 tx_phy_port_num[k] = token[j + k];
2207 tx_phy_port_num[k] = '\0';
2208 txport = atoi(tx_phy_port_num);
2212 RTE_LOG(INFO, LIBARP, "token: %s,"
2213 "rx_phy_port_str: %s, phy_port_num %d,"
2214 "tx_phy_port_str: %s, tx_phy_port_num %d\n",
2215 token, rx_phy_port_num, rxport,
2216 tx_phy_port_num, txport);
2218 if ((rxport >= PIPELINE_MAX_PORT_IN) ||
2219 (txport >= PIPELINE_MAX_PORT_IN)) {
2221 ("CG-NAPT parse error - incorrect prv-pub translation. Rx %d, Tx %d\n",
2226 if (in_port_dir_a[rxport] != 1) {
2227 printf("CG-NAPT parse error - incorrect rx_port supplied\n");
2231 prv_to_pub_map[rxport] = txport;
2232 pub_to_prv_map[txport] = rxport;
2233 token = strtok(NULL, "(");
2239 if (strcmp(arg_name, "n_vnf_threads") == 0) {
2240 if (n_vnf_threads_present)
2242 n_vnf_threads_present = 1;
2244 num_vnf_threads = atoi(arg_value);
2245 if (num_vnf_threads <= 0) {
2246 RTE_LOG(INFO, LIBARP,
2247 "n_vnf_threads is invalid\n");
2250 RTE_LOG(INFO, LIBARP, "n_vnf_threads: 0x%x\n",
2255 if (strcmp(arg_name, "lib_arp_debug") == 0) {
2256 ARPICMP_DEBUG = atoi(arg_value);
2262 if (strcmp(arg_name, "arp_route_tbl") == 0) {
2263 arp_route_tbl_present = 1;
2264 uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip = 0,
2265 i = 0, j = 0, k = 0, l = 0;
2266 uint32_t arp_route_tbl_str_max_len = 10;
2267 char dest_ip_str[arp_route_tbl_str_max_len];
2268 char mask_str[arp_route_tbl_str_max_len];
2269 char tx_port_str[arp_route_tbl_str_max_len];
2270 char nh_ip_str[arp_route_tbl_str_max_len];
2271 char *token = strtok(arg_value, "(");
2274 while ((i < (arp_route_tbl_str_max_len - 1))
2275 && (token[i] != ',')) {
2276 dest_ip_str[i] = token[i];
2279 dest_ip_str[i] = '\0';
2280 dest_ip = strtoul(dest_ip_str, NULL, 16);
2284 while ((j < (arp_route_tbl_str_max_len - 1))
2285 && (token[i + j] != ',')) {
2286 mask_str[j] = token[i + j];
2290 mask = strtoul(mask_str, NULL, 16);
2294 while ((k < (arp_route_tbl_str_max_len - 1))
2295 && (token[i + j + k] != ',')) {
2296 tx_port_str[k] = token[i + j + k];
2299 tx_port_str[k] = '\0';
2300 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2301 if (tx_port > MAX_ROUTE_ENTRY_SIZE) {
2302 printf("tx_port is greater than route entry max size\n");
2308 while ((l < (arp_route_tbl_str_max_len - 1))
2309 && (token[i + j + k + l] != ')')) {
2310 nh_ip_str[l] = token[i + j + k + l];
2313 nh_ip_str[l] = '\0';
2314 nh_ip = strtoul(nh_ip_str, NULL, 16); //atoi(nh_ip_str);
2317 RTE_LOG(INFO, LIBARP, "token: %s, "
2318 "dest_ip_str: %s, dest_ip %u, "
2319 "mask_str: %s, mask %x, "
2320 "tx_port_str: %s, tx_port %u, "
2321 "nh_ip_str: %s, nh_ip %u\n",
2322 token, dest_ip_str, dest_ip,
2323 mask_str, mask, tx_port_str,
2324 tx_port, nh_ip_str, nh_ip);
2327 /* if (tx_port >= params->n_ports_out)
2329 RTE_LOG(INFO, LIBARP,"ARP-ICMP parse error - incorrect tx_port %d, max %d\n",
2330 tx_port, params->n_ports_out);
2334 //Populate the static arp_route_table
2336 struct route_table_entry *lentry =
2337 &p_route_data[tx_port]->route_table
2338 [p_route_data[tx_port]->route_ent_cnt];
2339 lentry->mask = mask;
2340 lentry->port = tx_port;
2342 lentry->nh_mask = nh_ip & mask;
2343 printf("*********lentry_mask:%x lentry_port:%d lentry_nh:%x mask:%x\n", lentry->mask, lentry->port, lentry->nh, lentry->nh_mask);
2344 p_route_data[tx_port]->route_ent_cnt++;
2346 token = strtok(NULL, "(");
2353 if (strcmp(arg_name, "nd_route_tbl") == 0) {
2354 nd_route_tbl_present = 1;
2355 uint8_t dest_ipv6[16];
2356 char dest_ipv6_str[128];
2357 uint8_t depth = 0, tx_port = 0, nh_ipv6[16];
2358 uint8_t i = 0, j = 0, k = 0, l = 0;
2359 uint8_t nd_route_tbl_str_max_len = 128; //64;
2360 // char dest_ipv6_str[nd_route_tbl_str_max_len];
2361 char depth_str[nd_route_tbl_str_max_len];
2362 char tx_port_str[nd_route_tbl_str_max_len];
2363 char nh_ipv6_str[nd_route_tbl_str_max_len];
2364 char *token = strtok(arg_value, "(");
2367 while ((i < (nd_route_tbl_str_max_len - 1))
2368 && (token[i] != ',')) {
2369 dest_ipv6_str[i] = token[i];
2372 dest_ipv6_str[i] = '\0';
2373 my_inet_pton_ipv6(AF_INET6, dest_ipv6_str,
2378 while ((j < (nd_route_tbl_str_max_len - 1))
2379 && (token[i + j] != ',')) {
2380 depth_str[j] = token[i + j];
2383 depth_str[j] = '\0';
2384 //converting string char to integer
2386 for (s = 0; depth_str[s] != '\0'; ++s)
2387 depth = depth * 10 + depth_str[s] - '0';
2391 while ((k < (nd_route_tbl_str_max_len - 1))
2392 && (token[i + j + k] != ',')) {
2393 tx_port_str[k] = token[i + j + k];
2396 tx_port_str[k] = '\0';
2397 tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str);
2401 while ((l < (nd_route_tbl_str_max_len - 1))
2402 && (token[i + j + k + l] != ')')) {
2403 nh_ipv6_str[l] = token[i + j + k + l];
2406 nh_ipv6_str[l] = '\0';
2407 my_inet_pton_ipv6(AF_INET6, nh_ipv6_str,
2410 struct nd_route_table_entry *lentry =
2411 &p_nd_route_data[tx_port]->nd_route_table
2412 [p_nd_route_data[tx_port]->nd_route_ent_cnt];
2414 //Populate the static arp_route_table
2415 for (i = 0; i < 16; i++)
2416 lentry->nhipv6[i] = nh_ipv6[i];
2418 lentry->depth = depth;
2419 lentry->port = tx_port;
2421 p_nd_route_data[tx_port]->nd_route_ent_cnt++;
2424 token = strtok(NULL, "(");
2432 /* Check that mandatory arguments are present */
2434 if ((arp_route_tbl_present == 0) || (ports_mac_list_present == 0)) {
2435 RTE_LOG(INFO, LIBARP,"VNF common not all mandatory arguments are present\n");
2436 RTE_LOG(INFO, LIBARP,"%d, %d \n",
2437 arp_route_tbl_present, ports_mac_list_present);
2445 static void local_arp_cache_init(void)
2448 for (i=0; i<MAX_PORTS;i++) {
2449 for (j=0; j<MAX_LOCAL_MAC_ADDRESS;j++) {
2450 p_arp_data->arp_local_cache[i].nhip[j] = 0;
2452 p_arp_data->arp_local_cache[i].link_hw_laddr[j].addr_bytes[k] = 0;
2453 p_arp_data->arp_local_cache[i].num_nhip = 0;
2458 struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
2461 struct ether_addr *x = NULL;
2462 limit = p_arp_data->nd_local_cache[out_port].num_nhip;
2464 for (i=0; i < limit; i++) {
2465 for (j=0;j<16;j++) {
2466 if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
2470 x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
2473 for (j = 0; j < 6; j++)
2474 printf("%d %d", x->addr_bytes[j],
2475 p_arp_data->nd_local_cache[out_port].link_hw_laddr[i].addr_bytes[j]);
2483 struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip)
2487 struct ether_addr *x = NULL;
2488 limit = p_arp_data->arp_local_cache[out_port].num_nhip;
2489 for (i=0; i < limit; i++) {
2490 tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
2492 x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
2499 void lib_arp_init(struct pipeline_params *params,
2500 __rte_unused struct app_params *app)
2507 RTE_LOG(INFO, LIBARP, "ARP initialization ...\n");
2509 /* create arp data for table entries */
2510 size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
2511 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
2512 p_arp_data = (struct arp_data *)p;
2514 /* Parse arguments */
2515 if (arp_parse_args(params)) {
2516 RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
2520 /* acquire the mac addresses */
2521 struct ether_addr hw_addr;
2522 uint8_t nb_ports = rte_eth_dev_count();
2524 for (i = 0; i < nb_ports; i++) {
2525 rte_eth_macaddr_get(i, &hw_addr);
2526 ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
2527 p_arp_data->link_hw_addr_array_idx++;
2530 /* create a lock for arp/nd hash */
2531 rte_rwlock_init(&arp_hash_handle_lock);
2532 rte_rwlock_init(&nd_hash_handle_lock);
2534 /* create the arp_icmp mbuf rx pool */
2535 lib_arp_pktmbuf_tx_pool =
2536 rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2537 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2540 if (lib_arp_pktmbuf_tx_pool == NULL) {
2541 RTE_LOG(INFO, LIBARP, "ARP mbuf pool create failed.\n");
2545 for (i=0; i<MAX_PORTS; i++) {
2546 lib_arp_pkt[i] = rte_pktmbuf_alloc(lib_arp_pktmbuf_tx_pool);
2547 if (lib_arp_pkt[i] == NULL) {
2548 RTE_LOG(INFO, LIBARP, "ARP lib_arp_pkt alloc failed.\n");
2553 /* create the nd icmp mbuf rx pool */
2554 lib_nd_pktmbuf_tx_pool =
2555 rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
2556 0, RTE_MBUF_DEFAULT_BUF_SIZE,
2559 if (lib_nd_pktmbuf_tx_pool == NULL) {
2560 RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
2564 for (i=0; i<MAX_PORTS; i++) {
2565 lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
2566 if (lib_nd_pkt[i] == NULL) {
2567 RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
2572 /* create the arp_icmp mbuf rx pool */
2573 arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
2574 NB_ARPICMP_MBUF, MAX_POOL, 0,
2575 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2577 if (arp_icmp_pktmbuf_tx_pool == NULL) {
2578 RTE_LOG(INFO, LIBARP, "icmp_pktmbuf pool creation failed\n");
2582 arp_hash_params.socket_id = rte_socket_id();
2583 arp_hash_params.entries = MAX_NUM_ARP_ENTRIES;
2584 arp_hash_params.key_len = sizeof(struct arp_key_ipv4);
2585 arp_hash_handle = rte_hash_create(&arp_hash_params);
2587 if (arp_hash_handle == NULL) {
2588 RTE_LOG(INFO, LIBARP,
2589 "ARP rte_hash_create failed. socket %d ... \n",
2590 arp_hash_params.socket_id);
2592 RTE_LOG(INFO, LIBARP, "arp_hash_handle %p\n\n",
2593 (void *)arp_hash_handle);
2596 /* Create port alloc buffer */
2598 timer_mempool_arp = rte_mempool_create("timer_mempool_arp",
2599 timer_objs_mempool_count,
2600 sizeof(struct rte_timer),
2603 NULL, NULL, rte_socket_id(), 0);
2604 if (timer_mempool_arp == NULL) {
2605 rte_panic("timer_mempool create error\n");
2607 rte_timer_subsystem_init();
2608 list_add_type(ETHER_TYPE_ARP, process_arpicmp_pkt_parse);
2611 nd_hash_params.socket_id = rte_socket_id();
2612 nd_hash_params.entries = MAX_NUM_ND_ENTRIES;
2613 nd_hash_params.key_len = sizeof(struct nd_key_ipv6);
2614 nd_hash_handle = rte_hash_create(&nd_hash_params);
2615 if (nd_hash_handle == NULL) {
2616 RTE_LOG(INFO, LIBARP,
2617 "ND rte_hash_create failed. socket %d ... \n",
2618 nd_hash_params.socket_id);
2620 RTE_LOG(INFO, LIBARP, "nd_hash_handle %p\n\n",
2621 (void *)nd_hash_handle);
2624 /* Initialize the local arp cache */
2625 local_arp_cache_init();
2630 void arp_timer_callback(struct rte_timer *timer, void *arg)
2632 struct arp_timer_key *timer_key = (struct arp_timer_key *)arg;
2633 struct arp_key_ipv4 arp_key;
2634 arp_key.port_id = timer_key->port_id;
2635 arp_key.ip = timer_key->ip;
2636 arp_key.filler1 = 0;
2637 arp_key.filler2 = 0;
2638 arp_key.filler3 = 0;
2640 struct arp_entry_data *ret_arp_data = NULL;
2642 if (ARPICMP_DEBUG) {
2643 RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
2644 arp_key.ip, arp_key.port_id);
2647 int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
2648 (void **)&ret_arp_data);
2652 RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
2653 (int)timer->expire, now);
2655 printf("Should not have come here\n");
2658 if (ret_arp_data->mode == DYNAMIC_ARP) {
2659 rte_rwlock_write_lock(&ret_arp_data->queue_lock);
2660 if (ret_arp_data->status == PROBE ||
2661 ret_arp_data->status == INCOMPLETE) {
2662 if (ret_arp_data->retry_count == ARP_RETRY_COUNT) {
2663 remove_arp_entry(ret_arp_data, arg);
2665 ret_arp_data->retry_count++;
2667 if (ARPICMP_DEBUG) {
2668 RTE_LOG(INFO, LIBARP,
2669 "RETRY ARP..retry count : %u\n",
2670 ret_arp_data->retry_count);
2672 RTE_LOG(INFO, LIBARP,
2673 "TIMER STARTED FOR %u seconds\n",
2677 if (ifm_chk_port_ipv4_enabled
2678 (ret_arp_data->port) != IFM_FAILURE) {
2679 request_arp(ret_arp_data->port,
2683 RTE_LOG(INFO, LIBARP,
2684 "%s: IP is not enabled on port %u"
2685 ", not sending GARP\n\r",
2687 ret_arp_data->port);
2690 if (rte_timer_reset(ret_arp_data->timer,
2692 rte_get_tsc_hz()/ 1000),
2698 RTE_LOG(INFO, LIBARP,
2699 "Err : Timer already running\n");
2702 } else if (ret_arp_data->status == COMPLETE) {
2703 if (now <= (ret_arp_data->n_confirmed +
2704 (arp_timeout * rte_get_tsc_hz()))) {
2705 if (rte_timer_reset(ret_arp_data->timer,
2707 rte_get_tsc_hz()), SINGLE,
2712 RTE_LOG(INFO, LIBARP,
2713 "Err : Timer already running\n");
2714 } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2715 if (rte_timer_reset(ret_arp_data->timer,
2717 rte_get_tsc_hz()), SINGLE,
2722 RTE_LOG(INFO, LIBARP,
2723 "Err : Timer already running\n");
2725 ret_arp_data->status = STALE;
2726 p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
2729 rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
2731 rte_hash_del_key(arp_hash_handle, &arp_key);
2737 void nd_timer_callback(struct rte_timer *timer, void *arg)
2739 struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
2740 struct nd_key_ipv6 nd_key;
2742 struct nd_entry_data *ret_nd_data = NULL;
2744 l2_phy_interface_t *port;
2746 nd_key.port_id = timer_key->port_id;
2751 rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
2753 if (ARPICMP_DEBUG) {
2754 RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
2758 int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
2759 (void **)&ret_nd_data);
2763 RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
2764 (int)timer->expire, now);
2766 printf("Should not have come here \n");
2767 for (j = 0; j < 16; j++)
2768 printf("*%d ", nd_key.ipv6[j]);
2769 printf("*%d ", nd_key.port_id);
2772 if (ret_nd_data->mode == DYNAMIC_ARP) {
2773 rte_rwlock_write_lock(&ret_nd_data->queue_lock);
2774 if (ret_nd_data->status == PROBE ||
2775 ret_nd_data->status == INCOMPLETE) {
2776 if (ret_nd_data->retry_count == ARP_RETRY_COUNT) {
2777 remove_nd_entry_ipv6(ret_nd_data, arg);
2779 ret_nd_data->retry_count++;
2781 if (ARPICMP_DEBUG) {
2782 RTE_LOG(INFO, LIBARP,
2783 "RETRY ND..retry count : %u\n",
2784 ret_nd_data->retry_count);
2786 RTE_LOG(INFO, LIBARP,
2787 "TIMER STARTED FOR %u seconds\n",
2790 port = ifm_get_port(ret_nd_data->port);
2792 printf("port is NULL in nd_timer_callback\n");
2796 request_nd(ret_nd_data->ipv6, port);
2797 if (rte_timer_reset(ret_nd_data->timer,
2799 rte_get_tsc_hz()/ 1000),
2805 RTE_LOG(INFO, LIBARP,
2806 "Err : Timer already running\n");
2809 } else if (ret_nd_data->status == COMPLETE) {
2810 if (now <= (ret_nd_data->n_confirmed +
2811 (arp_timeout * rte_get_tsc_hz()))) {
2812 if (rte_timer_reset(ret_nd_data->timer,
2814 rte_get_tsc_hz()), SINGLE,
2819 RTE_LOG(INFO, LIBARP,
2820 "Err : Timer already running\n");
2821 } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
2822 if (rte_timer_reset(ret_nd_data->timer,
2824 rte_get_tsc_hz()), SINGLE,
2829 RTE_LOG(INFO, LIBARP,
2830 "Err : Timer already running\n");
2832 printf("making it stale\n");
2833 ret_nd_data->status = STALE;
2834 p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
2837 rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
2839 rte_hash_del_key(nd_hash_handle, &nd_key);
2845 void create_arp_table(void)
2849 for (i = 0; i < MAX_ARP_DATA_ENTRY_TABLE; i++) {
2850 populate_arp_entry((const struct ether_addr *)
2851 &arp_entry_data_table[i].eth_addr,
2852 arp_entry_data_table[i].ip,
2853 (uint8_t) arp_entry_data_table[i].port,
2861 void create_nd_table(void)
2865 for (i = 0; i < MAX_ND_DATA_ENTRY_TABLE; i++) {
2866 populate_nd_entry((const struct ether_addr *)
2867 nd_entry_data_table[i].eth_addr,
2868 nd_entry_data_table[i].ipv6,
2869 (uint8_t) nd_entry_data_table[i].port,
2876 void send_gratuitous_arp(l2_phy_interface_t *port)
2878 struct ether_hdr *eth_h;
2879 struct arp_hdr *arp_h;
2881 struct rte_mbuf *arp_pkt = lib_arp_pkt[port->pmdid];
2884 RTE_LOG(INFO, LIBARP, "PORT ID DOWN.. %s\n", __FUNCTION__);
2889 if (arp_pkt == NULL) {
2891 RTE_LOG(INFO, LIBARP,
2892 "Error allocating arp_pkt rte_mbuf\n");
2896 eth_h = rte_pktmbuf_mtod(arp_pkt, struct ether_hdr *);
2898 ether_addr_copy(&broadcast_ether_addr, ð_h->d_addr);
2899 ether_addr_copy((struct ether_addr *)
2900 &port->macaddr[0], ð_h->s_addr);
2901 eth_h->ether_type = CHECK_ENDIAN_16(ETHER_TYPE_ARP);
2903 arp_h = (struct arp_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
2904 arp_h->arp_hrd = CHECK_ENDIAN_16(ARP_HRD_ETHER);
2905 arp_h->arp_pro = CHECK_ENDIAN_16(ETHER_TYPE_IPv4);
2906 arp_h->arp_hln = ETHER_ADDR_LEN;
2907 arp_h->arp_pln = sizeof(uint32_t);
2908 arp_h->arp_op = CHECK_ENDIAN_16(ARP_OP_REQUEST);
2910 ether_addr_copy((struct ether_addr *)
2911 &port->macaddr[0], &arp_h->arp_data.arp_sha);
2912 if (port->ipv4_list == NULL) {
2914 RTE_LOG(INFO, LIBARP, "port->ipv4_list is NULL.. %s\n",
2918 arp_h->arp_data.arp_sip = (((ipv4list_t *) (port->ipv4_list))->ipaddr);
2919 ether_addr_copy(&null_ether_addr, &arp_h->arp_data.arp_tha);
2920 //arp_h->arp_data.arp_tip = rte_cpu_to_be_32(ip);
2921 arp_h->arp_data.arp_tip = 0; //(((ipv4list_t *) (port->ipv4_list))->ipaddr);
2922 // RTE_LOG(INFO, LIBARP,"arp tip:%x arp sip :%x\n", arp_h->arp_data.arp_tip,
2923 //arp_h->arp_data.arp_sip);
2924 // mmcd changed length from 60 to 42 - real length of arp request, no padding on ethernet needed - looks now like linux arp
2925 arp_pkt->pkt_len = 42;
2926 arp_pkt->data_len = 42;
2928 if (ARPICMP_DEBUG) {
2929 RTE_LOG(INFO, LIBARP, "SENDING GRATUITOUS ARP REQUEST\n");
2930 print_mbuf("TX", port->pmdid, arp_pkt, __LINE__);
2932 port->transmit_single_pkt(port, arp_pkt);
2935 void set_arpdebug(int flag)
2938 RTE_LOG(INFO, LIBARP, "Debugs turned on\n\r");
2943 RTE_LOG(INFO, LIBARP, "Debugs turned off\n\r");
2949 void set_arptimeout(uint32_t timeout_val)
2951 if (timeout_val == 0) {
2952 RTE_LOG(INFO, LIBARP, "Cannot be zero...\n\r");
2956 RTE_LOG(INFO, LIBARP,
2957 "set_arptimeout: arp_timeout %u, timeout_val %u\n\r",
2958 arp_timeout, timeout_val);
2959 arp_timeout = timeout_val;
2961 RTE_LOG(INFO, LIBARP, "set_arptimeout: arp_timeout %u\n\r",