[-]
[+]
|
Changed |
ipxe.tar.bz2/src/Makefile.housekeeping
|
@@ -450,14 +450,20 @@
# Enable per-item sections and section garbage collection. Note that
# some older versions of gcc support -fdata-sections but treat it as
-# implying -fno-common, which would break our build.
+# implying -fno-common, which would break our build. Some other older
+# versions issue a spurious and uninhibitable warning if
+# -ffunction-sections is used with -g, which would also break our
+# build since we use -Werror.
#
ifeq ($(CCTYPE),gcc)
DS_TEST = $(ECHO) 'char x;' | \
$(CC) -fdata-sections -S -x c - -o - 2>/dev/null | \
grep -E '\.comm' > /dev/null
DS_FLAGS := $(shell $(DS_TEST) && $(ECHO) '-fdata-sections')
-CFLAGS += -ffunction-sections $(DS_FLAGS)
+FS_TEST = $(CC) -ffunction-sections -g -c -x c /dev/null \
+ -o /dev/null 2>/dev/null
+FS_FLAGS := $(shell $(FS_TEST) && $(ECHO) '-ffunction-sections')
+CFLAGS += $(FS_FLAGS) $(DS_FLAGS)
endif
LDFLAGS += --gc-sections
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/core/cmdline.c
^
|
@@ -66,7 +66,8 @@
struct image *image = &cmdline_image;
userptr_t cmdline_user;
char *cmdline;
- char *tmp;
+ char *boot_image;
+ char *boot_image_end;
size_t len;
/* Do nothing if no command line was specified */
@@ -91,9 +92,18 @@
/* Check for unwanted cruft in the command line */
while ( isspace ( *cmdline ) )
cmdline++;
- if ( ( tmp = strstr ( cmdline, "BOOT_IMAGE=" ) ) != NULL ) {
- DBGC ( image, "CMDLINE stripping \"%s\"\n", tmp );
- *tmp = '\0';
+ if ( ( boot_image = strstr ( cmdline, "BOOT_IMAGE=" ) ) != NULL ) {
+ boot_image_end = strchr ( boot_image, ' ' );
+ if ( boot_image_end ) {
+ *boot_image_end = '\0';
+ DBGC ( image, "CMDLINE stripping \"%s\"\n",
+ boot_image );
+ strcpy ( boot_image, ( boot_image_end + 1 ) );
+ } else {
+ DBGC ( image, "CMDLINE stripping \"%s\"\n",
+ boot_image );
+ *boot_image = '\0';
+ }
}
DBGC ( image, "CMDLINE using \"%s\"\n", cmdline );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/include/efi/ipxe/dhcp_arch.h
^
|
@@ -33,7 +33,8 @@
'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '6', ':', \
'U', 'N', 'D', 'I', ':', '0', '0', '3', '0', '1', '0' )
-#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_WORD ( 6 )
+#define DHCP_ARCH_CLIENT_ARCHITECTURE \
+ DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_IA32 )
#define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 3, 10 /* v3.10 */ )
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h
^
|
@@ -33,7 +33,8 @@
'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '0', ':', \
'U', 'N', 'D', 'I', ':', '0', '0', '2', '0', '0', '1' )
-#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_WORD ( 0 )
+#define DHCP_ARCH_CLIENT_ARCHITECTURE \
+ DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_X86 )
#define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 2, 1 /* v2.1 */ )
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/interface/pcbios/int13.c
^
|
@@ -1334,6 +1334,20 @@
}
/**
+ * Check INT13 emulated drive flow control window
+ *
+ * @v int13 Emulated drive
+ */
+static size_t int13_block_window ( struct int13_drive *int13 __unused ) {
+
+ /* We are never ready to receive data via this interface.
+ * This prevents objects that support both block and stream
+ * interfaces from attempting to send us stream data.
+ */
+ return 0;
+}
+
+/**
* Handle INT 13 emulated drive underlying block device closing
*
* @v int13 Emulated drive
@@ -1357,6 +1371,7 @@
/** INT 13 drive interface operations */
static struct interface_operation int13_block_op[] = {
+ INTF_OP ( xfer_window, struct int13_drive *, int13_block_window ),
INTF_OP ( intf_close, struct int13_drive *, int13_block_close ),
};
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/interface/pxe/pxe_undi.c
^
|
@@ -652,6 +652,7 @@
const void *ll_dest;
const void *ll_source;
uint16_t net_proto;
+ unsigned int flags;
size_t ll_hlen;
struct net_protocol *net_protocol;
unsigned int prottype;
@@ -753,7 +754,8 @@
/* Strip link-layer header */
ll_protocol = pxe_netdev->ll_protocol;
if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest,
- &ll_source, &net_proto )) !=0){
+ &ll_source, &net_proto,
+ &flags ) ) != 0 ) {
/* Assume unknown net_proto and no ll_source */
net_proto = 0;
ll_source = NULL;
@@ -788,14 +790,12 @@
undi_isr->Frame.segment = rm_ds;
undi_isr->Frame.offset = __from_data16 ( basemem_packet );
undi_isr->ProtType = prottype;
- if ( memcmp ( ll_dest, pxe_netdev->ll_addr,
- ll_protocol->ll_addr_len ) == 0 ) {
- undi_isr->PktType = P_DIRECTED;
- } else if ( memcmp ( ll_dest, pxe_netdev->ll_broadcast,
- ll_protocol->ll_addr_len ) == 0 ) {
+ if ( flags & LL_BROADCAST ) {
undi_isr->PktType = P_BROADCAST;
- } else {
+ } else if ( flags & LL_MULTICAST ) {
undi_isr->PktType = P_MULTICAST;
+ } else {
+ undi_isr->PktType = P_DIRECTED;
}
DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d",
undi_isr->Frame.segment, undi_isr->Frame.offset,
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/prefix/lkrnprefix.S
^
|
@@ -160,7 +160,7 @@
pad2:
.byte 0, 0, 0
cmdline_size:
- .long 0
+ .long 0x7ff
hardware_subarch:
.long 0
hardware_subarch_data:
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/i386/prefix/romprefix.S
^
|
@@ -445,7 +445,7 @@
/* Preserve registers */
pushl %eax
pushw %di
- movw $' ', %di
+ movw $( ' ' ), %di
get_pmm_find:
/* Try to find existing block */
pushl %ebx /* PMM handle */
@@ -474,7 +474,7 @@
pushw %dx
pushw %ax
popl %esi
- movw $'+', %di /* Indicate allocation attempt */
+ movw $( '+' ), %di /* Indicate allocation attempt */
testl %esi, %esi
jnz get_pmm_done
stc
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h
^
|
@@ -30,10 +30,11 @@
#define DHCP_ARCH_VENDOR_CLASS_ID \
DHCP_STRING ( 'P', 'X', 'E', 'C', 'l', 'i', 'e', 'n', 't', ':', \
- 'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '7', ':', \
+ 'A', 'r', 'c', 'h', ':', '0', '0', '0', '0', '9', ':', \
'U', 'N', 'D', 'I', ':', '0', '0', '3', '0', '1', '0' )
-#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_WORD ( 7 )
+#define DHCP_ARCH_CLIENT_ARCHITECTURE \
+ DHCP_WORD ( DHCP_CLIENT_ARCHITECTURE_X86_64 )
#define DHCP_ARCH_CLIENT_NDI DHCP_OPTION ( 1 /* UNDI */ , 3, 10 /* v3.10 */ )
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/core/hw.c
^
|
@@ -26,15 +26,7 @@
process_del ( &hw->process );
}
-static struct interface_operation hw_xfer_operations[] = {
- INTF_OP ( intf_close, struct hw *, hw_finished ),
-};
-
-static struct interface_descriptor hw_xfer_desc =
- INTF_DESC ( struct hw, xfer, hw_xfer_operations );
-
-static void hw_step ( struct process *process ) {
- struct hw *hw = container_of ( process, struct hw, process );
+static void hw_step ( struct hw *hw ) {
int rc;
if ( xfer_window ( &hw->xfer ) ) {
@@ -43,6 +35,17 @@
}
}
+static struct interface_operation hw_xfer_operations[] = {
+ INTF_OP ( xfer_window_changed, struct hw *, hw_step ),
+ INTF_OP ( intf_close, struct hw *, hw_finished ),
+};
+
+static struct interface_descriptor hw_xfer_desc =
+ INTF_DESC ( struct hw, xfer, hw_xfer_operations );
+
+static struct process_descriptor hw_process_desc =
+ PROC_DESC_ONCE ( struct hw, process, hw_step );
+
static int hw_open ( struct interface *xfer, struct uri *uri __unused ) {
struct hw *hw;
@@ -52,7 +55,7 @@
return -ENOMEM;
ref_init ( &hw->refcnt, NULL );
intf_init ( &hw->xfer, &hw_xfer_desc, &hw->refcnt );
- process_init ( &hw->process, hw_step, &hw->refcnt );
+ process_init ( &hw->process, &hw_process_desc, &hw->refcnt );
/* Attach parent interface, mortalise self, and return */
intf_plug_plug ( &hw->xfer, xfer );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/core/process.c
^
|
@@ -34,6 +34,16 @@
static LIST_HEAD ( run_queue );
/**
+ * Get pointer to object containing process
+ *
+ * @v process Process
+ * @ret object Containing object
+ */
+void * process_object ( struct process *process ) {
+ return ( ( ( void * ) process ) - process->desc->offset );
+}
+
+/**
* Add process to process list
*
* @v process Process
@@ -43,13 +53,13 @@
*/
void process_add ( struct process *process ) {
if ( ! process_running ( process ) ) {
- DBGC ( process, "PROCESS %p (%p) starting\n",
- process, process->step );
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " starting\n", PROC_DBG ( process ) );
ref_get ( process->refcnt );
list_add_tail ( &process->list, &run_queue );
} else {
- DBGC ( process, "PROCESS %p (%p) already started\n",
- process, process->step );
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " already started\n", PROC_DBG ( process ) );
}
}
@@ -63,14 +73,14 @@
*/
void process_del ( struct process *process ) {
if ( process_running ( process ) ) {
- DBGC ( process, "PROCESS %p (%p) stopping\n",
- process, process->step );
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " stopping\n", PROC_DBG ( process ) );
list_del ( &process->list );
INIT_LIST_HEAD ( &process->list );
ref_put ( process->refcnt );
} else {
- DBGC ( process, "PROCESS %p (%p) already stopped\n",
- process, process->step );
+ DBGC ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " already stopped\n", PROC_DBG ( process ) );
}
}
@@ -82,17 +92,25 @@
*/
void step ( void ) {
struct process *process;
+ struct process_descriptor *desc;
+ void *object;
if ( ( process = list_first_entry ( &run_queue, struct process,
list ) ) ) {
- list_del ( &process->list );
- list_add_tail ( &process->list, &run_queue );
ref_get ( process->refcnt ); /* Inhibit destruction mid-step */
- DBGC2 ( process, "PROCESS %p (%p) executing\n",
- process, process->step );
- process->step ( process );
- DBGC2 ( process, "PROCESS %p (%p) finished executing\n",
- process, process->step );
+ desc = process->desc;
+ object = process_object ( process );
+ if ( desc->reschedule ) {
+ list_del ( &process->list );
+ list_add_tail ( &process->list, &run_queue );
+ } else {
+ process_del ( process );
+ }
+ DBGC2 ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " executing\n", PROC_DBG ( process ) );
+ desc->step ( object );
+ DBGC2 ( PROC_COL ( process ), "PROCESS " PROC_FMT
+ " finished executing\n", PROC_DBG ( process ) );
ref_put ( process->refcnt ); /* Allow destruction */
}
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/core/resolv.c
^
|
@@ -86,16 +86,16 @@
int rc;
};
-static void numeric_step ( struct process *process ) {
- struct numeric_resolv *numeric =
- container_of ( process, struct numeric_resolv, process );
+static void numeric_step ( struct numeric_resolv *numeric ) {
- process_del ( process );
if ( numeric->rc == 0 )
resolv_done ( &numeric->resolv, &numeric->sa );
intf_shutdown ( &numeric->resolv, numeric->rc );
}
+static struct process_descriptor numeric_process_desc =
+ PROC_DESC_ONCE ( struct numeric_resolv, process, numeric_step );
+
static int numeric_resolv ( struct interface *resolv,
const char *name, struct sockaddr *sa ) {
struct numeric_resolv *numeric;
@@ -107,7 +107,8 @@
return -ENOMEM;
ref_init ( &numeric->refcnt, NULL );
intf_init ( &numeric->resolv, &null_intf_desc, &numeric->refcnt );
- process_init ( &numeric->process, numeric_step, &numeric->refcnt );
+ process_init ( &numeric->process, &numeric_process_desc,
+ &numeric->refcnt );
memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) );
DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n",
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/core/vsprintf.c
^
|
@@ -61,11 +61,20 @@
#define ALT_FORM 0x02
/**
+ * Use zero padding
+ *
+ * Note that this value is set to 0x10 since that allows the pad
+ * character to be calculated as @c 0x20|(flags&ZPAD)
+ */
+#define ZPAD 0x10
+
+/**
* Format a hexadecimal number
*
* @v end End of buffer to contain number
* @v num Number to format
* @v width Minimum field width
+ * @v flags Format flags
* @ret ptr End of buffer
*
* Fills a buffer in reverse order with a formatted hexadecimal
@@ -79,18 +88,18 @@
static char * format_hex ( char *end, unsigned long long num, int width,
int flags ) {
char *ptr = end;
- int case_mod;
+ int case_mod = ( flags & LCASE );
+ int pad = ( ( flags & ZPAD ) | ' ' );
/* Generate the number */
- case_mod = flags & LCASE;
do {
*(--ptr) = "0123456789ABCDEF"[ num & 0xf ] | case_mod;
num >>= 4;
} while ( num );
- /* Zero-pad to width */
+ /* Pad to width */
while ( ( end - ptr ) < width )
- *(--ptr) = '0';
+ *(--ptr) = pad;
/* Add "0x" or "0X" if alternate form specified */
if ( flags & ALT_FORM ) {
@@ -107,6 +116,7 @@
* @v end End of buffer to contain number
* @v num Number to format
* @v width Minimum field width
+ * @v flags Format flags
* @ret ptr End of buffer
*
* Fills a buffer in reverse order with a formatted decimal number.
@@ -115,9 +125,12 @@
* There must be enough space in the buffer to contain the largest
* number that this function can format.
*/
-static char * format_decimal ( char *end, signed long num, int width ) {
+static char * format_decimal ( char *end, signed long num, int width,
+ int flags ) {
char *ptr = end;
int negative = 0;
+ int zpad = ( flags & ZPAD );
+ int pad = ( zpad | ' ' );
/* Generate the number */
if ( num < 0 ) {
@@ -130,12 +143,16 @@
} while ( num );
/* Add "-" if necessary */
- if ( negative )
+ if ( negative && ( ! zpad ) )
*(--ptr) = '-';
- /* Space-pad to width */
+ /* Pad to width */
while ( ( end - ptr ) < width )
- *(--ptr) = ' ';
+ *(--ptr) = pad;
+
+ /* Add "-" if necessary */
+ if ( negative && zpad )
+ *ptr = '-';
return ptr;
}
@@ -186,7 +203,7 @@
if ( *fmt == '#' ) {
flags |= ALT_FORM;
} else if ( *fmt == '0' ) {
- /* We always 0-pad hex and space-pad decimal */
+ flags |= ZPAD;
} else {
/* End of flag characters */
break;
@@ -250,7 +267,7 @@
} else {
decimal = va_arg ( args, signed int );
}
- ptr = format_decimal ( ptr, decimal, width );
+ ptr = format_decimal ( ptr, decimal, width, flags );
} else {
*(--ptr) = *fmt;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/core/xfer.c
^
|
@@ -54,6 +54,7 @@
* @ret rc Return status code
*/
int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
+ struct interface tmp = INTF_INIT ( null_intf_desc );
struct interface *dest;
xfer_vredirect_TYPE ( void * ) *op =
intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest );
@@ -66,8 +67,22 @@
if ( op ) {
rc = op ( object, type, args );
} else {
- /* Default is to reopen the interface as instructed */
+ /* Default is to reopen the interface as instructed,
+ * then send xfer_window_changed() messages to both
+ * new child and parent interfaces. Since our
+ * original child interface is likely to be closed and
+ * unplugged as a result of the call to
+ * xfer_vreopen(), we create a temporary interface in
+ * order to be able to send xfer_window_changed() to
+ * the parent.
+ */
+ intf_plug ( &tmp, dest );
rc = xfer_vreopen ( dest, type, args );
+ if ( rc == 0 ) {
+ xfer_window_changed ( dest );
+ xfer_window_changed ( &tmp );
+ }
+ intf_unplug ( &tmp );
}
if ( rc != 0 ) {
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/crypto/asn1.c
^
|
@@ -29,6 +29,20 @@
*
*/
+/* Disambiguate the various error causes */
+#define EINVAL_ASN1_EMPTY \
+ __einfo_error ( EINFO_EINVAL_ASN1_EMPTY )
+#define EINFO_EINVAL_ASN1_EMPTY \
+ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Empty or underlength cursor" )
+#define EINVAL_ASN1_LEN_LEN \
+ __einfo_error ( EINFO_EINVAL_ASN1_LEN_LEN )
+#define EINFO_EINVAL_ASN1_LEN_LEN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Length field overruns cursor" )
+#define EINVAL_ASN1_LEN \
+ __einfo_error ( EINFO_EINVAL_ASN1_LEN )
+#define EINFO_EINVAL_ASN1_LEN \
+ __einfo_uniqify ( EINFO_EINVAL, 0x03, "Field overruns cursor" )
+
/**
* Start parsing ASN.1 object
*
@@ -40,32 +54,23 @@
* object body (i.e. the first byte following the length byte(s)), and
* the length of the object body (i.e. the number of bytes until the
* following object tag, if any) is returned.
- *
- * If any error occurs (i.e. if the object is not of the expected
- * type, or if we overflow beyond the end of the ASN.1 object), then
- * the cursor will be invalidated and a negative value will be
- * returned.
*/
-static int asn1_start ( struct asn1_cursor *cursor,
- unsigned int type ) {
+static int asn1_start ( struct asn1_cursor *cursor, unsigned int type ) {
unsigned int len_len;
unsigned int len;
- int rc;
/* Sanity check */
if ( cursor->len < 2 /* Tag byte and first length byte */ ) {
if ( cursor->len )
DBGC ( cursor, "ASN1 %p too short\n", cursor );
- rc = -EINVAL;
- goto notfound;
+ return -EINVAL_ASN1_EMPTY;
}
/* Check the tag byte */
if ( *( ( uint8_t * ) cursor->data ) != type ) {
DBGC ( cursor, "ASN1 %p type mismatch (expected %d, got %d)\n",
cursor, type, *( ( uint8_t * ) cursor->data ) );
- rc = -ENXIO;
- goto notfound;
+ return -ENXIO;
}
cursor->data++;
cursor->len--;
@@ -82,8 +87,7 @@
if ( cursor->len < len_len ) {
DBGC ( cursor, "ASN1 %p bad length field length %d (max "
"%zd)\n", cursor, len_len, cursor->len );
- rc = -EINVAL;
- goto notfound;
+ return -EINVAL_ASN1_LEN_LEN;
}
/* Extract the length and sanity check */
@@ -96,16 +100,10 @@
if ( cursor->len < len ) {
DBGC ( cursor, "ASN1 %p bad length %d (max %zd)\n",
cursor, len, cursor->len );
- rc = -EINVAL;
- goto notfound;
+ return -EINVAL_ASN1_LEN;
}
return len;
-
- notfound:
- cursor->data = NULL;
- cursor->len = 0;
- return rc;
}
/**
@@ -123,8 +121,10 @@
int len;
len = asn1_start ( cursor, type );
- if ( len < 0 )
+ if ( len < 0 ) {
+ asn1_invalidate_cursor ( cursor );
return len;
+ }
cursor->len = len;
DBGC ( cursor, "ASN1 %p entered object type %02x (len %x)\n",
@@ -134,17 +134,17 @@
}
/**
- * Skip ASN.1 object
+ * Skip ASN.1 object if present
*
* @v cursor ASN.1 object cursor
* @v type Expected type
* @ret rc Return status code
*
* The object cursor will be updated to point to the next ASN.1
- * object. If any error occurs, the object cursor will be
- * invalidated.
+ * object. If any error occurs, the object cursor will not be
+ * modified.
*/
-int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
+int asn1_skip_if_exists ( struct asn1_cursor *cursor, unsigned int type ) {
int len;
len = asn1_start ( cursor, type );
@@ -158,9 +158,30 @@
if ( ! cursor->len ) {
DBGC ( cursor, "ASN1 %p reached end of object\n", cursor );
- cursor->data = NULL;
return -ENOENT;
}
return 0;
+}
+
+/**
+ * Skip ASN.1 object
+ *
+ * @v cursor ASN.1 object cursor
+ * @v type Expected type
+ * @ret rc Return status code
+ *
+ * The object cursor will be updated to point to the next ASN.1
+ * object. If any error occurs, the object cursor will be
+ * invalidated.
+ */
+int asn1_skip ( struct asn1_cursor *cursor, unsigned int type ) {
+ int rc;
+
+ if ( ( rc = asn1_skip_if_exists ( cursor, type ) ) < 0 ) {
+ asn1_invalidate_cursor ( cursor );
+ return rc;
+ }
+
+ return 0;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/crypto/x509.c
^
|
@@ -55,7 +55,7 @@
memcpy ( &cursor, certificate, sizeof ( cursor ) );
rc = ( asn1_enter ( &cursor, ASN1_SEQUENCE ), /* Certificate */
asn1_enter ( &cursor, ASN1_SEQUENCE ), /* tbsCertificate */
- asn1_skip ( &cursor, ASN1_EXPLICIT_TAG ), /* version */
+ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ), /* version */
asn1_skip ( &cursor, ASN1_INTEGER ), /* serialNumber */
asn1_skip ( &cursor, ASN1_SEQUENCE ), /* signature */
asn1_skip ( &cursor, ASN1_SEQUENCE ), /* issuer */
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/drivers/block/scsi.c
^
|
@@ -218,8 +218,10 @@
/** SCSI device flags */
enum scsi_device_flags {
- /** Unit is ready */
- SCSIDEV_UNIT_READY = 0x0001,
+ /** TEST UNIT READY has been issued */
+ SCSIDEV_UNIT_TESTED = 0x0001,
+ /** TEST UNIT READY has completed successfully */
+ SCSIDEV_UNIT_READY = 0x0002,
};
/** A SCSI command */
@@ -892,23 +894,25 @@
/**
* SCSI TEST UNIT READY process
*
- * @v process Process
+ * @v scsidev SCSI device
*/
-static void scsidev_step ( struct process *process ) {
- struct scsi_device *scsidev =
- container_of ( process, struct scsi_device, process );
+static void scsidev_step ( struct scsi_device *scsidev ) {
int rc;
+ /* Do nothing if we have already issued TEST UNIT READY */
+ if ( scsidev->flags & SCSIDEV_UNIT_TESTED )
+ return;
+
/* Wait until underlying SCSI device is ready */
if ( xfer_window ( &scsidev->scsi ) == 0 )
return;
- /* Stop process */
- process_del ( &scsidev->process );
-
DBGC ( scsidev, "SCSI %p waiting for unit to become ready\n",
scsidev );
+ /* Mark TEST UNIT READY as sent */
+ scsidev->flags |= SCSIDEV_UNIT_TESTED;
+
/* Issue TEST UNIT READY command */
if ( ( rc = scsidev_test_unit_ready ( scsidev, &scsidev->ready )) !=0){
scsidev_close ( scsidev, rc );
@@ -918,6 +922,7 @@
/** SCSI device SCSI interface operations */
static struct interface_operation scsidev_scsi_op[] = {
+ INTF_OP ( xfer_window_changed, struct scsi_device *, scsidev_step ),
INTF_OP ( intf_close, struct scsi_device *, scsidev_close ),
};
@@ -926,6 +931,10 @@
INTF_DESC_PASSTHRU ( struct scsi_device, scsi,
scsidev_scsi_op, block );
+/** SCSI device process descriptor */
+static struct process_descriptor scsidev_process_desc =
+ PROC_DESC_ONCE ( struct scsi_device, process, scsidev_step );
+
/**
* Open SCSI device
*
@@ -946,7 +955,8 @@
intf_init ( &scsidev->block, &scsidev_block_desc, &scsidev->refcnt );
intf_init ( &scsidev->scsi, &scsidev_scsi_desc, &scsidev->refcnt );
intf_init ( &scsidev->ready, &scsidev_ready_desc, &scsidev->refcnt );
- process_init ( &scsidev->process, scsidev_step, &scsidev->refcnt );
+ process_init ( &scsidev->process, &scsidev_process_desc,
+ &scsidev->refcnt );
INIT_LIST_HEAD ( &scsidev->cmds );
memcpy ( &scsidev->lun, lun, sizeof ( scsidev->lun ) );
DBGC ( scsidev, "SCSI %p created for LUN " SCSI_LUN_FORMAT "\n",
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/drivers/net/igb/igb_osdep.h
^
|
@@ -69,11 +69,6 @@
#define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE
#define ETH_ADDR_LEN ETH_ALEN
-#ifdef __BIG_ENDIAN
-#define E1000_BIG_ENDIAN __BIG_ENDIAN
-#endif
-
-
#define DEBUGOUT(S) if (0) { printf(S); }
#define DEBUGOUT1(S, A...) if (0) { printf(S, A); }
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/drivers/net/ipoib.c
^
|
@@ -224,11 +224,13 @@
* @ret ll_dest Link-layer destination address
* @ret ll_source Source link-layer address
* @ret net_proto Network-layer protocol, in network-byte order
+ * @ret flags Packet flags
* @ret rc Return status code
*/
static int ipoib_pull ( struct net_device *netdev,
struct io_buffer *iobuf, const void **ll_dest,
- const void **ll_source, uint16_t *net_proto ) {
+ const void **ll_source, uint16_t *net_proto,
+ unsigned int *flags ) {
struct ipoib_device *ipoib = netdev->priv;
struct ipoib_hdr *ipoib_hdr = iobuf->data;
struct ipoib_peer *dest;
@@ -255,6 +257,7 @@
*ll_dest = ( dest ? &dest->mac : &ipoib->broadcast );
*ll_source = ( source ? &source->mac : &ipoib->broadcast );
*net_proto = ipoib_hdr->proto;
+ *flags = ( ( *ll_dest == &ipoib->broadcast ) ? LL_BROADCAST : 0 );
return 0;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/image/script.c
^
|
@@ -221,11 +221,17 @@
* @ret rc Return status code
*/
static int goto_find_label ( const char *line ) {
+ size_t len = strlen ( goto_label );
if ( line[0] != ':' )
return -ENOENT;
- if ( strcmp ( goto_label, &line[1] ) != 0 )
+
+ if ( strncmp ( goto_label, &line[1], len ) != 0 )
+ return -ENOENT;
+
+ if ( line[ 1 + len ] && ! isspace ( line[ 1 + len ] ) )
return -ENOENT;
+
return 0;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/include/ipxe/asn1.h
^
|
@@ -28,7 +28,19 @@
size_t len;
};
+/**
+ * Invalidate ASN.1 object cursor
+ *
+ * @v cursor ASN.1 object cursor
+ */
+static inline __attribute__ (( always_inline )) void
+asn1_invalidate_cursor ( struct asn1_cursor *cursor ) {
+ cursor->len = 0;
+}
+
extern int asn1_enter ( struct asn1_cursor *cursor, unsigned int type );
+extern int asn1_skip_if_exists ( struct asn1_cursor *cursor,
+ unsigned int type );
extern int asn1_skip ( struct asn1_cursor *cursor, unsigned int type );
#endif /* _IPXE_ASN1_H */
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/include/ipxe/dhcp.h
^
|
@@ -240,6 +240,39 @@
/** Client system architecture */
#define DHCP_CLIENT_ARCHITECTURE 93
+/** DHCP client architecture */
+struct dhcp_client_architecture {
+ uint16_t arch;
+} __attribute__ (( packed ));
+
+/** DHCP client architecture values
+ *
+ * These are defined by the PXE specification and redefined by
+ * RFC4578.
+ */
+enum dhcp_client_architecture_values {
+ /** Intel x86 PC */
+ DHCP_CLIENT_ARCHITECTURE_X86 = 0x0000,
+ /** NEC/PC98 */
+ DHCP_CLIENT_ARCHITECTURE_PC98 = 0x0001,
+ /** EFI Itanium */
+ DHCP_CLIENT_ARCHITECTURE_IA64 = 0x0002,
+ /** DEC Alpha */
+ DHCP_CLIENT_ARCHITECTURE_ALPHA = 0x0003,
+ /** Arc x86 */
+ DHCP_CLIENT_ARCHITECTURE_ARCX86 = 0x0004,
+ /** Intel Lean Client */
+ DHCP_CLIENT_ARCHITECTURE_LC = 0x0005,
+ /** EFI IA32 */
+ DHCP_CLIENT_ARCHITECTURE_IA32 = 0x0006,
+ /** EFI BC */
+ DHCP_CLIENT_ARCHITECTURE_EFI = 0x0007,
+ /** EFI Xscale */
+ DHCP_CLIENT_ARCHITECTURE_XSCALE = 0x0008,
+ /** EFI x86-64 */
+ DHCP_CLIENT_ARCHITECTURE_X86_64 = 0x0009,
+};
+
/** Client network device interface */
#define DHCP_CLIENT_NDI 94
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/include/ipxe/fc.h
^
|
@@ -357,7 +357,15 @@
/** List of upper-layer protocols */
struct list_head ulps;
- /** Active usage count */
+ /** Active usage count
+ *
+ * A peer (and attached ULPs) may be created in response to
+ * unsolicited login requests received via the fabric. We
+ * track our own active usage count independently of the
+ * existence of the peer, so that if the peer becomes logged
+ * out (e.g. due to a link failure) then we know whether or
+ * not we should attempt to relogin.
+ */
unsigned int usage;
};
@@ -424,8 +432,15 @@
/** Service parameter length */
size_t param_len;
- /** Active usage count */
- unsigned int usage;
+ /** Active users of this upper-layer protocol
+ *
+ * As with peers, an upper-layer protocol may be created in
+ * response to an unsolicited login request received via the
+ * fabric. This list records the number of active users of
+ * the ULP; the number of entries in the list is equivalent to
+ * the peer usage count.
+ */
+ struct list_head users;
};
/** Fibre Channel upper-layer protocol flags */
@@ -434,6 +449,21 @@
FC_ULP_ORIGINATED_LOGIN_OK = 0x0001,
};
+/** A Fibre Channel upper-layer protocol user */
+struct fc_ulp_user {
+ /** Fibre Channel upper layer protocol */
+ struct fc_ulp *ulp;
+ /** List of users */
+ struct list_head list;
+ /** Containing object reference count, or NULL */
+ struct refcnt *refcnt;
+ /** Examine link state
+ *
+ * @v user Fibre Channel upper-layer-protocol user
+ */
+ void ( * examine ) ( struct fc_ulp_user *user );
+};
+
/**
* Get reference to Fibre Channel upper-layer protocol
*
@@ -456,14 +486,51 @@
ref_put ( &ulp->refcnt );
}
+/**
+ * Get reference to Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ * @ret user Fibre Channel upper-layer protocol user
+ */
+static inline __attribute__ (( always_inline )) struct fc_ulp_user *
+fc_ulp_user_get ( struct fc_ulp_user *user ) {
+ ref_get ( user->refcnt );
+ return user;
+}
+
+/**
+ * Drop reference to Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ */
+static inline __attribute__ (( always_inline )) void
+fc_ulp_user_put ( struct fc_ulp_user *user ) {
+ ref_put ( user->refcnt );
+}
+
+/**
+ * Initialise Fibre Channel upper-layer protocol user
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ * @v examine Examine link state method
+ * @v refcnt Containing object reference count, or NULL
+ */
+static inline __attribute__ (( always_inline )) void
+fc_ulp_user_init ( struct fc_ulp_user *user,
+ void ( * examine ) ( struct fc_ulp_user *user ),
+ struct refcnt *refcnt ) {
+ user->examine = examine;
+ user->refcnt = refcnt;
+}
+
extern struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name *port_wwn,
unsigned int type );
extern struct fc_ulp *
fc_ulp_get_port_id_type ( struct fc_port *port,
const struct fc_port_id *peer_port_id,
unsigned int type );
-extern void fc_ulp_increment ( struct fc_ulp *ulp );
-extern void fc_ulp_decrement ( struct fc_ulp *ulp );
+extern void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user );
+extern void fc_ulp_detach ( struct fc_ulp_user *user );
extern int fc_ulp_login ( struct fc_ulp *ulp, const void *param,
size_t param_len, int originated );
extern void fc_ulp_logout ( struct fc_ulp *ulp, int rc );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/include/ipxe/ip.h
^
|
@@ -31,9 +31,6 @@
#define IP_TOS 0
#define IP_TTL 64
-#define IP_FRAG_IOB_SIZE 1500
-#define IP_FRAG_TIMEOUT 50
-
/** An IPv4 packet header */
struct iphdr {
uint8_t verhdrlen;
@@ -73,20 +70,16 @@
struct in_addr gateway;
};
-/* Fragment reassembly buffer */
-struct frag_buffer {
- /* Identification number */
- uint16_t ident;
- /* Source network address */
- struct in_addr src;
- /* Destination network address */
- struct in_addr dest;
- /* Reassembled I/O buffer */
- struct io_buffer *frag_iob;
- /* Reassembly timer */
- struct retry_timer frag_timer;
+/* IPv4 fragment reassembly buffer */
+struct ipv4_fragment {
/* List of fragment reassembly buffers */
struct list_head list;
+ /** Reassembled packet */
+ struct io_buffer *iobuf;
+ /** Current offset */
+ size_t offset;
+ /** Reassembly timer */
+ struct retry_timer timer;
};
extern struct list_head ipv4_miniroutes;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/include/ipxe/netdevice.h
^
|
@@ -66,20 +66,23 @@
/**
* Process received packet
*
- * @v iobuf I/O buffer
- * @v netdev Network device
- * @v ll_dest Link-layer destination address
- * @v ll_source Link-layer source address
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer source address
+ * @v flags Packet flags
+ * @ret rc Return status code
*
* This method takes ownership of the I/O buffer.
*/
int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev,
- const void *ll_dest, const void *ll_source );
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags );
/**
* Transcribe network-layer address
*
- * @v net_addr Network-layer address
- * @ret string Human-readable transcription of address
+ * @v net_addr Network-layer address
+ * @ret string Human-readable transcription of address
*
* This method should convert the network-layer address into a
* human-readable format (e.g. dotted quad notation for IPv4).
@@ -97,6 +100,12 @@
uint8_t net_addr_len;
};
+/** Packet is a multicast (including broadcast) packet */
+#define LL_MULTICAST 0x0001
+
+/** Packet is a broadcast packet */
+#define LL_BROADCAST 0x0002
+
/**
* A link-layer protocol
*
@@ -125,11 +134,12 @@
* @ret ll_dest Link-layer destination address
* @ret ll_source Source link-layer address
* @ret net_proto Network-layer protocol, in network-byte order
+ * @ret flags Packet flags
* @ret rc Return status code
*/
int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf,
const void **ll_dest, const void **ll_source,
- uint16_t *net_proto );
+ uint16_t *net_proto, unsigned int *flags );
/**
* Initialise link-layer address
*
@@ -586,6 +596,8 @@
extern void netdev_link_err ( struct net_device *netdev, int rc );
extern void netdev_link_down ( struct net_device *netdev );
extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf );
+extern void netdev_tx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc );
extern void netdev_tx_complete_err ( struct net_device *netdev,
struct io_buffer *iobuf, int rc );
extern void netdev_tx_complete_next_err ( struct net_device *netdev, int rc );
@@ -609,7 +621,7 @@
const void *ll_source );
extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
uint16_t net_proto, const void *ll_dest,
- const void *ll_source );
+ const void *ll_source, unsigned int flags );
extern void net_poll ( void );
/**
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/include/ipxe/process.h
^
|
@@ -17,6 +17,20 @@
struct process {
/** List of processes */
struct list_head list;
+ /** Process descriptor */
+ struct process_descriptor *desc;
+ /** Reference counter
+ *
+ * If this process is not part of a reference-counted object,
+ * this field may be NULL.
+ */
+ struct refcnt *refcnt;
+};
+
+/** A process descriptor */
+struct process_descriptor {
+ /** Offset of process within containing object */
+ size_t offset;
/**
* Single-step the process
*
@@ -24,15 +38,81 @@
* Returning from this method is isomorphic to yielding the
* CPU to another process.
*/
- void ( * step ) ( struct process *process );
- /** Reference counter
- *
- * If this interface is not part of a reference-counted
- * object, this field may be NULL.
- */
- struct refcnt *refcnt;
+ void ( * step ) ( void *object );
+ /** Automatically reschedule the process */
+ int reschedule;
};
+/**
+ * Define a process step() method
+ *
+ * @v object_type Implementing method's expected object type
+ * @v step Implementing method
+ * @ret step Process step method
+ */
+#define PROC_STEP( object_type, step ) \
+ ( ( ( ( typeof ( step ) * ) NULL ) == \
+ ( ( void ( * ) ( object_type *object ) ) NULL ) ) ? \
+ ( void ( * ) ( void *object ) ) step : \
+ ( void ( * ) ( void *object ) ) step )
+
+/**
+ * Calculate offset of process within containing object
+ *
+ * @v object_type Containing object data type
+ * @v name Process name (i.e. field within object data type)
+ * @ret offset Offset of process within containing object
+ */
+#define process_offset( object_type, name ) \
+ ( ( ( ( typeof ( ( ( object_type * ) NULL )->name ) * ) NULL ) \
+ == ( ( struct process * ) NULL ) ) \
+ ? offsetof ( object_type, name ) \
+ : offsetof ( object_type, name ) )
+
+/**
+ * Define a process descriptor
+ *
+ * @v object_type Containing object data type
+ * @v process Process name (i.e. field within object data type)
+ * @v step Process' step() method
+ * @ret desc Object interface descriptor
+ */
+#define PROC_DESC( object_type, process, _step ) { \
+ .offset = process_offset ( object_type, process ), \
+ .step = PROC_STEP ( object_type, _step ), \
+ .reschedule = 1, \
+ }
+
+/**
+ * Define a process descriptor for a process that runs only once
+ *
+ * @v object_type Containing object data type
+ * @v process Process name (i.e. field within object data type)
+ * @v step Process' step() method
+ * @ret desc Object interface descriptor
+ */
+#define PROC_DESC_ONCE( object_type, process, _step ) { \
+ .offset = process_offset ( object_type, process ), \
+ .step = PROC_STEP ( object_type, _step ), \
+ .reschedule = 0, \
+ }
+
+/**
+ * Define a process descriptor for a pure process
+ *
+ * A pure process is a process that does not have a containing object.
+ *
+ * @v step Process' step() method
+ * @ret desc Object interface descriptor
+ */
+#define PROC_DESC_PURE( _step ) { \
+ .offset = 0, \
+ .step = PROC_STEP ( struct process, _step ), \
+ .reschedule = 1, \
+ }
+
+extern void * __attribute__ (( pure ))
+process_object ( struct process *process );
extern void process_add ( struct process *process );
extern void process_del ( struct process *process );
extern void step ( void );
@@ -41,14 +121,15 @@
* Initialise process without adding to process list
*
* @v process Process
- * @v step Process' step() method
+ * @v desc Process descriptor
+ * @v refcnt Containing object reference count, or NULL
*/
static inline __attribute__ (( always_inline )) void
process_init_stopped ( struct process *process,
- void ( * step ) ( struct process *process ),
+ struct process_descriptor *desc,
struct refcnt *refcnt ) {
INIT_LIST_HEAD ( &process->list );
- process->step = step;
+ process->desc = desc;
process->refcnt = refcnt;
}
@@ -56,13 +137,14 @@
* Initialise process and add to process list
*
* @v process Process
- * @v step Process' step() method
+ * @v desc Process descriptor
+ * @v refcnt Containing object reference count, or NULL
*/
static inline __attribute__ (( always_inline )) void
process_init ( struct process *process,
- void ( * step ) ( struct process *process ),
+ struct process_descriptor *desc,
struct refcnt *refcnt ) {
- process_init_stopped ( process, step, refcnt );
+ process_init_stopped ( process, desc, refcnt );
process_add ( process );
}
@@ -88,4 +170,36 @@
*/
#define __permanent_process __table_entry ( PERMANENT_PROCESSES, 01 )
+/** Define a permanent process
+ *
+ */
+#define PERMANENT_PROCESS( name, step ) \
+struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \
+struct process name __permanent_process = { \
+ .list = LIST_HEAD_INIT ( name.list ), \
+ .desc = & name ## _desc, \
+ .refcnt = NULL, \
+};
+
+/**
+ * Find debugging colourisation for a process
+ *
+ * @v process Process
+ * @ret col Debugging colourisation
+ *
+ * Use as the first argument to DBGC() or equivalent macro.
+ */
+#define PROC_COL( process ) process_object ( process )
+
+/** printf() format string for PROC_DBG() */
+#define PROC_FMT "%p+%zx"
+
+/**
+ * printf() arguments for representing a process
+ *
+ * @v process Process
+ * @ret args printf() argument list corresponding to PROC_FMT
+ */
+#define PROC_DBG( process ) process_object ( process ), (process)->desc->offset
+
#endif /* _IPXE_PROCESS_H */
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/interface/efi/efi_snp.c
^
|
@@ -658,6 +658,7 @@
const void *iob_ll_dest;
const void *iob_ll_src;
uint16_t iob_net_proto;
+ unsigned int iob_flags;
int rc;
EFI_STATUS efirc;
@@ -682,7 +683,8 @@
/* Attempt to decode link-layer header */
if ( ( rc = ll_protocol->pull ( snpdev->netdev, iobuf, &iob_ll_dest,
- &iob_ll_src, &iob_net_proto ) ) != 0 ){
+ &iob_ll_src, &iob_net_proto,
+ &iob_flags ) ) != 0 ) {
DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n",
snpdev, strerror ( rc ) );
efirc = RC_TO_EFIRC ( rc );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/80211/net80211.c
^
|
@@ -135,7 +135,8 @@
const void *ll_source, uint16_t net_proto );
static int net80211_ll_pull ( struct net_device *netdev,
struct io_buffer *iobuf, const void **ll_dest,
- const void **ll_source, uint16_t * net_proto );
+ const void **ll_source, uint16_t * net_proto,
+ unsigned int *flags );
/** @} */
/**
@@ -159,7 +160,7 @@
* @defgroup net80211_assoc_ll 802.11 association handling functions
* @{
*/
-static void net80211_step_associate ( struct process *proc );
+static void net80211_step_associate ( struct net80211_device *dev );
static void net80211_handle_auth ( struct net80211_device *dev,
struct io_buffer *iob );
static void net80211_handle_assoc_reply ( struct net80211_device *dev,
@@ -529,6 +530,7 @@
* @ret ll_dest Link-layer destination address
* @ret ll_source Link-layer source
* @ret net_proto Network-layer protocol, in network byte order
+ * @ret flags Packet flags
* @ret rc Return status code
*
* This expects and removes both the 802.11 frame header and the 802.2
@@ -537,7 +539,7 @@
static int net80211_ll_pull ( struct net_device *netdev __unused,
struct io_buffer *iobuf,
const void **ll_dest, const void **ll_source,
- uint16_t * net_proto )
+ uint16_t * net_proto, unsigned int *flags )
{
struct ieee80211_frame *hdr = iobuf->data;
struct ieee80211_llc_snap_header *lhdr =
@@ -586,6 +588,10 @@
*ll_dest = hdr->addr1;
*ll_source = hdr->addr3;
*net_proto = lhdr->ethertype;
+ *flags = ( ( is_multicast_ether_addr ( hdr->addr1 ) ?
+ LL_MULTICAST : 0 ) |
+ ( is_broadcast_ether_addr ( hdr->addr1 ) ?
+ LL_BROADCAST : 0 ) );
return 0;
}
@@ -729,6 +735,11 @@
/* ---------- Driver API ---------- */
+/** 802.11 association process descriptor */
+static struct process_descriptor net80211_process_desc =
+ PROC_DESC ( struct net80211_device, proc_assoc,
+ net80211_step_associate );
+
/**
* Allocate 802.11 device
*
@@ -760,7 +771,7 @@
dev->priv = ( u8 * ) dev + sizeof ( *dev );
dev->op = &net80211_null_ops;
- process_init_stopped ( &dev->proc_assoc, net80211_step_associate,
+ process_init_stopped ( &dev->proc_assoc, &net80211_process_desc,
&netdev->refcnt );
INIT_LIST_HEAD ( &dev->mgmt_queue );
INIT_LIST_HEAD ( &dev->mgmt_info_queue );
@@ -1630,12 +1641,10 @@
/**
* Step 802.11 association process
*
- * @v proc Association process
+ * @v dev 802.11 device
*/
-static void net80211_step_associate ( struct process *proc )
+static void net80211_step_associate ( struct net80211_device *dev )
{
- struct net80211_device *dev =
- container_of ( proc, struct net80211_device, proc_assoc );
int rc = 0;
int status = dev->state & NET80211_STATUS_MASK;
@@ -1836,7 +1845,7 @@
dev->rctl = rc80211_init ( dev );
- process_del ( proc );
+ process_del ( &dev->proc_assoc );
DBGC ( dev, "802.11 %p associated with %s (%s)\n", dev,
dev->essid, eth_ntoa ( dev->bssid ) );
@@ -1861,7 +1870,7 @@
net80211_free_wlan ( dev->associating );
dev->associating = NULL;
- process_del ( proc );
+ process_del ( &dev->proc_assoc );
DBGC ( dev, "802.11 %p association failed (state=%04x): "
"%s\n", dev, dev->state, strerror ( dev->assoc_rc ) );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/aoe.c
^
|
@@ -906,13 +906,14 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
- *
*/
static int aoe_rx ( struct io_buffer *iobuf,
struct net_device *netdev __unused,
const void *ll_dest __unused,
- const void *ll_source ) {
+ const void *ll_source,
+ unsigned int flags __unused ) {
struct aoehdr *aoehdr = iobuf->data;
struct aoe_command *aoecmd;
int rc;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/arp.c
^
|
@@ -186,6 +186,7 @@
* @v iobuf I/O buffer
* @v netdev Network device
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*
* This handles ARP requests and responses as detailed in RFC826. The
@@ -196,7 +197,8 @@
*/
static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
const void *ll_dest __unused,
- const void *ll_source __unused ) {
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
struct arphdr *arphdr = iobuf->data;
struct arp_net_protocol *arp_net_protocol;
struct net_protocol *net_protocol;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/eapol.c
^
|
@@ -38,11 +38,13 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
*
* This function takes ownership of the I/O buffer passed to it.
*/
static int eapol_rx ( struct io_buffer *iob, struct net_device *netdev,
- const void *ll_dest, const void *ll_source ) {
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags __unused ) {
struct eapol_frame *eapol = iob->data;
struct eapol_handler *handler;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/eth_slow.c
^
|
@@ -234,12 +234,14 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*/
static int eth_slow_rx ( struct io_buffer *iobuf,
struct net_device *netdev,
const void *ll_dest __unused,
- const void *ll_source __unused ) {
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
union eth_slow_packet *eth_slow = iobuf->data;
/* Sanity checks */
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/ethernet.c
^
|
@@ -71,11 +71,13 @@
* @ret ll_dest Link-layer destination address
* @ret ll_source Source link-layer address
* @ret net_proto Network-layer protocol, in network-byte order
+ * @ret flags Packet flags
* @ret rc Return status code
*/
static int eth_pull ( struct net_device *netdev __unused,
struct io_buffer *iobuf, const void **ll_dest,
- const void **ll_source, uint16_t *net_proto ) {
+ const void **ll_source, uint16_t *net_proto,
+ unsigned int *flags ) {
struct ethhdr *ethhdr = iobuf->data;
/* Sanity check */
@@ -92,6 +94,10 @@
*ll_dest = ethhdr->h_dest;
*ll_source = ethhdr->h_source;
*net_proto = ethhdr->h_protocol;
+ *flags = ( ( is_multicast_ether_addr ( ethhdr->h_dest ) ?
+ LL_MULTICAST : 0 ) |
+ ( is_broadcast_ether_addr ( ethhdr->h_dest ) ?
+ LL_BROADCAST : 0 ) );
return 0;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/fc.c
^
|
@@ -1580,7 +1580,7 @@
fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
/* Sanity check */
- assert ( ulp->usage == 0 );
+ assert ( list_empty ( &ulp->users ) );
/* Stop link monitor */
fc_link_stop ( &ulp->link );
@@ -1594,35 +1594,50 @@
}
/**
- * Increment Fibre Channel upper-layer protocol active usage count
+ * Attach Fibre Channel upper-layer protocol user
*
- * @v ulp Fibre Channel ulp
+ * @v ulp Fibre Channel upper-layer protocol
+ * @v user Fibre Channel upper-layer protocol user
*/
-void fc_ulp_increment ( struct fc_ulp *ulp ) {
+void fc_ulp_attach ( struct fc_ulp *ulp, struct fc_ulp_user *user ) {
+
+ /* Sanity check */
+ assert ( user->ulp == NULL );
/* Increment peer's usage count */
fc_peer_increment ( ulp->peer );
- /* Increment our usage count */
- ulp->usage++;
+ /* Attach user */
+ user->ulp = fc_ulp_get ( ulp );
+ list_add ( &user->list, &ulp->users );
}
/**
- * Decrement Fibre Channel upper-layer protocol active usage count
+ * Detach Fibre Channel upper-layer protocol user
*
- * @v ulp Fibre Channel ulp
+ * @v user Fibre Channel upper-layer protocol user
*/
-void fc_ulp_decrement ( struct fc_ulp *ulp ) {
+void fc_ulp_detach ( struct fc_ulp_user *user ) {
+ struct fc_ulp *ulp = user->ulp;
- /* Sanity check */
- assert ( ulp->usage > 0 );
+ /* Do nothing if not attached */
+ if ( ! ulp )
+ return;
+
+ /* Sanity checks */
+ list_check_contains ( user, &ulp->users, list );
- /* Decrement our usage count and log out if we reach zero */
- if ( --(ulp->usage) == 0 )
+ /* Detach user and log out if no users remain */
+ list_del ( &user->list );
+ if ( list_empty ( &ulp->users ) )
fc_ulp_logout ( ulp, 0 );
/* Decrement our peer's usage count */
fc_peer_decrement ( ulp->peer );
+
+ /* Drop reference */
+ user->ulp = NULL;
+ fc_ulp_put ( ulp );
}
/**
@@ -1636,6 +1651,8 @@
*/
int fc_ulp_login ( struct fc_ulp *ulp, const void *param, size_t param_len,
int originated ) {
+ struct fc_ulp_user *user;
+ struct fc_ulp_user *tmp;
/* Perform implicit logout if logged in and service parameters differ */
if ( fc_link_ok ( &ulp->link ) &&
@@ -1644,6 +1661,22 @@
fc_ulp_logout ( ulp, 0 );
}
+ /* Work around a bug in some versions of the Linux Fibre
+ * Channel stack, which fail to fully initialise image pairs
+ * established via a PRLI originated by the Linux stack
+ * itself.
+ */
+ if ( originated )
+ ulp->flags |= FC_ULP_ORIGINATED_LOGIN_OK;
+ if ( ! ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) ) {
+ DBGC ( ulp, "FCULP %s/%02x sending extra PRLI to work around "
+ "Linux bug\n",
+ fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
+ fc_link_stop ( &ulp->link );
+ fc_link_start ( &ulp->link );
+ return 0;
+ }
+
/* Log in, if applicable */
if ( ! fc_link_ok ( &ulp->link ) ) {
@@ -1670,18 +1703,11 @@
/* Record login */
fc_link_up ( &ulp->link );
- /* Work around a bug in some versions of the Linux Fibre
- * Channel stack, which fail to fully initialise image pairs
- * established via a PRLI originated by the Linux stack
- * itself.
- */
- if ( originated )
- ulp->flags |= FC_ULP_ORIGINATED_LOGIN_OK;
- if ( ! ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) ) {
- DBGC ( ulp, "FCULP %s/%02x sending extra PRLI to work around "
- "Linux bug\n",
- fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
- fc_link_start ( &ulp->link );
+ /* Notify users of link state change */
+ list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
+ fc_ulp_user_get ( user );
+ user->examine ( user );
+ fc_ulp_user_put ( user );
}
return 0;
@@ -1694,6 +1720,8 @@
* @v rc Reason for logout
*/
void fc_ulp_logout ( struct fc_ulp *ulp, int rc ) {
+ struct fc_ulp_user *user;
+ struct fc_ulp_user *tmp;
DBGC ( ulp, "FCULP %s/%02x logged out: %s\n",
fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
@@ -1711,8 +1739,15 @@
/* Record logout */
fc_link_err ( &ulp->link, rc );
+ /* Notify users of link state change */
+ list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
+ fc_ulp_user_get ( user );
+ user->examine ( user );
+ fc_ulp_user_put ( user );
+ }
+
/* Close ULP if there are no clients attached */
- if ( ulp->usage == 0 )
+ if ( list_empty ( &ulp->users ) )
fc_ulp_close ( ulp, rc );
}
@@ -1795,6 +1830,7 @@
ulp->peer = fc_peer_get ( peer );
list_add_tail ( &ulp->list, &peer->ulps );
ulp->type = type;
+ INIT_LIST_HEAD ( &ulp->users );
/* Start link state monitor */
fc_link_start ( &ulp->link );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/fcels.c
^
|
@@ -244,20 +244,15 @@
/**
* Fibre Channel ELS process
*
- * @v process Process
+ * @v els Fibre Channel ELS transaction
*/
-static void fc_els_step ( struct process *process ) {
- struct fc_els *els =
- container_of ( process, struct fc_els, process );
+static void fc_els_step ( struct fc_els *els ) {
int xchg_id;
int rc;
/* Sanity check */
assert ( fc_els_is_request ( els ) );
- /* Stop process */
- process_del ( &els->process );
-
/* Create exchange */
if ( ( xchg_id = fc_xchg_originate ( &els->xchg, els->port,
&els->peer_port_id,
@@ -278,6 +273,10 @@
}
}
+/** Fibre Channel ELS process descriptor */
+static struct process_descriptor fc_els_process_desc =
+ PROC_DESC_ONCE ( struct fc_els, process, fc_els_step );
+
/**
* Create ELS transaction
*
@@ -298,7 +297,8 @@
ref_init ( &els->refcnt, fc_els_free );
intf_init ( &els->job, &fc_els_job_desc, &els->refcnt );
intf_init ( &els->xchg, &fc_els_xchg_desc, &els->refcnt );
- process_init_stopped ( &els->process, fc_els_step, &els->refcnt );
+ process_init_stopped ( &els->process, &fc_els_process_desc,
+ &els->refcnt );
els->port = fc_port_get ( port );
memcpy ( &els->port_id, port_id, sizeof ( els->port_id ) );
memcpy ( &els->peer_port_id, peer_port_id,
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/fcns.c
^
|
@@ -153,19 +153,14 @@
/**
* Name server query process
*
- * @v process Process
+ * @v query Name server query
*/
-static void fc_ns_query_step ( struct process *process ) {
- struct fc_ns_query *query =
- container_of ( process, struct fc_ns_query, process );
+static void fc_ns_query_step ( struct fc_ns_query *query ) {
struct xfer_metadata meta;
struct fc_ns_gid_pn_request gid_pn;
int xchg_id;
int rc;
- /* Stop process */
- process_del ( &query->process );
-
/* Create exchange */
if ( ( xchg_id = fc_xchg_originate ( &query->xchg, query->port,
&fc_gs_port_id,
@@ -208,6 +203,10 @@
static struct interface_descriptor fc_ns_query_xchg_desc =
INTF_DESC ( struct fc_ns_query, xchg, fc_ns_query_xchg_op );
+/** Name server process descriptor */
+static struct process_descriptor fc_ns_query_process_desc =
+ PROC_DESC_ONCE ( struct fc_ns_query, process, fc_ns_query_step );
+
/**
* Issue Fibre Channel name server query
*
@@ -226,7 +225,8 @@
return -ENOMEM;
ref_init ( &query->refcnt, fc_ns_query_free );
intf_init ( &query->xchg, &fc_ns_query_xchg_desc, &query->refcnt );
- process_init ( &query->process, fc_ns_query_step, &query->refcnt );
+ process_init ( &query->process, &fc_ns_query_process_desc,
+ &query->refcnt );
query->peer = fc_peer_get ( peer );
query->port = fc_port_get ( port );
query->done = done;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/fcoe.c
^
|
@@ -331,10 +331,12 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*/
static int fcoe_rx ( struct io_buffer *iobuf, struct net_device *netdev,
- const void *ll_dest, const void *ll_source ) {
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags __unused ) {
struct fcoe_header *fcoehdr;
struct fcoe_footer *fcoeftr;
struct fcoe_port *fcoe;
@@ -924,12 +926,14 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*/
static int fcoe_fip_rx ( struct io_buffer *iobuf,
struct net_device *netdev,
const void *ll_dest,
- const void *ll_source __unused ) {
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
struct fip_header *fiphdr = iobuf->data;
struct fip_descriptors descs;
struct fip_handler *handler;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/fcp.c
^
|
@@ -146,8 +146,8 @@
struct fcp_device {
/** Reference count */
struct refcnt refcnt;
- /** Fibre Channel upper-layer protocol */
- struct fc_ulp *ulp;
+ /** Fibre Channel upper-layer protocol user */
+ struct fc_ulp_user user;
/** SCSI command issuing interface */
struct interface scsi;
/** List of active commands */
@@ -649,11 +649,9 @@
/**
* Transmit FCP frame
*
- * @v process FCP command process
+ * @v fcpcmd FCP command
*/
-static void fcpcmd_step ( struct process *process ) {
- struct fcp_command *fcpcmd =
- container_of ( process, struct fcp_command, process );
+static void fcpcmd_step ( struct fcp_command *fcpcmd ) {
int rc;
/* Send the current IU */
@@ -723,6 +721,10 @@
static struct interface_descriptor fcpcmd_xchg_desc =
INTF_DESC_PASSTHRU ( struct fcp_command, xchg, fcpcmd_xchg_op, scsi );
+/** FCP command process descriptor */
+static struct process_descriptor fcpcmd_process_desc =
+ PROC_DESC ( struct fcp_command, process, fcpcmd_step );
+
/**
* Issue FCP SCSI command
*
@@ -734,13 +736,13 @@
static int fcpdev_scsi_command ( struct fcp_device *fcpdev,
struct interface *parent,
struct scsi_cmd *command ) {
- struct fcp_prli_service_parameters *param = fcpdev->ulp->param;
+ struct fcp_prli_service_parameters *param = fcpdev->user.ulp->param;
struct fcp_command *fcpcmd;
int xchg_id;
int rc;
/* Check link */
- if ( ( rc = fcpdev->ulp->link.rc ) != 0 ) {
+ if ( ( rc = fcpdev->user.ulp->link.rc ) != 0 ) {
DBGC ( fcpdev, "FCP %p could not issue command while link is "
"down: %s\n", fcpdev, strerror ( rc ) );
goto err_link;
@@ -748,7 +750,7 @@
/* Check target capability */
assert ( param != NULL );
- assert ( fcpdev->ulp->param_len >= sizeof ( *param ) );
+ assert ( fcpdev->user.ulp->param_len >= sizeof ( *param ) );
if ( ! ( param->flags & htonl ( FCP_PRLI_TARGET ) ) ) {
DBGC ( fcpdev, "FCP %p could not issue command: not a target\n",
fcpdev );
@@ -765,15 +767,16 @@
ref_init ( &fcpcmd->refcnt, fcpcmd_free );
intf_init ( &fcpcmd->scsi, &fcpcmd_scsi_desc, &fcpcmd->refcnt );
intf_init ( &fcpcmd->xchg, &fcpcmd_xchg_desc, &fcpcmd->refcnt );
- process_init_stopped ( &fcpcmd->process, fcpcmd_step, &fcpcmd->refcnt );
+ process_init_stopped ( &fcpcmd->process, &fcpcmd_process_desc,
+ &fcpcmd->refcnt );
fcpcmd->fcpdev = fcpdev_get ( fcpdev );
list_add ( &fcpcmd->list, &fcpdev->fcpcmds );
memcpy ( &fcpcmd->command, command, sizeof ( fcpcmd->command ) );
/* Create new exchange */
if ( ( xchg_id = fc_xchg_originate ( &fcpcmd->xchg,
- fcpdev->ulp->peer->port,
- &fcpdev->ulp->peer->port_id,
+ fcpdev->user.ulp->peer->port,
+ &fcpdev->user.ulp->peer->port_id,
FC_TYPE_FCP ) ) < 0 ) {
rc = xchg_id;
DBGC ( fcpdev, "FCP %p could not create exchange: %s\n",
@@ -822,11 +825,7 @@
}
/* Drop reference to ULP */
- if ( fcpdev->ulp ) {
- fc_ulp_decrement ( fcpdev->ulp );
- fc_ulp_put ( fcpdev->ulp );
- fcpdev->ulp = NULL;
- }
+ fc_ulp_detach ( &fcpdev->user );
}
/**
@@ -836,7 +835,8 @@
* @ret len Length of window
*/
static size_t fcpdev_window ( struct fcp_device *fcpdev ) {
- return ( fc_link_ok ( &fcpdev->ulp->link ) ? ~( ( size_t ) 0 ) : 0 );
+ return ( fc_link_ok ( &fcpdev->user.ulp->link ) ?
+ ~( ( size_t ) 0 ) : 0 );
}
/**
@@ -897,15 +897,15 @@
/* We know the underlying device only if the link is up;
* otherwise we don't have a port to examine.
*/
- if ( ! fc_link_ok ( &fcpdev->ulp->link ) ) {
+ if ( ! fc_link_ok ( &fcpdev->user.ulp->link ) ) {
DBGC ( fcpdev, "FCP %p doesn't know underlying device "
"until link is up\n", fcpdev );
return NULL;
}
/* Hand off to port's transport interface */
- assert ( fcpdev->ulp->peer->port != NULL );
- return identify_device ( &fcpdev->ulp->peer->port->transport );
+ assert ( fcpdev->user.ulp->peer->port != NULL );
+ return identify_device ( &fcpdev->user.ulp->peer->port->transport );
}
/** FCP device SCSI interface operations */
@@ -924,6 +924,26 @@
INTF_DESC ( struct fcp_device, scsi, fcpdev_scsi_op );
/**
+ * Examine FCP ULP link state
+ *
+ * @v user Fibre Channel upper-layer protocol user
+ */
+static void fcpdev_examine ( struct fc_ulp_user *user ) {
+ struct fcp_device *fcpdev =
+ container_of ( user, struct fcp_device, user );
+
+ if ( fc_link_ok ( &fcpdev->user.ulp->link ) ) {
+ DBGC ( fcpdev, "FCP %p link is up\n", fcpdev );
+ } else {
+ DBGC ( fcpdev, "FCP %p link is down: %s\n",
+ fcpdev, strerror ( fcpdev->user.ulp->link.rc ) );
+ }
+
+ /* Notify SCSI layer of window change */
+ xfer_window_changed ( &fcpdev->scsi );
+}
+
+/**
* Open FCP device
*
* @v parent Parent interface
@@ -953,11 +973,13 @@
ref_init ( &fcpdev->refcnt, NULL );
intf_init ( &fcpdev->scsi, &fcpdev_scsi_desc, &fcpdev->refcnt );
INIT_LIST_HEAD ( &fcpdev->fcpcmds );
- fcpdev->ulp = fc_ulp_get ( ulp );
- fc_ulp_increment ( fcpdev->ulp );
+ fc_ulp_user_init ( &fcpdev->user, fcpdev_examine, &fcpdev->refcnt );
DBGC ( fcpdev, "FCP %p opened for %s\n", fcpdev, fc_ntoa ( wwn ) );
+ /* Attach to Fibre Channel ULP */
+ fc_ulp_attach ( ulp, &fcpdev->user );
+
/* Preserve parameters required for boot firmware table */
memcpy ( &fcpdev->wwn, wwn, sizeof ( fcpdev->wwn ) );
memcpy ( &fcpdev->lun, lun, sizeof ( fcpdev->lun ) );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/infiniband.c
^
|
@@ -866,10 +866,7 @@
}
/** Infiniband event queue process */
-struct process ib_process __permanent_process = {
- .list = LIST_HEAD_INIT ( ib_process.list ),
- .step = ib_step,
-};
+PERMANENT_PROCESS ( ib_process, ib_step );
/***************************************************************************
*
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/infiniband/ib_cmrc.c
^
|
@@ -92,7 +92,7 @@
/**
* Shut down CMRC connection gracefully
*
- * @v process Process
+ * @v cmrc Communication-Managed Reliable Connection
*
* The Infiniband data structures are not reference-counted or
* guarded. It is therefore unsafe to shut them down while we may be
@@ -107,9 +107,7 @@
* connection, ensuring that the structure is not freed before the
* shutdown process has run.
*/
-static void ib_cmrc_shutdown ( struct process *process ) {
- struct ib_cmrc_connection *cmrc =
- container_of ( process, struct ib_cmrc_connection, shutdown );
+static void ib_cmrc_shutdown ( struct ib_cmrc_connection *cmrc ) {
DBGC ( cmrc, "CMRC %p shutting down\n", cmrc );
@@ -119,9 +117,6 @@
ib_destroy_cq ( cmrc->ibdev, cmrc->cq );
ib_close ( cmrc->ibdev );
- /* Remove process from run queue */
- process_del ( &cmrc->shutdown );
-
/* Drop the remaining reference */
ref_put ( &cmrc->refcnt );
}
@@ -180,6 +175,9 @@
return;
}
+ /* Notify upper connection of window change */
+ xfer_window_changed ( &cmrc->xfer );
+
/* If we are disconnected, close the upper connection */
if ( rc_cm != 0 ) {
ib_cmrc_close ( cmrc, rc_cm );
@@ -360,6 +358,11 @@
static struct interface_descriptor ib_cmrc_xfer_desc =
INTF_DESC ( struct ib_cmrc_connection, xfer, ib_cmrc_xfer_operations );
+/** CMRC shutdown process descriptor */
+static struct process_descriptor ib_cmrc_shutdown_desc =
+ PROC_DESC_ONCE ( struct ib_cmrc_connection, shutdown,
+ ib_cmrc_shutdown );
+
/**
* Open CMRC connection
*
@@ -385,7 +388,7 @@
cmrc->ibdev = ibdev;
memcpy ( &cmrc->dgid, dgid, sizeof ( cmrc->dgid ) );
memcpy ( &cmrc->service_id, service_id, sizeof ( cmrc->service_id ) );
- process_init_stopped ( &cmrc->shutdown, ib_cmrc_shutdown,
+ process_init_stopped ( &cmrc->shutdown, &ib_cmrc_shutdown_desc,
&cmrc->refcnt );
/* Open Infiniband device */
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/ipv4.c
^
|
@@ -14,6 +14,7 @@
#include <ipxe/tcpip.h>
#include <ipxe/dhcp.h>
#include <ipxe/settings.h>
+#include <ipxe/timer.h>
/** @file
*
@@ -30,7 +31,10 @@
struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
/** List of fragment reassembly buffers */
-static LIST_HEAD ( frag_buffers );
+static LIST_HEAD ( ipv4_fragments );
+
+/** Fragment reassembly timeout */
+#define IP_FRAG_TIMEOUT ( TICKS_PER_SEC / 2 )
/**
* Add IPv4 minirouting table entry
@@ -46,16 +50,16 @@
struct in_addr netmask, struct in_addr gateway ) {
struct ipv4_miniroute *miniroute;
- DBG ( "IPv4 add %s", inet_ntoa ( address ) );
- DBG ( "/%s ", inet_ntoa ( netmask ) );
+ DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
+ DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) );
if ( gateway.s_addr )
- DBG ( "gw %s ", inet_ntoa ( gateway ) );
- DBG ( "via %s\n", netdev->name );
+ DBGC ( netdev, "gw %s ", inet_ntoa ( gateway ) );
+ DBGC ( netdev, "via %s\n", netdev->name );
/* Allocate and populate miniroute structure */
miniroute = malloc ( sizeof ( *miniroute ) );
if ( ! miniroute ) {
- DBG ( "IPv4 could not add miniroute\n" );
+ DBGC ( netdev, "IPv4 could not add miniroute\n" );
return NULL;
}
@@ -83,12 +87,13 @@
* @v miniroute Routing table entry
*/
static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
+ struct net_device *netdev = miniroute->netdev;
- DBG ( "IPv4 del %s", inet_ntoa ( miniroute->address ) );
- DBG ( "/%s ", inet_ntoa ( miniroute->netmask ) );
+ DBGC ( netdev, "IPv4 del %s", inet_ntoa ( miniroute->address ) );
+ DBGC ( netdev, "/%s ", inet_ntoa ( miniroute->netmask ) );
if ( miniroute->gateway.s_addr )
- DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) );
- DBG ( "via %s\n", miniroute->netdev->name );
+ DBGC ( netdev, "gw %s ", inet_ntoa ( miniroute->gateway ) );
+ DBGC ( netdev, "via %s\n", miniroute->netdev->name );
netdev_put ( miniroute->netdev );
list_del ( &miniroute->list );
@@ -110,10 +115,6 @@
int local;
int has_gw;
- /* Never attempt to route the broadcast address */
- if ( dest->s_addr == INADDR_BROADCAST )
- return NULL;
-
/* Find first usable route in routing table */
list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
if ( ! netdev_is_open ( miniroute->netdev ) )
@@ -132,103 +133,128 @@
}
/**
- * Fragment reassembly counter timeout
+ * Expire fragment reassembly buffer
*
- * @v timer Retry timer
- * @v over If asserted, the timer is greater than @c MAX_TIMEOUT
+ * @v timer Retry timer
+ * @v fail Failure indicator
*/
-static void ipv4_frag_expired ( struct retry_timer *timer __unused,
- int over ) {
- if ( over ) {
- DBG ( "Fragment reassembly timeout" );
- /* Free the fragment buffer */
- }
+static void ipv4_fragment_expired ( struct retry_timer *timer,
+ int fail __unused ) {
+ struct ipv4_fragment *frag =
+ container_of ( timer, struct ipv4_fragment, timer );
+ struct iphdr *iphdr = frag->iobuf->data;
+
+ DBGC ( iphdr->src, "IPv4 fragment %04x expired\n",
+ ntohs ( iphdr->ident ) );
+ free_iob ( frag->iobuf );
+ list_del ( &frag->list );
+ free ( frag );
}
/**
- * Free fragment buffer
+ * Find matching fragment reassembly buffer
*
- * @v fragbug Fragment buffer
+ * @v iphdr IPv4 header
+ * @ret frag Fragment reassembly buffer, or NULL
*/
-static void free_fragbuf ( struct frag_buffer *fragbuf ) {
- free ( fragbuf );
+static struct ipv4_fragment * ipv4_fragment ( struct iphdr *iphdr ) {
+ struct ipv4_fragment *frag;
+ struct iphdr *frag_iphdr;
+
+ list_for_each_entry ( frag, &ipv4_fragments, list ) {
+ frag_iphdr = frag->iobuf->data;
+
+ if ( ( iphdr->src.s_addr == frag_iphdr->src.s_addr ) &&
+ ( iphdr->ident == frag_iphdr->ident ) ) {
+ return frag;
+ }
+ }
+
+ return NULL;
}
/**
* Fragment reassembler
*
- * @v iobuf I/O buffer, fragment of the datagram
- * @ret frag_iob Reassembled packet, or NULL
+ * @v iobuf I/O buffer
+ * @ret iobuf Reassembled packet, or NULL
*/
-static struct io_buffer * ipv4_reassemble ( struct io_buffer * iobuf ) {
+static struct io_buffer * ipv4_reassemble ( struct io_buffer *iobuf ) {
struct iphdr *iphdr = iobuf->data;
- struct frag_buffer *fragbuf;
-
- /**
- * Check if the fragment belongs to any fragment series
- */
- list_for_each_entry ( fragbuf, &frag_buffers, list ) {
- if ( fragbuf->ident == iphdr->ident &&
- fragbuf->src.s_addr == iphdr->src.s_addr ) {
- /**
- * Check if the packet is the expected fragment
- *
- * The offset of the new packet must be equal to the
- * length of the data accumulated so far (the length of
- * the reassembled I/O buffer
- */
- if ( iob_len ( fragbuf->frag_iob ) ==
- ( iphdr->frags & IP_MASK_OFFSET ) ) {
- /**
- * Append the contents of the fragment to the
- * reassembled I/O buffer
- */
- iob_pull ( iobuf, sizeof ( *iphdr ) );
- memcpy ( iob_put ( fragbuf->frag_iob,
- iob_len ( iobuf ) ),
- iobuf->data, iob_len ( iobuf ) );
- free_iob ( iobuf );
-
- /** Check if the fragment series is over */
- if ( ! ( iphdr->frags & IP_MASK_MOREFRAGS ) ) {
- iobuf = fragbuf->frag_iob;
- free_fragbuf ( fragbuf );
- return iobuf;
- }
-
- } else {
- /* Discard the fragment series */
- free_fragbuf ( fragbuf );
- free_iob ( iobuf );
- }
- return NULL;
+ size_t offset = ( ( ntohs ( iphdr->frags ) & IP_MASK_OFFSET ) << 3 );
+ unsigned int more_frags = ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ));
+ size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
+ struct ipv4_fragment *frag;
+ size_t expected_offset;
+ struct io_buffer *new_iobuf;
+
+ /* Find matching fragment reassembly buffer, if any */
+ frag = ipv4_fragment ( iphdr );
+
+ /* Drop out-of-order fragments */
+ expected_offset = ( frag ? frag->offset : 0 );
+ if ( offset != expected_offset ) {
+ DBGC ( iphdr->src, "IPv4 dropping out-of-sequence fragment "
+ "%04x (%zd+%zd, expected %zd)\n",
+ ntohs ( iphdr->ident ), offset,
+ ( iob_len ( iobuf ) - hdrlen ), expected_offset );
+ goto drop;
+ }
+
+ /* Create or extend fragment reassembly buffer as applicable */
+ if ( frag == NULL ) {
+
+ /* Create new fragment reassembly buffer */
+ frag = zalloc ( sizeof ( *frag ) );
+ if ( ! frag )
+ goto drop;
+ list_add ( &frag->list, &ipv4_fragments );
+ frag->iobuf = iobuf;
+ frag->offset = ( iob_len ( iobuf ) - hdrlen );
+ timer_init ( &frag->timer, ipv4_fragment_expired, NULL );
+
+ } else {
+
+ /* Extend reassembly buffer */
+ iob_pull ( iobuf, hdrlen );
+ new_iobuf = alloc_iob ( iob_len ( frag->iobuf ) +
+ iob_len ( iobuf ) );
+ if ( ! new_iobuf ) {
+ DBGC ( iphdr->src, "IPv4 could not extend reassembly "
+ "buffer to %zd bytes\n",
+ iob_len ( frag->iobuf ) + iob_len ( iobuf ) );
+ goto drop;
}
- }
-
- /** Check if the fragment is the first in the fragment series */
- if ( iphdr->frags & IP_MASK_MOREFRAGS &&
- ( ( iphdr->frags & IP_MASK_OFFSET ) == 0 ) ) {
-
- /** Create a new fragment buffer */
- fragbuf = ( struct frag_buffer* ) malloc ( sizeof( *fragbuf ) );
- fragbuf->ident = iphdr->ident;
- fragbuf->src = iphdr->src;
-
- /* Set up the reassembly I/O buffer */
- fragbuf->frag_iob = alloc_iob ( IP_FRAG_IOB_SIZE );
- iob_pull ( iobuf, sizeof ( *iphdr ) );
- memcpy ( iob_put ( fragbuf->frag_iob, iob_len ( iobuf ) ),
+ memcpy ( iob_put ( new_iobuf, iob_len ( frag->iobuf ) ),
+ frag->iobuf->data, iob_len ( frag->iobuf ) );
+ memcpy ( iob_put ( new_iobuf, iob_len ( iobuf ) ),
iobuf->data, iob_len ( iobuf ) );
+ free_iob ( frag->iobuf );
+ frag->iobuf = new_iobuf;
+ frag->offset += iob_len ( iobuf );
free_iob ( iobuf );
+ iphdr = frag->iobuf->data;
+ iphdr->len = ntohs ( iob_len ( frag->iobuf ) );
- /* Set the reassembly timer */
- timer_init ( &fragbuf->frag_timer, ipv4_frag_expired, NULL );
- start_timer_fixed ( &fragbuf->frag_timer, IP_FRAG_TIMEOUT );
+ /* Stop fragment reassembly timer */
+ stop_timer ( &frag->timer );
- /* Add the fragment buffer to the list of fragment buffers */
- list_add ( &fragbuf->list, &frag_buffers );
+ /* If this is the final fragment, return it */
+ if ( ! more_frags ) {
+ iobuf = frag->iobuf;
+ list_del ( &frag->list );
+ free ( frag );
+ return iobuf;
+ }
}
-
+
+ /* (Re)start fragment reassembly timer */
+ start_timer_fixed ( &frag->timer, IP_FRAG_TIMEOUT );
+
+ return NULL;
+
+ drop:
+ free_iob ( iobuf );
return NULL;
}
@@ -260,15 +286,17 @@
*
* @v dest IPv4 destination address
* @v src IPv4 source address
+ * @v netmask IPv4 subnet mask
* @v netdev Network device
* @v ll_dest Link-layer destination address buffer
* @ret rc Return status code
*/
static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
- struct net_device *netdev, uint8_t *ll_dest ) {
+ struct in_addr netmask, struct net_device *netdev,
+ uint8_t *ll_dest ) {
struct ll_protocol *ll_protocol = netdev->ll_protocol;
- if ( dest.s_addr == INADDR_BROADCAST ) {
+ if ( ( ( dest.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0 ) {
/* Broadcast address */
memcpy ( ll_dest, netdev->ll_broadcast,
ll_protocol->ll_addr_len );
@@ -306,6 +334,7 @@
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
struct ipv4_miniroute *miniroute;
struct in_addr next_hop;
+ struct in_addr netmask = { .s_addr = 0 };
uint8_t ll_dest[MAX_LL_ADDR_LEN];
int rc;
@@ -326,10 +355,12 @@
( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) &&
( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
iphdr->src = miniroute->address;
+ netmask = miniroute->netmask;
netdev = miniroute->netdev;
}
if ( ! netdev ) {
- DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
+ DBGC ( sin_dest->sin_addr, "IPv4 has no route to %s\n",
+ inet_ntoa ( iphdr->dest ) );
rc = -ENETUNREACH;
goto err;
}
@@ -343,10 +374,12 @@
( ( netdev->rx_stats.good & 0xf ) << 0 ) );
/* Determine link-layer destination address */
- if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev,
+ if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netmask, netdev,
ll_dest ) ) != 0 ) {
- DBG ( "IPv4 has no link-layer address for %s: %s\n",
- inet_ntoa ( next_hop ), strerror ( rc ) );
+ DBGC ( sin_dest->sin_addr, "IPv4 has no link-layer address for "
+ "%s: %s\n", inet_ntoa ( next_hop ), strerror ( rc ) );
+ /* Record error for diagnosis */
+ netdev_tx_err ( netdev, iob_disown ( iobuf ), rc );
goto err;
}
@@ -356,16 +389,17 @@
iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
/* Print IP4 header for debugging */
- DBG ( "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
- DBG ( "%s len %d proto %d id %04x csum %04x\n",
- inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ), iphdr->protocol,
- ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
+ DBGC2 ( sin_dest->sin_addr, "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
+ DBGC2 ( sin_dest->sin_addr, "%s len %d proto %d id %04x csum %04x\n",
+ inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ),
+ iphdr->protocol, ntohs ( iphdr->ident ),
+ ntohs ( iphdr->chksum ) );
/* Hand off to link layer */
if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
netdev->ll_addr ) ) != 0 ) {
- DBG ( "IPv4 could not transmit packet via %s: %s\n",
- netdev->name, strerror ( rc ) );
+ DBGC ( sin_dest->sin_addr, "IPv4 could not transmit packet "
+ "via %s: %s\n", netdev->name, strerror ( rc ) );
return rc;
}
@@ -377,20 +411,59 @@
}
/**
+ * Check if network device has any IPv4 address
+ *
+ * @v netdev Network device
+ * @ret has_any_addr Network device has any IPv4 address
+ */
+static int ipv4_has_any_addr ( struct net_device *netdev ) {
+ struct ipv4_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ if ( miniroute->netdev == netdev )
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Check if network device has a specific IPv4 address
+ *
+ * @v netdev Network device
+ * @v addr IPv4 address
+ * @ret has_addr Network device has this IPv4 address
+ */
+static int ipv4_has_addr ( struct net_device *netdev, struct in_addr addr ) {
+ struct ipv4_miniroute *miniroute;
+
+ list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+ if ( ( miniroute->netdev == netdev ) &&
+ ( miniroute->address.s_addr == addr.s_addr ) ) {
+ /* Found matching address */
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
* Process incoming packets
*
- * @v iobuf I/O buffer
- * @v netdev Network device
- * @v ll_dest Link-layer destination address
- * @v ll_source Link-layer destination source
+ * @v iobuf I/O buffer
+ * @v netdev Network device
+ * @v ll_dest Link-layer destination address
+ * @v ll_source Link-layer destination source
+ * @v flags Packet flags
+ * @ret rc Return status code
*
* This function expects an IP4 network datagram. It processes the headers
* and sends it to the transport layer.
*/
static int ipv4_rx ( struct io_buffer *iobuf,
- struct net_device *netdev __unused,
+ struct net_device *netdev,
const void *ll_dest __unused,
- const void *ll_source __unused ) {
+ const void *ll_source __unused,
+ unsigned int flags ) {
struct iphdr *iphdr = iobuf->data;
size_t hdrlen;
size_t len;
@@ -404,77 +477,88 @@
/* Sanity check the IPv4 header */
if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
- DBG ( "IPv4 packet too short at %zd bytes (min %zd bytes)\n",
- iob_len ( iobuf ), sizeof ( *iphdr ) );
+ DBGC ( iphdr->src, "IPv4 packet too short at %zd bytes (min "
+ "%zd bytes)\n", iob_len ( iobuf ), sizeof ( *iphdr ) );
goto err;
}
if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
- DBG ( "IPv4 version %#02x not supported\n", iphdr->verhdrlen );
+ DBGC ( iphdr->src, "IPv4 version %#02x not supported\n",
+ iphdr->verhdrlen );
goto err;
}
hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
if ( hdrlen < sizeof ( *iphdr ) ) {
- DBG ( "IPv4 header too short at %zd bytes (min %zd bytes)\n",
- hdrlen, sizeof ( *iphdr ) );
+ DBGC ( iphdr->src, "IPv4 header too short at %zd bytes (min "
+ "%zd bytes)\n", hdrlen, sizeof ( *iphdr ) );
goto err;
}
if ( hdrlen > iob_len ( iobuf ) ) {
- DBG ( "IPv4 header too long at %zd bytes "
- "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
+ DBGC ( iphdr->src, "IPv4 header too long at %zd bytes "
+ "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
goto err;
}
if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
- DBG ( "IPv4 checksum incorrect (is %04x including checksum "
- "field, should be 0000)\n", csum );
+ DBGC ( iphdr->src, "IPv4 checksum incorrect (is %04x "
+ "including checksum field, should be 0000)\n", csum );
goto err;
}
len = ntohs ( iphdr->len );
if ( len < hdrlen ) {
- DBG ( "IPv4 length too short at %zd bytes "
- "(header is %zd bytes)\n", len, hdrlen );
+ DBGC ( iphdr->src, "IPv4 length too short at %zd bytes "
+ "(header is %zd bytes)\n", len, hdrlen );
goto err;
}
if ( len > iob_len ( iobuf ) ) {
- DBG ( "IPv4 length too long at %zd bytes "
- "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
+ DBGC ( iphdr->src, "IPv4 length too long at %zd bytes "
+ "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
goto err;
}
- /* Print IPv4 header for debugging */
- DBG ( "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
- DBG ( "%s len %d proto %d id %04x csum %04x\n",
- inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol,
- ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
-
- /* Truncate packet to correct length, calculate pseudo-header
- * checksum and then strip off the IPv4 header.
- */
+ /* Truncate packet to correct length */
iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
- pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
- iob_pull ( iobuf, hdrlen );
- /* Fragment reassembly */
- if ( ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) ) ||
- ( ( iphdr->frags & htons ( IP_MASK_OFFSET ) ) != 0 ) ) {
- /* Pass the fragment to ipv4_reassemble() which either
- * returns a fully reassembled I/O buffer or NULL.
+ /* Print IPv4 header for debugging */
+ DBGC2 ( iphdr->src, "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
+ DBGC2 ( iphdr->src, "%s len %d proto %d id %04x csum %04x\n",
+ inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol,
+ ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
+
+ /* Discard unicast packets not destined for us */
+ if ( ( ! ( flags & LL_MULTICAST ) ) &&
+ ipv4_has_any_addr ( netdev ) &&
+ ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
+ DBGC ( iphdr->src, "IPv4 discarding non-local unicast packet "
+ "for %s\n", inet_ntoa ( iphdr->dest ) );
+ goto err;
+ }
+
+ /* Perform fragment reassembly if applicable */
+ if ( iphdr->frags & htons ( IP_MASK_OFFSET | IP_MASK_MOREFRAGS ) ) {
+ /* Pass the fragment to ipv4_reassemble() which returns
+ * either a fully reassembled I/O buffer or NULL.
*/
iobuf = ipv4_reassemble ( iobuf );
if ( ! iobuf )
return 0;
+ iphdr = iobuf->data;
+ hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
}
- /* Construct socket addresses and hand off to transport layer */
+ /* Construct socket addresses, calculate pseudo-header
+ * checksum, and hand off to transport layer
+ */
memset ( &src, 0, sizeof ( src ) );
src.sin.sin_family = AF_INET;
src.sin.sin_addr = iphdr->src;
memset ( &dest, 0, sizeof ( dest ) );
dest.sin.sin_family = AF_INET;
dest.sin.sin_addr = iphdr->dest;
+ pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
+ iob_pull ( iobuf, hdrlen );
if ( ( rc = tcpip_rx ( iobuf, iphdr->protocol, &src.st,
&dest.st, pshdr_csum ) ) != 0 ) {
- DBG ( "IPv4 received packet rejected by stack: %s\n",
- strerror ( rc ) );
+ DBGC ( src.sin.sin_addr, "IPv4 received packet rejected by "
+ "stack: %s\n", strerror ( rc ) );
return rc;
}
@@ -494,15 +578,10 @@
*/
static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
const struct in_addr *address = net_addr;
- struct ipv4_miniroute *miniroute;
- list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
- if ( ( miniroute->netdev == netdev ) &&
- ( miniroute->address.s_addr == address->s_addr ) ) {
- /* Found matching address */
- return 0;
- }
- }
+ if ( ipv4_has_addr ( netdev, *address ) )
+ return 0;
+
return -ENOENT;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/ipv6.c
^
|
@@ -288,13 +288,15 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
*
* This function processes a IPv6 packet
*/
static int ipv6_rx ( struct io_buffer *iobuf,
__unused struct net_device *netdev,
__unused const void *ll_dest,
- __unused const void *ll_source ) {
+ __unused const void *ll_source,
+ __unused unsigned int flags ) {
struct ip6_header *ip6hdr = iobuf->data;
union {
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/netdevice.c
^
|
@@ -194,16 +194,17 @@
}
/**
- * Complete network transmission
+ * Discard transmitted packet
*
* @v netdev Network device
- * @v iobuf I/O buffer
+ * @v iobuf I/O buffer, or NULL
* @v rc Packet status code
*
- * The packet must currently be in the network device's TX queue.
+ * The packet is discarded and a TX error is recorded. This function
+ * takes ownership of the I/O buffer.
*/
-void netdev_tx_complete_err ( struct net_device *netdev,
- struct io_buffer *iobuf, int rc ) {
+void netdev_tx_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
/* Update statistics counter */
netdev_record_stat ( &netdev->tx_stats, rc );
@@ -215,12 +216,28 @@
netdev->name, iobuf, strerror ( rc ) );
}
+ /* Discard packet */
+ free_iob ( iobuf );
+}
+
+/**
+ * Complete network transmission
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @v rc Packet status code
+ *
+ * The packet must currently be in the network device's TX queue.
+ */
+void netdev_tx_complete_err ( struct net_device *netdev,
+ struct io_buffer *iobuf, int rc ) {
+
/* Catch data corruption as early as possible */
list_check_contains ( iobuf, &netdev->tx_queue, list );
/* Dequeue and free I/O buffer */
list_del ( &iobuf->list );
- free_iob ( iobuf );
+ netdev_tx_err ( netdev, iobuf, rc );
}
/**
@@ -644,7 +661,8 @@
/* Add link-layer header */
if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source,
net_protocol->net_proto ) ) != 0 ) {
- free_iob ( iobuf );
+ /* Record error for diagnosis */
+ netdev_tx_err ( netdev, iobuf, rc );
return rc;
}
@@ -660,17 +678,19 @@
* @v net_proto Network-layer protocol, in network-byte order
* @v ll_dest Destination link-layer address
* @v ll_source Source link-layer address
+ * @v flags Packet flags
* @ret rc Return status code
*/
int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
- uint16_t net_proto, const void *ll_dest, const void *ll_source ) {
+ uint16_t net_proto, const void *ll_dest, const void *ll_source,
+ unsigned int flags ) {
struct net_protocol *net_protocol;
/* Hand off to network-layer protocol, if any */
for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
if ( net_protocol->net_proto == net_proto )
return net_protocol->rx ( iobuf, netdev, ll_dest,
- ll_source );
+ ll_source, flags );
}
DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
@@ -692,6 +712,7 @@
const void *ll_dest;
const void *ll_source;
uint16_t net_proto;
+ unsigned int flags;
int rc;
/* Poll and process each network device */
@@ -725,7 +746,8 @@
ll_protocol = netdev->ll_protocol;
if ( ( rc = ll_protocol->pull ( netdev, iobuf,
&ll_dest, &ll_source,
- &net_proto ) ) != 0 ) {
+ &net_proto,
+ &flags ) ) != 0 ) {
free_iob ( iobuf );
continue;
}
@@ -733,7 +755,7 @@
/* Hand packet to network layer */
if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
net_proto, ll_dest,
- ll_source ) ) != 0 ) {
+ ll_source, flags ) ) != 0 ) {
/* Record error for diagnosis */
netdev_rx_err ( netdev, NULL, rc );
}
@@ -751,7 +773,4 @@
}
/** Networking stack process */
-struct process net_process __permanent_process = {
- .list = LIST_HEAD_INIT ( net_process.list ),
- .step = net_step,
-};
+PERMANENT_PROCESS ( net_process, net_step );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/rarp.c
^
|
@@ -38,6 +38,7 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*
* This is a dummy method which simply discards RARP packets.
@@ -45,7 +46,8 @@
static int rarp_rx ( struct io_buffer *iobuf,
struct net_device *netdev __unused,
const void *ll_dest __unused,
- const void *ll_source __unused ) {
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
free_iob ( iobuf );
return 0;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/retry.c
^
|
@@ -148,6 +148,7 @@
* @v timer Retry timer
*/
static void timer_expired ( struct retry_timer *timer ) {
+ struct refcnt *refcnt = timer->refcnt;
int fail;
/* Stop timer without performing RTT calculations */
@@ -169,8 +170,9 @@
/* Call expiry callback */
timer->expired ( timer, fail );
+ /* If refcnt is NULL, then timer may already have been freed */
- ref_put ( timer->refcnt );
+ ref_put ( refcnt );
}
/**
@@ -198,7 +200,4 @@
}
/** Retry timer process */
-struct process retry_process __permanent_process = {
- .list = LIST_HEAD_INIT ( retry_process.list ),
- .step = retry_step,
-};
+PERMANENT_PROCESS ( retry_process, retry_step );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/tcp.c
^
|
@@ -392,6 +392,25 @@
}
/**
+ * Check data-transfer flow control window
+ *
+ * @v tcp TCP connection
+ * @ret len Length of window
+ */
+static size_t tcp_xfer_window ( struct tcp_connection *tcp ) {
+
+ /* Not ready if data queue is non-empty. This imposes a limit
+ * of only one unACKed packet in the TX queue at any time; we
+ * do this to conserve memory usage.
+ */
+ if ( ! list_empty ( &tcp->tx_queue ) )
+ return 0;
+
+ /* Return TCP window length */
+ return tcp_xmit_win ( tcp );
+}
+
+/**
* Process TCP transmit queue
*
* @v tcp TCP connection
@@ -1084,6 +1103,7 @@
unsigned int flags;
size_t len;
uint32_t seq_len;
+ size_t old_xfer_window;
int rc;
/* Sanity check packet */
@@ -1145,6 +1165,9 @@
goto discard;
}
+ /* Record old data-transfer window */
+ old_xfer_window = tcp_xfer_window ( tcp );
+
/* Handle ACK, if present */
if ( flags & TCP_ACK ) {
if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) {
@@ -1191,6 +1214,10 @@
start_timer_fixed ( &tcp->wait, ( 2 * TCP_MSL ) );
}
+ /* Notify application if window has changed */
+ if ( tcp_xfer_window ( tcp ) != old_xfer_window )
+ xfer_window_changed ( &tcp->xfer );
+
return 0;
discard:
@@ -1257,25 +1284,6 @@
}
/**
- * Check flow control window
- *
- * @v tcp TCP connection
- * @ret len Length of window
- */
-static size_t tcp_xfer_window ( struct tcp_connection *tcp ) {
-
- /* Not ready if data queue is non-empty. This imposes a limit
- * of only one unACKed packet in the TX queue at any time; we
- * do this to conserve memory usage.
- */
- if ( ! list_empty ( &tcp->tx_queue ) )
- return 0;
-
- /* Return TCP window length */
- return tcp_xmit_win ( tcp );
-}
-
-/**
* Deliver datagram as I/O buffer
*
* @v tcp TCP connection
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/tcp/ftp.c
^
|
@@ -378,37 +378,15 @@
}
}
-/**
- * Handle data delivery via FTP data channel
- *
- * @v ftp FTP request
- * @v iobuf I/O buffer
- * @v meta Data transfer metadata
- * @ret rc Return status code
- */
-static int ftp_data_deliver ( struct ftp_request *ftp,
- struct io_buffer *iobuf,
- struct xfer_metadata *meta __unused ) {
- int rc;
-
- if ( ( rc = xfer_deliver_iob ( &ftp->xfer, iobuf ) ) != 0 ) {
- DBGC ( ftp, "FTP %p failed to deliver data: %s\n",
- ftp, strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
/** FTP data channel interface operations */
static struct interface_operation ftp_data_operations[] = {
- INTF_OP ( xfer_deliver, struct ftp_request *, ftp_data_deliver ),
INTF_OP ( intf_close, struct ftp_request *, ftp_data_closed ),
};
/** FTP data channel interface descriptor */
static struct interface_descriptor ftp_data_desc =
- INTF_DESC ( struct ftp_request, data, ftp_data_operations );
+ INTF_DESC_PASSTHRU ( struct ftp_request, data, ftp_data_operations,
+ xfer );
/*****************************************************************************
*
@@ -423,7 +401,8 @@
/** FTP data transfer interface descriptor */
static struct interface_descriptor ftp_xfer_desc =
- INTF_DESC ( struct ftp_request, xfer, ftp_xfer_operations );
+ INTF_DESC_PASSTHRU ( struct ftp_request, xfer, ftp_xfer_operations,
+ data );
/*****************************************************************************
*
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/tcp/http.c
^
|
@@ -44,10 +44,25 @@
#include <ipxe/linebuf.h>
#include <ipxe/features.h>
#include <ipxe/base64.h>
+#include <ipxe/blockdev.h>
+#include <ipxe/acpi.h>
#include <ipxe/http.h>
FEATURE ( FEATURE_PROTOCOL, "HTTP", DHCP_EB_FEATURE_HTTP, 1 );
+/** Block size used for HTTP block device request */
+#define HTTP_BLKSIZE 512
+
+/** HTTP flags */
+enum http_flags {
+ /** Request is waiting to be transmitted */
+ HTTP_TX_PENDING = 0x0001,
+ /** Fetch header only */
+ HTTP_HEAD_ONLY = 0x0002,
+ /** Keep connection alive */
+ HTTP_KEEPALIVE = 0x0004,
+};
+
/** HTTP receive state */
enum http_rx_state {
HTTP_RX_RESPONSE = 0,
@@ -55,6 +70,7 @@
HTTP_RX_CHUNK_LEN,
HTTP_RX_DATA,
HTTP_RX_TRAILER,
+ HTTP_RX_IDLE,
HTTP_RX_DEAD,
};
@@ -67,29 +83,38 @@
struct refcnt refcnt;
/** Data transfer interface */
struct interface xfer;
+ /** Partial transfer interface */
+ struct interface partial;
/** URI being fetched */
struct uri *uri;
/** Transport layer interface */
struct interface socket;
+ /** Flags */
+ unsigned int flags;
+ /** Starting offset of partial transfer (if applicable) */
+ size_t partial_start;
+ /** Length of partial transfer (if applicable) */
+ size_t partial_len;
+
/** TX process */
struct process process;
- /** HTTP response code */
- unsigned int response;
- /** HTTP Content-Length */
- size_t content_length;
- /** HTTP is using Transfer-Encoding: chunked */
- int chunked;
- /** Current chunk length */
- size_t chunk_len;
- /** Received length */
- size_t rx_len;
/** RX state */
enum http_rx_state rx_state;
+ /** Received length */
+ size_t rx_len;
+ /** Length remaining (or 0 if unknown) */
+ size_t remaining;
+ /** HTTP is using Transfer-Encoding: chunked */
+ int chunked;
+ /** Current chunk length remaining (if applicable) */
+ size_t chunk_remaining;
/** Line buffer for received header lines */
struct line_buffer linebuf;
+ /** Receive data buffer (if applicable) */
+ userptr_t rx_buffer;
};
/**
@@ -107,12 +132,12 @@
};
/**
- * Mark HTTP request as complete
+ * Close HTTP request
*
* @v http HTTP request
* @v rc Return status code
*/
-static void http_done ( struct http_request *http, int rc ) {
+static void http_close ( struct http_request *http, int rc ) {
/* Prevent further processing of any current packet */
http->rx_state = HTTP_RX_DEAD;
@@ -120,11 +145,11 @@
/* If we had a Content-Length, and the received content length
* isn't correct, flag an error
*/
- if ( http->content_length &&
- ( http->content_length != http->rx_len ) ) {
+ if ( http->remaining != 0 ) {
DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n",
- http, http->rx_len, http->content_length );
- rc = -EIO;
+ http, http->rx_len, ( http->rx_len + http->remaining ) );
+ if ( rc == 0 )
+ rc = -EIO;
}
/* Remove process */
@@ -132,10 +157,41 @@
/* Close all data transfer interfaces */
intf_shutdown ( &http->socket, rc );
+ intf_shutdown ( &http->partial, rc );
intf_shutdown ( &http->xfer, rc );
}
/**
+ * Mark HTTP request as completed successfully
+ *
+ * @v http HTTP request
+ */
+static void http_done ( struct http_request *http ) {
+
+ /* If we had a Content-Length, and the received content length
+ * isn't correct, force an error
+ */
+ if ( http->remaining != 0 ) {
+ http_close ( http, -EIO );
+ return;
+ }
+
+ /* Enter idle state */
+ http->rx_state = HTTP_RX_IDLE;
+ http->rx_len = 0;
+ assert ( http->remaining == 0 );
+ assert ( http->chunked == 0 );
+ assert ( http->chunk_remaining == 0 );
+
+ /* Close partial transfer interface */
+ intf_restart ( &http->partial, 0 );
+
+ /* Close everything unless we are keeping the connection alive */
+ if ( ! ( http->flags & HTTP_KEEPALIVE ) )
+ http_close ( http, 0 );
+}
+
+/**
* Convert HTTP response code to return status code
*
* @v response HTTP response code
@@ -144,6 +200,7 @@
static int http_response_to_rc ( unsigned int response ) {
switch ( response ) {
case 200:
+ case 206:
case 301:
case 302:
return 0;
@@ -167,6 +224,7 @@
*/
static int http_rx_response ( struct http_request *http, char *response ) {
char *spc;
+ unsigned int code;
int rc;
DBGC ( http, "HTTP %p response \"%s\"\n", http, response );
@@ -179,8 +237,8 @@
spc = strchr ( response, ' ' );
if ( ! spc )
return -EIO;
- http->response = strtoul ( spc, NULL, 10 );
- if ( ( rc = http_response_to_rc ( http->response ) ) != 0 )
+ code = strtoul ( spc, NULL, 10 );
+ if ( ( rc = http_response_to_rc ( code ) ) != 0 )
return rc;
/* Move to received headers */
@@ -219,19 +277,40 @@
*/
static int http_rx_content_length ( struct http_request *http,
const char *value ) {
+ struct block_device_capacity capacity;
+ size_t content_len;
char *endp;
- http->content_length = strtoul ( value, &endp, 10 );
+ /* Parse content length */
+ content_len = strtoul ( value, &endp, 10 );
if ( *endp != '\0' ) {
DBGC ( http, "HTTP %p invalid Content-Length \"%s\"\n",
http, value );
return -EIO;
}
+ /* If we already have an expected content length, and this
+ * isn't it, then complain
+ */
+ if ( http->remaining && ( http->remaining != content_len ) ) {
+ DBGC ( http, "HTTP %p incorrect Content-Length %zd (expected "
+ "%zd)\n", http, content_len, http->remaining );
+ return -EIO;
+ }
+ if ( ! ( http->flags & HTTP_HEAD_ONLY ) )
+ http->remaining = content_len;
+
/* Use seek() to notify recipient of filesize */
- xfer_seek ( &http->xfer, http->content_length );
+ xfer_seek ( &http->xfer, http->remaining );
xfer_seek ( &http->xfer, 0 );
+ /* Report block device capacity if applicable */
+ if ( http->flags & HTTP_HEAD_ONLY ) {
+ capacity.blocks = ( content_len / HTTP_BLKSIZE );
+ capacity.blksize = HTTP_BLKSIZE;
+ capacity.max_count = -1U;
+ block_capacity ( &http->partial, &capacity );
+ }
return 0;
}
@@ -301,14 +380,15 @@
/* An empty header line marks the end of this phase */
if ( ! header[0] ) {
empty_line_buffer ( &http->linebuf );
- if ( http->rx_state == HTTP_RX_HEADER ) {
+ if ( ( http->rx_state == HTTP_RX_HEADER ) &&
+ ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) {
DBGC ( http, "HTTP %p start of data\n", http );
http->rx_state = ( http->chunked ?
HTTP_RX_CHUNK_LEN : HTTP_RX_DATA );
return 0;
} else {
DBGC ( http, "HTTP %p end of trailer\n", http );
- http_done ( http, 0 );
+ http_done ( http );
return 0;
}
}
@@ -350,7 +430,7 @@
return 0;
/* Parse chunk length */
- http->chunk_len = strtoul ( length, &endp, 16 );
+ http->chunk_remaining = strtoul ( length, &endp, 16 );
if ( *endp != '\0' ) {
DBGC ( http, "HTTP %p invalid chunk length \"%s\"\n",
http, length );
@@ -358,7 +438,7 @@
}
/* Terminate chunked encoding if applicable */
- if ( http->chunk_len == 0 ) {
+ if ( http->chunk_remaining == 0 ) {
DBGC ( http, "HTTP %p end of chunks\n", http );
http->chunked = 0;
http->rx_state = HTTP_RX_TRAILER;
@@ -367,8 +447,8 @@
/* Use seek() to notify recipient of new filesize */
DBGC ( http, "HTTP %p start of chunk of length %zd\n",
- http, http->chunk_len );
- xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_len ) );
+ http, http->chunk_remaining );
+ xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_remaining ) );
xfer_seek ( &http->xfer, http->rx_len );
/* Start receiving data */
@@ -414,34 +494,60 @@
int rc = 0;
while ( iobuf && iob_len ( iobuf ) ) {
+
switch ( http->rx_state ) {
+ case HTTP_RX_IDLE:
+ /* Receiving any data in this state is an error */
+ DBGC ( http, "HTTP %p received %zd bytes while %s\n",
+ http, iob_len ( iobuf ),
+ ( ( http->rx_state == HTTP_RX_IDLE ) ?
+ "idle" : "dead" ) );
+ rc = -EPROTO;
+ goto done;
case HTTP_RX_DEAD:
/* Do no further processing */
goto done;
case HTTP_RX_DATA:
/* Pass received data to caller */
data_len = iob_len ( iobuf );
- if ( http->chunk_len && ( http->chunk_len < data_len )){
- data_len = http->chunk_len;
+ if ( http->chunk_remaining &&
+ ( http->chunk_remaining < data_len ) ) {
+ data_len = http->chunk_remaining;
+ }
+ if ( http->remaining &&
+ ( http->remaining < data_len ) ) {
+ data_len = http->remaining;
+ }
+ if ( http->rx_buffer != UNULL ) {
+ /* Copy to partial transfer buffer */
+ copy_to_user ( http->rx_buffer, http->rx_len,
+ iobuf->data, data_len );
+ iob_pull ( iobuf, data_len );
+ } else if ( data_len < iob_len ( iobuf ) ) {
+ /* Deliver partial buffer as raw data */
rc = xfer_deliver_raw ( &http->xfer,
iobuf->data, data_len );
iob_pull ( iobuf, data_len );
+ if ( rc != 0 )
+ goto done;
} else {
- rc = xfer_deliver_iob ( &http->xfer,
- iob_disown ( iobuf ) );
+ /* Deliver whole I/O buffer */
+ if ( ( rc = xfer_deliver_iob ( &http->xfer,
+ iob_disown ( iobuf ) ) ) != 0 )
+ goto done;
}
- if ( rc != 0 )
- goto done;
- if ( http->chunk_len ) {
- http->chunk_len -= data_len;
- if ( http->chunk_len == 0 )
+ http->rx_len += data_len;
+ if ( http->chunk_remaining ) {
+ http->chunk_remaining -= data_len;
+ if ( http->chunk_remaining == 0 )
http->rx_state = HTTP_RX_CHUNK_LEN;
}
- http->rx_len += data_len;
- if ( http->content_length &&
- ( http->rx_len >= http->content_length ) ) {
- http_done ( http, 0 );
- goto done;
+ if ( http->remaining ) {
+ http->remaining -= data_len;
+ if ( ( http->remaining == 0 ) &&
+ ( http->rx_state == HTTP_RX_DATA ) ) {
+ http_done ( http );
+ }
}
break;
case HTTP_RX_RESPONSE:
@@ -475,19 +581,31 @@
done:
if ( rc )
- http_done ( http, rc );
+ http_close ( http, rc );
free_iob ( iobuf );
return rc;
}
/**
+ * Check HTTP socket flow control window
+ *
+ * @v http HTTP request
+ * @ret len Length of window
+ */
+static size_t http_socket_window ( struct http_request *http __unused ) {
+
+ /* Window is always open. This is to prevent TCP from
+ * stalling if our parent window is not currently open.
+ */
+ return ( ~( ( size_t ) 0 ) );
+}
+
+/**
* HTTP process
*
- * @v process Process
+ * @v http HTTP request
*/
-static void http_step ( struct process *process ) {
- struct http_request *http =
- container_of ( process, struct http_request, process );
+static void http_step ( struct http_request *http ) {
const char *host = http->uri->host;
const char *user = http->uri->user;
const char *password =
@@ -500,50 +618,181 @@
int rc;
int request_len = unparse_uri ( NULL, 0, http->uri,
URI_PATH_BIT | URI_QUERY_BIT );
+ char request[ request_len + 1 /* NUL */ ];
+ char range[48]; /* Enough for two 64-bit integers in decimal */
+ int partial;
+
+ /* Do nothing if we have already transmitted the request */
+ if ( ! ( http->flags & HTTP_TX_PENDING ) )
+ return;
+
+ /* Do nothing until socket is ready */
+ if ( ! xfer_window ( &http->socket ) )
+ return;
+
+ /* Construct path?query request */
+ unparse_uri ( request, sizeof ( request ), http->uri,
+ URI_PATH_BIT | URI_QUERY_BIT );
+
+ /* Construct authorisation, if applicable */
+ if ( user ) {
+ /* Make "user:password" string from decoded fields */
+ snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
+ "%s:%s", user, password );
+
+ /* Base64-encode the "user:password" string */
+ base64_encode ( user_pw, user_pw_len, user_pw_base64 );
+ }
+
+ /* Force a HEAD request if we have nowhere to send any received data */
+ if ( ( xfer_window ( &http->xfer ) == 0 ) &&
+ ( http->rx_buffer == UNULL ) ) {
+ http->flags |= ( HTTP_HEAD_ONLY | HTTP_KEEPALIVE );
+ }
+
+ /* Determine type of request */
+ partial = ( http->partial_len != 0 );
+ snprintf ( range, sizeof ( range ), "%zd-%zd", http->partial_start,
+ ( http->partial_start + http->partial_len - 1 ) );
+
+ /* Mark request as transmitted */
+ http->flags &= ~HTTP_TX_PENDING;
+
+ /* Send GET request */
+ if ( ( rc = xfer_printf ( &http->socket,
+ "%s %s%s HTTP/1.1\r\n"
+ "User-Agent: iPXE/" VERSION "\r\n"
+ "Host: %s%s%s\r\n"
+ "%s%s%s%s%s%s%s"
+ "\r\n",
+ ( ( http->flags & HTTP_HEAD_ONLY ) ?
+ "HEAD" : "GET" ),
+ ( http->uri->path ? "" : "/" ),
+ request, host,
+ ( http->uri->port ?
+ ":" : "" ),
+ ( http->uri->port ?
+ http->uri->port : "" ),
+ ( ( http->flags & HTTP_KEEPALIVE ) ?
+ "Connection: Keep-Alive\r\n" : "" ),
+ ( partial ? "Range: bytes=" : "" ),
+ ( partial ? range : "" ),
+ ( partial ? "\r\n" : "" ),
+ ( user ?
+ "Authorization: Basic " : "" ),
+ ( user ? user_pw_base64 : "" ),
+ ( user ? "\r\n" : "" ) ) ) != 0 ) {
+ http_close ( http, rc );
+ }
+}
- if ( xfer_window ( &http->socket ) ) {
- char request[request_len + 1];
+/**
+ * Check HTTP data transfer flow control window
+ *
+ * @v http HTTP request
+ * @ret len Length of window
+ */
+static size_t http_xfer_window ( struct http_request *http ) {
- /* Construct path?query request */
- unparse_uri ( request, sizeof ( request ), http->uri,
- URI_PATH_BIT | URI_QUERY_BIT );
-
- /* We want to execute only once */
- process_del ( &http->process );
-
- /* Construct authorisation, if applicable */
- if ( user ) {
- /* Make "user:password" string from decoded fields */
- snprintf ( ( ( char * ) user_pw ), sizeof ( user_pw ),
- "%s:%s", user, password );
+ /* New block commands may be issued only when we are idle */
+ return ( ( http->rx_state == HTTP_RX_IDLE ) ? 1 : 0 );
+}
- /* Base64-encode the "user:password" string */
- base64_encode ( user_pw, user_pw_len, user_pw_base64 );
- }
+/**
+ * Initiate HTTP partial read
+ *
+ * @v http HTTP request
+ * @v partial Partial transfer interface
+ * @v offset Starting offset
+ * @v buffer Data buffer
+ * @v len Length
+ * @ret rc Return status code
+ */
+static int http_partial_read ( struct http_request *http,
+ struct interface *partial,
+ size_t offset, userptr_t buffer, size_t len ) {
+
+ /* Sanity check */
+ if ( http_xfer_window ( http ) == 0 )
+ return -EBUSY;
+
+ /* Initialise partial transfer parameters */
+ http->rx_buffer = buffer;
+ http->partial_start = offset;
+ http->partial_len = len;
+ http->remaining = len;
+
+ /* Schedule request */
+ http->rx_state = HTTP_RX_RESPONSE;
+ http->flags = ( HTTP_TX_PENDING | HTTP_KEEPALIVE );
+ if ( ! len )
+ http->flags |= HTTP_HEAD_ONLY;
+ process_add ( &http->process );
- /* Send GET request */
- if ( ( rc = xfer_printf ( &http->socket,
- "GET %s%s HTTP/1.1\r\n"
- "User-Agent: iPXE/" VERSION "\r\n"
- "%s%s%s"
- "Host: %s\r\n"
- "\r\n",
- http->uri->path ? "" : "/",
- request,
- ( user ?
- "Authorization: Basic " : "" ),
- ( user ? user_pw_base64 : "" ),
- ( user ? "\r\n" : "" ),
- host ) ) != 0 ) {
- http_done ( http, rc );
- }
- }
+ /* Attach to parent interface and return */
+ intf_plug_plug ( &http->partial, partial );
+
+ return 0;
+}
+
+/**
+ * Issue HTTP block device read
+ *
+ * @v http HTTP request
+ * @v block Block data interface
+ * @v lba Starting logical block address
+ * @v count Number of blocks to transfer
+ * @v buffer Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+static int http_block_read ( struct http_request *http,
+ struct interface *block,
+ uint64_t lba, unsigned int count,
+ userptr_t buffer, size_t len __unused ) {
+
+ return http_partial_read ( http, block, ( lba * HTTP_BLKSIZE ),
+ buffer, ( count * HTTP_BLKSIZE ) );
+}
+
+/**
+ * Read HTTP block device capacity
+ *
+ * @v http HTTP request
+ * @v block Block data interface
+ * @ret rc Return status code
+ */
+static int http_block_read_capacity ( struct http_request *http,
+ struct interface *block ) {
+
+ return http_partial_read ( http, block, 0, 0, 0 );
+}
+
+/**
+ * Describe HTTP device in an ACPI table
+ *
+ * @v http HTTP request
+ * @v acpi ACPI table
+ * @v len Length of ACPI table
+ * @ret rc Return status code
+ */
+static int http_acpi_describe ( struct http_request *http,
+ struct acpi_description_header *acpi,
+ size_t len ) {
+
+ DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n",
+ http );
+ ( void ) acpi;
+ ( void ) len;
+ return 0;
}
/** HTTP socket interface operations */
static struct interface_operation http_socket_operations[] = {
+ INTF_OP ( xfer_window, struct http_request *, http_socket_window ),
INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ),
- INTF_OP ( intf_close, struct http_request *, http_done ),
+ INTF_OP ( xfer_window_changed, struct http_request *, http_step ),
+ INTF_OP ( intf_close, struct http_request *, http_close ),
};
/** HTTP socket interface descriptor */
@@ -551,9 +800,23 @@
INTF_DESC_PASSTHRU ( struct http_request, socket,
http_socket_operations, xfer );
+/** HTTP partial transfer interface operations */
+static struct interface_operation http_partial_operations[] = {
+ INTF_OP ( intf_close, struct http_request *, http_close ),
+};
+
+/** HTTP partial transfer interface descriptor */
+static struct interface_descriptor http_partial_desc =
+ INTF_DESC ( struct http_request, partial, http_partial_operations );
+
/** HTTP data transfer interface operations */
static struct interface_operation http_xfer_operations[] = {
- INTF_OP ( intf_close, struct http_request *, http_done ),
+ INTF_OP ( xfer_window, struct http_request *, http_xfer_window ),
+ INTF_OP ( block_read, struct http_request *, http_block_read ),
+ INTF_OP ( block_read_capacity, struct http_request *,
+ http_block_read_capacity ),
+ INTF_OP ( intf_close, struct http_request *, http_close ),
+ INTF_OP ( acpi_describe, struct http_request *, http_acpi_describe ),
};
/** HTTP data transfer interface descriptor */
@@ -561,6 +824,10 @@
INTF_DESC_PASSTHRU ( struct http_request, xfer,
http_xfer_operations, socket );
+/** HTTP process descriptor */
+static struct process_descriptor http_process_desc =
+ PROC_DESC_ONCE ( struct http_request, process, http_step );
+
/**
* Initiate an HTTP connection, with optional filter
*
@@ -589,9 +856,11 @@
return -ENOMEM;
ref_init ( &http->refcnt, http_free );
intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt );
+ intf_init ( &http->partial, &http_partial_desc, &http->refcnt );
http->uri = uri_get ( uri );
intf_init ( &http->socket, &http_socket_desc, &http->refcnt );
- process_init ( &http->process, http_step, &http->refcnt );
+ process_init ( &http->process, &http_process_desc, &http->refcnt );
+ http->flags = HTTP_TX_PENDING;
/* Open socket */
memset ( &server, 0, sizeof ( server ) );
@@ -614,7 +883,7 @@
err:
DBGC ( http, "HTTP %p could not create request: %s\n",
http, strerror ( rc ) );
- http_done ( http, rc );
+ http_close ( http, rc );
ref_put ( &http->refcnt );
return rc;
}
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/tcp/iscsi.c
^
|
@@ -1305,6 +1305,24 @@
*/
/**
+ * Pause TX engine
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_tx_pause ( struct iscsi_session *iscsi ) {
+ process_del ( &iscsi->process );
+}
+
+/**
+ * Resume TX engine
+ *
+ * @v iscsi iSCSI session
+ */
+static void iscsi_tx_resume ( struct iscsi_session *iscsi ) {
+ process_add ( &iscsi->process );
+}
+
+/**
* Start up a new TX PDU
*
* @v iscsi iSCSI session
@@ -1315,8 +1333,7 @@
static void iscsi_start_tx ( struct iscsi_session *iscsi ) {
assert ( iscsi->tx_state == ISCSI_TX_IDLE );
- assert ( ! process_running ( &iscsi->process ) );
-
+
/* Initialise TX BHS */
memset ( &iscsi->tx_bhs, 0, sizeof ( iscsi->tx_bhs ) );
@@ -1324,7 +1341,7 @@
iscsi->tx_state = ISCSI_TX_BHS;
/* Start transmission process */
- process_add ( &iscsi->process );
+ iscsi_tx_resume ( iscsi );
}
/**
@@ -1405,7 +1422,7 @@
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
/* Stop transmission process */
- process_del ( &iscsi->process );
+ iscsi_tx_pause ( iscsi );
switch ( common->opcode & ISCSI_OPCODE_MASK ) {
case ISCSI_OPCODE_DATA_OUT:
@@ -1427,9 +1444,7 @@
*
* Constructs data to be sent for the current TX state
*/
-static void iscsi_tx_step ( struct process *process ) {
- struct iscsi_session *iscsi =
- container_of ( process, struct iscsi_session, process );
+static void iscsi_tx_step ( struct iscsi_session *iscsi ) {
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
int ( * tx ) ( struct iscsi_session *iscsi );
enum iscsi_tx_state next_state;
@@ -1460,8 +1475,8 @@
next_state = ISCSI_TX_IDLE;
break;
case ISCSI_TX_IDLE:
- /* Stop processing */
- iscsi_tx_done ( iscsi );
+ /* Nothing to do; pause processing */
+ iscsi_tx_pause ( iscsi );
return;
default:
assert ( 0 );
@@ -1470,7 +1485,10 @@
/* Check for window availability, if needed */
if ( tx_len && ( xfer_window ( &iscsi->socket ) == 0 ) ) {
- /* Cannot transmit at this point; stop processing */
+ /* Cannot transmit at this point; pause
+ * processing and wait for window to reopen
+ */
+ iscsi_tx_pause ( iscsi );
return;
}
@@ -1485,9 +1503,19 @@
/* Move to next state */
iscsi->tx_state = next_state;
+
+ /* If we have moved to the idle state, mark
+ * transmission as complete
+ */
+ if ( iscsi->tx_state == ISCSI_TX_IDLE )
+ iscsi_tx_done ( iscsi );
}
}
+/** iSCSI TX process descriptor */
+static struct process_descriptor iscsi_process_desc =
+ PROC_DESC ( struct iscsi_session, process, iscsi_tx_step );
+
/**
* Receive basic header segment of an iSCSI PDU
*
@@ -1694,6 +1722,8 @@
/** iSCSI socket interface operations */
static struct interface_operation iscsi_socket_operations[] = {
INTF_OP ( xfer_deliver, struct iscsi_session *, iscsi_socket_deliver ),
+ INTF_OP ( xfer_window_changed, struct iscsi_session *,
+ iscsi_tx_resume ),
INTF_OP ( xfer_vredirect, struct iscsi_session *, iscsi_vredirect ),
INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ),
};
@@ -2034,7 +2064,7 @@
intf_init ( &iscsi->control, &iscsi_control_desc, &iscsi->refcnt );
intf_init ( &iscsi->data, &iscsi_data_desc, &iscsi->refcnt );
intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt );
- process_init_stopped ( &iscsi->process, iscsi_tx_step,
+ process_init_stopped ( &iscsi->process, &iscsi_process_desc,
&iscsi->refcnt );
/* Parse root path */
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/tls.c
^
|
@@ -582,6 +582,62 @@
/******************************************************************************
*
+ * TX state machine transitions
+ *
+ ******************************************************************************
+ */
+
+/**
+ * Resume TX state machine
+ *
+ * @v tls TLS session
+ */
+static void tls_tx_resume ( struct tls_session *tls ) {
+ process_add ( &tls->process );
+}
+
+/**
+ * Enter TX state machine active state
+ *
+ * @v tls TLS session
+ * @v state TX state
+ */
+static void tls_tx_start ( struct tls_session *tls, enum tls_tx_state state ) {
+
+ /* Enter specified state */
+ tls->tx_state = state;
+
+ /* Resume state machine */
+ tls_tx_resume ( tls );
+}
+
+/**
+ * Enter TX state machine idle state
+ *
+ * @v tls TLS session
+ */
+static void tls_tx_none ( struct tls_session *tls ) {
+
+ /* Enter idle state */
+ tls->tx_state = TLS_TX_NONE;
+}
+
+/**
+ * Enter TX state machine data state
+ *
+ * @v tls TLS session
+ */
+static void tls_tx_data ( struct tls_session *tls ) {
+
+ /* Enter data state */
+ tls->tx_state = TLS_TX_DATA;
+
+ /* Send notification of a window change */
+ xfer_window_changed ( &tls->plainstream );
+}
+
+/******************************************************************************
+ *
* Record handling
*
******************************************************************************
@@ -929,7 +985,7 @@
}
/* Start sending the Client Key Exchange */
- tls->tx_state = TLS_TX_CLIENT_KEY_EXCHANGE;
+ tls_tx_start ( tls, TLS_TX_CLIENT_KEY_EXCHANGE );
return 0;
}
@@ -946,9 +1002,10 @@
void *data, size_t len ) {
/* FIXME: Handle this properly */
- tls->tx_state = TLS_TX_DATA;
+ tls_tx_data ( tls );
( void ) data;
( void ) len;
+
return 0;
}
@@ -1623,6 +1680,7 @@
static struct interface_operation tls_cipherstream_ops[] = {
INTF_OP ( xfer_deliver, struct tls_session *,
tls_cipherstream_deliver ),
+ INTF_OP ( xfer_window_changed, struct tls_session *, tls_tx_resume ),
INTF_OP ( intf_close, struct tls_session *, tls_close ),
};
@@ -1641,11 +1699,9 @@
/**
* TLS TX state machine
*
- * @v process TLS process
+ * @v tls TLS session
*/
-static void tls_step ( struct process *process ) {
- struct tls_session *tls =
- container_of ( process, struct tls_session, process );
+static void tls_tx_step ( struct tls_session *tls ) {
int rc;
/* Wait for cipherstream to become ready */
@@ -1663,7 +1719,7 @@
tls, strerror ( rc ) );
goto err;
}
- tls->tx_state = TLS_TX_NONE;
+ tls_tx_none ( tls );
break;
case TLS_TX_CLIENT_KEY_EXCHANGE:
/* Send Client Key Exchange */
@@ -1672,7 +1728,7 @@
"%s\n", tls, strerror ( rc ) );
goto err;
}
- tls->tx_state = TLS_TX_CHANGE_CIPHER;
+ tls_tx_start ( tls, TLS_TX_CHANGE_CIPHER );
break;
case TLS_TX_CHANGE_CIPHER:
/* Send Change Cipher, and then change the cipher in use */
@@ -1689,7 +1745,7 @@
goto err;
}
tls->tx_seq = 0;
- tls->tx_state = TLS_TX_FINISHED;
+ tls_tx_start ( tls, TLS_TX_FINISHED );
break;
case TLS_TX_FINISHED:
/* Send Finished */
@@ -1698,7 +1754,7 @@
tls, strerror ( rc ) );
goto err;
}
- tls->tx_state = TLS_TX_NONE;
+ tls_tx_none ( tls );
break;
case TLS_TX_DATA:
/* Nothing to do */
@@ -1713,6 +1769,10 @@
tls_close ( tls, rc );
}
+/** TLS TX process descriptor */
+static struct process_descriptor tls_process_desc =
+ PROC_DESC_ONCE ( struct tls_session, process, tls_tx_step );
+
/******************************************************************************
*
* Instantiator
@@ -1743,8 +1803,8 @@
( sizeof ( tls->pre_master_secret.random ) ) );
digest_init ( &md5_algorithm, tls->handshake_md5_ctx );
digest_init ( &sha1_algorithm, tls->handshake_sha1_ctx );
- tls->tx_state = TLS_TX_CLIENT_HELLO;
- process_init ( &tls->process, tls_step, &tls->refcnt );
+ process_init_stopped ( &tls->process, &tls_process_desc, &tls->refcnt );
+ tls_tx_start ( tls, TLS_TX_CLIENT_HELLO );
/* Attach to parent interface, mortalise self, and return */
intf_plug_plug ( &tls->plainstream, xfer );
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/net/vlan.c
^
|
@@ -91,12 +91,13 @@
const void *ll_dest;
const void *ll_source;
uint16_t net_proto;
+ unsigned int flags;
int rc;
/* Strip link-layer header and preserve link-layer header fields */
ll_protocol = netdev->ll_protocol;
if ( ( rc = ll_protocol->pull ( netdev, iobuf, &ll_dest, &ll_source,
- &net_proto ) ) != 0 ) {
+ &net_proto, &flags ) ) != 0 ) {
DBGC ( netdev, "VLAN %s could not parse link-layer header: "
"%s\n", netdev->name, strerror ( rc ) );
return rc;
@@ -214,10 +215,12 @@
* @v trunk Trunk network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*/
static int vlan_rx ( struct io_buffer *iobuf, struct net_device *trunk,
- const void *ll_dest, const void *ll_source ) {
+ const void *ll_dest, const void *ll_source,
+ unsigned int flags __unused ) {
struct vlan_header *vlanhdr = iobuf->data;
struct net_device *netdev;
struct ll_protocol *ll_protocol;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/usr/fcmgmt.c
^
|
@@ -74,8 +74,7 @@
}
list_for_each_entry ( ulp, &peer->ulps, list ) {
- printf ( " [Type %02x usage %d link:",
- ulp->type, ulp->usage );
+ printf ( " [Type %02x link:", ulp->type );
if ( fc_link_ok ( &ulp->link ) ) {
printf ( " up, params" );
param = ulp->param;
|
[-]
[+]
|
Changed |
ipxe.tar.bz2/src/usr/lotest.c
^
|
@@ -47,12 +47,14 @@
* @v netdev Network device
* @v ll_dest Link-layer destination address
* @v ll_source Link-layer source address
+ * @v flags Packet flags
* @ret rc Return status code
*/
static int lotest_rx ( struct io_buffer *iobuf,
struct net_device *netdev __unused,
const void *ll_dest __unused,
- const void *ll_source __unused ) {
+ const void *ll_source __unused,
+ unsigned int flags __unused ) {
free_iob ( iobuf );
return -ENOTSUP;
}
@@ -97,6 +99,7 @@
const void *ll_dest;
const void *ll_source;
uint16_t net_proto;
+ unsigned int flags;
unsigned int i;
unsigned int successes;
int rc;
@@ -166,7 +169,8 @@
/* Check received packet */
if ( ( rc = receiver->ll_protocol->pull ( receiver, iobuf,
&ll_dest, &ll_source,
- &net_proto ) ) != 0 ){
+ &net_proto,
+ &flags ) ) != 0 ) {
printf ( "\nFailed to strip link-layer header: %s",
strerror ( rc ) );
goto done;
|