aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/skbuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r--net/core/skbuff.c131
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 */
2134void 2136int
2135skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) 2137skb_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}
2180EXPORT_SYMBOL_GPL(skb_zerocopy); 2190EXPORT_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 */
2851struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) 2861struct 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
3026skip_fraglist: 3045skip_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