[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Fix netfront to accept received packets at a wider range of



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 4e9c643968ffd0526258dc1ae7d1fee6123be718
# Parent  8b5c047f6e23c8e9dea7a84187b284b18bd44250
Fix netfront to accept received packets at a wider range of
offsets within a memory page. Also fix, skb realloc-and-copy
when copying really is required (we were forgetting whether
the packet data is known valid, and checksumming packets that
do not have the csum field filled in).

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 8b5c047f6e23 -r 4e9c643968ff 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Tue Dec  6 
11:49:05 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Tue Dec  6 
14:02:54 2005
@@ -76,9 +76,6 @@
         skb_shinfo(_skb)->frag_list = NULL;           \
     } while (0)
 
-/* Allow headroom on each rx pkt for Ethernet header, alignment padding, ... */
-#define RX_HEADROOM 200
-
 static unsigned long rx_pfn_array[NET_RX_RING_SIZE];
 static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+1];
 static mmu_update_t rx_mmu[NET_RX_RING_SIZE];
@@ -153,14 +150,15 @@
 #endif
 
 #ifdef DEBUG
-#define DPRINTK(fmt, args...) \
-       printk(KERN_ALERT "netfront (%s:%d) " fmt, __FUNCTION__, __LINE__, 
##args)
+#define DPRINTK(fmt, args...)                                          \
+       printk(KERN_ALERT "netfront (%s:%d) " fmt, __FUNCTION__,        \
+              __LINE__, ##args)
 #else
 #define DPRINTK(fmt, args...) ((void)0)
 #endif
-#define IPRINTK(fmt, args...) \
+#define IPRINTK(fmt, args...)                          \
        printk(KERN_INFO "netfront: " fmt, ##args)
-#define WPRINTK(fmt, args...) \
+#define WPRINTK(fmt, args...)                          \
        printk(KERN_WARNING "netfront: " fmt, ##args)
 
 
@@ -537,7 +535,9 @@
         */
        batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
        for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
-               skb = alloc_xen_skb(dev->mtu + RX_HEADROOM);
+               skb = alloc_xen_skb(
+                       (PAGE_SIZE - sizeof(struct skb_shared_info)) &
+                       (-SKB_DATA_ALIGN(1)));
                if (skb == NULL)
                        break;
                __skb_queue_tail(&np->rx_batch, skb);
@@ -567,7 +567,8 @@
                rx_pfn_array[i] = virt_to_mfn(skb->head);
 
                /* Remove this page from map before passing back to Xen. */
-               set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, 
INVALID_P2M_ENTRY);
+               set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
+                                   INVALID_P2M_ENTRY);
 
                MULTI_update_va_mapping(rx_mcl+i, (unsigned long)skb->head,
                                        __pte(0), 0);
@@ -809,36 +810,43 @@
        }
 
        while ((skb = __skb_dequeue(&rxq)) != NULL) {
+               if (skb->len > (dev->mtu + ETH_HLEN)) {
+                       if (net_ratelimit())
+                               printk(KERN_INFO "Received packet too big for "
+                                      "MTU (%d > %d)\n",
+                                      skb->len - ETH_HLEN, dev->mtu);
+                       skb->len  = 0;
+                       skb->tail = skb->data;
+                       init_skb_shinfo(skb);
+                       dev_kfree_skb(skb);
+                       continue;
+               }
+
                /*
                 * Enough room in skbuff for the data we were passed? Also,
                 * Linux expects at least 16 bytes headroom in each rx buffer.
                 */
                if (unlikely(skb->tail > skb->end) || 
                    unlikely((skb->data - skb->head) < 16)) {
-                       nskb = NULL;
-
-                       /* Only copy the packet if it fits in the MTU. */
-                       if (skb->len <= (dev->mtu + ETH_HLEN)) {
-                               if ((skb->tail > skb->end) && net_ratelimit())
+                       if (net_ratelimit()) {
+                               if (skb->tail > skb->end)
                                        printk(KERN_INFO "Received packet "
-                                              "needs %zd bytes more "
-                                              "headroom.\n",
+                                              "is %zd bytes beyond tail.\n",
                                               skb->tail - skb->end);
-
-                               nskb = alloc_xen_skb(skb->len + 2);
-                               if (nskb != NULL) {
-                                       skb_reserve(nskb, 2);
-                                       skb_put(nskb, skb->len);
-                                       memcpy(nskb->data,
-                                              skb->data,
-                                              skb->len);
-                                       nskb->dev = skb->dev;
-                               }
+                               else
+                                       printk(KERN_INFO "Received packet "
+                                              "is %zd bytes before head.\n",
+                                              16 - (skb->data - skb->head));
                        }
-                       else if (net_ratelimit())
-                               printk(KERN_INFO "Received packet too big for "
-                                      "MTU (%d > %d)\n",
-                                      skb->len - ETH_HLEN, dev->mtu);
+
+                       nskb = alloc_xen_skb(skb->len + 2);
+                       if (nskb != NULL) {
+                               skb_reserve(nskb, 2);
+                               skb_put(nskb, skb->len);
+                               memcpy(nskb->data, skb->data, skb->len);
+                               nskb->dev = skb->dev;
+                               nskb->ip_summed = skb->ip_summed;
+                       }
 
                        /* Reinitialise and then destroy the old skbuff. */
                        skb->len  = 0;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.