summaryrefslogtreecommitdiffstats
path: root/common/VIL/l2l3_stack
diff options
context:
space:
mode:
authorDeepak S <deepak.s@linux.intel.com>2017-07-20 11:22:33 +0000
committerGerrit Code Review <gerrit@opnfv.org>2017-07-20 11:22:33 +0000
commitd923180e4af2612361dd7d4bf1627092a4d552d8 (patch)
tree6809880ce8c96365778514f3c820f08588910ae5 /common/VIL/l2l3_stack
parent51759157a499326cfe69ec0eecb00b1c5879bf50 (diff)
parent5997f97a236457f2994820d39e3738dfd61076e4 (diff)
Merge "[l2l3 stack] implements new nd state machine & nd buffering"
Diffstat (limited to 'common/VIL/l2l3_stack')
-rw-r--r--common/VIL/l2l3_stack/interface.h2
-rw-r--r--common/VIL/l2l3_stack/l3fwd_lpm6.c2
-rw-r--r--common/VIL/l2l3_stack/lib_arp.c1034
-rw-r--r--common/VIL/l2l3_stack/lib_arp.h111
-rw-r--r--common/VIL/l2l3_stack/lib_icmpv6.c40
-rw-r--r--common/VIL/l2l3_stack/lib_icmpv6.h1
6 files changed, 726 insertions, 464 deletions
diff --git a/common/VIL/l2l3_stack/interface.h b/common/VIL/l2l3_stack/interface.h
index f8d35cb2..0f654fa1 100644
--- a/common/VIL/l2l3_stack/interface.h
+++ b/common/VIL/l2l3_stack/interface.h
@@ -102,7 +102,7 @@
#define IFM_QUEUE_STAT_CNTRS 16
#define IFM_TX_DEFAULT_Q 0
#define IFM_RX_DEFAULT_Q 0
-#define IFM_RX_DESC_DEFAULT 512
+#define IFM_RX_DESC_DEFAULT 128
#define IFM_TX_DESC_DEFAULT 512
#define IFM_BURST_SIZE 32
#define IFM_BURST_TX_WAIT_US 1
diff --git a/common/VIL/l2l3_stack/l3fwd_lpm6.c b/common/VIL/l2l3_stack/l3fwd_lpm6.c
index 7aa7fb6a..7d3cf4fb 100644
--- a/common/VIL/l2l3_stack/l3fwd_lpm6.c
+++ b/common/VIL/l2l3_stack/l3fwd_lpm6.c
@@ -705,7 +705,7 @@ int get_dest_mac_for_nexthop_ipv6(uint8_t nh_ipv6[RTE_LPM_IPV6_ADDR_SIZE],
}
tmp_nd_key.port_id = out_phy_port;
- nd_data = retrieve_nd_entry(tmp_nd_key);
+ nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND);
if (nd_data == NULL) {
printf("ND entry is not found\n");
return 0;
diff --git a/common/VIL/l2l3_stack/lib_arp.c b/common/VIL/l2l3_stack/lib_arp.c
index 43d0c8e5..0c597301 100644
--- a/common/VIL/l2l3_stack/lib_arp.c
+++ b/common/VIL/l2l3_stack/lib_arp.c
@@ -54,7 +54,7 @@
#define IP_VERSION_4 0x40
#define IP_HDRLEN 0x05 /**< default IP header length == five 32-bits words. */
#define IP_VHL_DEF (IP_VERSION_4 | IP_HDRLEN)
-
+#define MAX_POOL 32
#define is_multicast_ipv4_addr(ipv4_addr) \
(((rte_be_to_cpu_32((ipv4_addr)) >> 24) & 0x000000FF) == 0xE0)
@@ -63,6 +63,7 @@ extern uint32_t timer_lcore;
extern int USE_RTM_LOCKS;
uint32_t arp_timeout = ARP_TIMER_EXPIRY;
uint32_t arp_buffer = ARP_BUF_DEFAULT;
+uint32_t nd_buffer = ARP_BUF_DEFAULT;
/*ND IPV6 */
#define INADDRSZ 4
@@ -73,6 +74,7 @@ static int my_inet_pton_ipv6(int af, const char *src, void *dst);
static int inet_pton_ipv6(const char *src, unsigned char *dst);
static int inet_pton_ipv4(const char *src, unsigned char *dst);
static void local_arp_cache_init(void);
+struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]);
extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth,
uint8_t netmask_ipv6[]);
@@ -108,7 +110,7 @@ struct rte_mempool *lib_arp_pktmbuf_tx_pool;
struct rte_mempool *lib_nd_pktmbuf_tx_pool;
struct rte_mbuf *lib_arp_pkt[MAX_PORTS];
-struct rte_mbuf *lib_nd_pkt;
+struct rte_mbuf *lib_nd_pkt[MAX_PORTS];
uint8_t default_ether_addr[6] = { 0, 0, 0, 0, 1, 1 };
uint8_t default_ip[4] = { 0, 0, 1, 1 };
@@ -127,32 +129,17 @@ uint8_t arp_cache_hw_laddr_valid[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
0, 0, 0, 0, 0, 0, 0, 0
};
-void prefetch(void)
+/**
+ * handler lock.
+ */
+rte_rwlock_t arp_hash_handle_lock;
+rte_rwlock_t nd_hash_handle_lock;
+
+void update_nhip_access(uint8_t dest_if)
{
- rte_prefetch0(p_arp_data);
+ p_arp_data->update_tsc[dest_if] = rte_rdtsc();
}
-struct arp_entry_data *arp_data_ptr[MAX_NUM_ARP_CACHE_MAC_ADDRESS];
-
-struct ether_addr arp_cache_hw_laddr[MAX_NUM_ARP_CACHE_MAC_ADDRESS] = {
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
- {.addr_bytes = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }
-};
-
/**
* A structure defining the mbuf meta data for VFW.
*/
@@ -167,6 +154,11 @@ static struct arp_entry_data arp_entry_data_default = {
.num_pkts = 0,
};
+static struct nd_entry_data nd_entry_data_default = {
+ .status = COMPLETE,
+ .num_pkts = 0,
+};
+
/**
* memory pool for queued up user pkts.
*/
@@ -234,7 +226,8 @@ int timer_objs_mempool_count = 70000;
#define MAX_NUM_ND_ENTRIES 64
inline uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr);
-void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[]);
+void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[],
+ struct ether_addr *hw_addr);
#define MAX_ARP_DATA_ENTRY_TABLE 7
@@ -334,41 +327,6 @@ struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }
};
-struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY] = {
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0}
-};
-
void print_trace(void);
uint32_t get_arp_buf(void)
@@ -376,11 +334,21 @@ uint32_t get_arp_buf(void)
return arp_buffer;
}
+uint32_t get_nd_buf(void)
+{
+ return nd_buffer;
+}
+
uint8_t arp_cache_dest_mac_present(uint32_t out_port)
{
return p_arp_data->arp_cache_hw_laddr_valid[out_port];
}
+uint8_t nd_cache_dest_mac_present(uint32_t out_port)
+{
+ return p_arp_data->nd_cache_hw_laddr_valid[out_port];
+}
+
/* Obtain a backtrace and print it to stdout. */
void print_trace(void)
{
@@ -409,7 +377,9 @@ uint32_t get_nh(uint32_t ip, uint32_t *port, struct ether_addr *addr)
*port = p_arp_data->lib_arp_route_table[i].port;
if (arp_cache_dest_mac_present(*port))
- ether_addr_copy(get_local_link_hw_addr(*port, p_arp_data->lib_arp_route_table[i].nh), addr);
+ ether_addr_copy(
+ get_local_link_hw_addr(*port,
+ p_arp_data->lib_arp_route_table[i].nh), addr);
return p_arp_data->lib_arp_route_table[i].nh;
}
}
@@ -418,7 +388,8 @@ uint32_t get_nh(uint32_t ip, uint32_t *port, struct ether_addr *addr)
}
/*ND IPv6 */
-void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
+void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[],
+struct ether_addr *hw_addr)
{
int i = 0;
uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16];
@@ -456,6 +427,11 @@ void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
for (j = 0; j < 16; j++)
nhipv6[j] = lib_nd_route_table[i].nhipv6[j];
+ if (nd_cache_dest_mac_present(*port)) {
+ ether_addr_copy(
+ get_nd_local_link_hw_addr(*port, nhipv6),
+ (struct ether_addr *)hw_addr);
+ }
return;
}
@@ -465,7 +441,7 @@ void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[])
depthflags1 = 0;
}
if (NDIPV6_DEBUG)
- printf("No NH - ip 0x%x, port %u\n", ipv6[0], *port);
+ printf("No NH - ip 0x%x, \n", ipv6[0]);
lib_nd_no_nh_found++;
}
@@ -477,7 +453,6 @@ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
uint32_t nhip = 0;
uint8_t index;
- //lib_arp_get_mac_req++;
nhip = get_nh(ipaddr, phy_port, hw_addr);
if (unlikely(nhip == 0)) {
if (ARPICMP_DEBUG)
@@ -490,7 +465,6 @@ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
* & thus can be sent without having to retrieve
*/
if (arp_cache_dest_mac_present(*phy_port)) {
- //arp_data_ptr[*phy_port]->n_last_update = time(NULL);
return &arp_entry_data_default;
}
@@ -506,44 +480,45 @@ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
if (ret_arp_data == NULL) {
if (ARPICMP_DEBUG && ipaddr)
{
- RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x, port %u\n", ipaddr, *phy_port);
+ RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x,"
+ " port %u\n", ipaddr, *phy_port);
print_arp_table();
}
lib_arp_no_arp_entry_found++;
} else if (ret_arp_data->status == COMPLETE) {
+ rte_rwlock_write_lock(&ret_arp_data->queue_lock);
ether_addr_copy(&ret_arp_data->eth_addr, hw_addr);
- printf("Setting mac found for port:%d\n", *phy_port);
p_arp_data->arp_cache_hw_laddr_valid[*phy_port] = 1;
- arp_data_ptr[*phy_port] = ret_arp_data;
- //memcpy(&arp_cache_hw_laddr[*phy_port], hw_addr,
- // sizeof(struct ether_addr));
index = p_arp_data->arp_local_cache[*phy_port].num_nhip;
p_arp_data->arp_local_cache[*phy_port].nhip[index] = nhip;
- ether_addr_copy(hw_addr, &p_arp_data->arp_local_cache[*phy_port].link_hw_laddr[index]);
+ ether_addr_copy(hw_addr,
+ &p_arp_data->arp_local_cache[*phy_port].link_hw_laddr[index]);
p_arp_data->arp_local_cache[*phy_port].num_nhip++;
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
lib_arp_arp_entry_found++;
-
if (ARPICMP_DEBUG)
printf("%s: ARPICMP hwaddr found\n", __FUNCTION__);
}
if (ret_arp_data)
- ret_arp_data->n_last_update = time(NULL);
+ p_arp_data->update_tsc[*phy_port] = rte_rdtsc();
return ret_arp_data;
}
-int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
- struct ether_addr *hw_addr, uint8_t nhipv6[])
+struct nd_entry_data *get_dest_mac_address_ipv6_port(uint8_t ipv6addr[],
+ uint32_t *phy_port, struct ether_addr *hw_addr, uint8_t nhipv6[])
{
int i = 0, j = 0, flag = 0;
+ uint8_t index;
lib_nd_get_mac_req++;
- get_nh_ipv6(ipv6addr, phy_port, nhipv6);
+ get_nh_ipv6(ipv6addr, phy_port, nhipv6, hw_addr);
for (j = 0; j < 16; j++) {
if (nhipv6[j])
flag++;
}
+
if (flag == 0) {
if (NDIPV6_DEBUG)
printf("NDIPV6 no nh found for ipv6 "
@@ -562,73 +537,41 @@ int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
struct nd_key_ipv6 tmp_nd_key;
tmp_nd_key.port_id = *phy_port;
+ if (nd_cache_dest_mac_present(*phy_port)) {
+ return &nd_entry_data_default;
+ }
+
+
for (i = 0; i < 16; i++)
tmp_nd_key.ipv6[i] = nhipv6[i];
- ret_nd_data = retrieve_nd_entry(tmp_nd_key);
+ ret_nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND);
if (ret_nd_data == NULL) {
if (NDIPV6_DEBUG) {
printf("NDIPV6 no nd entry found for ip %x, port %d\n",
ipv6addr[0], *phy_port);
}
lib_nd_no_arp_entry_found++;
- return 0;
- }
- ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
- lib_nd_nd_entry_found++;
- return 1;
-}
-
-int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t *phy_port,
- struct ether_addr *hw_addr, uint8_t nhipv6[])
-{
- int i = 0, j = 0, flag = 0;
- lib_nd_get_mac_req++;
-
- get_nh_ipv6(ipv6addr, phy_port, nhipv6);
- for (j = 0; j < 16; j++) {
- if (nhipv6[j]) {
- flag++;
- }
- }
- if (flag == 0) {
- if (NDIPV6_DEBUG && ipv6addr)
- RTE_LOG(INFO, LIBARP,
- "NDIPV6 no nh found for ipv6 %x, port %d\n",
- ipv6addr[0], *phy_port);
- return 0;
- }
-
- struct nd_entry_data *ret_nd_data = NULL;
- struct nd_key_ipv6 tmp_nd_key;
- tmp_nd_key.port_id = *phy_port;
+ return NULL;
+ } else if (ret_nd_data->status == COMPLETE) {
+ rte_rwlock_write_lock(&ret_nd_data->queue_lock);
+ ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
+ p_arp_data->nd_cache_hw_laddr_valid[*phy_port] = 1;
+ index = p_arp_data->nd_local_cache[*phy_port].num_nhip;
+ rte_mov16(&p_arp_data->nd_local_cache[*phy_port].nhip[index][0],
+ &nhipv6[0]);
+ ether_addr_copy(hw_addr,
+ &p_arp_data->nd_local_cache[*phy_port].link_hw_laddr[index]);
+ p_arp_data->nd_local_cache[*phy_port].num_nhip++;
- for (i = 0; i < 16; i++) {
- tmp_nd_key.ipv6[i] = nhipv6[i];
+ lib_nd_nd_entry_found++;
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
}
- ret_nd_data = retrieve_nd_entry(tmp_nd_key);
- if (ret_nd_data == NULL) {
- if (NDIPV6_DEBUG && ipv6addr) {
- RTE_LOG(INFO, LIBARP,
- "NDIPV6 no nd entry found for ip %x, port %d\n",
- ipv6addr[0], *phy_port);
- }
- if (flag != 0) {
- if (ARPICMP_DEBUG > 4)
- printf
- ("Requesting ARP for ipv6 addr and port %d\n",
- *phy_port);
- request_nd(&nhipv6[0], ifm_get_port(*phy_port));
+ if (ret_nd_data)
+ p_arp_data->update_tsc[*phy_port] = rte_rdtsc();
- }
-
- lib_nd_no_arp_entry_found++;
- return 0;
- }
- ether_addr_copy(&ret_nd_data->eth_addr, hw_addr);
- lib_nd_nd_entry_found++;
- return 1;
+ return ret_nd_data;
}
/**
@@ -783,6 +726,91 @@ print_mbuf(const char *rx_tx, uint8_t portid, struct rte_mbuf *mbuf,
fflush(stdout);
}
+/**
+ * Add entry in ND table.
+ *
+ * @param nd_key
+ * key.
+ * @param ret_nd_data
+ * return nd entry from table.
+ *
+ */
+static int add_nd_data(struct nd_key_ipv6 *nd_key,
+ struct nd_entry_data *ret_nd_data)
+{
+ int ret;
+ struct nd_entry_data *tmp_nd_data = NULL;
+ rte_rwlock_write_lock(&nd_hash_handle_lock);
+ /* Check for value while locked */
+ ret = rte_hash_lookup_data(nd_hash_handle, nd_key, (void **)&tmp_nd_data);
+
+ if (ret == -ENOENT) {
+ /* entry not yet added, do so now */
+ ret = rte_hash_add_key_data(nd_hash_handle, nd_key, ret_nd_data);
+ if (ret) {
+ /* We panic here because either:
+ * ret == -EINVAL and a parameter got messed up, or
+ * ret == -ENOSPC and the hash table isn't big enough
+ */
+ rte_panic("ND: Error on entry add for %s", rte_strerror(abs(ret)));
+ }
+ } else if (ret < 0) {
+ /* We panic here because ret == -EINVAL and a parameter got
+ * messed up, or dpdk hash lib changed and this needs corrected */
+ rte_panic("ARP: Error on entry add for %s", rte_strerror(abs(ret)));
+ } else {
+ /* entry already exists */
+ ret = EEXIST;
+ }
+
+ rte_rwlock_write_unlock(&nd_hash_handle_lock);
+ return ret;
+}
+
+/**
+ * Add entry in ARP table.
+ *
+ * @param arp_key
+ * key.
+ * @param ret_arp_data
+ * return arp entry from table.
+ *
+ */
+static int add_arp_data(struct arp_key_ipv4 *arp_key,
+ struct arp_entry_data *ret_arp_data) {
+ int ret;
+ struct arp_entry_data *tmp_arp_data = NULL;
+ rte_rwlock_write_lock(&arp_hash_handle_lock);
+ /* Check for value while locked */
+ ret = rte_hash_lookup_data(arp_hash_handle, arp_key, (void **)&tmp_arp_data);
+
+ if (ret == -ENOENT) {
+ /* entry not yet added, do so now */
+ ret = rte_hash_add_key_data(arp_hash_handle, arp_key, ret_arp_data);
+ if (ret) {
+ /* We panic here because either:
+ * ret == -EINVAL and a parameter got messed up, or
+ * ret == -ENOSPC and the hash table isn't big enough
+ */
+ rte_panic("ARP: Error on entry add for %s - %s",
+ inet_ntoa(*(struct in_addr *)&arp_key->ip),
+ rte_strerror(abs(ret)));
+ }
+ } else if (ret < 0) {
+ /* We panic here because ret == -EINVAL and a parameter got
+ * messed up, or dpdk hash lib changed and this needs corrected */
+ rte_panic("ARP: Error on entry add for %s - %s",
+ inet_ntoa(*(struct in_addr *)&arp_key->ip),
+ rte_strerror(abs(ret)));
+ } else {
+ /* entry already exists */
+ ret = EEXIST;
+ }
+
+ rte_rwlock_write_unlock(&arp_hash_handle_lock);
+ return ret;
+}
+
struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t mode)
{
struct arp_entry_data *ret_arp_data = NULL;
@@ -794,7 +822,8 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m
(void **)&ret_arp_data);
if (ret < 0 && (mode == DYNAMIC_ARP)) {
if (ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",arp_key.ip);
+ RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",
+ arp_key.ip);
/* add INCOMPLETE arp entry */
ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data),
@@ -805,22 +834,36 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m
ret_arp_data->ip = arp_key.ip;
ret_arp_data->mode = mode;
ret_arp_data->num_pkts = 0;
- ret_arp_data->buffered_pkt_list_head = NULL;
- ret_arp_data->buffered_pkt_list_tail = NULL;
rte_rwlock_init(&ret_arp_data->queue_lock);
rte_rwlock_write_lock(&ret_arp_data->queue_lock);
+ /* attempt to add arp_entry to hash */
+ ret = add_arp_data(&arp_key, ret_arp_data);
+
+ if (ret == EEXIST) {
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
+ rte_free(ret_arp_data);
+ /* Some other thread has 'beat' this thread in
+ creation of arp_data, try again */
+ return NULL;
+ }
+
if (rte_mempool_get(timer_mempool_arp,
(void **) &(ret_arp_data->timer) ) < 0) {
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
return NULL;
}
- ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
+ ret_arp_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
NULL, sizeof(struct rte_mbuf *) * arp_buffer,
RTE_CACHE_LINE_SIZE, rte_socket_id());
- rte_hash_add_key_data(arp_hash_handle, &arp_key, ret_arp_data);
+ if (ret_arp_data->buf_pkts == NULL) {
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
+ RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
+ return NULL;
+ }
rte_timer_init(ret_arp_data->timer);
struct arp_timer_key * callback_key =
@@ -829,7 +872,8 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m
callback_key->port_id = arp_key.port_id;
callback_key->ip = arp_key.ip;
if(ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",ARP_TIMER_EXPIRY);
+ RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
+ ARP_TIMER_EXPIRY);
if(rte_timer_reset(ret_arp_data->timer,
(PROBE_TIME * rte_get_tsc_hz() / 1000),
SINGLE,timer_lcore,
@@ -842,30 +886,34 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m
/* send arp request */
request_arp(arp_key.port_id, arp_key.ip);
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
} else {
if (ret_arp_data &&
ret_arp_data->mode == DYNAMIC_ARP && ret_arp_data->status == STALE) {
+ rte_rwlock_write_lock(&ret_arp_data->queue_lock);
ether_addr_copy(&null_ether_addr, &ret_arp_data->eth_addr);
ret_arp_data->status = PROBE;
- struct arp_timer_key * callback_key =
- (struct arp_timer_key*) rte_malloc(NULL,
- sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
- callback_key->port_id = arp_key.port_id;
- callback_key->ip = arp_key.ip;
- if(ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",ARP_TIMER_EXPIRY);
- if(rte_timer_reset(ret_arp_data->timer,
+ struct arp_timer_key * callback_key =
+ (struct arp_timer_key*) rte_malloc(NULL,
+ sizeof(struct arp_timer_key*),RTE_CACHE_LINE_SIZE);
+ callback_key->port_id = arp_key.port_id;
+ callback_key->ip = arp_key.ip;
+ if(ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u"
+ " seconds\n",ARP_TIMER_EXPIRY);
+ if(rte_timer_reset(ret_arp_data->timer,
(arp_timeout * rte_get_tsc_hz()),
SINGLE,timer_lcore,
arp_timer_callback,
callback_key) < 0)
- if(ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
+ if(ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
- ret_arp_data->timer_key = callback_key;
+ ret_arp_data->timer_key = callback_key;
/* send arp request */
request_arp(arp_key.port_id, arp_key.ip);
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
}
}
@@ -873,7 +921,7 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m
return ret_arp_data;
}
-struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
+struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode)
{
struct nd_entry_data *ret_nd_data = NULL;
nd_key.filler1 = 0;
@@ -884,31 +932,109 @@ struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key)
/*Find a nd IPv6 key-data pair in the hash table for ND IPv6 */
int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
(void **)&ret_nd_data);
- if (ret < 0) {
-/* RTE_LOG(INFO, LIBARP,"nd-hash: no lookup Entry Found - ret %d, EINVAL %d, ENOENT %d\n",
- ret, EINVAL, ENOENT);*/
- } else {
- if (ret_nd_data->mode == DYNAMIC_ND) {
- struct nd_timer_key callback_key;
- callback_key.port_id = ret_nd_data->port;
+ if (ret < 0 && (mode == DYNAMIC_ND)) {
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP, "ND entry not found for ip \n");
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
- callback_key.ipv6[i] = ret_nd_data->ipv6[i];
+ /* add INCOMPLETE arp entry */
+ ret_nd_data = rte_malloc_socket(NULL, sizeof(struct nd_entry_data),
+ RTE_CACHE_LINE_SIZE, rte_socket_id());
+ ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
+ ret_nd_data->status = INCOMPLETE;
+ ret_nd_data->port = nd_key.port_id;
+
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ ret_nd_data->ipv6[i] = nd_key.ipv6[i];
+ ret_nd_data->mode = mode;
+ ret_nd_data->num_pkts = 0;
+ rte_rwlock_init(&ret_nd_data->queue_lock);
+ rte_rwlock_write_lock(&ret_nd_data->queue_lock);
+
+ /* attempt to add arp_entry to hash */
+ ret = add_nd_data(&nd_key, ret_nd_data);
+
+ if (ret == EEXIST) {
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ rte_free(ret_nd_data);
+ /* Some other thread has 'beat' this thread in
+ creation of arp_data, try again */
+ return NULL;
+ }
+
+
+ if (rte_mempool_get(timer_mempool_arp,
+ (void **) &(ret_nd_data->timer) ) < 0) {
+ RTE_LOG(INFO, LIBARP,"Error in getting timer alloc buf\n");
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ return NULL;
+ }
+
+ ret_nd_data->buf_pkts = (struct rte_mbuf **)rte_zmalloc_socket(
+ NULL, sizeof(struct rte_mbuf *) * nd_buffer,
+ RTE_CACHE_LINE_SIZE, rte_socket_id());
+
+ if (ret_nd_data->buf_pkts == NULL) {
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ RTE_LOG(INFO, LIBARP,"Could not allocate buf for queueing\n");
+ return NULL;
+ }
+
+ rte_timer_init(ret_nd_data->timer);
+ struct nd_timer_key * callback_key =
+ (struct nd_timer_key*) rte_malloc(NULL,
+ sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
+ callback_key->port_id = nd_key.port_id;
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
+ callback_key->ipv6[i] = ret_nd_data->ipv6[i];
+ }
+
+ if(ARPICMP_DEBUG) {
+ RTE_LOG(INFO, LIBARP,"TIMER STARTED FOR %u seconds\n",
+ ARP_TIMER_EXPIRY);
+ }
+ if(rte_timer_reset(ret_nd_data->timer,
+ (PROBE_TIME * rte_get_tsc_hz() / 1000),
+ SINGLE,timer_lcore,
+ nd_timer_callback,
+ callback_key) < 0)
+ if(ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,"Err : Timer already running\n");
+
+ ret_nd_data->timer_key = callback_key;
+ /* send nd request */
+ request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ } else {
+ if (ret_nd_data &&
+ ret_nd_data->mode == DYNAMIC_ND && ret_nd_data->status == STALE) {
+ rte_rwlock_write_lock(&ret_nd_data->queue_lock);
+ ether_addr_copy(&null_ether_addr, &ret_nd_data->eth_addr);
+ ret_nd_data->status = PROBE;
+ struct nd_timer_key * callback_key =
+ (struct nd_timer_key*) rte_malloc(NULL,
+ sizeof(struct nd_timer_key*),RTE_CACHE_LINE_SIZE);
+
+ callback_key->port_id = nd_key.port_id;
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
+ callback_key->ipv6[i] = ret_nd_data->ipv6[i];
}
if (rte_timer_reset
- (ret_nd_data->timer,
- (arp_timeout * rte_get_tsc_hz()), SINGLE,
- timer_lcore, nd_timer_callback, &callback_key) < 0)
- if (ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP,
- "Err : Timer already running\n");
+ (ret_nd_data->timer,
+ (arp_timeout * rte_get_tsc_hz()), SINGLE,
+ timer_lcore, nd_timer_callback, callback_key) < 0)
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,
+ "Err : Timer already running\n");
+ ret_nd_data->timer_key = callback_key;
+
+ /* send nd request */
+ request_nd(callback_key->ipv6, ifm_get_port(callback_key->port_id));
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
}
- return ret_nd_data;
}
-
- return NULL;
+ return ret_nd_data;
}
static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"};
@@ -919,13 +1045,10 @@ void print_arp_table(void)
void *next_data;
uint32_t iter = 0;
- printf
- ("------------------------ ARP CACHE -----------------------------------------\n");
- printf
- ("----------------------------------------------------------------------------\n");
+ printf("------------------------ ARP CACHE ------------------------------------\n");
+ printf("-----------------------------------------------------------------------\n");
printf("\tport hw addr status ip addr\n");
- printf
- ("----------------------------------------------------------------------------\n");
+ printf("-----------------------------------------------------------------------\n");
while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter)
>= 0) {
@@ -934,8 +1057,8 @@ void print_arp_table(void)
(struct arp_entry_data *)next_data;
struct arp_key_ipv4 tmp_arp_key;
memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4));
- printf
- ("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n",
+ printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X"
+ " %10s %d.%d.%d.%d\n",
tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0],
tmp_arp_data->eth_addr.addr_bytes[1],
tmp_arp_data->eth_addr.addr_bytes[2],
@@ -956,11 +1079,12 @@ void print_arp_table(void)
printf("0x%x 0x%x %d 0x%x\n",
p_arp_data->lib_arp_route_table[i].ip,
p_arp_data->lib_arp_route_table[i].mask,
- p_arp_data->lib_arp_route_table[i].port, p_arp_data->lib_arp_route_table[i].nh);
+ p_arp_data->lib_arp_route_table[i].port,
+ p_arp_data->lib_arp_route_table[i].nh);
}
- printf
- ("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
+ printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u,"
+ " no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found,
lib_arp_arp_entry_found, lib_arp_no_arp_entry_found,
lib_arp_populate_called, lib_arp_delete_called,
@@ -976,12 +1100,10 @@ void print_nd_table(void)
void *next_data;
uint32_t iter = 0;
uint8_t ii = 0, j = 0, k = 0;
- printf
- ("------------------------------------------------------------------------------------------------------\n");
+ printf("-----------------------------------------------------------------------\n");
printf("\tport hw addr status ip addr\n");
- printf
- ("------------------------------------------------------------------------------------------------------\n");
+ printf("-----------------------------------------------------------------------\n");
while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >=
0) {
@@ -997,8 +1119,7 @@ void print_nd_table(void)
tmp_nd_data->eth_addr.addr_bytes[3],
tmp_nd_data->eth_addr.addr_bytes[4],
tmp_nd_data->eth_addr.addr_bytes[5],
- tmp_nd_data->status ==
- COMPLETE ? "COMPLETE" : "INCOMPLETE");
+ arp_status[tmp_nd_data->status]);
printf("\t\t\t\t\t\t");
for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) {
printf("%02X%02X ", tmp_nd_data->ipv6[ii],
@@ -1010,8 +1131,8 @@ void print_nd_table(void)
uint32_t i = 0;
printf("\n\nND IPV6 routing table has %d entries\n",
nd_route_tbl_index);
- printf
- ("\nIP_Address Depth Port NH_IP_Address\n");
+ printf("\nIP_Address Depth");
+ printf(" Port NH_IP_Address\n");
for (i = 0; i < nd_route_tbl_index; i++) {
printf("\n");
@@ -1030,8 +1151,8 @@ void print_nd_table(void)
lib_nd_route_table[i].ipv6[k + 1]);
}
}
- printf
- ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
+ printf("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u,"
+ " no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n",
lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found,
lib_nd_nd_entry_found, lib_nd_no_arp_entry_found,
lib_nd_populate_called, lib_nd_delete_called,
@@ -1053,10 +1174,8 @@ void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
RTE_LOG(INFO, LIBARP,
"ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n",
(arp_key->ip >> 24),
- ((arp_key->ip & 0x00ff0000) >>
- 16),
- ((arp_key->ip & 0x0000ff00) >>
- 8),
+ ((arp_key->ip & 0x00ff0000) >> 16),
+ ((arp_key->ip & 0x0000ff00) >> 8),
((arp_key->ip & 0x000000ff)),
arp_key->port_id);
}
@@ -1065,80 +1184,65 @@ void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg)
}
/* ND IPv6 */
-void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid)
+void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg)
{
int i = 0;
- struct nd_entry_data *ret_nd_data = NULL;
- struct nd_key_ipv6 nd_key;
- nd_key.port_id = portid;
-
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
- nd_key.ipv6[i] = ipv6addr[i];
- }
-
- nd_key.filler1 = 0;
- nd_key.filler2 = 0;
- nd_key.filler3 = 0;
+ struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
lib_nd_delete_called++;
- if (NDIPV6_DEBUG) {
- RTE_LOG(INFO, LIBARP,
- "Deletes rte hash table nd entry for port %d ipv6=",
- nd_key.port_id);
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
- RTE_LOG(INFO, LIBARP, "%02X%02X ", nd_key.ipv6[i],
- nd_key.ipv6[i + 1]);
- }
- }
- struct nd_timer_key callback_key;
- callback_key.port_id = portid;
-
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
- callback_key.ipv6[i] = ipv6addr[i];
-
- }
- int ret = rte_hash_lookup_data(arp_hash_handle, &callback_key,
- (void **)&ret_nd_data);
- if (ret < 0) {
-// RTE_LOG(INFO, LIBARP,"arp-hash lookup failed ret %d, EINVAL %d, ENOENT %d\n", ret, EINVAL, ENOENT);
- } else {
- if (ret_nd_data->mode == DYNAMIC_ND) {
- rte_timer_stop(ret_nd_data->timer);
- rte_free(ret_nd_data->timer);
- }
- }
- rte_hash_del_key(nd_hash_handle, &nd_key);
+ rte_timer_stop(ret_nd_data->timer);
+ rte_free(ret_nd_data->timer_key);
+ rte_free(ret_nd_data->buf_pkts);
+ ret_nd_data->buf_pkts = NULL;
+
+ if (NDIPV6_DEBUG) {
+ RTE_LOG(INFO, LIBARP,
+ "Deletes rte hash table nd entry for port %d ipv6=",
+ timer_key->port_id);
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
+ RTE_LOG(INFO, LIBARP, "%02X%02X ", timer_key->ipv6[i],
+ timer_key->ipv6[i + 1]);
+ }
+ }
+ rte_hash_del_key(nd_hash_handle, timer_key);
}
int
arp_queue_unresolved_packet(struct arp_entry_data *ret_arp_data, struct rte_mbuf *pkt)
{
+ rte_rwlock_write_lock(&ret_arp_data->queue_lock);
if (ret_arp_data->num_pkts == NUM_DESC) {
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
return 0;
}
+
ret_arp_data->buf_pkts[ret_arp_data->num_pkts++] = pkt;
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
return 0;
}
void
-arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,struct ether_addr *hw_addr, uint8_t port_id)
+arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,
+ struct ether_addr *hw_addr, uint8_t port_id)
{
l2_phy_interface_t *port = ifm_get_port(port_id);
struct rte_mbuf *pkt, *tmp;
uint8_t *eth_dest, *eth_src;
int i;
-
+
if (!hw_addr || !ret_arp_data)
return;
+ rte_rwlock_write_lock(&ret_arp_data->queue_lock);
for (i=0;i<(int)ret_arp_data->num_pkts;i++) {
pkt = ret_arp_data->buf_pkts[i];
- eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
- eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
- memcpy(eth_dest, &hw_addr, sizeof(struct ether_addr));
+ eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+
+ memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
memcpy(eth_src, get_link_hw_addr(port_id),
sizeof(struct ether_addr));
port->transmit_single_pkt(port, pkt);
@@ -1146,8 +1250,50 @@ arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,struct ether_addr *hw
rte_pktmbuf_free(tmp);
}
ret_arp_data->num_pkts = 0;
- ret_arp_data->buffered_pkt_list_head = NULL;
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
+}
+int
+nd_queue_unresolved_packet(struct nd_entry_data *ret_nd_data, struct rte_mbuf *pkt)
+{
+ rte_rwlock_write_lock(&ret_nd_data->queue_lock);
+ if (ret_nd_data->num_pkts == get_nd_buf()) {
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ return 0;
+ }
+
+ ret_nd_data->buf_pkts[ret_nd_data->num_pkts++] = pkt;
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ return 0;
+}
+
+void
+nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,
+ struct ether_addr *hw_addr, uint8_t port_id)
+{
+ l2_phy_interface_t *port = ifm_get_port(port_id);
+ struct rte_mbuf *pkt, *tmp;
+ uint8_t *eth_dest, *eth_src;
+ int i;
+
+ if (!hw_addr || !ret_nd_data)
+ return;
+
+ rte_rwlock_write_lock(&ret_nd_data->queue_lock);
+ for (i=0;i<(int)ret_nd_data->num_pkts;i++) {
+ pkt = ret_nd_data->buf_pkts[i];
+ eth_dest = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM);
+ eth_src = RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6);
+
+ memcpy(eth_dest, hw_addr, sizeof(struct ether_addr));
+ memcpy(eth_src, get_link_hw_addr(port_id),
+ sizeof(struct ether_addr));
+ port->transmit_single_pkt(port, pkt);
+ tmp = pkt;
+ rte_pktmbuf_free(tmp);
+ }
+ ret_nd_data->num_pkts = 0;
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
}
void
@@ -1171,14 +1317,13 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
new_arp_data = retrieve_arp_entry(arp_key, mode);
if (new_arp_data && ((new_arp_data->mode == STATIC_ARP
- && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
- && mode == STATIC_ARP))) {
- if (ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry already exists(%d %d)\n",
- new_arp_data->mode, mode);
-
- return;
- }
+ && mode == DYNAMIC_ARP) || (new_arp_data->mode == DYNAMIC_ARP
+ && mode == STATIC_ARP))) {
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,"populate_arp_entry: ARP entry "
+ "already exists(%d %d)\n", new_arp_data->mode, mode);
+ return;
+ }
if (mode == DYNAMIC_ARP) {
@@ -1196,6 +1341,7 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
arp_key.port_id);
}
lib_arp_duplicate_found++;
+ rte_rwlock_write_lock(&new_arp_data->queue_lock);
new_arp_data->retry_count = 0; // Reset
if (new_arp_data->status == STALE) {
new_arp_data->status = PROBE;
@@ -1211,7 +1357,7 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
new_arp_data->port);
}
}
-
+
if (rte_timer_reset(new_arp_data->timer,
(arp_timeout * rte_get_tsc_hz()),
SINGLE, timer_lcore,
@@ -1221,16 +1367,16 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
RTE_LOG(INFO, LIBARP,
"Err : Timer already running\n");
}
+ rte_rwlock_write_unlock(&new_arp_data->queue_lock);
return;
} else {
+ rte_rwlock_write_lock(&new_arp_data->queue_lock);
ether_addr_copy(hw_addr, &new_arp_data->eth_addr);
if ((new_arp_data->status == INCOMPLETE) ||
(new_arp_data->status == PROBE)) {
new_arp_data->status = COMPLETE;
new_arp_data->mode = mode;
- new_arp_data->n_confirmed = time(NULL);
- //end_tsc[new_arp_data->port] = rte_rdtsc();
- //printf("confirmed val is %x %dms\n",new_arp_data->ip, (end_tsc[new_arp_data->port] - start_tsc[new_arp_data->port] + ticks_per_ms/2)/ticks_per_ms);
+ new_arp_data->n_confirmed = rte_rdtsc();
new_arp_data->retry_count = 0;
if (rte_timer_reset(new_arp_data->timer,
(arp_timeout * rte_get_tsc_hz()),
@@ -1242,6 +1388,7 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
"Err : Timer already running\n");
}
}
+ rte_rwlock_write_unlock(&new_arp_data->queue_lock);
return;
}
} else {
@@ -1269,12 +1416,16 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
new_arp_data->port = portid;
new_arp_data->ip = ipaddr;
new_arp_data->mode = mode;
- new_arp_data->buffered_pkt_list_head = NULL;
- new_arp_data->buffered_pkt_list_tail = NULL;
new_arp_data->num_pkts = 0;
-
- rte_hash_add_key_data(arp_hash_handle, &arp_key,
- new_arp_data);
+
+ /* attempt to add arp_entry to hash */
+ int ret;
+ ret = add_arp_data(&arp_key, new_arp_data);
+ if (ret) {
+ /* Some other thread created an entry for this ip */
+ rte_free(new_arp_data);
+ }
+
if (ARPICMP_DEBUG) {
RTE_LOG(INFO, LIBARP,
"arp_entry exists ip :%d.%d.%d.%d , port %d\n",
@@ -1314,21 +1465,24 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr,
* Install key - data pair in Hash table - From Pipeline Configuration
*
*/
-
void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
uint8_t portid, uint8_t mode)
{
/* need to lock here if multi-threaded */
/* rte_hash_add_key_data is not thread safe */
- uint8_t i;
+ uint8_t i, val = 0;
struct nd_key_ipv6 nd_key;
nd_key.port_id = portid;
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
+ for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
nd_key.ipv6[i] = ipv6[i];
+ val |= ipv6[i];
+ }
+
+ if (!val)
+ return;
-// RTE_LOG(INFO, LIBARP,"\n");
nd_key.filler1 = 0;
nd_key.filler2 = 0;
nd_key.filler3 = 0;
@@ -1336,11 +1490,18 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
lib_nd_populate_called++;
/* Validate if key-value pair already exists in the hash table for ND IPv6 */
- struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
+ struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, mode);
+ if (new_nd_data && ((new_nd_data->mode == STATIC_ND
+ && mode == DYNAMIC_ND) || (new_nd_data->mode == DYNAMIC_ND
+ && mode == STATIC_ND))) {
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP, "populate_arp_entry: ND entry already"
+ " exists(%d %d)\n", new_nd_data->mode, mode);
+ return;
+ }
if (mode == DYNAMIC_ND) {
- if (new_nd_data
- && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
+ if (new_nd_data && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
if (NDIPV6_DEBUG) {
RTE_LOG(INFO, LIBARP,
@@ -1355,61 +1516,48 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
}
lib_nd_duplicate_found++;
- RTE_LOG(INFO, LIBARP, "nd_entry exists\n");
- return;
- }
- uint32_t size =
- RTE_CACHE_LINE_ROUNDUP(sizeof(struct nd_entry_data));
- new_nd_data = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
-
- //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
- new_nd_data->eth_addr = *hw_addr;
- new_nd_data->status = COMPLETE;
- new_nd_data->port = portid;
- new_nd_data->mode = mode;
- if (rte_mempool_get
- (timer_mempool_arp, (void **)&(new_nd_data->timer)) < 0) {
- RTE_LOG(INFO, LIBARP,
- "TIMER - Error in getting timer alloc buffer\n");
+ rte_rwlock_write_lock(&new_nd_data->queue_lock);
+ if (new_nd_data->status == STALE) {
+ new_nd_data->retry_count = 0; // Reset
+ new_nd_data->status = PROBE;
+ request_nd(new_nd_data->ipv6,
+ ifm_get_port(new_nd_data->port));
+
+ if (rte_timer_reset(new_nd_data->timer,
+ (arp_timeout * rte_get_tsc_hz()),
+ SINGLE, timer_lcore,
+ nd_timer_callback,
+ new_nd_data->timer_key) < 0) {
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,
+ "Err : Timer already running\n");
+ }
+ }
+ rte_rwlock_write_unlock(&new_nd_data->queue_lock);
return;
- }
-
- if (NDIPV6_DEBUG)
- RTE_LOG(INFO, LIBARP, "populate_nd_entry ipv6=");
-
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
- new_nd_data->ipv6[i] = ipv6[i];
- }
-
- if (NDIPV6_DEBUG) {
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i += 2) {
-
- RTE_LOG(INFO, LIBARP, "%02X%02X ",
- new_nd_data->ipv6[i],
- new_nd_data->ipv6[i + 1]);
+ } else {
+ rte_rwlock_write_lock(&new_nd_data->queue_lock);
+ ether_addr_copy(hw_addr, &new_nd_data->eth_addr);
+ if ((new_nd_data->status == INCOMPLETE) ||
+ (new_nd_data->status == PROBE)) {
+ new_nd_data->status = COMPLETE;
+ new_nd_data->mode = mode;
+ new_nd_data->n_confirmed = rte_rdtsc();
+ new_nd_data->retry_count = 0;
+ if (rte_timer_reset(new_nd_data->timer,
+ (arp_timeout * rte_get_tsc_hz()),
+ SINGLE, timer_lcore,
+ nd_timer_callback,
+ new_nd_data->timer_key) < 0) {
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,
+ "Err : Timer already running\n");
+ }
}
- }
-
- /*Add a key-data pair at hash table for ND IPv6 static routing */
- rte_hash_add_key_data(nd_hash_handle, &nd_key, new_nd_data);
- /* need to check the return value of the hash add */
-
- /* after the hash is created then time is started */
- rte_timer_init(new_nd_data->timer);
- struct nd_timer_key *callback_key =
- (struct nd_timer_key *)rte_malloc(NULL,
- sizeof(struct nd_timer_key
- *),
- RTE_CACHE_LINE_SIZE);
- callback_key->port_id = portid;
+ rte_rwlock_write_unlock(&new_nd_data->queue_lock);
+ return;
+ }
- for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
- callback_key->ipv6[i] = ipv6[i];
- }
- if (rte_timer_reset
- (new_nd_data->timer, (arp_timeout * rte_get_tsc_hz()),
- SINGLE, timer_lcore, nd_timer_callback, callback_key) < 0)
- RTE_LOG(INFO, LIBARP, "Err : Timer already running\n");
} else {
if (new_nd_data
&& is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) {
@@ -1433,7 +1581,6 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
new_nd_data =
rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
- //new_nd_data = (struct nd_entry_data *)rte_malloc(NULL, sizeof(struct nd_entry_data *),RTE_CACHE_LINE_SIZE);
new_nd_data->eth_addr = *hw_addr;
new_nd_data->status = COMPLETE;
new_nd_data->port = portid;
@@ -1441,13 +1588,25 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[],
for (i = 0; i < ND_IPV6_ADDR_SIZE; i++) {
new_nd_data->ipv6[i] = ipv6[i];
}
+ new_nd_data->mode = mode;
+ new_nd_data->num_pkts = 0;
/*Add a key-data pair at hash table for ND IPv6 static routing */
- rte_hash_add_key_data(nd_hash_handle, &nd_key,
- new_nd_data);
+ /* attempt to add arp_entry to hash */
+ int ret;
+ ret = add_nd_data(&nd_key, new_nd_data);
+ if (ret) {
+ rte_free(new_nd_data);
+ }
+
/* need to check the return value of the hash add */
+ #ifdef L3_STACK_SUPPORT
+ // Call l3fwd module for resolving 2_adj structure.
+ resolve_l2_adj(ipaddr, portid, hw_addr);
+ #endif
}
}
+
if (NDIPV6_DEBUG)
printf
("\n....Added a key-data pair at rte hash table for ND IPv6 static routing\n");
@@ -1743,7 +1902,6 @@ void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
print_mbuf("TX", port->pmdid, pkt,
__LINE__);
printf("replying arp pkt done\n");
- //rte_pktmbuf_free(pkt);
return;
} else if (arp_h->arp_op ==
rte_cpu_to_be_16(ARP_OP_REPLY)) {
@@ -1759,7 +1917,6 @@ void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
arp_data.arp_sip),
in_port_id, DYNAMIC_ARP);
- //rte_pktmbuf_free(pkt);
return;
} else {
if (ARPICMP_DEBUG)
@@ -1887,7 +2044,8 @@ void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
arp_key.filler3 = 0;
struct arp_entry_data *arp_entry =
- retrieve_arp_entry(arp_key, DYNAMIC_ARP);
+ retrieve_arp_entry(arp_key,
+ DYNAMIC_ARP);
if (arp_entry == NULL) {
if (ARPICMP_DEBUG)
RTE_LOG(INFO, LIBARP,
@@ -1903,7 +2061,6 @@ void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
rte_pktmbuf_free(pkt);
}
- printf("reached end of process_arpicmp\n");
}
/* int
@@ -2095,7 +2252,6 @@ static int arp_parse_args(struct pipeline_params *params)
{
uint32_t arp_route_tbl_present = 0;
uint32_t nd_route_tbl_present = 0;
- uint32_t ports_mac_list_present = 0;
uint32_t numArg;
uint32_t n_vnf_threads_present = 0;
@@ -2110,7 +2266,6 @@ static int arp_parse_args(struct pipeline_params *params)
pub_to_prv_map[i] = 0xff;
}
- RTE_SET_USED(ports_mac_list_present);
RTE_SET_USED(nd_route_tbl_present);
RTE_SET_USED(arp_route_tbl_present);
for (numArg = 0; numArg < params->n_args; numArg++) {
@@ -2164,6 +2319,12 @@ static int arp_parse_args(struct pipeline_params *params)
if (strcmp(arg_name, "arp_buf") == 0) {
arp_buffer = atoi(arg_value);
+ continue;
+ }
+
+ if (strcmp(arg_name, "nd_buf") == 0) {
+ nd_buffer = atoi(arg_value);
+ continue;
}
/* prv_to_pub_map */
@@ -2247,50 +2408,6 @@ static int arp_parse_args(struct pipeline_params *params)
continue;
}
- /* ports_mac_list */
- if (strcmp(arg_name, "ports_mac_list") == 0) {
- ports_mac_list_present = 1;
-
- uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6;
-
- char byteStr[MAC_NUM_BYTES][3];
- uint32_t byte[MAC_NUM_BYTES];
-
- char *token = strtok(arg_value, " ");
- while (token) {
- k = 0;
- for (i = 0; i < MAC_NUM_BYTES; i++) {
- for (j = 0; j < 2; j++) {
- byteStr[i][j] = token[k++];
- }
- byteStr[i][j] = '\0';
- k++;
- }
-
- for (i = 0; i < MAC_NUM_BYTES; i++) {
- byte[i] = strtoul(byteStr[i], NULL, 16);
- }
-
- if (ARPICMP_DEBUG) {
- RTE_LOG(INFO, LIBARP, "token: %s",
- token);
- for (i = 0; i < MAC_NUM_BYTES; i++)
- RTE_LOG(INFO, LIBARP,
- ", byte[%u] %u", i,
- byte[i]);
- RTE_LOG(INFO, LIBARP, "\n");
- }
- //Populate the static arp_route_table
- for (i = 0; i < MAC_NUM_BYTES; i++)
- p_arp_data->link_hw_addr[p_arp_data->link_hw_addr_array_idx].addr_bytes[i] = byte[i];
-
- p_arp_data->link_hw_addr_array_idx++;
- token = strtok(NULL, " ");
- }
-
- continue;
- }
-
/* arp_route_tbl */
if (strcmp(arg_name, "arp_route_tbl") == 0) {
arp_route_tbl_present = 1;
@@ -2364,7 +2481,7 @@ static int arp_parse_args(struct pipeline_params *params)
//Populate the static arp_route_table
struct lib_arp_route_table_entry *lentry =
&p_arp_data->lib_arp_route_table
- [p_arp_data->lib_arp_route_ent_cnt];
+ [p_arp_data->lib_arp_route_ent_cnt];
lentry->ip = dest_ip;
lentry->mask = mask;
lentry->port = tx_port;
@@ -2483,6 +2600,25 @@ static void local_arp_cache_init(void)
}
}
+struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[])
+{
+ int i, j, limit;
+ struct ether_addr *x = NULL;
+ limit = p_arp_data->nd_local_cache[out_port].num_nhip;
+
+ for (i=0; i < limit; i++) {
+ for (j=0;j<16;j++) {
+ if (p_arp_data->nd_local_cache[out_port].nhip[i][j] != nhip[j])
+ continue;
+ }
+
+ x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i];
+ return x;
+ }
+
+ return x;
+}
+
struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip)
{
int i, limit;
@@ -2492,7 +2628,7 @@ struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip)
for (i=0; i < limit; i++) {
tmp = p_arp_data->arp_local_cache[out_port].nhip[i];
if (tmp == nhip) {
- x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
+ x = &p_arp_data->arp_local_cache[out_port].link_hw_laddr[i];
return x;
}
}
@@ -2513,13 +2649,27 @@ void lib_arp_init(struct pipeline_params *params,
size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct arp_data));
p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
p_arp_data = (struct arp_data *)p;
-
+
/* Parse arguments */
if (arp_parse_args(params)) {
RTE_LOG(INFO, LIBARP, "arp_parse_args failed ...\n");
return;
}
+ /* acquire the mac addresses */
+ struct ether_addr hw_addr;
+ uint8_t nb_ports = rte_eth_dev_count();
+
+ for (i = 0; i < nb_ports; i++) {
+ rte_eth_macaddr_get(i, &hw_addr);
+ ether_addr_copy(&hw_addr, &p_arp_data->link_hw_addr[i]);
+ p_arp_data->link_hw_addr_array_idx++;
+ }
+
+ /* create a lock for arp/nd hash */
+ rte_rwlock_init(&arp_hash_handle_lock);
+ rte_rwlock_init(&nd_hash_handle_lock);
+
/* create the arp_icmp mbuf rx pool */
lib_arp_pktmbuf_tx_pool =
rte_pktmbuf_pool_create("lib_arp_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
@@ -2538,9 +2688,29 @@ void lib_arp_init(struct pipeline_params *params,
return;
}
}
+
+ /* create the nd icmp mbuf rx pool */
+ lib_nd_pktmbuf_tx_pool =
+ rte_pktmbuf_pool_create("lib_nd_mbuf_tx_pool", NB_ARPICMP_MBUF, 32,
+ 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+ rte_socket_id());
+
+ if (lib_nd_pktmbuf_tx_pool == NULL) {
+ RTE_LOG(INFO, LIBARP, "ND mbuf pool create failed.\n");
+ return;
+ }
+
+ for (i=0; i<MAX_PORTS; i++) {
+ lib_nd_pkt[i] = rte_pktmbuf_alloc(lib_nd_pktmbuf_tx_pool);
+ if (lib_nd_pkt[i] == NULL) {
+ RTE_LOG(INFO, LIBARP, "ND lib_nd_pkt alloc failed.\n");
+ return;
+ }
+ }
+
/* create the arp_icmp mbuf rx pool */
- arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
- NB_ARPICMP_MBUF, 32, 0,
+ arp_icmp_pktmbuf_tx_pool = rte_pktmbuf_pool_create("arp_icmp_mbuf_tx_pool",
+ NB_ARPICMP_MBUF, MAX_POOL, 0,
RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
if (arp_icmp_pktmbuf_tx_pool == NULL) {
@@ -2607,7 +2777,7 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
arp_key.filler3 = 0;
struct arp_entry_data *ret_arp_data = NULL;
- time_t now;
+ uint64_t now;
if (ARPICMP_DEBUG) {
RTE_LOG(INFO, LIBARP, "arp_timer_callback ip %x, port %d\n",
arp_key.ip, arp_key.port_id);
@@ -2615,7 +2785,7 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
int ret = rte_hash_lookup_data(arp_hash_handle, &arp_key,
(void **)&ret_arp_data);
- now = time(NULL);
+ now = rte_rdtsc();
if (ARPICMP_DEBUG)
RTE_LOG(INFO, LIBARP, "ARP TIMER callback : expire :%d now:%ld\n",
@@ -2625,13 +2795,14 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
return;
} else {
if (ret_arp_data->mode == DYNAMIC_ARP) {
- if (ret_arp_data->status == PROBE ||
+ rte_rwlock_write_lock(&ret_arp_data->queue_lock);
+ if (ret_arp_data->status == PROBE ||
ret_arp_data->status == INCOMPLETE) {
if (ret_arp_data->retry_count == 3) {
remove_arp_entry(ret_arp_data, arg);
} else {
ret_arp_data->retry_count++;
-
+
if (ARPICMP_DEBUG) {
RTE_LOG(INFO, LIBARP,
"RETRY ARP..retry count : %u\n",
@@ -2644,17 +2815,17 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
if (ifm_chk_port_ipv4_enabled
(ret_arp_data->port)) {
- //printf("inside arp timer callback numpkts:%d\n", ret_arp_data->num_pkts);
request_arp(ret_arp_data->port,
ret_arp_data->ip);
} else {
if (ARPICMP_DEBUG)
RTE_LOG(INFO, LIBARP,
- "%s: IP is not enabled on port %u, not sending GARP\n\r",
+ "%s: IP is not enabled on port %u"
+ ", not sending GARP\n\r",
__FUNCTION__,
ret_arp_data->port);
}
-
+
if (rte_timer_reset(ret_arp_data->timer,
(PROBE_TIME *
rte_get_tsc_hz()/ 1000),
@@ -2668,7 +2839,8 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
}
} else if (ret_arp_data->status == COMPLETE) {
- if (now <= (ret_arp_data->n_confirmed + arp_timeout)) {
+ if (now <= (ret_arp_data->n_confirmed +
+ (arp_timeout * rte_get_tsc_hz()))) {
if (rte_timer_reset(ret_arp_data->timer,
(arp_timeout *
rte_get_tsc_hz()), SINGLE,
@@ -2678,7 +2850,7 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
if (ARPICMP_DEBUG)
RTE_LOG(INFO, LIBARP,
"Err : Timer already running\n");
- } else if (now <= (ret_arp_data->n_last_update + USED_TIME)) {
+ } else if (now <= (p_arp_data->update_tsc[ret_arp_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
if (rte_timer_reset(ret_arp_data->timer,
(arp_timeout *
rte_get_tsc_hz()), SINGLE,
@@ -2693,6 +2865,7 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
p_arp_data->arp_cache_hw_laddr_valid[ret_arp_data->port] = 0;
}
}
+ rte_rwlock_write_unlock(&ret_arp_data->queue_lock);
} else {
rte_hash_del_key(arp_hash_handle, &arp_key);
}
@@ -2702,11 +2875,104 @@ void arp_timer_callback(struct rte_timer *timer, void *arg)
void nd_timer_callback(struct rte_timer *timer, void *arg)
{
- struct nd_timer_key *remove_key = (struct nd_timer_key *)arg;
+ struct nd_timer_key *timer_key = (struct nd_timer_key *)arg;
+ struct nd_key_ipv6 nd_key;
+ int j;
+ struct nd_entry_data *ret_nd_data = NULL;
+ uint64_t now;
+
+ nd_key.port_id = timer_key->port_id;
+ nd_key.filler1 = 0;
+ nd_key.filler2 = 0;
+ nd_key.filler3 = 0;
+
+ rte_mov16(&nd_key.ipv6[0], timer_key->ipv6);
+
+ if (ARPICMP_DEBUG) {
+ RTE_LOG(INFO, LIBARP, "nd_timer_callback port %d\n",
+ nd_key.port_id);
+ }
+
+ int ret = rte_hash_lookup_data(nd_hash_handle, &nd_key,
+ (void **)&ret_nd_data);
+ now = rte_rdtsc();
+
if (ARPICMP_DEBUG)
- RTE_LOG(INFO, LIBARP, "nd time callback : expire :%d\n",
- (int)timer->expire);
- remove_nd_entry_ipv6(remove_key->ipv6, remove_key->port_id);
+ RTE_LOG(INFO, LIBARP, "ND TIMER callback : expire :%d now:%ld\n",
+ (int)timer->expire, now);
+ if (ret < 0) {
+ printf("Should not have come here \n");
+ for (j = 0; j < 16; j++)
+ printf("*%d ", nd_key.ipv6[j]);
+ printf("*%d ", nd_key.port_id);
+ return;
+ } else {
+ if (ret_nd_data->mode == DYNAMIC_ARP) {
+ rte_rwlock_write_lock(&ret_nd_data->queue_lock);
+ if (ret_nd_data->status == PROBE ||
+ ret_nd_data->status == INCOMPLETE) {
+ if (ret_nd_data->retry_count == 3) {
+ remove_nd_entry_ipv6(ret_nd_data, arg);
+ } else {
+ ret_nd_data->retry_count++;
+
+ if (ARPICMP_DEBUG) {
+ RTE_LOG(INFO, LIBARP,
+ "RETRY ND..retry count : %u\n",
+ ret_nd_data->retry_count);
+
+ RTE_LOG(INFO, LIBARP,
+ "TIMER STARTED FOR %u seconds\n",
+ ARP_TIMER_EXPIRY);
+ }
+
+ request_nd(ret_nd_data->ipv6,
+ ifm_get_port(ret_nd_data->port));
+ if (rte_timer_reset(ret_nd_data->timer,
+ (PROBE_TIME *
+ rte_get_tsc_hz()/ 1000),
+ SINGLE,
+ timer_lcore,
+ nd_timer_callback,
+ arg) < 0)
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,
+ "Err : Timer already running\n");
+
+ }
+ } else if (ret_nd_data->status == COMPLETE) {
+ if (now <= (ret_nd_data->n_confirmed +
+ (arp_timeout * rte_get_tsc_hz()))) {
+ if (rte_timer_reset(ret_nd_data->timer,
+ (arp_timeout *
+ rte_get_tsc_hz()), SINGLE,
+ timer_lcore,
+ nd_timer_callback,
+ arg) < 0)
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,
+ "Err : Timer already running\n");
+ } else if (now <= (p_arp_data->update_tsc[ret_nd_data->port] + (USED_TIME * rte_get_tsc_hz()))) {
+ if (rte_timer_reset(ret_nd_data->timer,
+ (arp_timeout *
+ rte_get_tsc_hz()), SINGLE,
+ timer_lcore,
+ nd_timer_callback,
+ arg) < 0)
+ if (ARPICMP_DEBUG)
+ RTE_LOG(INFO, LIBARP,
+ "Err : Timer already running\n");
+ } else {
+ printf("making it stale\n");
+ ret_nd_data->status = STALE;
+ p_arp_data->nd_cache_hw_laddr_valid[ret_nd_data->port] = 0;
+ }
+ }
+ rte_rwlock_write_unlock(&ret_nd_data->queue_lock);
+ } else {
+ rte_hash_del_key(nd_hash_handle, &nd_key);
+ }
+ }
return;
}
diff --git a/common/VIL/l2l3_stack/lib_arp.h b/common/VIL/l2l3_stack/lib_arp.h
index e7fcb421..9cb0205f 100644
--- a/common/VIL/l2l3_stack/lib_arp.h
+++ b/common/VIL/l2l3_stack/lib_arp.h
@@ -31,7 +31,7 @@
#define MAX_ARP_RT_ENTRY 32
#define NUM_DESC (get_arp_buf())
#define ARP_BUF_DEFAULT 30000
-#define PROBE_TIME 500
+#define PROBE_TIME 50
#undef L3_STACK_SUPPORT
/**
@@ -54,6 +54,12 @@ struct arp_cache {
uint32_t num_nhip;
};
+struct nd_cache {
+ uint8_t nhip[MAX_LOCAL_MAC_ADDRESS][16];
+ struct ether_addr link_hw_laddr[MAX_LOCAL_MAC_ADDRESS];
+ uint32_t num_nhip;
+};
+
/**
* A structure for Route table entires of IPv6
*
@@ -65,28 +71,17 @@ struct lib_nd_route_table_entry {
uint8_t nhipv6[16]; /**< next hop Ipv6 */
};
-struct arp_data {
- struct lib_arp_route_table_entry
- lib_arp_route_table[MAX_ARP_RT_ENTRY];
- uint8_t lib_arp_route_ent_cnt;
- struct lib_nd_route_table_entry
- lib_nd_route_table[MAX_ARP_RT_ENTRY];
- uint8_t lib_nd_route_ent_cnt;
- struct arp_cache arp_local_cache[MAX_PORTS];
- struct ether_addr link_hw_addr[MAX_LOCAL_MAC_ADDRESS];
- uint32_t link_hw_addr_array_idx;
- uint8_t arp_cache_hw_laddr_valid[MAX_LOCAL_MAC_ADDRESS];
-} __rte_cache_aligned;
-
uint8_t arp_cache_dest_mac_present(uint32_t out_port);
-
+uint8_t nd_cache_dest_mac_present(uint32_t out_port);
extern struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY];
extern struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY];
extern struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip);
+extern struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]);
extern struct arp_cache arp_local_cache[MAX_PORTS];
extern void prefetch(void);
-extern struct arp_entry_data *arp_data_ptr[16];
+extern void update_nhip_access(uint8_t);
uint32_t get_arp_buf(void);
+uint32_t get_nd_buf(void);
enum {
ARP_FOUND,
@@ -156,8 +151,6 @@ enum {
STALE
};
#define USED_TIME 5
-//#define COMPLETE 1 /**< ARP entry populated and echo reply recieved. */
-//#define INCOMPLETE 0 /**< ARP entry populated and either awaiting echo reply or stale entry. */
extern uint32_t NDIPV6_DEBUG; /**< ND IPv6 */
@@ -182,14 +175,10 @@ struct arp_entry_data {
uint8_t retry_count; /**< retry count for ARP*/
struct rte_timer *timer; /**< Timer Associated with ARP*/
struct arp_timer_key *timer_key;
- struct rte_ring *queue; /** pkts queued */
rte_rwlock_t queue_lock; /** queue lock */
struct rte_mbuf **buf_pkts;
- struct rte_mbuf *buffered_pkt_list_head;
- struct rte_mbuf *buffered_pkt_list_tail;
uint32_t num_pkts;
- uint32_t n_confirmed;
- uint32_t n_last_update;
+ uint64_t n_confirmed;
} __attribute__ ((packed));
/**
@@ -215,7 +204,13 @@ struct nd_entry_data {
uint8_t status; /**< statusof the entry */
uint8_t mode; /**< Mode */
uint8_t ipv6[ND_IPV6_ADDR_SIZE]; /**< Ipv6 address */
+ uint8_t retry_count; /**< retry count for ARP*/
struct rte_timer *timer; /**< Timer */
+ struct nd_timer_key *timer_key;
+ rte_rwlock_t queue_lock; /** queue lock */
+ struct rte_mbuf **buf_pkts;
+ uint32_t num_pkts;
+ uint64_t n_confirmed;
} __attribute__ ((packed));
/**
@@ -232,21 +227,22 @@ struct table_nd_entry_data {
struct rte_timer *timer; /**< Timer */
} __attribute__ ((packed));
-/**
-* To get the destination MAC address andnext hop for the ip address and outgoing port
-* @param1 ip addr
-* IP address for which MAC address is needed.
-* @param2 phy_port
-* Physical Port
-* @param3 ether_addr
-* pointer to the ether_addr, This gets update with valid MAC addresss
-* @Param4 next nhip
-* Gets the next hop IP by Ip address and physical port
-* @return
-* 0 if failure, and 1 if success
-*/
+struct arp_data {
+ struct lib_arp_route_table_entry
+ lib_arp_route_table[MAX_ARP_RT_ENTRY];
+ uint8_t lib_arp_route_ent_cnt;
+ struct lib_nd_route_table_entry
+ lib_nd_route_table[MAX_ARP_RT_ENTRY];
+ uint8_t lib_nd_route_ent_cnt;
+ struct arp_cache arp_local_cache[MAX_PORTS];
+ struct nd_cache nd_local_cache[MAX_PORTS];
+ struct ether_addr link_hw_addr[MAX_LOCAL_MAC_ADDRESS];
+ uint32_t link_hw_addr_array_idx;
+ uint8_t arp_cache_hw_laddr_valid[MAX_LOCAL_MAC_ADDRESS];
+ uint8_t nd_cache_hw_laddr_valid[MAX_LOCAL_MAC_ADDRESS];
+ uint64_t update_tsc[MAX_LOCAL_MAC_ADDRESS];
+} __rte_cache_aligned;
-struct arp_entry_data *get_dest_mac_address(const uint32_t ipaddr, uint32_t *phy_port, struct ether_addr *hw_addr, uint32_t *nhip);
/**
* To get the destination MAC address andnext hop for the ip address and outgoing port
* @param1 ip addr
@@ -264,35 +260,6 @@ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr,
uint32_t *phy_port, struct ether_addr *hw_addr);
/**
-* To get the destination mac address for IPv4 address
-* @param Ipaddr
-* IP address which need the destination mac address
-* @param Phy_port
-* physical port
-* @param ether_addr
-* pointer to the ether_addr, This gets update with valid mac address
-* @return
-* 0 if failure, 1 if success
-*/
-int get_dest_mac_addr(const uint32_t ipaddr, uint32_t *phy_port,
- struct ether_addr *hw_addr);
-
-/**
-* To get the destination mac address for IPV6 address
-* @param ipv6addr
-* IPv6 address which need the destination mac adress
-* @param Phy_Port
-* physical prt
-* @param ether_addr
-* pointer to the ether_address, This gets update with valid mac address
-* @param Nhipv6[]
-* Gets the next hop ipv6 address by ipv6 address and physical port
-* @return
-* 0 if failure, 1 ifsuccess
-*/
-int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t *phy_port,
- struct ether_addr *hw_addr, uint8_t nhipv6[]);
-/**
* To get the destination mac address for IPV6 address
* @param ipv6addr
* IPv6 address which need the destination mac adress
@@ -306,13 +273,17 @@ int get_dest_mac_address_ipv6(uint8_t ipv6addr[], uint32_t *phy_port,
* 0 if failure, 1 ifsuccess
*/
-int get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
+struct nd_entry_data *get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port,
struct ether_addr *hw_addr,
uint8_t nhipv6[]);
int arp_queue_unresolved_packet(struct arp_entry_data * arp_data,
struct rte_mbuf * m);
extern void arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,struct ether_addr *hw_addr, uint8_t port_id);
+int nd_queue_unresolved_packet(struct nd_entry_data *nd_data,
+ struct rte_mbuf * m);
+extern void nd_send_buffered_pkts(struct nd_entry_data *ret_nd_data,struct ether_addr *hw_addr, uint8_t port_id);
+
/**
* To get hardware link address
* @param out_port
@@ -352,7 +323,7 @@ void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg);
* Port id
*/
-void remove_nd_entry_ipv6(uint8_t ipv6addr[], uint8_t portid);
+void remove_nd_entry_ipv6(struct nd_entry_data *ret_nd_data, void *arg);
/**
* Populate arp entry in arp Table
@@ -446,7 +417,7 @@ struct arp_entry_data *retrieve_arp_entry(const struct arp_key_ipv4 arp_key, uin
* Nd key to validate Nd entry
*/
-struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key);
+struct nd_entry_data *retrieve_nd_entry(struct nd_key_ipv6 nd_key, uint8_t mode);
/**
* Setsup Arp Initilization
@@ -552,5 +523,5 @@ uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr);
* @Param nhipv6
* next hop ipv6
*/
-void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[]);
+void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[], struct ether_addr *hw_addr);
#endif
diff --git a/common/VIL/l2l3_stack/lib_icmpv6.c b/common/VIL/l2l3_stack/lib_icmpv6.c
index 44f30cbf..eea67b0d 100644
--- a/common/VIL/l2l3_stack/lib_icmpv6.c
+++ b/common/VIL/l2l3_stack/lib_icmpv6.c
@@ -184,7 +184,7 @@ void process_icmpv6_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
nd_key.filler3 = 0;
/*Validate if key-value pair already exists in the hash table for ND IPv6 */
- struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key);
+ struct nd_entry_data *new_nd_data = retrieve_nd_entry(nd_key, DYNAMIC_ND);
if (new_nd_data == NULL) {
printf
("Received unsolicited ICMPv6 echo reply on port %d\n",
@@ -209,6 +209,7 @@ void process_icmpv6_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
src_ipv6[i] = ipv6_h->src_addr[i];
+
for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
dst_ipv6[i] = ipv6_h->dst_addr[i];
@@ -217,6 +218,7 @@ void process_icmpv6_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port)
/* Check for Multicast Address */
if ((IPV6_MULTICAST & ((multi_addr << 8) | dst_ipv6[1]))
|| !memcmp(&port->macaddr[0], &eth_h->d_addr, 6)) {
+
populate_nd_entry(src_hw_addr, src_ipv6, port->pmdid,
DYNAMIC_ND);
@@ -346,6 +348,9 @@ struct rte_mbuf *request_icmpv6_echo(uint8_t ipv6[], l2_phy_interface_t *port)
sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr) + 64;
icmpv6_pkt->data_len = icmpv6_pkt->pkt_len;
+ if (port)
+ port->transmit_single_pkt(port, icmpv6_pkt);
+
return icmpv6_pkt;
}
@@ -357,13 +362,16 @@ struct rte_mbuf *request_nd(uint8_t ipv6[], l2_phy_interface_t *port)
struct icmpv6_nd_hdr *icmpv6_nd_h;
int i;
- struct rte_mbuf *icmpv6_pkt = lib_icmpv6_pkt;
+ struct rte_mbuf *icmpv6_pkt = lib_nd_pkt[port->pmdid];
if (icmpv6_pkt == NULL) {
if (ARPICMP_DEBUG)
printf("Error allocating icmpv6_pkt rte_mbuf\n");
return NULL;
}
+ uint8_t dst_ip[] = {255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 16, 100, 20};
+ uint8_t dst_mac[] = {51,51,255, 16, 100, 20};
+
eth_h = rte_pktmbuf_mtod(icmpv6_pkt, struct ether_hdr *);
ipv6_h = (struct ipv6_hdr *)((char *)eth_h + sizeof(struct ether_hdr));
@@ -375,24 +383,37 @@ struct rte_mbuf *request_nd(uint8_t ipv6[], l2_phy_interface_t *port)
ether_addr_copy((struct ether_addr *)&port->macaddr[0], &eth_h->s_addr);
eth_h->ether_type = rte_bswap16(0x86dd);
+
for (i = 0; i < 6; i++) {
- eth_h->d_addr.addr_bytes[i] = 0;
+ if (i < 3)
+ eth_h->d_addr.addr_bytes[i] = dst_mac[i];
+ else
+ eth_h->d_addr.addr_bytes[i] = ipv6[i];
}
- ipv6_h->vtc_flow = 0x60000000;
+ for (i=13; i<16; i++)
+ dst_ip[i] = ipv6[i];
+
+ uint8_t *addr = ((ipv6list_t *) (port->ipv6_list))->ipaddr;
+
+ ipv6_h->vtc_flow = rte_bswap32(0x60000000);
ipv6_h->payload_len = rte_bswap16(32);
ipv6_h->proto = 58;
- ipv6_h->hop_limits = 64;
+ ipv6_h->hop_limits = 255;
for (i = 0; i < 16; i++) {
- ipv6_h->src_addr[i] = 0x0;
- ipv6_h->dst_addr[i] = ipv6[i];
+ ipv6_h->src_addr[i] = *(addr + i);
+ ipv6_h->dst_addr[i] = dst_ip[i];
}
icmpv6_h->icmpv6_type = ICMPV6_NEIGHBOR_SOLICITATION;
icmpv6_h->icmpv6_code = 0;
icmpv6_nd_h->icmpv6_reserved = 0x0;
+ icmpv6_nd_h->icmpv6_reserved |=
+ rte_cpu_to_be_32
+ (NEIGHBOR_ROUTER_OVERRIDE_SET);
+
for (i = 0; i < ND_IPV6_ADDR_SIZE; i++)
icmpv6_nd_h->target_ipv6[i] = ipv6[i];
icmpv6_nd_h->type = e_Source_Link_Layer_Address;
@@ -401,10 +422,13 @@ struct rte_mbuf *request_nd(uint8_t ipv6[], l2_phy_interface_t *port)
icmpv6_h->icmpv6_cksum = 0;
icmpv6_h->icmpv6_cksum = ~icmpv6_ipv6_nd_checksum(icmpv6_pkt);
-
icmpv6_pkt->pkt_len =
sizeof(struct ether_hdr) + sizeof(struct ipv6_hdr) + 32;
icmpv6_pkt->data_len = icmpv6_pkt->pkt_len;
+ if (port) {
+ port->transmit_single_pkt(port, icmpv6_pkt);
+ }
+
return icmpv6_pkt;
}
diff --git a/common/VIL/l2l3_stack/lib_icmpv6.h b/common/VIL/l2l3_stack/lib_icmpv6.h
index e9ccca14..b713d822 100644
--- a/common/VIL/l2l3_stack/lib_icmpv6.h
+++ b/common/VIL/l2l3_stack/lib_icmpv6.h
@@ -111,3 +111,4 @@ struct rte_mbuf *lib_icmpv6_pkt;
* port - port structure
*/
void process_icmpv6_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port);
+extern struct rte_mbuf *lib_nd_pkt[MAX_PORTS];