diff options
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r-- | net/core/skbuff.c | 131 |
1 files changed, 75 insertions, 56 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5976ef0846bd..90b96a11b974 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -707,9 +707,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
707 | new->mark = old->mark; | 707 | new->mark = old->mark; |
708 | new->skb_iif = old->skb_iif; | 708 | new->skb_iif = old->skb_iif; |
709 | __nf_copy(new, old); | 709 | __nf_copy(new, old); |
710 | #if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) | ||
711 | new->nf_trace = old->nf_trace; | ||
712 | #endif | ||
713 | #ifdef CONFIG_NET_SCHED | 710 | #ifdef CONFIG_NET_SCHED |
714 | new->tc_index = old->tc_index; | 711 | new->tc_index = old->tc_index; |
715 | #ifdef CONFIG_NET_CLS_ACT | 712 | #ifdef CONFIG_NET_CLS_ACT |
@@ -2130,25 +2127,31 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen); | |||
2130 | * | 2127 | * |
2131 | * The `hlen` as calculated by skb_zerocopy_headlen() specifies the | 2128 | * The `hlen` as calculated by skb_zerocopy_headlen() specifies the |
2132 | * headroom in the `to` buffer. | 2129 | * headroom in the `to` buffer. |
2130 | * | ||
2131 | * Return value: | ||
2132 | * 0: everything is OK | ||
2133 | * -ENOMEM: couldn't orphan frags of @from due to lack of memory | ||
2134 | * -EFAULT: skb_copy_bits() found some problem with skb geometry | ||
2133 | */ | 2135 | */ |
2134 | void | 2136 | int |
2135 | skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | 2137 | skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen) |
2136 | { | 2138 | { |
2137 | int i, j = 0; | 2139 | int i, j = 0; |
2138 | int plen = 0; /* length of skb->head fragment */ | 2140 | int plen = 0; /* length of skb->head fragment */ |
2141 | int ret; | ||
2139 | struct page *page; | 2142 | struct page *page; |
2140 | unsigned int offset; | 2143 | unsigned int offset; |
2141 | 2144 | ||
2142 | BUG_ON(!from->head_frag && !hlen); | 2145 | BUG_ON(!from->head_frag && !hlen); |
2143 | 2146 | ||
2144 | /* dont bother with small payloads */ | 2147 | /* dont bother with small payloads */ |
2145 | if (len <= skb_tailroom(to)) { | 2148 | if (len <= skb_tailroom(to)) |
2146 | skb_copy_bits(from, 0, skb_put(to, len), len); | 2149 | return skb_copy_bits(from, 0, skb_put(to, len), len); |
2147 | return; | ||
2148 | } | ||
2149 | 2150 | ||
2150 | if (hlen) { | 2151 | if (hlen) { |
2151 | skb_copy_bits(from, 0, skb_put(to, hlen), hlen); | 2152 | ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen); |
2153 | if (unlikely(ret)) | ||
2154 | return ret; | ||
2152 | len -= hlen; | 2155 | len -= hlen; |
2153 | } else { | 2156 | } else { |
2154 | plen = min_t(int, skb_headlen(from), len); | 2157 | plen = min_t(int, skb_headlen(from), len); |
@@ -2166,6 +2169,11 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
2166 | to->len += len + plen; | 2169 | to->len += len + plen; |
2167 | to->data_len += len + plen; | 2170 | to->data_len += len + plen; |
2168 | 2171 | ||
2172 | if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) { | ||
2173 | skb_tx_error(from); | ||
2174 | return -ENOMEM; | ||
2175 | } | ||
2176 | |||
2169 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { | 2177 | for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { |
2170 | if (!len) | 2178 | if (!len) |
2171 | break; | 2179 | break; |
@@ -2176,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) | |||
2176 | j++; | 2184 | j++; |
2177 | } | 2185 | } |
2178 | skb_shinfo(to)->nr_frags = j; | 2186 | skb_shinfo(to)->nr_frags = j; |
2187 | |||
2188 | return 0; | ||
2179 | } | 2189 | } |
2180 | EXPORT_SYMBOL_GPL(skb_zerocopy); | 2190 | EXPORT_SYMBOL_GPL(skb_zerocopy); |
2181 | 2191 | ||
@@ -2841,81 +2851,85 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); | |||
2841 | 2851 | ||
2842 | /** | 2852 | /** |
2843 | * skb_segment - Perform protocol segmentation on skb. | 2853 | * skb_segment - Perform protocol segmentation on skb. |
2844 | * @skb: buffer to segment | 2854 | * @head_skb: buffer to segment |
2845 | * @features: features for the output path (see dev->features) | 2855 | * @features: features for the output path (see dev->features) |
2846 | * | 2856 | * |
2847 | * This function performs segmentation on the given skb. It returns | 2857 | * This function performs segmentation on the given skb. It returns |
2848 | * a pointer to the first in a list of new skbs for the segments. | 2858 | * a pointer to the first in a list of new skbs for the segments. |
2849 | * In case of error it returns ERR_PTR(err). | 2859 | * In case of error it returns ERR_PTR(err). |
2850 | */ | 2860 | */ |
2851 | struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | 2861 | struct sk_buff *skb_segment(struct sk_buff *head_skb, |
2862 | netdev_features_t features) | ||
2852 | { | 2863 | { |
2853 | struct sk_buff *segs = NULL; | 2864 | struct sk_buff *segs = NULL; |
2854 | struct sk_buff *tail = NULL; | 2865 | struct sk_buff *tail = NULL; |
2855 | struct sk_buff *fskb = skb_shinfo(skb)->frag_list; | 2866 | struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; |
2856 | skb_frag_t *skb_frag = skb_shinfo(skb)->frags; | 2867 | skb_frag_t *frag = skb_shinfo(head_skb)->frags; |
2857 | unsigned int mss = skb_shinfo(skb)->gso_size; | 2868 | unsigned int mss = skb_shinfo(head_skb)->gso_size; |
2858 | unsigned int doffset = skb->data - skb_mac_header(skb); | 2869 | unsigned int doffset = head_skb->data - skb_mac_header(head_skb); |
2870 | struct sk_buff *frag_skb = head_skb; | ||
2859 | unsigned int offset = doffset; | 2871 | unsigned int offset = doffset; |
2860 | unsigned int tnl_hlen = skb_tnl_header_len(skb); | 2872 | unsigned int tnl_hlen = skb_tnl_header_len(head_skb); |
2861 | unsigned int headroom; | 2873 | unsigned int headroom; |
2862 | unsigned int len; | 2874 | unsigned int len; |
2863 | __be16 proto; | 2875 | __be16 proto; |
2864 | bool csum; | 2876 | bool csum; |
2865 | int sg = !!(features & NETIF_F_SG); | 2877 | int sg = !!(features & NETIF_F_SG); |
2866 | int nfrags = skb_shinfo(skb)->nr_frags; | 2878 | int nfrags = skb_shinfo(head_skb)->nr_frags; |
2867 | int err = -ENOMEM; | 2879 | int err = -ENOMEM; |
2868 | int i = 0; | 2880 | int i = 0; |
2869 | int pos; | 2881 | int pos; |
2882 | int dummy; | ||
2870 | 2883 | ||
2871 | proto = skb_network_protocol(skb); | 2884 | proto = skb_network_protocol(head_skb, &dummy); |
2872 | if (unlikely(!proto)) | 2885 | if (unlikely(!proto)) |
2873 | return ERR_PTR(-EINVAL); | 2886 | return ERR_PTR(-EINVAL); |
2874 | 2887 | ||
2875 | csum = !!can_checksum_protocol(features, proto); | 2888 | csum = !!can_checksum_protocol(features, proto); |
2876 | __skb_push(skb, doffset); | 2889 | __skb_push(head_skb, doffset); |
2877 | headroom = skb_headroom(skb); | 2890 | headroom = skb_headroom(head_skb); |
2878 | pos = skb_headlen(skb); | 2891 | pos = skb_headlen(head_skb); |
2879 | 2892 | ||
2880 | do { | 2893 | do { |
2881 | struct sk_buff *nskb; | 2894 | struct sk_buff *nskb; |
2882 | skb_frag_t *frag; | 2895 | skb_frag_t *nskb_frag; |
2883 | int hsize; | 2896 | int hsize; |
2884 | int size; | 2897 | int size; |
2885 | 2898 | ||
2886 | len = skb->len - offset; | 2899 | len = head_skb->len - offset; |
2887 | if (len > mss) | 2900 | if (len > mss) |
2888 | len = mss; | 2901 | len = mss; |
2889 | 2902 | ||
2890 | hsize = skb_headlen(skb) - offset; | 2903 | hsize = skb_headlen(head_skb) - offset; |
2891 | if (hsize < 0) | 2904 | if (hsize < 0) |
2892 | hsize = 0; | 2905 | hsize = 0; |
2893 | if (hsize > len || !sg) | 2906 | if (hsize > len || !sg) |
2894 | hsize = len; | 2907 | hsize = len; |
2895 | 2908 | ||
2896 | if (!hsize && i >= nfrags && skb_headlen(fskb) && | 2909 | if (!hsize && i >= nfrags && skb_headlen(list_skb) && |
2897 | (skb_headlen(fskb) == len || sg)) { | 2910 | (skb_headlen(list_skb) == len || sg)) { |
2898 | BUG_ON(skb_headlen(fskb) > len); | 2911 | BUG_ON(skb_headlen(list_skb) > len); |
2899 | 2912 | ||
2900 | i = 0; | 2913 | i = 0; |
2901 | nfrags = skb_shinfo(fskb)->nr_frags; | 2914 | nfrags = skb_shinfo(list_skb)->nr_frags; |
2902 | skb_frag = skb_shinfo(fskb)->frags; | 2915 | frag = skb_shinfo(list_skb)->frags; |
2903 | pos += skb_headlen(fskb); | 2916 | frag_skb = list_skb; |
2917 | pos += skb_headlen(list_skb); | ||
2904 | 2918 | ||
2905 | while (pos < offset + len) { | 2919 | while (pos < offset + len) { |
2906 | BUG_ON(i >= nfrags); | 2920 | BUG_ON(i >= nfrags); |
2907 | 2921 | ||
2908 | size = skb_frag_size(skb_frag); | 2922 | size = skb_frag_size(frag); |
2909 | if (pos + size > offset + len) | 2923 | if (pos + size > offset + len) |
2910 | break; | 2924 | break; |
2911 | 2925 | ||
2912 | i++; | 2926 | i++; |
2913 | pos += size; | 2927 | pos += size; |
2914 | skb_frag++; | 2928 | frag++; |
2915 | } | 2929 | } |
2916 | 2930 | ||
2917 | nskb = skb_clone(fskb, GFP_ATOMIC); | 2931 | nskb = skb_clone(list_skb, GFP_ATOMIC); |
2918 | fskb = fskb->next; | 2932 | list_skb = list_skb->next; |
2919 | 2933 | ||
2920 | if (unlikely(!nskb)) | 2934 | if (unlikely(!nskb)) |
2921 | goto err; | 2935 | goto err; |
@@ -2936,7 +2950,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2936 | __skb_push(nskb, doffset); | 2950 | __skb_push(nskb, doffset); |
2937 | } else { | 2951 | } else { |
2938 | nskb = __alloc_skb(hsize + doffset + headroom, | 2952 | nskb = __alloc_skb(hsize + doffset + headroom, |
2939 | GFP_ATOMIC, skb_alloc_rx_flag(skb), | 2953 | GFP_ATOMIC, skb_alloc_rx_flag(head_skb), |
2940 | NUMA_NO_NODE); | 2954 | NUMA_NO_NODE); |
2941 | 2955 | ||
2942 | if (unlikely(!nskb)) | 2956 | if (unlikely(!nskb)) |
@@ -2952,12 +2966,12 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2952 | segs = nskb; | 2966 | segs = nskb; |
2953 | tail = nskb; | 2967 | tail = nskb; |
2954 | 2968 | ||
2955 | __copy_skb_header(nskb, skb); | 2969 | __copy_skb_header(nskb, head_skb); |
2956 | nskb->mac_len = skb->mac_len; | 2970 | nskb->mac_len = head_skb->mac_len; |
2957 | 2971 | ||
2958 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); | 2972 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); |
2959 | 2973 | ||
2960 | skb_copy_from_linear_data_offset(skb, -tnl_hlen, | 2974 | skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, |
2961 | nskb->data - tnl_hlen, | 2975 | nskb->data - tnl_hlen, |
2962 | doffset + tnl_hlen); | 2976 | doffset + tnl_hlen); |
2963 | 2977 | ||
@@ -2966,30 +2980,32 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2966 | 2980 | ||
2967 | if (!sg) { | 2981 | if (!sg) { |
2968 | nskb->ip_summed = CHECKSUM_NONE; | 2982 | nskb->ip_summed = CHECKSUM_NONE; |
2969 | nskb->csum = skb_copy_and_csum_bits(skb, offset, | 2983 | nskb->csum = skb_copy_and_csum_bits(head_skb, offset, |
2970 | skb_put(nskb, len), | 2984 | skb_put(nskb, len), |
2971 | len, 0); | 2985 | len, 0); |
2972 | continue; | 2986 | continue; |
2973 | } | 2987 | } |
2974 | 2988 | ||
2975 | frag = skb_shinfo(nskb)->frags; | 2989 | nskb_frag = skb_shinfo(nskb)->frags; |
2976 | 2990 | ||
2977 | skb_copy_from_linear_data_offset(skb, offset, | 2991 | skb_copy_from_linear_data_offset(head_skb, offset, |
2978 | skb_put(nskb, hsize), hsize); | 2992 | skb_put(nskb, hsize), hsize); |
2979 | 2993 | ||
2980 | skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; | 2994 | skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags & |
2995 | SKBTX_SHARED_FRAG; | ||
2981 | 2996 | ||
2982 | while (pos < offset + len) { | 2997 | while (pos < offset + len) { |
2983 | if (i >= nfrags) { | 2998 | if (i >= nfrags) { |
2984 | BUG_ON(skb_headlen(fskb)); | 2999 | BUG_ON(skb_headlen(list_skb)); |
2985 | 3000 | ||
2986 | i = 0; | 3001 | i = 0; |
2987 | nfrags = skb_shinfo(fskb)->nr_frags; | 3002 | nfrags = skb_shinfo(list_skb)->nr_frags; |
2988 | skb_frag = skb_shinfo(fskb)->frags; | 3003 | frag = skb_shinfo(list_skb)->frags; |
3004 | frag_skb = list_skb; | ||
2989 | 3005 | ||
2990 | BUG_ON(!nfrags); | 3006 | BUG_ON(!nfrags); |
2991 | 3007 | ||
2992 | fskb = fskb->next; | 3008 | list_skb = list_skb->next; |
2993 | } | 3009 | } |
2994 | 3010 | ||
2995 | if (unlikely(skb_shinfo(nskb)->nr_frags >= | 3011 | if (unlikely(skb_shinfo(nskb)->nr_frags >= |
@@ -3000,27 +3016,30 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
3000 | goto err; | 3016 | goto err; |
3001 | } | 3017 | } |
3002 | 3018 | ||
3003 | *frag = *skb_frag; | 3019 | if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC))) |
3004 | __skb_frag_ref(frag); | 3020 | goto err; |
3005 | size = skb_frag_size(frag); | 3021 | |
3022 | *nskb_frag = *frag; | ||
3023 | __skb_frag_ref(nskb_frag); | ||
3024 | size = skb_frag_size(nskb_frag); | ||
3006 | 3025 | ||
3007 | if (pos < offset) { | 3026 | if (pos < offset) { |
3008 | frag->page_offset += offset - pos; | 3027 | nskb_frag->page_offset += offset - pos; |
3009 | skb_frag_size_sub(frag, offset - pos); | 3028 | skb_frag_size_sub(nskb_frag, offset - pos); |
3010 | } | 3029 | } |
3011 | 3030 | ||
3012 | skb_shinfo(nskb)->nr_frags++; | 3031 | skb_shinfo(nskb)->nr_frags++; |
3013 | 3032 | ||
3014 | if (pos + size <= offset + len) { | 3033 | if (pos + size <= offset + len) { |
3015 | i++; | 3034 | i++; |
3016 | skb_frag++; | 3035 | frag++; |
3017 | pos += size; | 3036 | pos += size; |
3018 | } else { | 3037 | } else { |
3019 | skb_frag_size_sub(frag, pos + size - (offset + len)); | 3038 | skb_frag_size_sub(nskb_frag, pos + size - (offset + len)); |
3020 | goto skip_fraglist; | 3039 | goto skip_fraglist; |
3021 | } | 3040 | } |
3022 | 3041 | ||
3023 | frag++; | 3042 | nskb_frag++; |
3024 | } | 3043 | } |
3025 | 3044 | ||
3026 | skip_fraglist: | 3045 | skip_fraglist: |
@@ -3034,7 +3053,7 @@ perform_csum_check: | |||
3034 | nskb->len - doffset, 0); | 3053 | nskb->len - doffset, 0); |
3035 | nskb->ip_summed = CHECKSUM_NONE; | 3054 | nskb->ip_summed = CHECKSUM_NONE; |
3036 | } | 3055 | } |
3037 | } while ((offset += len) < skb->len); | 3056 | } while ((offset += len) < head_skb->len); |
3038 | 3057 | ||
3039 | return segs; | 3058 | return segs; |
3040 | 3059 | ||