
The network stack does not appear to be designed to handle simultaneous netconsole and network operations (such as ping, nfs, and tftp) because of re-use of the netconsole output buffer.
* Add new net_send_udp_packet2, net_send_ip_packet2 APIs.
* Teach netconsole to use a private TX buffer. This is needed in order to avoid overwriting the ICMP ECHO REQUEST if a ping is started while netconsole is active.
Signed-off-by: Ian Ray ian.ray@ge.com --- drivers/net/netconsole.c | 19 +++++++++++-------- include/net.h | 5 +++++ net/arp.c | 7 +++++-- net/arp.h | 1 + net/net.c | 36 ++++++++++++++++++++++++++++-------- net/ping.c | 3 ++- 6 files changed, 52 insertions(+), 19 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index b6d2e22..ef65d75 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -27,6 +27,8 @@ static short nc_out_port; /* target output port */ static short nc_in_port; /* source input port */ static const char *output_packet; /* used by first send udp */ static int output_packet_len; +static uchar nc_pkt_buf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; +static uchar *nc_tx_packet;
static void nc_wait_arp_handler(uchar *pkt, unsigned dest, struct in_addr sip, unsigned src, @@ -120,10 +122,10 @@ void nc_start(void) /* send arp request */ uchar *pkt; net_set_arp_handler(nc_wait_arp_handler); - pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + + pkt = (uchar *)nc_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; memcpy(pkt, output_packet, output_packet_len); - net_send_udp_packet(nc_ether, nc_ip, nc_out_port, nc_in_port, + net_send_udp_packet2(nc_tx_packet, nc_ether, nc_ip, nc_out_port, nc_in_port, output_packet_len); } } @@ -173,8 +175,6 @@ static void nc_send_packet(const char *buf, int len) struct eth_device *eth; #endif uchar *pkt; - uchar *ether; - struct in_addr ip;
debug_cond(DEBUG_DEV_PKT, "output: "%*.*s"\n", len, len, buf);
@@ -198,11 +198,9 @@ static void nc_send_packet(const char *buf, int len) return; }
- pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; + pkt = (uchar *)nc_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; memcpy(pkt, buf, len); - ether = nc_ether; - ip = nc_ip; - net_send_udp_packet(ether, ip, nc_out_port, nc_in_port, len); + net_send_udp_packet2(nc_tx_packet, nc_ether, nc_ip, nc_out_port, nc_in_port, len);
net_down(); } @@ -218,6 +216,11 @@ static int nc_stdio_start(struct stdio_dev *dev) if (retval != 0) return retval;
+ if (nc_tx_packet == NULL) { + nc_tx_packet = &nc_pkt_buf[0] + (PKTALIGN - 1); + nc_tx_packet -= (ulong)nc_tx_packet % PKTALIGN; + } + /* * Initialize the static IP settings and buffer pointers * incase we call net_send_udp_packet before net_loop diff --git a/include/net.h b/include/net.h index cc6be60..74f7ce1 100644 --- a/include/net.h +++ b/include/net.h @@ -694,9 +694,14 @@ static inline void net_send_packet(uchar *pkt, int len) * @param sport Source UDP port * @param payload_len Length of data after the UDP header */ +int net_send_ip_packet2(uchar *pkt, uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto, u8 action, u32 tcp_seq_num, + u32 tcp_ack_num); int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len, int proto, u8 action, u32 tcp_seq_num, u32 tcp_ack_num); +int net_send_udp_packet2(uchar *pkt, uchar *ether, struct in_addr dest, int dport, + int sport, int payload_len); int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len);
diff --git a/net/arp.c b/net/arp.c index 1d06ed2..f19958f 100644 --- a/net/arp.c +++ b/net/arp.c @@ -35,6 +35,7 @@ struct in_addr net_arp_wait_packet_ip; static struct in_addr net_arp_wait_reply_ip; /* MAC address of waiting packet's destination */ uchar *arp_wait_packet_ethaddr; +uchar *arp_wait_tx_packet; int arp_wait_tx_packet_size; ulong arp_wait_timer_start; int arp_wait_try; @@ -47,6 +48,7 @@ void arp_init(void) arp_wait_packet_ethaddr = NULL; net_arp_wait_packet_ip.s_addr = 0; net_arp_wait_reply_ip.s_addr = 0; + arp_wait_tx_packet = NULL; arp_wait_tx_packet_size = 0; arp_tx_packet = &arp_tx_packet_buf[0] + (PKTALIGN - 1); arp_tx_packet -= (ulong)arp_tx_packet % PKTALIGN; @@ -222,12 +224,13 @@ void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
/* set the mac address in the waiting packet's header and transmit it */ - memcpy(((struct ethernet_hdr *)net_tx_packet)->et_dest, + memcpy(((struct ethernet_hdr *)arp_wait_tx_packet)->et_dest, &arp->ar_sha, ARP_HLEN); - net_send_packet(net_tx_packet, arp_wait_tx_packet_size); + net_send_packet(arp_wait_tx_packet, arp_wait_tx_packet_size);
/* no arp request pending now */ net_arp_wait_packet_ip.s_addr = 0; + arp_wait_tx_packet = NULL; arp_wait_tx_packet_size = 0; arp_wait_packet_ethaddr = NULL; } diff --git a/net/arp.h b/net/arp.h index 25b3c00..8154ebc 100644 --- a/net/arp.h +++ b/net/arp.h @@ -17,6 +17,7 @@ extern struct in_addr net_arp_wait_packet_ip; /* MAC address of waiting packet's destination */ extern uchar *arp_wait_packet_ethaddr; +extern uchar *arp_wait_tx_packet; extern int arp_wait_tx_packet_size; extern ulong arp_wait_timer_start; extern int arp_wait_try; diff --git a/net/net.c b/net/net.c index 45d4f19..b1dba80 100644 --- a/net/net.c +++ b/net/net.c @@ -855,17 +855,38 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, IPPROTO_UDP, 0, 0, 0); }
+int net_send_udp_packet2(uchar *pkt, uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len) +{ + return net_send_ip_packet2(pkt, ether, dest, dport, sport, payload_len, + IPPROTO_UDP, 0, 0, 0); +} + +/// Sends net_tx_packet + int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len, int proto, u8 action, u32 tcp_seq_num, u32 tcp_ack_num) { - uchar *pkt; + return net_send_ip_packet2(net_tx_packet, ether, dest, dport, sport, + payload_len, + proto, action, tcp_seq_num, tcp_ack_num); +} + +/// Global variables / state. +/// - Uses const net_bcast_ethaddr if destination is broadcast address +/// - net_set_ether() checks net_our_vlan +/// - If ether is null, fills net_arp_wait_packet_ip and does ARP + +int net_send_ip_packet2(uchar *pkt, uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto, u8 action, u32 tcp_seq_num, + u32 tcp_ack_num) +{ int eth_hdr_size; int pkt_hdr_size;
- /* make sure the net_tx_packet is initialized (net_init() was called) */ - assert(net_tx_packet != NULL); - if (net_tx_packet == NULL) + assert(pkt != NULL); + if (pkt == NULL) return -1;
/* convert to new style broadcast */ @@ -876,8 +897,6 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, if (dest.s_addr == 0xFFFFFFFF) ether = (uchar *)net_bcast_ethaddr;
- pkt = (uchar *)net_tx_packet; - eth_hdr_size = net_set_ether(pkt, ether, PROT_IP);
switch (proto) { @@ -898,7 +917,8 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, net_arp_wait_packet_ip = dest; arp_wait_packet_ethaddr = ether;
- /* size of the waiting packet */ + /* waiting packet */ + arp_wait_tx_packet = pkt; arp_wait_tx_packet_size = pkt_hdr_size + payload_len;
/* and do the ARP request */ @@ -909,7 +929,7 @@ int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, } else { debug_cond(DEBUG_DEV_PKT, "sending UDP to %pI4/%pM\n", &dest, ether); - net_send_packet(net_tx_packet, pkt_hdr_size + payload_len); + net_send_packet(pkt, pkt_hdr_size + payload_len); return 0; /* transmitted */ } } diff --git a/net/ping.c b/net/ping.c index 2c92806..74c4726 100644 --- a/net/ping.c +++ b/net/ping.c @@ -52,7 +52,8 @@ static int ping_send(void)
set_icmp_header(pkt, net_ping_ip);
- /* size of the waiting packet */ + /* waiting packet */ + arp_wait_tx_packet = net_tx_packet; arp_wait_tx_packet_size = eth_hdr_size + IP_ICMP_HDR_SIZE;
/* and do the ARP request */