Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149590783
D21541.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D21541.id.diff
View Options
Index: head/sys/net/debugnet.h
===================================================================
--- head/sys/net/debugnet.h
+++ head/sys/net/debugnet.h
@@ -90,6 +90,8 @@
#define DEBUGNET_SUPPORTED_NIC(ifp) \
((ifp)->if_debugnet_methods != NULL && (ifp)->if_type == IFT_ETHER)
+struct debugnet_pcb; /* opaque */
+
/*
* Debugnet consumer API.
*/
@@ -100,13 +102,30 @@
in_addr_t dc_gateway;
uint16_t dc_herald_port;
- uint16_t dc_client_ack_port;
+ uint16_t dc_client_port;
const void *dc_herald_data;
uint32_t dc_herald_datalen;
-};
-struct debugnet_pcb; /* opaque */
+ /*
+ * If NULL, debugnet is a unidirectional channel from panic machine to
+ * remote server (like netdump).
+ *
+ * If handler is non-NULL, packets received on the client port that are
+ * not just tx acks are forwarded to the provided handler.
+ *
+ * The mbuf chain will have all non-debugnet framing headers removed
+ * (ethernet, inet, udp). It will start with a debugnet_msg_hdr, of
+ * which the header is guaranteed to be contiguous. If m_pullup is
+ * used, the supplied in-out mbuf pointer should be updated
+ * appropriately.
+ *
+ * If the handler frees the mbuf chain, it should set the mbuf pointer
+ * to NULL. Otherwise, the debugnet input framework will free the
+ * chain.
+ */
+ void (*dc_rx_handler)(struct debugnet_pcb *, struct mbuf **);
+};
/*
* Open a unidirectional stream to the specified server's herald port.
Index: head/sys/net/debugnet.c
===================================================================
--- head/sys/net/debugnet.c
+++ head/sys/net/debugnet.c
@@ -175,7 +175,7 @@
udp = mtod(m, void *);
udp->uh_ulen = htons(m->m_pkthdr.len);
/* Use this src port so that the server can connect() the socket */
- udp->uh_sport = htons(pcb->dp_client_ack_port);
+ udp->uh_sport = htons(pcb->dp_client_port);
udp->uh_dport = htons(pcb->dp_server_port);
/* Computed later (protocol-dependent). */
udp->uh_sum = 0;
@@ -183,6 +183,28 @@
return (debugnet_ip_output(pcb, m));
}
+static int
+debugnet_ack_output(struct debugnet_pcb *pcb, uint32_t seqno /* net endian */)
+{
+ struct debugnet_ack *dn_ack;
+ struct mbuf *m;
+
+ DNETDEBUG("Acking with seqno %u\n", ntohl(seqno));
+
+ m = m_gethdr(M_NOWAIT, MT_DATA);
+ if (m == NULL) {
+ printf("%s: Out of mbufs\n", __func__);
+ return (ENOBUFS);
+ }
+ m->m_len = sizeof(*dn_ack);
+ m->m_pkthdr.len = sizeof(*dn_ack);
+ MH_ALIGN(m, sizeof(*dn_ack));
+ dn_ack = mtod(m, void *);
+ dn_ack->da_seqno = seqno;
+
+ return (debugnet_udp_output(pcb, m));
+}
+
/*
* Dummy free function for debugnet clusters.
*/
@@ -216,6 +238,9 @@
uint32_t i, pktlen, sent_so_far;
int retries, polls, error;
+ if (pcb->dp_state == DN_STATE_REMOTE_CLOSED)
+ return (ECONNRESET);
+
want_acks = 0;
pcb->dp_rcvd_acks = 0;
retries = 0;
@@ -307,6 +332,8 @@
}
debugnet_network_poll(pcb->dp_ifp);
DELAY(500);
+ if (pcb->dp_state == DN_STATE_REMOTE_CLOSED)
+ return (ECONNRESET);
}
pcb->dp_seqno += i;
return (0);
@@ -316,7 +343,63 @@
* Network input primitives.
*/
+/*
+ * Just introspect the header enough to fire off a seqno ack and validate
+ * length fits.
+ */
static void
+debugnet_handle_rx_msg(struct debugnet_pcb *pcb, struct mbuf **mb)
+{
+ const struct debugnet_msg_hdr *dnh;
+ struct mbuf *m;
+ int error;
+
+ m = *mb;
+
+ if (m->m_pkthdr.len < sizeof(*dnh)) {
+ DNETDEBUG("ignoring small debugnet_msg packet\n");
+ return;
+ }
+
+ /* Get ND header. */
+ if (m->m_len < sizeof(*dnh)) {
+ m = m_pullup(m, sizeof(*dnh));
+ *mb = m;
+ if (m == NULL) {
+ DNETDEBUG("m_pullup failed\n");
+ return;
+ }
+ }
+ dnh = mtod(m, const void *);
+
+ if (ntohl(dnh->mh_len) + sizeof(*dnh) > m->m_pkthdr.len) {
+ DNETDEBUG("Dropping short packet.\n");
+ return;
+ }
+
+ /*
+ * If the issue is transient (ENOBUFS), sender should resend. If
+ * non-transient (like driver objecting to rx -> tx from the same
+ * thread), not much else we can do.
+ */
+ error = debugnet_ack_output(pcb, dnh->mh_seqno);
+ if (error != 0)
+ return;
+
+ if (ntohl(dnh->mh_type) == DEBUGNET_FINISHED) {
+ printf("Remote shut down the connection on us!\n");
+ pcb->dp_state = DN_STATE_REMOTE_CLOSED;
+
+ /*
+ * Continue through to the user handler so they are signalled
+ * not to wait for further rx.
+ */
+ }
+
+ pcb->dp_rx_handler(pcb, mb);
+}
+
+static void
debugnet_handle_ack(struct debugnet_pcb *pcb, struct mbuf **mb, uint16_t sport)
{
const struct debugnet_ack *dn_ack;
@@ -325,10 +408,6 @@
m = *mb;
- if (m->m_pkthdr.len < sizeof(*dn_ack)) {
- DNETDEBUG("ignoring small ACK packet\n");
- return;
- }
/* Get Ack. */
if (m->m_len < sizeof(*dn_ack)) {
m = m_pullup(m, sizeof(*dn_ack));
@@ -363,7 +442,7 @@
{
const struct udphdr *udp;
struct mbuf *m;
- uint16_t sport;
+ uint16_t sport, ulen;
/* UDP processing. */
@@ -384,15 +463,39 @@
}
udp = mtod(m, const void *);
- /* For now, the only UDP packets we expect to receive are acks. */
- if (ntohs(udp->uh_dport) != pcb->dp_client_ack_port) {
- DNETDEBUG("not on the expected ACK port.\n");
+ /* We expect to receive UDP packets on the configured client port. */
+ if (ntohs(udp->uh_dport) != pcb->dp_client_port) {
+ DNETDEBUG("not on the expected port.\n");
return;
}
+
+ /* Check that ulen does not exceed actual size of data. */
+ ulen = ntohs(udp->uh_ulen);
+ if (m->m_pkthdr.len < ulen) {
+ DNETDEBUG("ignoring runt UDP packet\n");
+ return;
+ }
+
sport = ntohs(udp->uh_sport);
m_adj(m, sizeof(*udp));
- debugnet_handle_ack(pcb, mb, sport);
+ ulen -= sizeof(*udp);
+
+ if (ulen == sizeof(struct debugnet_ack)) {
+ debugnet_handle_ack(pcb, mb, sport);
+ return;
+ }
+
+ if (pcb->dp_rx_handler == NULL) {
+ if (ulen < sizeof(struct debugnet_ack))
+ DNETDEBUG("ignoring small ACK packet\n");
+ else
+ DNETDEBUG("ignoring unexpected non-ACK packet on "
+ "half-duplex connection.\n");
+ return;
+ }
+
+ debugnet_handle_rx_msg(pcb, mb);
}
/*
@@ -523,9 +626,10 @@
.dp_server = dcp->dc_server,
.dp_gateway = dcp->dc_gateway,
.dp_server_port = dcp->dc_herald_port, /* Initially */
- .dp_client_ack_port = dcp->dc_client_ack_port,
+ .dp_client_port = dcp->dc_client_port,
.dp_seqno = 1,
.dp_ifp = dcp->dc_ifp,
+ .dp_rx_handler = dcp->dc_rx_handler,
};
/* Switch to the debugnet mbuf zones. */
@@ -593,7 +697,7 @@
serbuf, pcb->dp_server_port,
(pcb->dp_gateway == INADDR_ANY) ? "" : " via ",
(pcb->dp_gateway == INADDR_ANY) ? "" : gwbuf,
- clibuf, pcb->dp_client_ack_port, if_name(ifp));
+ clibuf, pcb->dp_client_port, if_name(ifp));
}
/* Validate iface is online and supported. */
Index: head/sys/net/debugnet_int.h
===================================================================
--- head/sys/net/debugnet_int.h
+++ head/sys/net/debugnet_int.h
@@ -50,6 +50,7 @@
DN_STATE_INIT = 1,
DN_STATE_HAVE_GW_MAC,
DN_STATE_GOT_HERALD_PORT,
+ DN_STATE_REMOTE_CLOSED,
};
struct debugnet_pcb {
@@ -67,8 +68,12 @@
/* Saved driver if_input to restore on close. */
void (*dp_drv_input)(struct ifnet *, struct mbuf *);
+ /* RX handler for bidirectional protocols. */
+ void (*dp_rx_handler)(struct debugnet_pcb *,
+ struct mbuf **);
+
enum dnet_pcb_st dp_state;
- uint16_t dp_client_ack_port;
+ uint16_t dp_client_port;
bool dp_event_started;
};
Index: head/sys/netinet/netdump/netdump_client.c
===================================================================
--- head/sys/netinet/netdump/netdump_client.c
+++ head/sys/netinet/netdump/netdump_client.c
@@ -316,7 +316,7 @@
dcp.dc_gateway = nd_gateway.s_addr;
dcp.dc_herald_port = NETDUMP_PORT;
- dcp.dc_client_ack_port = NETDUMP_ACKPORT;
+ dcp.dc_client_port = NETDUMP_ACKPORT;
dcp.dc_herald_data = nd_path;
dcp.dc_herald_datalen = (nd_path[0] == 0) ? 0 : strlen(nd_path) + 1;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 26, 11:21 AM (19 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30380212
Default Alt Text
D21541.id.diff (7 KB)
Attached To
Mode
D21541: debugnet(4): Add optional full-duplex mode
Attached
Detach File
Event Timeline
Log In to Comment