Autopadding was sometimes overwriting the struct list_head at the end
authorMichael Brown <mcb30@etherboot.org>
Tue, 9 Jan 2007 21:01:55 +0000 (21:01 +0000)
committerMichael Brown <mcb30@etherboot.org>
Tue, 9 Jan 2007 21:01:55 +0000 (21:01 +0000)
of the packet buffer.  Although pkbuffs are guaranteed to be at least
PKB_ZLEN bytes long, there's no guarantee that the data starts at the
start of the packet buffer.

Since we have to align data for rtl8139 anyway, and since the start of
the packet buffer is guaranteed to be aligned to PKB_ALIGN, we may as
well just shuffle the packet down so that it starts at the start of
the packet buffer.  This simultaneously aligns the packet and ensures
that there is enough room for the zero-padding.

src/drivers/net/rtl8139.c

index 5e37f9c..4981329 100644 (file)
@@ -367,8 +367,10 @@ static void rtl_close ( struct net_device *netdev ) {
  */
 static int rtl_transmit ( struct net_device *netdev, struct pk_buff *pkb ) {
        struct rtl8139_nic *rtl = netdev->priv;
-       int align;
-       int pad_len;
+       void *data;
+       size_t len;
+       size_t headroom;
+       signed int pad_len;
 
        /* Check for space in TX ring */
        if ( rtl->tx.pkb[rtl->tx.next] != NULL ) {
@@ -376,11 +378,18 @@ static int rtl_transmit ( struct net_device *netdev, struct pk_buff *pkb ) {
                return -ENOBUFS;
        }
 
-       /* Align packet data */
-       align = ( virt_to_bus ( pkb->data ) & 0x3 );
-       pkb_push ( pkb, align );
-       memmove ( pkb->data, pkb->data + align, pkb_len ( pkb ) - align );
-       pkb_unput ( pkb, align );
+       /* Move packet data to start of packet buffer.  This will both
+        * align the data (since packet buffers are aligned to
+        * PKB_ALIGN) and give us sufficient space for the
+        * zero-padding
+        */
+       data = pkb->data;
+       len = pkb_len ( pkb );
+       headroom = pkb_headroom ( pkb );
+       pkb_push ( pkb, headroom );
+       memmove ( pkb->data, data, len );
+       pkb_unput ( pkb, headroom );
+       assert ( ( virt_to_bus ( pkb->data ) & 0x3 ) == 0 );
 
        /* Pad to minimum packet length */
        pad_len = ( ETH_ZLEN - pkb_len ( pkb ) );