RE: skb_pull()

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

 



Hi,
	thanks for your reply.  skb_pull() was fine for splitting the large
frame into small chunks for passing down to our card.  I didn't need
skb_push() as I didn't want the segments added to the front of the skb,
skb_put was indeed what I needed.  It all seems to work OK.  We can now send
and receive 32K frames (a limit of the hdlc controller on our card), passed
to the card in small chunks.


Thanks

Kevin

-----Original Message-----
From: nospamnospam@vip.cybercity.dk
[mailto:nospamnospam@vip.cybercity.dk]
Sent: 14 May 2003 17:34
To: kevin.curtis@farsite.co.uk
Cc: linux-net@vger.kernel.org
Subject: Re: skb_pull()



> It looks to me as though the skb-pull() function is what I want.  I can
pull
> each 1K chunk off at a time.  Is it really that simple?  However, an
element
> of doubt has been put in my mind by the description of the function in the
> Linux Device Drivers book ("Removes data from the head of the packet.  The
> driver won't need to use this function, but is included for
completeness.")
> Hopefully, it is complete.

I think "completeness" refers to the book, not to the functionality of
skb_pull(). I think it is most unsual to use skb_pull() in a network device
driver.

> Will I be able to use skb_push()
> function to assemble a 4K frame in a similar manner on the receive side?

Normally, you'd use skb_put(). This assumes that the first chunk is received
first:

skb = dev_alloc_skb (4K + alignment);
skb_reserve (skb, alignment);
insl (ioaddr + x, skb_put (skb, 1K), 1K); /* 1st chunk. */
...
insl (ioaddr + x, skb_put (skb, 1K), 1K); /* 2nd chunk. */
...
insl (ioaddr + x, skb_put (skb, 1K), 1K); /* 3rd chunk. */
...
insl (ioaddr + x, skb_put (skb, 1K), 1K); /* 4th chunk. */

If you get the first chunk last, then use skb_push():

skb = dev_alloc_skb (4K + alignment);
skb_reserve (skb, 4K + alignment);
insl (ioaddr + x, skb_push (skb, 1K), 1K); /* 4th chunk. */
...
insl (ioaddr + x, skb_push (skb, 1K), 1K); /* 3rd chunk. */
...
insl (ioaddr + x, skb_push (skb, 1K), 1K); /* 2nd chunk. */
...
insl (ioaddr + x, skb_push (skb, 1K), 1K); /* 1st chunk. */

(I don't know what skb_push() returns, I'm assuming it returns a pointer to
the new 1K chunk in skb_put() style. If not, modify accordingly.)

This should work fine with 2.2 kernels too.

All of the above assumed that you use PIO transfers. With a DMA device,
you'll need to manage the pointers yourself on the receive side when dealing
with the chunks. Something like:

skb = dev_alloc_skb (4K + alignment);
skb_reserve (skb, alignment);
dma_pointer = pci_map_single (pdev, skb->head, 4K, PCI_DMA_FROMDEVICE);
/* await completion of DMA */
skb_put (skb, length_of_whole_packet);
pci_unmap_single (pdev, dma_pointer, skb->head, 4K, PCI_DMA_FROMDEVICE);

(Please the the order of the arguments.)

Regards,
Rask Ingemann Lambertsen


-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux