From 4da0effed52e73e23f73884af771d2aff1332efc Mon Sep 17 00:00:00 2001 From: Xavier Simonart Date: Tue, 27 Nov 2018 15:03:21 +0100 Subject: Fix issue in l3 mode when no arp reply was received When no arp reply was received in l3 mode, the requesting core continuously sends ARP requests every seconds (which is correct). But master core was keeping a list of all requests, while all those requests are the same, resulting in potential table overflow. Change-Id: I13aa1ec4ea88404a690a25678fb6ec72df19a9b9 Signed-off-by: Xavier Simonart --- VNFs/DPPD-PROX/handle_master.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'VNFs/DPPD-PROX') diff --git a/VNFs/DPPD-PROX/handle_master.c b/VNFs/DPPD-PROX/handle_master.c index 853df428..22527413 100644 --- a/VNFs/DPPD-PROX/handle_master.c +++ b/VNFs/DPPD-PROX/handle_master.c @@ -118,7 +118,7 @@ void register_ip_to_ctrl_plane(struct task_base *tbase, uint32_t ip, uint8_t por plogx_dbg("\tregistering IP %d.%d.%d.%d with port %d core %d and task %d\n", IP4(ip), port_id, core_id, task_id); if (port_id >= PROX_MAX_PORTS) { - plog_err("Unable to register ip %x, port %d\n", ip, port_id); + plog_err("Unable to register ip %d.%d.%d.%d, port %d\n", IP4(ip), port_id); return; } @@ -138,7 +138,7 @@ void register_ip_to_ctrl_plane(struct task_base *tbase, uint32_t ip, uint8_t por key.port = port_id; int ret = rte_hash_add_key(task->internal_ip_hash, (const void *)&key); if (unlikely(ret < 0)) { - plog_err("Unable to register ip %x\n", ip); + plog_err("Unable to register ip %d.%d.%d.%d\n", IP4(ip)); return; } memcpy(&task->internal_ip_table[ret].mac, &prox_port_cfg[port_id].eth_addr, 6); @@ -216,7 +216,7 @@ static inline void handle_unknown_ip(struct task_base *tbase, struct rte_mbuf *m struct ether_hdr_arp *hdr_arp = rte_pktmbuf_mtod(mbuf, struct ether_hdr_arp *); uint8_t port = get_port(mbuf); uint32_t ip_dst = get_ip(mbuf); - int ret1, ret2; + int ret1, ret2, i; plogx_dbg("\tMaster handling unknown ip %d.%d.%d.%d for port %d\n", IP4(ip_dst), port); if (unlikely(port >= PROX_MAX_PORTS)) { @@ -236,13 +236,32 @@ static inline void handle_unknown_ip(struct task_base *tbase, struct rte_mbuf *m ret2 = rte_hash_add_key(task->external_ip_hash, (const void *)&ip_dst); if (unlikely(ret2 < 0)) { // entry not found for this IP: delete the reply - plogx_dbg("Unable to add IP %x in external_ip_hash\n", rte_be_to_cpu_32(hdr_arp->arp.data.tpa)); + plogx_dbg("Unable to add IP %d.%d.%d.%d in external_ip_hash\n", IP4(ip_dst)); tx_drop(mbuf); return; } - task->external_ip_table[ret2].rings[task->external_ip_table[ret2].nb_requests] = ring; - task->external_ip_table[ret2].nb_requests++; - memcpy(&task->external_ip_table[ret2].mac, &task->internal_port_table[port].mac, 6); + + // If multiple tasks requesting the same info, we will need to send a reply to all of them + // However if one task sends multiple requests to the same IP (e.g. because it is not answering) + // then we should not send multiple replies to the same task + if (task->external_ip_table[ret2].nb_requests >= PROX_MAX_ARP_REQUESTS) { + // This can only happen if really many tasks requests the same IP + plogx_dbg("Unable to add request for IP %d.%d.%d.%d in external_ip_table\n", IP4(ip_dst)); + tx_drop(mbuf); + return; + } + for (i = 0; i < task->external_ip_table[ret2].nb_requests; i++) { + if (task->external_ip_table[ret2].rings[i] == ring) + break; + } + if (i >= task->external_ip_table[ret2].nb_requests) { + // If this is a new request i.e. a new task requesting a new IP + task->external_ip_table[ret2].rings[task->external_ip_table[ret2].nb_requests] = ring; + task->external_ip_table[ret2].nb_requests++; + // Only needed for first request - but avoid test and copy the same 6 bytes + // In most cases we will only have one request per IP. + memcpy(&task->external_ip_table[ret2].mac, &task->internal_port_table[port].mac, 6); + } // We send an ARP request even if one was just sent (and not yet answered) by another task mbuf->ol_flags &= ~(PKT_TX_IP_CKSUM|PKT_TX_UDP_CKSUM); -- cgit 1.2.3-korg