I have wrote a driver that adds vlan and my own sfab header to packets
(both defined in struct sfab_hdr ). I have increased hard_header_len so
new headers will always fit to skb. skb->dev is changed to bonding
device that will then at the end use real ethernet device to send the
packet over the network. So it goes like: -> sfab -> bond -> eth0 ->
network

The driver works fine, but it just leaks memory and seems to me the sent
skb is not freed somehow.

int hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
        struct sfab_priv *priv = netdev_priv(dev);
        struct sfab_hdr *sfab;
        struct sk_buff *sk_tmp;

        /* if no space in skb headroom for vlan and sfab, increase the
size */
        if(skb_headroom(skb) < (sizeof(struct sfab_hdr)-ETH_HLEN))
        {
                /*We should never end up here because hard_header_len
enough*/
                sk_tmp = skb;   
                skb = skb_realloc_headroom(sk_tmp, 
                (sizeof(struct sfab_hdr)-ETH_HLEN));    
                kfree_skb(sk_tmp);
                if (!skb) {
                        printk(KERN_ERR "sfab: failed to realloc
headroom\n");
                        priv->stats.tx_errors++;
                        return 0;
                }
        }
        else {
                skb = skb_unshare(skb, GFP_ATOMIC);
                if (!skb) {
                        printk(KERN_ERR "sfab: failed to unshare
skbuff\n");
                        priv->stats.tx_errors++;
                        return 0;
                }
        }       
        sfab = (struct sfab_hdr *)skb_push(skb, 
        (sizeof(struct sfab_hdr)-ETH_HLEN));

        skb->mac.raw -= (sizeof(struct sfab_hdr)-ETH_HLEN);
        skb->nh.raw -= (sizeof(struct sfab_hdr)-ETH_HLEN);
        
        set_sfab_header(sfab,skb);/* make VLAN header + sfab header */
                
        /* try to fix skb so it works*/
        skb->nfct=NULL;
        skb->protocol = __constant_htons(ETH_P_8021Q); /* VLAN */
        skb->dev=priv->lower_dev; /* bonding device will send this
further */
        dev->trans_start = jiffies; /* save the timestamp */    
                        
        priv->stats.tx_packets++;
        priv->stats.tx_bytes+=skb->len;
        
        if(dev_queue_xmit(skb)<0)
        {
                /* Not able to transmit, free it */
                skb_unlink(skb);
                kfree_skb(skb);
                priv->stats.tx_errors++;
        }
        return 0;
}

What should I do? If the skb pointer changes, should it be updated to
some list or what?

Tomi

 


-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to