66cc6143a55e778305f283b4e723593860e233d8
[cascardo/ovs.git] / datapath / linux / compat / skbuff-openvswitch.c
1 #include <linux/module.h>
2 #include <linux/netdevice.h>
3 #include <linux/skbuff.h>
4
5 #if !defined(HAVE_SKB_WARN_LRO) && defined(NETIF_F_LRO)
6
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9 void __skb_warn_lro_forwarding(const struct sk_buff *skb)
10 {
11         if (net_ratelimit())
12                 pr_warn("%s: received packets cannot be forwarded while LRO is enabled\n",
13                         skb->dev->name);
14 }
15
16 #endif
17
18 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
19
20 static inline bool head_frag(const struct sk_buff *skb)
21 {
22 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
23         return skb->head_frag;
24 #else
25         return false;
26 #endif
27 }
28
29  /**
30  *      skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy()
31  *      @from: source buffer
32  *
33  *      Calculates the amount of linear headroom needed in the 'to' skb passed
34  *      into skb_zerocopy().
35  */
36 unsigned int
37 skb_zerocopy_headlen(const struct sk_buff *from)
38 {
39         unsigned int hlen = 0;
40
41         if (!head_frag(from) ||
42             skb_headlen(from) < L1_CACHE_BYTES ||
43             skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS)
44                 hlen = skb_headlen(from);
45
46         if (skb_has_frag_list(from))
47                 hlen = from->len;
48
49         return hlen;
50 }
51
52 #ifndef HAVE_SKB_ZEROCOPY
53 /**
54  *      skb_zerocopy - Zero copy skb to skb
55  *      @to: destination buffer
56  *      @source: source buffer
57  *      @len: number of bytes to copy from source buffer
58  *      @hlen: size of linear headroom in destination buffer
59  *
60  *      Copies up to `len` bytes from `from` to `to` by creating references
61  *      to the frags in the source buffer.
62  *
63  *      The `hlen` as calculated by skb_zerocopy_headlen() specifies the
64  *      headroom in the `to` buffer.
65  *
66  *      Return value:
67  *      0: everything is OK
68  *      -ENOMEM: couldn't orphan frags of @from due to lack of memory
69  *      -EFAULT: skb_copy_bits() found some problem with skb geometry
70  */
71 int
72 skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
73 {
74         int i, j = 0;
75         int plen = 0; /* length of skb->head fragment */
76         int ret;
77         struct page *page;
78         unsigned int offset;
79
80         BUG_ON(!head_frag(from) && !hlen);
81
82         /* dont bother with small payloads */
83         if (len <= skb_tailroom(to))
84                 return skb_copy_bits(from, 0, skb_put(to, len), len);
85
86         if (hlen) {
87                 ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
88                 if (unlikely(ret))
89                         return ret;
90                 len -= hlen;
91         } else {
92                 plen = min_t(int, skb_headlen(from), len);
93                 if (plen) {
94                         page = virt_to_head_page(from->head);
95                         offset = from->data - (unsigned char *)page_address(page);
96                         __skb_fill_page_desc(to, 0, page, offset, plen);
97                         get_page(page);
98                         j = 1;
99                         len -= plen;
100                 }
101         }
102
103         to->truesize += len + plen;
104         to->len += len + plen;
105         to->data_len += len + plen;
106
107         if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
108                 skb_tx_error(from);
109                 return -ENOMEM;
110         }
111
112         for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
113                 if (!len)
114                         break;
115                 skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i];
116                 skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len);
117                 len -= skb_shinfo(to)->frags[j].size;
118                 skb_frag_ref(to, j);
119                 j++;
120         }
121         skb_shinfo(to)->nr_frags = j;
122
123         return 0;
124 }
125 #endif
126 #endif
127
128 #ifndef HAVE_SKB_ENSURE_WRITABLE
129 int skb_ensure_writable(struct sk_buff *skb, int write_len)
130 {
131         if (!pskb_may_pull(skb, write_len))
132                 return -ENOMEM;
133
134         if (!skb_cloned(skb) || skb_clone_writable(skb, write_len))
135                 return 0;
136
137         return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
138 }
139 #endif