diff options
| author | Michael Brown | 2006-12-28 00:09:46 +0100 |
|---|---|---|
| committer | Michael Brown | 2006-12-28 00:09:46 +0100 |
| commit | 61ed298bc7dc60c84fea456444e853a73de0c901 (patch) | |
| tree | 99978dfeb667df0f79356cc4132f99922e2fd803 /src/include/gpxe | |
| parent | Keep running the main processing loop while waiting for input. (diff) | |
| download | ipxe-61ed298bc7dc60c84fea456444e853a73de0c901.tar.gz ipxe-61ed298bc7dc60c84fea456444e853a73de0c901.tar.xz ipxe-61ed298bc7dc60c84fea456444e853a73de0c901.zip | |
Merge changes from mcb-tcp-fixes branch.
Diffstat (limited to 'src/include/gpxe')
| -rw-r--r-- | src/include/gpxe/ftp.h | 17 | ||||
| -rw-r--r-- | src/include/gpxe/hello.h | 17 | ||||
| -rw-r--r-- | src/include/gpxe/http.h | 6 | ||||
| -rw-r--r-- | src/include/gpxe/iscsi.h | 44 | ||||
| -rw-r--r-- | src/include/gpxe/tcp.h | 380 |
5 files changed, 282 insertions, 182 deletions
diff --git a/src/include/gpxe/ftp.h b/src/include/gpxe/ftp.h index 1a0861e9c..c3eafb670 100644 --- a/src/include/gpxe/ftp.h +++ b/src/include/gpxe/ftp.h @@ -36,8 +36,8 @@ enum ftp_state { * */ struct ftp_request { - /** TCP connection for this request */ - struct tcp_connection tcp; + /** Server address */ + struct sockaddr_tcpip server; /** File to download */ const char *filename; /** Callback function @@ -49,10 +49,6 @@ struct ftp_request { * remote server. */ void ( *callback ) ( char *data, size_t len ); - /** Eventual return status */ - int rc; - /** Asynchronous operation for this FTP operation */ - struct async_operation aop; /** Current state */ enum ftp_state state; @@ -67,8 +63,13 @@ struct ftp_request { /** Passive-mode parameters, as text */ char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */ - /** TCP connection for the data channel */ - struct tcp_connection tcp_data; + /** TCP application for the control channel */ + struct tcp_application tcp; + /** TCP application for the data channel */ + struct tcp_application tcp_data; + + /** Asynchronous operation for this FTP operation */ + struct async_operation aop; }; struct async_operation * ftp_get ( struct ftp_request *ftp ); diff --git a/src/include/gpxe/hello.h b/src/include/gpxe/hello.h index cdd26adfa..18d0b3781 100644 --- a/src/include/gpxe/hello.h +++ b/src/include/gpxe/hello.h @@ -21,14 +21,10 @@ enum hello_state { * */ struct hello_request { - /** TCP connection for this request */ - struct tcp_connection tcp; - /** Current state */ - enum hello_state state; + /** Server to connect to */ + struct sockaddr_tcpip server; /** Message to be transmitted */ const char *message; - /** Amount of message remaining to be transmitted */ - size_t remaining; /** Callback function * * @v data Received data @@ -38,6 +34,15 @@ struct hello_request { * remote server. */ void ( *callback ) ( char *data, size_t len ); + + /** Current state */ + enum hello_state state; + /** Amount of message remaining to be transmitted */ + size_t remaining; + + /** TCP application for this request */ + struct tcp_application tcp; + /** Asynchronous operation */ struct async_operation aop; }; diff --git a/src/include/gpxe/http.h b/src/include/gpxe/http.h index 02c9be410..f858c5ffb 100644 --- a/src/include/gpxe/http.h +++ b/src/include/gpxe/http.h @@ -29,8 +29,10 @@ enum http_state { struct http_request; struct http_request { - /** TCP connection for this request */ - struct tcp_connection tcp; + /** Server address */ + struct sockaddr_tcpip server; + /** TCP application for this request */ + struct tcp_application tcp; /** Current state */ enum http_state state; /** File to download */ diff --git a/src/include/gpxe/iscsi.h b/src/include/gpxe/iscsi.h index 1b9ef9261..526ef43b4 100644 --- a/src/include/gpxe/iscsi.h +++ b/src/include/gpxe/iscsi.h @@ -486,40 +486,33 @@ enum iscsi_rx_state { /** An iSCSI session */ struct iscsi_session { - /** TCP connection for this session */ - struct tcp_connection tcp; + /** Initiator IQN */ + const char *initiator_iqn; + /** Target address */ + struct sockaddr_tcpip target; + /** Target IQN */ + const char *target_iqn; + /** Logical Unit Number (LUN) */ + uint64_t lun; + /** Username */ + const char *username; + /** Password */ + const char *password; + + /** TCP application for this session */ + struct tcp_application tcp; /** Session status * * This is the bitwise-OR of zero or more ISCSI_STATUS_XXX * constants. */ int status; - /** Asynchronous operation for the current iSCSI operation */ - struct async_operation aop; /** Retry count * * Number of times that the connection has been retried. * Reset upon a successful connection. */ int retry_count; - - /** Initiator IQN */ - const char *initiator_iqn; - /** Target address - * - * Kept separate from the TCP connection structure because we - * may need to handle login redirection. - */ - struct sockaddr_tcpip target; - /** Target IQN */ - const char *target_iqn; - /** Logical Unit Number (LUN) */ - uint64_t lun; - - /** Username */ - const char *username; - /** Password */ - const char *password; /** CHAP challenge/response */ struct chap_challenge chap; @@ -597,6 +590,8 @@ struct iscsi_session { * Set to NULL when command is complete. */ struct scsi_command *command; + /** Asynchronous operation for the current iSCSI operation */ + struct async_operation aop; }; /** iSCSI session is currently in the security negotiation phase */ @@ -632,15 +627,12 @@ struct iscsi_session { /** Mask for all iSCSI "needs to send" flags */ #define ISCSI_STATUS_STRINGS_MASK 0xff00 -/** iSCSI session is closing down */ -#define ISCSI_STATUS_CLOSING 0x00010000 - /** Maximum number of retries at connecting */ #define ISCSI_MAX_RETRIES 2 extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi, struct scsi_command *command ); -extern struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi ); +extern void iscsi_shutdown ( struct iscsi_session *iscsi ); /** An iSCSI device */ struct iscsi_device { diff --git a/src/include/gpxe/tcp.h b/src/include/gpxe/tcp.h index 9afb061b8..f5df8cbae 100644 --- a/src/include/gpxe/tcp.h +++ b/src/include/gpxe/tcp.h @@ -9,13 +9,215 @@ * */ -#include <stddef.h> -#include <gpxe/list.h> +#include "latch.h" #include <gpxe/tcpip.h> -#include <gpxe/pkbuff.h> -#include <gpxe/retry.h> -struct tcp_connection; +/** + * A TCP header + */ +struct tcp_header { + uint16_t src; /* Source port */ + uint16_t dest; /* Destination port */ + uint32_t seq; /* Sequence number */ + uint32_t ack; /* Acknowledgement number */ + uint8_t hlen; /* Header length (4), Reserved (4) */ + uint8_t flags; /* Reserved (2), Flags (6) */ + uint16_t win; /* Advertised window */ + uint16_t csum; /* Checksum */ + uint16_t urg; /* Urgent pointer */ +}; + +/* + * TCP flags + */ +#define TCP_CWR 0x80 +#define TCP_ECE 0x40 +#define TCP_URG 0x20 +#define TCP_ACK 0x10 +#define TCP_PSH 0x08 +#define TCP_RST 0x04 +#define TCP_SYN 0x02 +#define TCP_FIN 0x01 + +/** +* @defgroup tcpstates TCP states +* +* The TCP state is defined by a combination of the flags that are +* currently being sent in outgoing packets, the flags that have been +* sent and acknowledged by the peer, and the flags that have been +* received from the peer. +* +* @{ +*/ + +/** TCP flags that are currently being sent in outgoing packets */ +#define TCP_STATE_SENDING(flags) ( (flags) << 0 ) +#define TCP_FLAGS_SENDING(state) ( ( (state) >> 0 ) & 0xff ) + +/** TCP flags that have been acknowledged by the peer + * + * Note that this applies only to SYN and FIN. + */ +#define TCP_STATE_ACKED(flags) ( (flags) << 8 ) +#define TCP_FLAGS_ACKED(state) ( ( (state) >> 8 ) & 0x03 ) + +/** TCP flags that have been received from the peer + * + * Note that this applies only to SYN and FIN, and that once SYN has + * been received, we should always be sending ACK. + */ +#define TCP_STATE_RCVD(flags) ( (flags) << 12 ) +#define TCP_FLAGS_RCVD(state) ( ( (state) >> 12 ) & 0x03 ) + +/** CLOSED + * + * The connection has not yet been used for anything. + */ +#define TCP_CLOSED TCP_RST + +/** LISTEN + * + * Not currently used as a state; we have no support for listening + * connections. Given a unique value to avoid compiler warnings. + */ +#define TCP_LISTEN 0 + +/** SYN_SENT + * + * SYN has been sent, nothing has yet been received or acknowledged. + */ +#define TCP_SYN_SENT ( TCP_STATE_SENDING ( TCP_SYN ) ) + +/** SYN_RCVD + * + * SYN has been sent but not acknowledged, SYN has been received. + */ +#define TCP_SYN_RCVD ( TCP_STATE_SENDING ( TCP_SYN | TCP_ACK ) | \ + TCP_STATE_RCVD ( TCP_SYN ) ) + +/** ESTABLISHED + * + * SYN has been sent and acknowledged, SYN has been received. + */ +#define TCP_ESTABLISHED ( TCP_STATE_SENDING ( TCP_ACK ) | \ + TCP_STATE_ACKED ( TCP_SYN ) | \ + TCP_STATE_RCVD ( TCP_SYN ) ) + +/** FIN_WAIT_1 + * + * SYN has been sent and acknowledged, SYN has been received, FIN has + * been sent but not acknowledged, FIN has not been received. + * + * RFC 793 shows that we can enter FIN_WAIT_1 without have had SYN + * acknowledged, i.e. if the application closes the connection after + * sending and receiving SYN, but before having had SYN acknowledged. + * However, we have to *pretend* that SYN has been acknowledged + * anyway, otherwise we end up sending SYN and FIN in the same + * sequence number slot. Therefore, when we transition from SYN_RCVD + * to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN) + * and increment our sequence number. + */ +#define TCP_FIN_WAIT_1 ( TCP_STATE_SENDING ( TCP_ACK | TCP_FIN ) | \ + TCP_STATE_ACKED ( TCP_SYN ) | \ + TCP_STATE_RCVD ( TCP_SYN ) ) + +/** FIN_WAIT_2 + * + * SYN has been sent and acknowledged, SYN has been received, FIN has + * been sent and acknowledged, FIN ha not been received. + */ +#define TCP_FIN_WAIT_2 ( TCP_STATE_SENDING ( TCP_ACK ) | \ + TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \ + TCP_STATE_RCVD ( TCP_SYN ) ) + +/** CLOSING / LAST_ACK + * + * SYN has been sent and acknowledged, SYN has been received, FIN has + * been sent but not acknowledged, FIN has been received. + * + * This state actually encompasses both CLOSING and LAST_ACK; they are + * identical with the definition of state that we use. I don't + * *believe* that they need to be distinguished. + */ +#define TCP_CLOSING_OR_LAST_ACK \ + ( TCP_STATE_SENDING ( TCP_ACK | TCP_FIN ) | \ + TCP_STATE_ACKED ( TCP_SYN ) | \ + TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) ) + +/** TIME_WAIT + * + * SYN has been sent and acknowledged, SYN has been received, FIN has + * been sent and acknowledged, FIN has been received. + */ +#define TCP_TIME_WAIT ( TCP_STATE_SENDING ( TCP_ACK ) | \ + TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \ + TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) ) + +/** CLOSE_WAIT + * + * SYN has been sent and acknowledged, SYN has been received, FIN has + * been received. + */ +#define TCP_CLOSE_WAIT ( TCP_STATE_SENDING ( TCP_ACK ) | \ + TCP_STATE_ACKED ( TCP_SYN ) | \ + TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) ) + +/** Can send data in current state + * + * We can send data if and only if we have had our SYN acked and we + * have not yet sent our FIN. + */ +#define TCP_CAN_SEND_DATA(state) \ + ( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \ + TCP_STATE_SENDING ( TCP_FIN ) ) ) \ + == TCP_STATE_ACKED ( TCP_SYN ) ) + +/** Have closed gracefully + * + * We have closed gracefully if we have both received a FIN and had + * our own FIN acked. + */ +#define TCP_CLOSED_GRACEFULLY(state) \ + ( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) | \ + TCP_STATE_RCVD ( TCP_FIN ) ) ) \ + == ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) ) + +/** @} */ + +/** Mask for TCP header length field */ +#define TCP_MASK_HLEN 0xf0 + +/** Smallest port number on which a TCP connection can listen */ +#define TCP_MIN_PORT 1 + +/* Some PKB constants */ +#define MAX_HDR_LEN 100 +#define MAX_PKB_LEN 1500 +#define MIN_PKB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */ + +/** + * Advertised TCP window size + * + * Our TCP window is actually limited by the amount of space available + * for RX packets in the NIC's RX ring; we tend to populate the rings + * with far fewer descriptors than a typical driver. Since we have no + * way of knowing how much of this RX ring space will be available for + * received TCP packets (consider, for example, that they may all be + * consumed by a series of unrelated ARP requests between other + * machines on the network), it is actually not even theoretically + * possible for us to specify an accurate window size. We therefore + * guess an arbitrary number that is empirically as large as possible + * while avoiding retransmissions due to dropped packets. + */ +#define TCP_WINDOW_SIZE 2048 + +/** TCP maximum segment lifetime + * + * Currently set to 2 minutes, as per RFC 793. + */ +#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC ) + +struct tcp_application; /** * TCP operations @@ -25,7 +227,7 @@ struct tcp_operations { /* * Connection closed * - * @v conn TCP connection + * @v app TCP application * @v status Error code, if any * * This is called when the connection is closed for any @@ -33,42 +235,41 @@ struct tcp_operations { * contains the negative error number, if the closure is due * to an error. * - * Note that acked() and newdata() may be called after - * closed(), if the packet containing the FIN also - * acknowledged data or contained new data. Note also that - * connected() may not have been called before closed(), if - * the close is due to an error. + * When closed() is called, the application no longer has a + * valid TCP connection. Note that connected() may not have + * been called before closed(), if the close is due to an + * error during connection setup. */ - void ( * closed ) ( struct tcp_connection *conn, int status ); + void ( * closed ) ( struct tcp_application *app, int status ); /** - * Connection established (SYNACK received) + * Connection established * - * @v conn TCP connection + * @v app TCP application */ - void ( * connected ) ( struct tcp_connection *conn ); + void ( * connected ) ( struct tcp_application *app ); /** * Data acknowledged * - * @v conn TCP connection + * @v app TCP application * @v len Length of acknowledged data * * @c len is guaranteed to not exceed the outstanding amount * of unacknowledged data. */ - void ( * acked ) ( struct tcp_connection *conn, size_t len ); + void ( * acked ) ( struct tcp_application *app, size_t len ); /** * New data received * - * @v conn TCP connection + * @v app TCP application * @v data Data * @v len Length of data */ - void ( * newdata ) ( struct tcp_connection *conn, + void ( * newdata ) ( struct tcp_application *app, void *data, size_t len ); /** * Transmit data * - * @v conn TCP connection + * @v app TCP application * @v buf Temporary data buffer * @v len Length of temporary data buffer * @@ -86,137 +287,36 @@ struct tcp_operations { * the buffer is not compulsory; the application may call * tcp_send() on any block of data. */ - void ( * senddata ) ( struct tcp_connection *conn, void *buf, + void ( * senddata ) ( struct tcp_application *app, void *buf, size_t len ); }; -#if USE_UIP +struct tcp_connection; /** - * A TCP connection + * A TCP application * + * This data structure represents an application with a TCP connection. */ -struct tcp_connection { - /** Address of the remote end of the connection */ - struct sockaddr_in sin; - /** Operations table for this connection */ +struct tcp_application { + /** TCP connection data + * + * This is filled in by TCP calls that initiate a connection, + * and reset to NULL when the connection is closed. + */ + struct tcp_connection *conn; + /** TCP connection operations table */ struct tcp_operations *tcp_op; }; -extern void tcp_connect ( struct tcp_connection *conn ); -extern void tcp_send ( struct tcp_connection *conn, const void *data, - size_t len ); -extern void tcp_kick ( struct tcp_connection *conn ); -extern void tcp_close ( struct tcp_connection *conn ); - -#else - -#define TCP_NOMSG "" -#define TCP_NOMSG_LEN 0 - -/* Smallest port number on which a TCP connection can listen */ -#define TCP_MIN_PORT 1 - -/* Some PKB constants */ -#define MAX_HDR_LEN 100 -#define MAX_PKB_LEN 1500 -#define MIN_PKB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */ - -/** - * TCP states - */ -#define TCP_CLOSED 0 -#define TCP_LISTEN 1 -#define TCP_SYN_SENT 2 -#define TCP_SYN_RCVD 3 -#define TCP_ESTABLISHED 4 -#define TCP_FIN_WAIT_1 5 -#define TCP_FIN_WAIT_2 6 -#define TCP_CLOSING 7 -#define TCP_TIME_WAIT 8 -#define TCP_CLOSE_WAIT 9 -#define TCP_LAST_ACK 10 - -#define TCP_INVALID 11 - -/** - * A TCP connection - */ -struct tcp_connection { - struct sockaddr_tcpip peer; /* Remote socket address */ - uint16_t local_port; /* Local port, in network byte order */ - int tcp_state; /* TCP state */ - int tcp_lstate; /* Last TCP state */ - uint32_t snd_una; /* Lowest unacked byte on snd stream */ - uint32_t snd_win; /* Offered by remote end */ - uint32_t rcv_nxt; /* Next expected byte on rcv stream */ - uint32_t rcv_win; /* Advertised to receiver */ - uint8_t tcp_flags; /* TCP header flags */ - struct list_head list; /* List of TCP connections */ - struct pk_buff *tx_pkb; /* Transmit packet buffer */ - struct retry_timer timer; /* Retransmission timer */ - struct tcp_operations *tcp_op; /* Operations table for connection */ -}; - -/** Retry timer values */ -#define MAX_RETRANSMITS 3 - -/** - * Connection closed status codes - */ -#define CONN_SNDCLOSE 0 -#define CONN_RESTART 1 -#define CONN_TIMEOUT 2 -#define CONN_RCVCLOSE 3 - -/** - * A TCP header - */ -struct tcp_header { - uint16_t src; /* Source port */ - uint16_t dest; /* Destination port */ - uint32_t seq; /* Sequence number */ - uint32_t ack; /* Acknowledgement number */ - uint8_t hlen; /* Header length (4), Reserved (4) */ - uint8_t flags; /* Reserved (2), Flags (6) */ - uint16_t win; /* Advertised window */ - uint16_t csum; /* Checksum */ - uint16_t urg; /* Urgent pointer */ -}; - -/** - * TCP masks - */ -#define TCP_MASK_HLEN 0xf0 -#define TCP_MASK_FLAGS 0x3f - -/** - * TCP flags - */ -#define TCP_URG 0x20 -#define TCP_ACK 0x10 -#define TCP_PSH 0x08 -#define TCP_RST 0x04 -#define TCP_SYN 0x02 -#define TCP_FIN 0x01 - -extern struct tcpip_protocol tcp_protocol; - -static inline int tcp_closed ( struct tcp_connection *conn ) { - return ( conn->tcp_state == TCP_CLOSED ); -} - -extern void tcp_init_conn ( struct tcp_connection *conn ); -extern int tcp_connect ( struct tcp_connection *conn ); -extern int tcp_connectto ( struct tcp_connection *conn, - struct sockaddr_tcpip *peer ); -extern int tcp_listen ( struct tcp_connection *conn, uint16_t port ); -extern int tcp_senddata ( struct tcp_connection *conn ); -extern int tcp_close ( struct tcp_connection *conn ); - -extern int tcp_send ( struct tcp_connection *conn, const void *data, +extern int tcp_connect ( struct tcp_application *app, + struct sockaddr_tcpip *peer, + uint16_t local_port ); +extern void tcp_close ( struct tcp_application *app ); +extern int tcp_senddata ( struct tcp_application *app ); +extern int tcp_send ( struct tcp_application *app, const void *data, size_t len ); -#endif /* USE_UIP */ +extern struct tcpip_protocol tcp_protocol; #endif /* _GPXE_TCP_H */ |
