# 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
|