aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvik Sil <aviksil@linux.vnet.ibm.com>2013-11-17 16:22:03 +0530
committerAvik Sil <aviksil@linux.vnet.ibm.com>2013-11-17 16:22:03 +0530
commit345a00a3d7df54ff03c0bd49dfc095e13c0d777d (patch)
treed06a60b5981ab13de3e03d83fb7cc7eb288c4808
parent69d32fe332662829d16c7130935d38c220c81d9b (diff)
downloadSLOF-345a00a3d7df54ff03c0bd49dfc095e13c0d777d.zip
SLOF-345a00a3d7df54ff03c0bd49dfc095e13c0d777d.tar.gz
SLOF-345a00a3d7df54ff03c0bd49dfc095e13c0d777d.tar.bz2
ipv4: fix frame overwriting following arp_send_request
Sometimes before ARP request frame is written to the line by qemu, the data gets overwritten by next outgoing frame (typically tftp request) since both use the same ARP table index for the frame buffer. This is fixed by copying the next outgoing packet data to a different buffer instead of writing it to same ARP table index's frame buffer. Signed-off-by: Avik Sil <aviksil@linux.vnet.ibm.com>
-rw-r--r--clients/net-snk/app/netlib/ipv4.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/clients/net-snk/app/netlib/ipv4.c b/clients/net-snk/app/netlib/ipv4.c
index e55b582..f6752ec 100644
--- a/clients/net-snk/app/netlib/ipv4.c
+++ b/clients/net-snk/app/netlib/ipv4.c
@@ -17,6 +17,7 @@
#include <udp.h>
#include <tcp.h>
#include <ethernet.h>
+#include <time.h>
#include <sys/socket.h>
#include <string.h>
@@ -49,6 +50,7 @@ struct arp_entry {
uint8_t mac_addr[6];
uint8_t eth_frame[ETH_MTU_SIZE];
int eth_len;
+ int pkt_pending;
};
/** \struct icmphdr
@@ -124,6 +126,7 @@ static uint8_t multicast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static unsigned int arp_consumer = 0;
static unsigned int arp_producer = 0;
static arp_entry_t arp_table[ARP_ENTRIES];
+static arp_entry_t pending_pkt;
/* Function pointer send_ip. Points either to send_ipv4() or send_ipv6() */
int (*send_ip) (void *, int);
@@ -147,6 +150,7 @@ ipv4_init(void)
arp_table[i].ipv4_addr = 0;
memset(arp_table[i].mac_addr, 0, 6);
arp_table[i].eth_len = 0;
+ arp_table[i].pkt_pending = 0;
}
/* Set IP send function to send_ipv4() */
@@ -419,7 +423,7 @@ handle_ipv4(uint8_t * ip_packet, int32_t packetsize)
int
send_ipv4(void* buffer, int len)
{
- arp_entry_t *arp_entry;
+ arp_entry_t *arp_entry = 0;
struct iphdr *ip;
const uint8_t *mac_addr = 0;
@@ -493,13 +497,23 @@ send_ipv4(void* buffer, int len)
arp_consumer = (arp_consumer+1)%ARP_ENTRIES;
// store the packet to be send if the ARP reply is received
+ arp_entry->pkt_pending = 1;
arp_entry->ipv4_addr = ip->ip_dst;
memset(arp_entry->mac_addr, 0, 6);
- fill_ethhdr (arp_entry->eth_frame, htons(ETHERTYPE_IP),
+ pending_pkt.ipv4_addr = ip->ip_dst;
+ memset(pending_pkt.mac_addr, 0, 6);
+ fill_ethhdr (pending_pkt.eth_frame, htons(ETHERTYPE_IP),
get_mac_address(), null_mac_addr);
- memcpy(&arp_entry->eth_frame[sizeof(struct ethhdr)],
+ memcpy(&pending_pkt.eth_frame[sizeof(struct ethhdr)],
buffer, len);
- arp_entry->eth_len = len + sizeof(struct ethhdr);
+ pending_pkt.eth_len = len + sizeof(struct ethhdr);
+
+ set_timer(TICKS_SEC);
+ do {
+ receive_ether();
+ if (!arp_entry->eth_len)
+ break;
+ } while (get_timer() > 0);
return 0;
}
@@ -723,11 +737,12 @@ handle_arp(uint8_t * packet, int32_t packetsize)
memcpy(arp_table[i].mac_addr, arph->src_mac, 6);
// do we have something to send
- if(arp_table[i].eth_len > 0) {
- struct ethhdr * ethh = (struct ethhdr *) arp_table[i].eth_frame;
+ if (arp_table[i].pkt_pending) {
+ struct ethhdr * ethh = (struct ethhdr *) pending_pkt.eth_frame;
memcpy(ethh -> dest_mac, arp_table[i].mac_addr, 6);
- send_ether(arp_table[i].eth_frame, arp_table[i].eth_len);
+ send_ether(pending_pkt.eth_frame, pending_pkt.eth_len);
+ pending_pkt.pkt_pending = 0;
arp_table[i].eth_len = 0;
}
return 0; // no error