aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-01-06 19:48:38 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-06 19:48:38 -0500
commit39b6b2992f9dc65d1de5c66e7ec2271b8a5fac33 (patch)
treec0fc4e2be0429bb4d7643e6b6f8f5a56212f9284 /net/core
parent56a4342dfe3145cd66f766adccb28fd9b571606d (diff)
parent443cd88c8a31379e95326428bbbd40af25c1d440 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jesse/openvswitch
Jesse Gross says: ==================== [GIT net-next] Open vSwitch Open vSwitch changes for net-next/3.14. Highlights are: * Performance improvements in the mechanism to get packets to userspace using memory mapped netlink and skb zero copy where appropriate. * Per-cpu flow stats in situations where flows are likely to be shared across CPUs. Standard flow stats are used in other situations to save memory and allocation time. * A handful of code cleanups and rationalization. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/skbuff.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index eb96c2c22400..1d641e781f85 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2121,6 +2121,91 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset,
2121} 2121}
2122EXPORT_SYMBOL(skb_copy_and_csum_bits); 2122EXPORT_SYMBOL(skb_copy_and_csum_bits);
2123 2123
2124 /**
2125 * skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy()
2126 * @from: source buffer
2127 *
2128 * Calculates the amount of linear headroom needed in the 'to' skb passed
2129 * into skb_zerocopy().
2130 */
2131unsigned int
2132skb_zerocopy_headlen(const struct sk_buff *from)
2133{
2134 unsigned int hlen = 0;
2135
2136 if (!from->head_frag ||
2137 skb_headlen(from) < L1_CACHE_BYTES ||
2138 skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
2139 hlen = skb_headlen(from);
2140
2141 if (skb_has_frag_list(from))
2142 hlen = from->len;
2143
2144 return hlen;
2145}
2146EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
2147
2148/**
2149 * skb_zerocopy - Zero copy skb to skb
2150 * @to: destination buffer
2151 * @source: source buffer
2152 * @len: number of bytes to copy from source buffer
2153 * @hlen: size of linear headroom in destination buffer
2154 *
2155 * Copies up to `len` bytes from `from` to `to` by creating references
2156 * to the frags in the source buffer.
2157 *
2158 * The `hlen` as calculated by skb_zerocopy_headlen() specifies the
2159 * headroom in the `to` buffer.
2160 */
2161void
2162skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
2163{
2164 int i, j = 0;
2165 int plen = 0; /* length of skb->head fragment */
2166 struct page *page;
2167 unsigned int offset;
2168
2169 BUG_ON(!from->head_frag && !hlen);
2170
2171 /* dont bother with small payloads */
2172 if (len <= skb_tailroom(to)) {
2173 skb_copy_bits(from, 0, skb_put(to, len), len);
2174 return;
2175 }
2176
2177 if (hlen) {
2178 skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
2179 len -= hlen;
2180 } else {
2181 plen = min_t(int, skb_headlen(from), len);
2182 if (plen) {
2183 page = virt_to_head_page(from->head);
2184 offset = from->data - (unsigned char *)page_address(page);
2185 __skb_fill_page_desc(to, 0, page, offset, plen);
2186 get_page(page);
2187 j = 1;
2188 len -= plen;
2189 }
2190 }
2191
2192 to->truesize += len + plen;
2193 to->len += len + plen;
2194 to->data_len += len + plen;
2195
2196 for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
2197 if (!len)
2198 break;
2199 skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
2200 skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len);
2201 len -= skb_shinfo(to)->frags[j].size;
2202 skb_frag_ref(to, j);
2203 j++;
2204 }
2205 skb_shinfo(to)->nr_frags = j;
2206}
2207EXPORT_SYMBOL_GPL(skb_zerocopy);
2208
2124void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) 2209void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to)
2125{ 2210{
2126 __wsum csum; 2211 __wsum csum;