xen/ipxe-ipv4-fragment.patch
Charles Arnold 80e28a00ec - Update to Xen 4.2.0 FCS c/s 25844
- unmodified_drivers: handle IRQF_SAMPLE_RANDOM, it was removed
  in 3.6-rc1

- bnc#778105 - first XEN-PV VM fails to spawn
  xend: Increase wait time for disk to appear in host bootloader
  Modified existing xen-domUloader.diff

- Disable the snapshot patches. Snapshot only supported the qcow2
  image format which was poorly implemented qemu 0.10.2. Snapshot
  support may be restored in the future when the newer upstream
  qemu is used by Xen.

- bnc#776995 - attaching scsi control luns with pvscsi
  - xend/pvscsi: fix passing of SCSI control LUNs
  xen-bug776995-pvscsi-no-devname.patch
  - xend/pvscsi: fix usage of persistant device names for SCSI devices
  xen-bug776995-pvscsi-persistent-names.patch
  - xend/pvscsi: update sysfs parser for Linux 3.0
  xen-bug776995-pvscsi-sysfs-parser.patch

- Update to Xen 4.2.0 RC3+ c/s 25779 

- Update to Xen 4.2.0 RC2+ c/s 25765

OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=199
2012-09-17 15:49:23 +00:00

367 lines
12 KiB
Diff

Index: xen-4.2.0-testing/tools/firmware/etherboot/patches/ipxe-git-13186b64b6c3
===================================================================
--- /dev/null
+++ xen-4.2.0-testing/tools/firmware/etherboot/patches/ipxe-git-13186b64b6c3
@@ -0,0 +1,354 @@
+commit 13186b64b6c3d5cbe9ed13bda1532e79b1afe81d
+Author: Michael Brown <mcb30@ipxe.org>
+Date: Sat Jul 16 01:15:53 2011 +0100
+
+ [ipv4] Fix fragment reassembly
+
+ Signed-off-by: Michael Brown <mcb30@ipxe.org>
+ Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
+
+diff -up a/src/include/gpxe/ip.h.orig-frag b/src/include/gpxe/ip.h
+--- a/src/include/gpxe/ip.h.orig-frag 2010-02-02 17:12:44.000000000 +0100
++++ b/src/include/gpxe/ip.h 2011-11-18 15:49:17.202660163 +0100
+@@ -32,9 +32,6 @@ struct net_protocol;
+ #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;
+@@ -74,20 +71,16 @@ struct ipv4_miniroute {
+ 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;
+diff -up a/src/include/gpxe/retry.h.orig-frag b/src/include/gpxe/retry.h
+--- a/src/include/gpxe/retry.h.orig-frag 2010-02-02 17:12:44.000000000 +0100
++++ b/src/include/gpxe/retry.h 2011-11-18 15:59:25.258837891 +0100
+@@ -51,6 +51,19 @@ struct retry_timer {
+ void ( * expired ) ( struct retry_timer *timer, int over );
+ };
+
++/**
++ * Initialise a timer
++ *
++ * @v timer Retry timer
++ * @v expired Timer expired callback
++ */
++static inline __attribute__ (( always_inline )) void
++timer_init ( struct retry_timer *timer,
++ void ( * expired ) ( struct retry_timer *timer, int over ) )
++{
++ timer->expired = expired;
++}
++
+ extern void start_timer ( struct retry_timer *timer );
+ extern void start_timer_fixed ( struct retry_timer *timer,
+ unsigned long timeout );
+diff -up a/src/net/ipv4.c.orig-frag b/src/net/ipv4.c
+--- a/src/net/ipv4.c.orig-frag 2010-02-02 17:12:44.000000000 +0100
++++ b/src/net/ipv4.c 2011-11-18 15:49:17.203660142 +0100
+@@ -14,6 +14,7 @@
+ #include <gpxe/tcpip.h>
+ #include <gpxe/dhcp.h>
+ #include <gpxe/settings.h>
++#include <gpxe/timer.h>
+
+ /** @file
+ *
+@@ -32,7 +33,10 @@ struct net_protocol ipv4_protocol;
+ 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
+@@ -134,104 +138,126 @@ static struct ipv4_miniroute * ipv4_rout
+ }
+
+ /**
+- * 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;
++
++ DBG ( "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 ) {
++ DBG ( "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 );
++
++ } else {
++
++ /* Extend reassembly buffer */
++ iob_pull ( iobuf, hdrlen );
++ new_iobuf = alloc_iob ( iob_len ( frag->iobuf ) +
++ iob_len ( iobuf ) );
++ if ( ! new_iobuf ) {
++ DBG ( "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 */
+- fragbuf->frag_timer.timeout = IP_FRAG_TIMEOUT;
+- fragbuf->frag_timer.expired = ipv4_frag_expired;
+- start_timer ( &fragbuf->frag_timer );
++ /* 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;
+ }
+
+@@ -432,37 +458,38 @@ static int ipv4_rx ( struct io_buffer *i
+ goto err;
+ }
+
++ /* Truncate packet to correct length */
++ iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
++
+ /* 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.
+- */
+- 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.
++ /* 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",
Index: xen-4.2.0-testing/tools/firmware/etherboot/patches/series
===================================================================
--- xen-4.2.0-testing.orig/tools/firmware/etherboot/patches/series
+++ xen-4.2.0-testing/tools/firmware/etherboot/patches/series
@@ -1 +1,2 @@
boot_prompt_option.patch
+ipxe-git-13186b64b6c3