diff options
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r-- | net/core/skbuff.c | 277 |
1 files changed, 262 insertions, 15 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 65f7757465bd..b8d0abb26433 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -501,7 +501,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
501 | new->network_header = old->network_header; | 501 | new->network_header = old->network_header; |
502 | new->mac_header = old->mac_header; | 502 | new->mac_header = old->mac_header; |
503 | new->dst = dst_clone(old->dst); | 503 | new->dst = dst_clone(old->dst); |
504 | #ifdef CONFIG_INET | 504 | #ifdef CONFIG_XFRM |
505 | new->sp = secpath_get(old->sp); | 505 | new->sp = secpath_get(old->sp); |
506 | #endif | 506 | #endif |
507 | memcpy(new->cb, old->cb, sizeof(old->cb)); | 507 | memcpy(new->cb, old->cb, sizeof(old->cb)); |
@@ -556,6 +556,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | |||
556 | C(truesize); | 556 | C(truesize); |
557 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) | 557 | #if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE) |
558 | C(do_not_encrypt); | 558 | C(do_not_encrypt); |
559 | C(requeue); | ||
559 | #endif | 560 | #endif |
560 | atomic_set(&n->users, 1); | 561 | atomic_set(&n->users, 1); |
561 | 562 | ||
@@ -2017,6 +2018,148 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) | |||
2017 | skb_split_no_header(skb, skb1, len, pos); | 2018 | skb_split_no_header(skb, skb1, len, pos); |
2018 | } | 2019 | } |
2019 | 2020 | ||
2021 | /* Shifting from/to a cloned skb is a no-go. | ||
2022 | * | ||
2023 | * Caller cannot keep skb_shinfo related pointers past calling here! | ||
2024 | */ | ||
2025 | static int skb_prepare_for_shift(struct sk_buff *skb) | ||
2026 | { | ||
2027 | return skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC); | ||
2028 | } | ||
2029 | |||
2030 | /** | ||
2031 | * skb_shift - Shifts paged data partially from skb to another | ||
2032 | * @tgt: buffer into which tail data gets added | ||
2033 | * @skb: buffer from which the paged data comes from | ||
2034 | * @shiftlen: shift up to this many bytes | ||
2035 | * | ||
2036 | * Attempts to shift up to shiftlen worth of bytes, which may be less than | ||
2037 | * the length of the skb, from tgt to skb. Returns number bytes shifted. | ||
2038 | * It's up to caller to free skb if everything was shifted. | ||
2039 | * | ||
2040 | * If @tgt runs out of frags, the whole operation is aborted. | ||
2041 | * | ||
2042 | * Skb cannot include anything else but paged data while tgt is allowed | ||
2043 | * to have non-paged data as well. | ||
2044 | * | ||
2045 | * TODO: full sized shift could be optimized but that would need | ||
2046 | * specialized skb free'er to handle frags without up-to-date nr_frags. | ||
2047 | */ | ||
2048 | int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) | ||
2049 | { | ||
2050 | int from, to, merge, todo; | ||
2051 | struct skb_frag_struct *fragfrom, *fragto; | ||
2052 | |||
2053 | BUG_ON(shiftlen > skb->len); | ||
2054 | BUG_ON(skb_headlen(skb)); /* Would corrupt stream */ | ||
2055 | |||
2056 | todo = shiftlen; | ||
2057 | from = 0; | ||
2058 | to = skb_shinfo(tgt)->nr_frags; | ||
2059 | fragfrom = &skb_shinfo(skb)->frags[from]; | ||
2060 | |||
2061 | /* Actual merge is delayed until the point when we know we can | ||
2062 | * commit all, so that we don't have to undo partial changes | ||
2063 | */ | ||
2064 | if (!to || | ||
2065 | !skb_can_coalesce(tgt, to, fragfrom->page, fragfrom->page_offset)) { | ||
2066 | merge = -1; | ||
2067 | } else { | ||
2068 | merge = to - 1; | ||
2069 | |||
2070 | todo -= fragfrom->size; | ||
2071 | if (todo < 0) { | ||
2072 | if (skb_prepare_for_shift(skb) || | ||
2073 | skb_prepare_for_shift(tgt)) | ||
2074 | return 0; | ||
2075 | |||
2076 | /* All previous frag pointers might be stale! */ | ||
2077 | fragfrom = &skb_shinfo(skb)->frags[from]; | ||
2078 | fragto = &skb_shinfo(tgt)->frags[merge]; | ||
2079 | |||
2080 | fragto->size += shiftlen; | ||
2081 | fragfrom->size -= shiftlen; | ||
2082 | fragfrom->page_offset += shiftlen; | ||
2083 | |||
2084 | goto onlymerged; | ||
2085 | } | ||
2086 | |||
2087 | from++; | ||
2088 | } | ||
2089 | |||
2090 | /* Skip full, not-fitting skb to avoid expensive operations */ | ||
2091 | if ((shiftlen == skb->len) && | ||
2092 | (skb_shinfo(skb)->nr_frags - from) > (MAX_SKB_FRAGS - to)) | ||
2093 | return 0; | ||
2094 | |||
2095 | if (skb_prepare_for_shift(skb) || skb_prepare_for_shift(tgt)) | ||
2096 | return 0; | ||
2097 | |||
2098 | while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) { | ||
2099 | if (to == MAX_SKB_FRAGS) | ||
2100 | return 0; | ||
2101 | |||
2102 | fragfrom = &skb_shinfo(skb)->frags[from]; | ||
2103 | fragto = &skb_shinfo(tgt)->frags[to]; | ||
2104 | |||
2105 | if (todo >= fragfrom->size) { | ||
2106 | *fragto = *fragfrom; | ||
2107 | todo -= fragfrom->size; | ||
2108 | from++; | ||
2109 | to++; | ||
2110 | |||
2111 | } else { | ||
2112 | get_page(fragfrom->page); | ||
2113 | fragto->page = fragfrom->page; | ||
2114 | fragto->page_offset = fragfrom->page_offset; | ||
2115 | fragto->size = todo; | ||
2116 | |||
2117 | fragfrom->page_offset += todo; | ||
2118 | fragfrom->size -= todo; | ||
2119 | todo = 0; | ||
2120 | |||
2121 | to++; | ||
2122 | break; | ||
2123 | } | ||
2124 | } | ||
2125 | |||
2126 | /* Ready to "commit" this state change to tgt */ | ||
2127 | skb_shinfo(tgt)->nr_frags = to; | ||
2128 | |||
2129 | if (merge >= 0) { | ||
2130 | fragfrom = &skb_shinfo(skb)->frags[0]; | ||
2131 | fragto = &skb_shinfo(tgt)->frags[merge]; | ||
2132 | |||
2133 | fragto->size += fragfrom->size; | ||
2134 | put_page(fragfrom->page); | ||
2135 | } | ||
2136 | |||
2137 | /* Reposition in the original skb */ | ||
2138 | to = 0; | ||
2139 | while (from < skb_shinfo(skb)->nr_frags) | ||
2140 | skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++]; | ||
2141 | skb_shinfo(skb)->nr_frags = to; | ||
2142 | |||
2143 | BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags); | ||
2144 | |||
2145 | onlymerged: | ||
2146 | /* Most likely the tgt won't ever need its checksum anymore, skb on | ||
2147 | * the other hand might need it if it needs to be resent | ||
2148 | */ | ||
2149 | tgt->ip_summed = CHECKSUM_PARTIAL; | ||
2150 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
2151 | |||
2152 | /* Yak, is it really working this way? Some helper please? */ | ||
2153 | skb->len -= shiftlen; | ||
2154 | skb->data_len -= shiftlen; | ||
2155 | skb->truesize -= shiftlen; | ||
2156 | tgt->len += shiftlen; | ||
2157 | tgt->data_len += shiftlen; | ||
2158 | tgt->truesize += shiftlen; | ||
2159 | |||
2160 | return shiftlen; | ||
2161 | } | ||
2162 | |||
2020 | /** | 2163 | /** |
2021 | * skb_prepare_seq_read - Prepare a sequential read of skb data | 2164 | * skb_prepare_seq_read - Prepare a sequential read of skb data |
2022 | * @skb: the buffer to read | 2165 | * @skb: the buffer to read |
@@ -2285,6 +2428,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
2285 | { | 2428 | { |
2286 | struct sk_buff *segs = NULL; | 2429 | struct sk_buff *segs = NULL; |
2287 | struct sk_buff *tail = NULL; | 2430 | struct sk_buff *tail = NULL; |
2431 | struct sk_buff *fskb = skb_shinfo(skb)->frag_list; | ||
2288 | unsigned int mss = skb_shinfo(skb)->gso_size; | 2432 | unsigned int mss = skb_shinfo(skb)->gso_size; |
2289 | unsigned int doffset = skb->data - skb_mac_header(skb); | 2433 | unsigned int doffset = skb->data - skb_mac_header(skb); |
2290 | unsigned int offset = doffset; | 2434 | unsigned int offset = doffset; |
@@ -2304,7 +2448,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
2304 | struct sk_buff *nskb; | 2448 | struct sk_buff *nskb; |
2305 | skb_frag_t *frag; | 2449 | skb_frag_t *frag; |
2306 | int hsize; | 2450 | int hsize; |
2307 | int k; | ||
2308 | int size; | 2451 | int size; |
2309 | 2452 | ||
2310 | len = skb->len - offset; | 2453 | len = skb->len - offset; |
@@ -2317,9 +2460,36 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
2317 | if (hsize > len || !sg) | 2460 | if (hsize > len || !sg) |
2318 | hsize = len; | 2461 | hsize = len; |
2319 | 2462 | ||
2320 | nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC); | 2463 | if (!hsize && i >= nfrags) { |
2321 | if (unlikely(!nskb)) | 2464 | BUG_ON(fskb->len != len); |
2322 | goto err; | 2465 | |
2466 | pos += len; | ||
2467 | nskb = skb_clone(fskb, GFP_ATOMIC); | ||
2468 | fskb = fskb->next; | ||
2469 | |||
2470 | if (unlikely(!nskb)) | ||
2471 | goto err; | ||
2472 | |||
2473 | hsize = skb_end_pointer(nskb) - nskb->head; | ||
2474 | if (skb_cow_head(nskb, doffset + headroom)) { | ||
2475 | kfree_skb(nskb); | ||
2476 | goto err; | ||
2477 | } | ||
2478 | |||
2479 | nskb->truesize += skb_end_pointer(nskb) - nskb->head - | ||
2480 | hsize; | ||
2481 | skb_release_head_state(nskb); | ||
2482 | __skb_push(nskb, doffset); | ||
2483 | } else { | ||
2484 | nskb = alloc_skb(hsize + doffset + headroom, | ||
2485 | GFP_ATOMIC); | ||
2486 | |||
2487 | if (unlikely(!nskb)) | ||
2488 | goto err; | ||
2489 | |||
2490 | skb_reserve(nskb, headroom); | ||
2491 | __skb_put(nskb, doffset); | ||
2492 | } | ||
2323 | 2493 | ||
2324 | if (segs) | 2494 | if (segs) |
2325 | tail->next = nskb; | 2495 | tail->next = nskb; |
@@ -2330,13 +2500,15 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
2330 | __copy_skb_header(nskb, skb); | 2500 | __copy_skb_header(nskb, skb); |
2331 | nskb->mac_len = skb->mac_len; | 2501 | nskb->mac_len = skb->mac_len; |
2332 | 2502 | ||
2333 | skb_reserve(nskb, headroom); | ||
2334 | skb_reset_mac_header(nskb); | 2503 | skb_reset_mac_header(nskb); |
2335 | skb_set_network_header(nskb, skb->mac_len); | 2504 | skb_set_network_header(nskb, skb->mac_len); |
2336 | nskb->transport_header = (nskb->network_header + | 2505 | nskb->transport_header = (nskb->network_header + |
2337 | skb_network_header_len(skb)); | 2506 | skb_network_header_len(skb)); |
2338 | skb_copy_from_linear_data(skb, skb_put(nskb, doffset), | 2507 | skb_copy_from_linear_data(skb, nskb->data, doffset); |
2339 | doffset); | 2508 | |
2509 | if (pos >= offset + len) | ||
2510 | continue; | ||
2511 | |||
2340 | if (!sg) { | 2512 | if (!sg) { |
2341 | nskb->ip_summed = CHECKSUM_NONE; | 2513 | nskb->ip_summed = CHECKSUM_NONE; |
2342 | nskb->csum = skb_copy_and_csum_bits(skb, offset, | 2514 | nskb->csum = skb_copy_and_csum_bits(skb, offset, |
@@ -2346,14 +2518,11 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
2346 | } | 2518 | } |
2347 | 2519 | ||
2348 | frag = skb_shinfo(nskb)->frags; | 2520 | frag = skb_shinfo(nskb)->frags; |
2349 | k = 0; | ||
2350 | 2521 | ||
2351 | skb_copy_from_linear_data_offset(skb, offset, | 2522 | skb_copy_from_linear_data_offset(skb, offset, |
2352 | skb_put(nskb, hsize), hsize); | 2523 | skb_put(nskb, hsize), hsize); |
2353 | 2524 | ||
2354 | while (pos < offset + len) { | 2525 | while (pos < offset + len && i < nfrags) { |
2355 | BUG_ON(i >= nfrags); | ||
2356 | |||
2357 | *frag = skb_shinfo(skb)->frags[i]; | 2526 | *frag = skb_shinfo(skb)->frags[i]; |
2358 | get_page(frag->page); | 2527 | get_page(frag->page); |
2359 | size = frag->size; | 2528 | size = frag->size; |
@@ -2363,20 +2532,39 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) | |||
2363 | frag->size -= offset - pos; | 2532 | frag->size -= offset - pos; |
2364 | } | 2533 | } |
2365 | 2534 | ||
2366 | k++; | 2535 | skb_shinfo(nskb)->nr_frags++; |
2367 | 2536 | ||
2368 | if (pos + size <= offset + len) { | 2537 | if (pos + size <= offset + len) { |
2369 | i++; | 2538 | i++; |
2370 | pos += size; | 2539 | pos += size; |
2371 | } else { | 2540 | } else { |
2372 | frag->size -= pos + size - (offset + len); | 2541 | frag->size -= pos + size - (offset + len); |
2373 | break; | 2542 | goto skip_fraglist; |
2374 | } | 2543 | } |
2375 | 2544 | ||
2376 | frag++; | 2545 | frag++; |
2377 | } | 2546 | } |
2378 | 2547 | ||
2379 | skb_shinfo(nskb)->nr_frags = k; | 2548 | if (pos < offset + len) { |
2549 | struct sk_buff *fskb2 = fskb; | ||
2550 | |||
2551 | BUG_ON(pos + fskb->len != offset + len); | ||
2552 | |||
2553 | pos += fskb->len; | ||
2554 | fskb = fskb->next; | ||
2555 | |||
2556 | if (fskb2->next) { | ||
2557 | fskb2 = skb_clone(fskb2, GFP_ATOMIC); | ||
2558 | if (!fskb2) | ||
2559 | goto err; | ||
2560 | } else | ||
2561 | skb_get(fskb2); | ||
2562 | |||
2563 | BUG_ON(skb_shinfo(nskb)->frag_list); | ||
2564 | skb_shinfo(nskb)->frag_list = fskb2; | ||
2565 | } | ||
2566 | |||
2567 | skip_fraglist: | ||
2380 | nskb->data_len = len - hsize; | 2568 | nskb->data_len = len - hsize; |
2381 | nskb->len += nskb->data_len; | 2569 | nskb->len += nskb->data_len; |
2382 | nskb->truesize += nskb->data_len; | 2570 | nskb->truesize += nskb->data_len; |
@@ -2394,6 +2582,65 @@ err: | |||
2394 | 2582 | ||
2395 | EXPORT_SYMBOL_GPL(skb_segment); | 2583 | EXPORT_SYMBOL_GPL(skb_segment); |
2396 | 2584 | ||
2585 | int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | ||
2586 | { | ||
2587 | struct sk_buff *p = *head; | ||
2588 | struct sk_buff *nskb; | ||
2589 | unsigned int headroom; | ||
2590 | unsigned int hlen = p->data - skb_mac_header(p); | ||
2591 | |||
2592 | if (hlen + p->len + skb->len >= 65536) | ||
2593 | return -E2BIG; | ||
2594 | |||
2595 | if (skb_shinfo(p)->frag_list) | ||
2596 | goto merge; | ||
2597 | |||
2598 | headroom = skb_headroom(p); | ||
2599 | nskb = netdev_alloc_skb(p->dev, headroom); | ||
2600 | if (unlikely(!nskb)) | ||
2601 | return -ENOMEM; | ||
2602 | |||
2603 | __copy_skb_header(nskb, p); | ||
2604 | nskb->mac_len = p->mac_len; | ||
2605 | |||
2606 | skb_reserve(nskb, headroom); | ||
2607 | |||
2608 | skb_set_mac_header(nskb, -hlen); | ||
2609 | skb_set_network_header(nskb, skb_network_offset(p)); | ||
2610 | skb_set_transport_header(nskb, skb_transport_offset(p)); | ||
2611 | |||
2612 | memcpy(skb_mac_header(nskb), skb_mac_header(p), hlen); | ||
2613 | |||
2614 | *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p); | ||
2615 | skb_shinfo(nskb)->frag_list = p; | ||
2616 | skb_header_release(p); | ||
2617 | nskb->prev = p; | ||
2618 | |||
2619 | nskb->data_len += p->len; | ||
2620 | nskb->truesize += p->len; | ||
2621 | nskb->len += p->len; | ||
2622 | |||
2623 | *head = nskb; | ||
2624 | nskb->next = p->next; | ||
2625 | p->next = NULL; | ||
2626 | |||
2627 | p = nskb; | ||
2628 | |||
2629 | merge: | ||
2630 | NAPI_GRO_CB(p)->count++; | ||
2631 | p->prev->next = skb; | ||
2632 | p->prev = skb; | ||
2633 | skb_header_release(skb); | ||
2634 | |||
2635 | p->data_len += skb->len; | ||
2636 | p->truesize += skb->len; | ||
2637 | p->len += skb->len; | ||
2638 | |||
2639 | NAPI_GRO_CB(skb)->same_flow = 1; | ||
2640 | return 0; | ||
2641 | } | ||
2642 | EXPORT_SYMBOL_GPL(skb_gro_receive); | ||
2643 | |||
2397 | void __init skb_init(void) | 2644 | void __init skb_init(void) |
2398 | { | 2645 | { |
2399 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", | 2646 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", |