transition away from uIP.
Prepared ipv4.c for transition away from uIP.
* Transmit data
*
* @v conn TCP connection
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*
* The application should transmit whatever it currently wants
* to send using tcp_send(). If retransmissions are required,
* regenerate the data. The easiest way to implement this is
* to ensure that senddata() never changes the application's
* state.
+ *
+ * The application may use the temporary data buffer to
+ * construct the data to be sent. Note that merely filling
+ * the buffer will do nothing; the application must call
+ * tcp_send() in order to actually transmit the data. Use of
+ * the buffer is not compulsory; the application may call
+ * tcp_send() on any block of data.
*/
- void ( * senddata ) ( struct tcp_connection *conn );
+ void ( * senddata ) ( struct tcp_connection *conn, void *buf,
+ size_t len );
};
/**
struct tcp_operations *tcp_op;
};
-extern void *tcp_buffer;
-extern size_t tcp_buflen;
extern void tcp_connect ( struct tcp_connection *conn );
extern void tcp_send ( struct tcp_connection *conn, const void *data,
size_t len );
* This handles IP packets by handing them off to the uIP protocol
* stack.
*/
-static int ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
- const void *ll_source __unused ) {
+static int ipv4_uip_rx ( struct pk_buff *pkb,
+ struct net_device *netdev __unused,
+ const void *ll_source __unused ) {
/* Transfer to uIP buffer. Horrendously space-inefficient,
* but will do as a proof-of-concept for now.
.name = "IP",
.net_proto = htons ( ETH_P_IP ),
.net_addr_len = sizeof ( struct in_addr ),
+#if USE_UIP
+ .rx = ipv4_uip_rx,
+#else
.rx = ipv4_rx,
+#endif
.ntoa = ipv4_ntoa,
};
*
* @code
*
- * static void my_senddata ( struct tcp_connection *conn ) {
- * int len;
- *
- * len = snprintf ( tcp_buffer, tcp_buflen, "FETCH %s\r\n", filename );
- * tcp_send ( conn, tcp_buffer + already_sent, len - already_sent );
+ * static void my_senddata ( struct tcp_connection *conn, void *buf,
+ * size_t len ) {
+ * len = snprintf ( buf, len, "FETCH %s\r\n", filename );
+ * tcp_send ( conn, buf + already_sent, len - already_sent );
* }
*
* @endcode
* variably-sized data.
*
* Note that you cannot use this simple mechanism if you want to be
- * able to construct single data blocks of more than #tcp_buflen
- * bytes.
+ * able to construct single data blocks of more than #len bytes.
*/
-void *tcp_buffer = uip_buf + ( 40 + UIP_LLH_LEN );
+static void *tcp_buffer = uip_buf + ( 40 + UIP_LLH_LEN );
/** Size of #tcp_buffer */
-size_t tcp_buflen = UIP_BUFSIZE - ( 40 + UIP_LLH_LEN );
+static size_t tcp_buflen = UIP_BUFSIZE - ( 40 + UIP_LLH_LEN );
/**
* Open a TCP connection
op->newdata ( conn, ( void * ) uip_appdata, uip_len );
if ( ( uip_rexmit() || uip_newdata() || uip_acked() ||
uip_connected() || uip_poll() ) && op->senddata )
- op->senddata ( conn );
+ op->senddata ( conn, tcp_buffer, tcp_buflen );
}
/* Present here to allow everything to link. Will go into separate
* Construct data to send on FTP control channel
*
* @v conn TCP connection
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*/
-static void ftp_senddata ( struct tcp_connection *conn ) {
+static void ftp_senddata ( struct tcp_connection *conn,
+ void *buf, size_t len ) {
struct ftp_request *ftp = tcp_to_ftp ( conn );
const struct ftp_string *string;
- size_t len;
/* Send the as-yet-unACKed portion of the string for the
* current state.
*/
string = &ftp_strings[ftp->state];
- len = snprintf ( tcp_buffer, tcp_buflen, string->format,
+ len = snprintf ( buf, len, string->format,
ftp_string_data ( ftp, string->data_offset ) );
- tcp_send ( conn, tcp_buffer + ftp->already_sent,
- len - ftp->already_sent );
+ tcp_send ( conn, buf + ftp->already_sent, len - ftp->already_sent );
}
/**
* Send iSCSI data-out data segment
*
* @v iscsi iSCSI session
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*/
-static void iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
+static void iscsi_tx_data_out ( struct iscsi_session *iscsi,
+ void *buf, size_t len ) {
struct iscsi_bhs_data_out *data_out = &iscsi->tx_bhs.data_out;
unsigned long offset;
- unsigned long len;
+ unsigned long remaining;
offset = ( iscsi->transfer_offset + ntohl ( data_out->offset ) +
iscsi->tx_offset );
- len = ( ISCSI_DATA_LEN ( data_out->lengths ) - iscsi->tx_offset );
+ remaining = ( ISCSI_DATA_LEN ( data_out->lengths ) - iscsi->tx_offset);
assert ( iscsi->command != NULL );
assert ( iscsi->command->data_out != NULL );
assert ( ( offset + len ) <= iscsi->command->data_out_len );
- if ( len > tcp_buflen )
- len = tcp_buflen;
- copy_from_user ( tcp_buffer, iscsi->command->data_out, offset, len );
+ if ( remaining < len )
+ len = remaining;
+ copy_from_user ( buf, iscsi->command->data_out, offset, len );
- tcp_send ( &iscsi->tcp, tcp_buffer, len );
+ tcp_send ( &iscsi->tcp, buf, len );
}
/****************************************************************************
* Transmit data segment of an iSCSI login request PDU
*
* @v iscsi iSCSI session
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*
* For login requests, the data segment consists of the login strings.
*/
-static void iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
- int len;
-
- len = iscsi_build_login_request_strings ( iscsi, tcp_buffer,
- tcp_buflen );
- tcp_send ( &iscsi->tcp, tcp_buffer + iscsi->tx_offset,
+static void iscsi_tx_login_request ( struct iscsi_session *iscsi,
+ void *buf, size_t len ) {
+ len = iscsi_build_login_request_strings ( iscsi, buf, len );
+ tcp_send ( &iscsi->tcp, buf + iscsi->tx_offset,
len - iscsi->tx_offset );
}
* Transmit data segment of an iSCSI PDU
*
* @v iscsi iSCSI session
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*
* Handle transmission of part of a PDU data segment. iscsi::tx_bhs
* will be valid when this is called.
*/
-static void iscsi_tx_data ( struct iscsi_session *iscsi ) {
+static void iscsi_tx_data ( struct iscsi_session *iscsi,
+ void *buf, size_t len ) {
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
switch ( common->opcode & ISCSI_OPCODE_MASK ) {
case ISCSI_OPCODE_DATA_OUT:
- iscsi_tx_data_out ( iscsi );
+ iscsi_tx_data_out ( iscsi, buf, len );
break;
case ISCSI_OPCODE_LOGIN_REQUEST:
- iscsi_tx_login_request ( iscsi );
+ iscsi_tx_login_request ( iscsi, buf, len );
break;
default:
assert ( 0 );
* Transmit iSCSI PDU
*
* @v iscsi iSCSI session
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*
* Constructs data to be sent for the current TX state
*/
-static void iscsi_senddata ( struct tcp_connection *conn ) {
+static void iscsi_senddata ( struct tcp_connection *conn,
+ void *buf, size_t len ) {
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
static const char pad[] = { '\0', '\0', '\0' };
assert ( 0 );
break;
case ISCSI_TX_DATA:
- iscsi_tx_data ( iscsi );
+ iscsi_tx_data ( iscsi, buf, len );
break;
case ISCSI_TX_DATA_PADDING:
tcp_send ( conn, pad, ( ISCSI_DATA_PAD_LEN ( common->lengths )
#define UIP_IPADDR2 254
#define UIP_IPADDR3 1
+#define USE_UIP 1
+
#endif /* __UIPOPT_H__ */