diff options
author | Ian Campbell <Ian.Campbell@citrix.com> | 2011-08-19 02:25:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-22 19:59:54 -0400 |
commit | 131ea6675c761f655d43b808dd0fe83d15d5cdd3 (patch) | |
tree | 0d8cb6a3ea524f216d846f172c218fababead4a0 | |
parent | 7ae9ed8d3221c9f7dd4bc2773ff58797487d5ed8 (diff) |
net: add APIs for manipulating skb page fragments.
The primary aim is to add skb_frag_(ref|unref) in order to remove the use of
bare get/put_page on SKB pages fragments and to isolate users from subsequent
changes to the skb_frag_t data structure.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: "Michał Mirosław" <mirq-linux@rere.qmqm.pl>
Cc: netdev@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/skbuff.h | 170 |
1 files changed, 168 insertions, 2 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ea0b3746386..7b0e1773f9c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/rcupdate.h> | 29 | #include <linux/rcupdate.h> |
30 | #include <linux/dmaengine.h> | 30 | #include <linux/dmaengine.h> |
31 | #include <linux/hrtimer.h> | 31 | #include <linux/hrtimer.h> |
32 | #include <linux/dma-mapping.h> | ||
32 | 33 | ||
33 | /* Don't change this without changing skb_csum_unnecessary! */ | 34 | /* Don't change this without changing skb_csum_unnecessary! */ |
34 | #define CHECKSUM_NONE 0 | 35 | #define CHECKSUM_NONE 0 |
@@ -1129,14 +1130,47 @@ static inline int skb_pagelen(const struct sk_buff *skb) | |||
1129 | return len + skb_headlen(skb); | 1130 | return len + skb_headlen(skb); |
1130 | } | 1131 | } |
1131 | 1132 | ||
1132 | static inline void skb_fill_page_desc(struct sk_buff *skb, int i, | 1133 | /** |
1133 | struct page *page, int off, int size) | 1134 | * __skb_fill_page_desc - initialise a paged fragment in an skb |
1135 | * @skb: buffer containing fragment to be initialised | ||
1136 | * @i: paged fragment index to initialise | ||
1137 | * @page: the page to use for this fragment | ||
1138 | * @off: the offset to the data with @page | ||
1139 | * @size: the length of the data | ||
1140 | * | ||
1141 | * Initialises the @i'th fragment of @skb to point to &size bytes at | ||
1142 | * offset @off within @page. | ||
1143 | * | ||
1144 | * Does not take any additional reference on the fragment. | ||
1145 | */ | ||
1146 | static inline void __skb_fill_page_desc(struct sk_buff *skb, int i, | ||
1147 | struct page *page, int off, int size) | ||
1134 | { | 1148 | { |
1135 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | 1149 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; |
1136 | 1150 | ||
1137 | frag->page = page; | 1151 | frag->page = page; |
1138 | frag->page_offset = off; | 1152 | frag->page_offset = off; |
1139 | frag->size = size; | 1153 | frag->size = size; |
1154 | } | ||
1155 | |||
1156 | /** | ||
1157 | * skb_fill_page_desc - initialise a paged fragment in an skb | ||
1158 | * @skb: buffer containing fragment to be initialised | ||
1159 | * @i: paged fragment index to initialise | ||
1160 | * @page: the page to use for this fragment | ||
1161 | * @off: the offset to the data with @page | ||
1162 | * @size: the length of the data | ||
1163 | * | ||
1164 | * As per __skb_fill_page_desc() -- initialises the @i'th fragment of | ||
1165 | * @skb to point to &size bytes at offset @off within @page. In | ||
1166 | * addition updates @skb such that @i is the last fragment. | ||
1167 | * | ||
1168 | * Does not take any additional reference on the fragment. | ||
1169 | */ | ||
1170 | static inline void skb_fill_page_desc(struct sk_buff *skb, int i, | ||
1171 | struct page *page, int off, int size) | ||
1172 | { | ||
1173 | __skb_fill_page_desc(skb, i, page, off, size); | ||
1140 | skb_shinfo(skb)->nr_frags = i + 1; | 1174 | skb_shinfo(skb)->nr_frags = i + 1; |
1141 | } | 1175 | } |
1142 | 1176 | ||
@@ -1631,6 +1665,138 @@ static inline void netdev_free_page(struct net_device *dev, struct page *page) | |||
1631 | } | 1665 | } |
1632 | 1666 | ||
1633 | /** | 1667 | /** |
1668 | * skb_frag_page - retrieve the page refered to by a paged fragment | ||
1669 | * @frag: the paged fragment | ||
1670 | * | ||
1671 | * Returns the &struct page associated with @frag. | ||
1672 | */ | ||
1673 | static inline struct page *skb_frag_page(const skb_frag_t *frag) | ||
1674 | { | ||
1675 | return frag->page; | ||
1676 | } | ||
1677 | |||
1678 | /** | ||
1679 | * __skb_frag_ref - take an addition reference on a paged fragment. | ||
1680 | * @frag: the paged fragment | ||
1681 | * | ||
1682 | * Takes an additional reference on the paged fragment @frag. | ||
1683 | */ | ||
1684 | static inline void __skb_frag_ref(skb_frag_t *frag) | ||
1685 | { | ||
1686 | get_page(skb_frag_page(frag)); | ||
1687 | } | ||
1688 | |||
1689 | /** | ||
1690 | * skb_frag_ref - take an addition reference on a paged fragment of an skb. | ||
1691 | * @skb: the buffer | ||
1692 | * @f: the fragment offset. | ||
1693 | * | ||
1694 | * Takes an additional reference on the @f'th paged fragment of @skb. | ||
1695 | */ | ||
1696 | static inline void skb_frag_ref(struct sk_buff *skb, int f) | ||
1697 | { | ||
1698 | __skb_frag_ref(&skb_shinfo(skb)->frags[f]); | ||
1699 | } | ||
1700 | |||
1701 | /** | ||
1702 | * __skb_frag_unref - release a reference on a paged fragment. | ||
1703 | * @frag: the paged fragment | ||
1704 | * | ||
1705 | * Releases a reference on the paged fragment @frag. | ||
1706 | */ | ||
1707 | static inline void __skb_frag_unref(skb_frag_t *frag) | ||
1708 | { | ||
1709 | put_page(skb_frag_page(frag)); | ||
1710 | } | ||
1711 | |||
1712 | /** | ||
1713 | * skb_frag_unref - release a reference on a paged fragment of an skb. | ||
1714 | * @skb: the buffer | ||
1715 | * @f: the fragment offset | ||
1716 | * | ||
1717 | * Releases a reference on the @f'th paged fragment of @skb. | ||
1718 | */ | ||
1719 | static inline void skb_frag_unref(struct sk_buff *skb, int f) | ||
1720 | { | ||
1721 | __skb_frag_unref(&skb_shinfo(skb)->frags[f]); | ||
1722 | } | ||
1723 | |||
1724 | /** | ||
1725 | * skb_frag_address - gets the address of the data contained in a paged fragment | ||
1726 | * @frag: the paged fragment buffer | ||
1727 | * | ||
1728 | * Returns the address of the data within @frag. The page must already | ||
1729 | * be mapped. | ||
1730 | */ | ||
1731 | static inline void *skb_frag_address(const skb_frag_t *frag) | ||
1732 | { | ||
1733 | return page_address(skb_frag_page(frag)) + frag->page_offset; | ||
1734 | } | ||
1735 | |||
1736 | /** | ||
1737 | * skb_frag_address_safe - gets the address of the data contained in a paged fragment | ||
1738 | * @frag: the paged fragment buffer | ||
1739 | * | ||
1740 | * Returns the address of the data within @frag. Checks that the page | ||
1741 | * is mapped and returns %NULL otherwise. | ||
1742 | */ | ||
1743 | static inline void *skb_frag_address_safe(const skb_frag_t *frag) | ||
1744 | { | ||
1745 | void *ptr = page_address(skb_frag_page(frag)); | ||
1746 | if (unlikely(!ptr)) | ||
1747 | return NULL; | ||
1748 | |||
1749 | return ptr + frag->page_offset; | ||
1750 | } | ||
1751 | |||
1752 | /** | ||
1753 | * __skb_frag_set_page - sets the page contained in a paged fragment | ||
1754 | * @frag: the paged fragment | ||
1755 | * @page: the page to set | ||
1756 | * | ||
1757 | * Sets the fragment @frag to contain @page. | ||
1758 | */ | ||
1759 | static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page) | ||
1760 | { | ||
1761 | frag->page = page; | ||
1762 | __skb_frag_ref(frag); | ||
1763 | } | ||
1764 | |||
1765 | /** | ||
1766 | * skb_frag_set_page - sets the page contained in a paged fragment of an skb | ||
1767 | * @skb: the buffer | ||
1768 | * @f: the fragment offset | ||
1769 | * @page: the page to set | ||
1770 | * | ||
1771 | * Sets the @f'th fragment of @skb to contain @page. | ||
1772 | */ | ||
1773 | static inline void skb_frag_set_page(struct sk_buff *skb, int f, | ||
1774 | struct page *page) | ||
1775 | { | ||
1776 | __skb_frag_set_page(&skb_shinfo(skb)->frags[f], page); | ||
1777 | } | ||
1778 | |||
1779 | /** | ||
1780 | * skb_frag_dma_map - maps a paged fragment via the DMA API | ||
1781 | * @device: the device to map the fragment to | ||
1782 | * @frag: the paged fragment to map | ||
1783 | * @offset: the offset within the fragment (starting at the | ||
1784 | * fragment's own offset) | ||
1785 | * @size: the number of bytes to map | ||
1786 | * @direction: the direction of the mapping (%PCI_DMA_*) | ||
1787 | * | ||
1788 | * Maps the page associated with @frag to @device. | ||
1789 | */ | ||
1790 | static inline dma_addr_t skb_frag_dma_map(struct device *dev, | ||
1791 | const skb_frag_t *frag, | ||
1792 | size_t offset, size_t size, | ||
1793 | enum dma_data_direction dir) | ||
1794 | { | ||
1795 | return dma_map_page(dev, skb_frag_page(frag), | ||
1796 | frag->page_offset + offset, size, dir); | ||
1797 | } | ||
1798 | |||
1799 | /** | ||
1634 | * skb_clone_writable - is the header of a clone writable | 1800 | * skb_clone_writable - is the header of a clone writable |
1635 | * @skb: buffer to check | 1801 | * @skb: buffer to check |
1636 | * @len: length up to which to write | 1802 | * @len: length up to which to write |