bitkeeper revision 1.1159.79.10 (41505c58w6Hk7xUbFnsEdE5r462MrQ)

Rewrite our skb cache. Fix frontend driver to ask for sensibly-sized
skbuffs.
This commit is contained in:
kaf24@freefall.cl.cam.ac.uk committed 2004-09-21 16:52:40 +00:00
1 parent 17e9169722
commit c2f2607dc5
8 files changed
+2896 -44

No files matched your search

+2
View File
@@ -126,6 +126,7 @@
409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4.27-xen-sparse/mm/page_alloc.c
3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.27-xen-sparse/mm/swapfile.c
41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.27-xen-sparse/mm/vmalloc.c
41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.27-xen-sparse/net/core/skbuff.c
413aa1d0oNP8HXLvfPuMe6cSroUfSA linux-2.6.8.1-patches/agpgart.patch
413aa1d0ewvSv-ohnNnQQNGsbPTTNA linux-2.6.8.1-patches/drm.patch
40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.8.1-xen-sparse/arch/xen/Kconfig
@@ -259,6 +260,7 @@
40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.8.1-xen-sparse/mkbuildtree
412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.8.1-xen-sparse/mm/memory.c
410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.8.1-xen-sparse/mm/page_alloc.c
41505c572m-s9ATiO1LiD1GPznTTIg linux-2.6.8.1-xen-sparse/net/core/skbuff.c
4149ec79wMpIHdvbntxqVGLRZZjPxw linux-2.6.8.1-xen-sparse/net/ipv4/raw.c
413cb1e4zst25MDYjg63Y-NGC5_pLg netbsd-2.0-xen-sparse/Makefile
413cb1e5c_Mkxf_X0zimEhTKI_l4DA netbsd-2.0-xen-sparse/mkbuildtree
@@ -231,6 +231,7 @@ struct sk_buff {
extern void __kfree_skb(struct sk_buff *skb);
extern struct sk_buff * alloc_skb(unsigned int size, int priority);
extern struct sk_buff * alloc_skb_from_cache(kmem_cache_t *cp, unsigned int size, int priority);
extern void kfree_skbmem(struct sk_buff *skb);
extern struct sk_buff * skb_clone(struct sk_buff *skb, int priority);
extern struct sk_buff * skb_copy(const struct sk_buff *skb, int priority);
File diff suppressed because it is too large. Load diff
@@ -27,34 +27,9 @@ EXPORT_SYMBOL(__dev_alloc_skb);
struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask)
{
struct sk_buff *skb;
u8 *new_data, *new_shinfo;
/*
* Yuk! There is no way to get a skbuff head without allocating the
* data area using kmalloc(). So we do that and then replace the default
* data area with our own.
*/
skb = alloc_skb(0, gfp_mask);
if ( unlikely(skb == NULL) )
return NULL;
new_data = kmem_cache_alloc(skbuff_cachep, gfp_mask);
if ( new_data == NULL )
{
dev_kfree_skb(skb);
return NULL;
}
new_shinfo = new_data + XEN_SKB_SIZE;
memcpy(new_shinfo, skb_shinfo(skb), sizeof(struct skb_shared_info));
kfree(skb->head);
skb->head = new_data;
skb->data = skb->tail = new_data + 16; /* __dev_alloc_skb does this */
skb->end = new_shinfo;
skb->truesize = 1500; /* is this important? */
skb = alloc_skb_from_cache(skbuff_cachep, length + 16, gfp_mask);
if ( likely(skb != NULL) )
skb_reserve(skb, 16);
return skb;
}
@@ -144,11 +144,12 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
if ( skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb) )
{
struct sk_buff *nskb = dev_alloc_skb(PAGE_SIZE);
int hlen = skb->data - skb->head;
struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len);
if ( unlikely(nskb == NULL) )
goto drop;
skb_reserve(nskb, hlen);
/* Account for any reservation already made by dev_alloc_skb(). */
skb_reserve(nskb, hlen - (nskb->data - nskb->head));
__skb_put(nskb, skb->len);
(void)skb_copy_bits(skb, -hlen, nskb->head, hlen + skb->len);
nskb->dev = skb->dev;
@@ -39,7 +39,17 @@
#ifndef __GFP_NOWARN
#define __GFP_NOWARN 0
#endif
#define alloc_skb_page() __dev_alloc_skb(PAGE_SIZE, GFP_ATOMIC|__GFP_NOWARN)
#define alloc_xen_skb(_l) __dev_alloc_skb((_l), GFP_ATOMIC|__GFP_NOWARN)
#define init_skb_shinfo(_skb) \
do { \
atomic_set(&(skb_shinfo(_skb)->dataref), 1); \
skb_shinfo(_skb)->nr_frags = 0; \
skb_shinfo(_skb)->frag_list = NULL; \
} while ( 0 )
/* Allow headroom on each rx pkt for Ethernet header, alignment padding, ... */
#define RX_HEADROOM 100
/*
* If the backend driver is pipelining transmit requests then we can be very
@@ -249,7 +259,7 @@ static void network_tx_buf_gc(struct net_device *dev)
id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
skb = np->tx_skbs[id];
ADD_ID_TO_FREELIST(np->tx_skbs, id);
dev_kfree_skb_any(skb);
dev_kfree_skb_irq(skb);
}
np->tx_resp_cons = prod;
@@ -292,7 +302,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
return;
do {
if ( unlikely((skb = alloc_skb_page()) == NULL) )
if ( unlikely((skb = alloc_xen_skb(dev->mtu + RX_HEADROOM)) == NULL) )
break;
skb->dev = dev;
@@ -368,7 +378,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
PAGE_SIZE) )
{
struct sk_buff *new_skb;
if ( unlikely((new_skb = alloc_skb_page()) == NULL) )
if ( unlikely((new_skb = alloc_xen_skb(skb->len)) == NULL) )
goto drop;
skb_put(new_skb, skb->len);
memcpy(new_skb->data, skb->data, skb->len);
@@ -446,7 +456,7 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
static int netif_poll(struct net_device *dev, int *pbudget)
{
struct net_private *np = dev->priv;
struct sk_buff *skb;
struct sk_buff *skb, *nskb;
netif_rx_response_t *rx;
NETIF_RING_IDX i, rp;
mmu_update_t *mmu = rx_mmu;
@@ -494,8 +504,10 @@ static int netif_poll(struct net_device *dev, int *pbudget)
skb = np->rx_skbs[rx->id];
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
skb->data = skb->tail = skb->head + (rx->addr & ~PAGE_MASK);
skb_put(skb, rx->status);
/* NB. We handle skb overflow later. */
skb->data = skb->head + (rx->addr & ~PAGE_MASK);
skb->len = rx->status;
skb->tail = skb->data + skb->len;
np->stats.rx_packets++;
np->stats.rx_bytes += rx->status;
@@ -529,10 +541,39 @@ static int netif_poll(struct net_device *dev, int *pbudget)
while ( (skb = __skb_dequeue(&rxq)) != NULL )
{
/*
* Enough room in skbuff for the data we were passed? Also, Linux
* expects at least 16 bytes headroom in each receive buffer.
*/
if ( unlikely(skb->tail > skb->end) ||
unlikely((skb->data - skb->head) < 16) )
{
nskb = NULL;
/* Only copy the packet if it fits in the current MTU. */
if ( skb->len <= (dev->mtu + ETH_HLEN) )
{
if ( (nskb = alloc_xen_skb(skb->len + 2)) != NULL )
{
skb_reserve(nskb, 2);
skb_put(nskb, skb->len);
memcpy(nskb->data, skb->data, skb->len);
}
}
/* Reinitialise and then destroy the old skbuff. */
skb->len = 0;
skb->tail = skb->data;
init_skb_shinfo(skb);
dev_kfree_skb(skb);
/* Switch old for new, if we copied the buffer. */
if ( (skb = nskb) == NULL )
continue;
}
/* Set the shared-info area, which is hidden behind the real data. */
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->frag_list = NULL;
init_skb_shinfo(skb);
/* Ethernet-specific work. Delayed to here as it peeks the header. */
skb->protocol = eth_type_trans(skb, dev);
@@ -596,8 +637,8 @@ static void network_connect(struct net_device *dev,
netif_tx_request_t *tx;
np = dev->priv;
spin_lock_irq(&np->rx_lock);
spin_lock(&np->tx_lock);
spin_lock_irq(&np->tx_lock);
spin_lock(&np->rx_lock);
/* Recovery procedure: */
@@ -664,8 +705,8 @@ printk(KERN_ALERT"Netfront recovered tx=%d rxfree=%d\n",
if ( np->user_state == UST_OPEN )
netif_start_queue(dev);
spin_unlock(&np->tx_lock);
spin_unlock_irq(&np->rx_lock);
spin_unlock(&np->rx_lock);
spin_unlock_irq(&np->tx_lock);
}
static void netif_status_change(netif_fe_interface_status_changed_t *status)
@@ -293,6 +293,8 @@ struct sk_buff {
extern void __kfree_skb(struct sk_buff *skb);
extern struct sk_buff *alloc_skb(unsigned int size, int priority);
extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp,
unsigned int size, int priority);
extern void kfree_skbmem(struct sk_buff *skb);
extern struct sk_buff *skb_clone(struct sk_buff *skb, int priority);
extern struct sk_buff *skb_copy(const struct sk_buff *skb, int priority);
File diff suppressed because it is too large. Load diff
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.