diff options
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 59 |
1 files changed, 4 insertions, 55 deletions
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 21258cf70091..615ee12647ae 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -235,51 +235,6 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) | |||
235 | spin_unlock_bh(&queue->lock); | 235 | spin_unlock_bh(&queue->lock); |
236 | } | 236 | } |
237 | 237 | ||
238 | static void | ||
239 | nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | ||
240 | { | ||
241 | int i, j = 0; | ||
242 | int plen = 0; /* length of skb->head fragment */ | ||
243 | struct page *page; | ||
244 | unsigned int offset; | ||
245 | |||
246 | /* dont bother with small payloads */ | ||
247 | if (len <= skb_tailroom(to)) { | ||
248 | skb_copy_bits(from, 0, skb_put(to, len), len); | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | if (hlen) { | ||
253 | skb_copy_bits(from, 0, skb_put(to, hlen), hlen); | ||
254 | len -= hlen; | ||
255 | } else { | ||
256 | plen = min_t(int, skb_headlen(from), len); | ||
257 | if (plen) { | ||
258 | page = virt_to_head_page(from->head); | ||
259 | offset = from->data - (unsigned char *)page_address(page); | ||
260 | __skb_fill_page_desc(to, 0, page, offset, plen); | ||
261 | get_page(page); | ||
262 | j = 1; | ||
263 | len -= plen; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | to->truesize += len + plen; | ||
268 | to->len += len + plen; | ||
269 | to->data_len += len + plen; | ||
270 | |||
271 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { | ||
272 | if (!len) | ||
273 | break; | ||
274 | skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i]; | ||
275 | skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len); | ||
276 | len -= skb_shinfo(to)->frags[j].size; | ||
277 | skb_frag_ref(to, j); | ||
278 | j++; | ||
279 | } | ||
280 | skb_shinfo(to)->nr_frags = j; | ||
281 | } | ||
282 | |||
283 | static int | 238 | static int |
284 | nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet, | 239 | nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet, |
285 | bool csum_verify) | 240 | bool csum_verify) |
@@ -304,7 +259,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
304 | { | 259 | { |
305 | size_t size; | 260 | size_t size; |
306 | size_t data_len = 0, cap_len = 0; | 261 | size_t data_len = 0, cap_len = 0; |
307 | int hlen = 0; | 262 | unsigned int hlen = 0; |
308 | struct sk_buff *skb; | 263 | struct sk_buff *skb; |
309 | struct nlattr *nla; | 264 | struct nlattr *nla; |
310 | struct nfqnl_msg_packet_hdr *pmsg; | 265 | struct nfqnl_msg_packet_hdr *pmsg; |
@@ -356,14 +311,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
356 | if (data_len > entskb->len) | 311 | if (data_len > entskb->len) |
357 | data_len = entskb->len; | 312 | data_len = entskb->len; |
358 | 313 | ||
359 | if (!entskb->head_frag || | 314 | hlen = skb_zerocopy_headlen(entskb); |
360 | skb_headlen(entskb) < L1_CACHE_BYTES || | 315 | hlen = min_t(unsigned int, hlen, data_len); |
361 | skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS) | ||
362 | hlen = skb_headlen(entskb); | ||
363 | |||
364 | if (skb_has_frag_list(entskb)) | ||
365 | hlen = entskb->len; | ||
366 | hlen = min_t(int, data_len, hlen); | ||
367 | size += sizeof(struct nlattr) + hlen; | 316 | size += sizeof(struct nlattr) + hlen; |
368 | cap_len = entskb->len; | 317 | cap_len = entskb->len; |
369 | break; | 318 | break; |
@@ -504,7 +453,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, | |||
504 | nla->nla_type = NFQA_PAYLOAD; | 453 | nla->nla_type = NFQA_PAYLOAD; |
505 | nla->nla_len = nla_attr_size(data_len); | 454 | nla->nla_len = nla_attr_size(data_len); |
506 | 455 | ||
507 | nfqnl_zcopy(skb, entskb, data_len, hlen); | 456 | skb_zerocopy(skb, entskb, data_len, hlen); |
508 | } | 457 | } |
509 | 458 | ||
510 | nlh->nlmsg_len = skb->len; | 459 | nlh->nlmsg_len = skb->len; |