[RFC 2/2] netconsole and networking co-existence
Ian Ray
ian.ray at ge.com
Mon May 3 13:55:38 CEST 2021
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 at 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 */
--
2.10.1
More information about the U-Boot
mailing list