2 * Copyright (c) 2007-2013 Nicira, Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 #include <linux/module.h>
21 #include <linux/if_tunnel.h>
22 #include <linux/icmp.h>
25 #include <linux/kernel.h>
26 #include <linux/kmod.h>
27 #include <linux/netdevice.h>
28 #include <linux/skbuff.h>
29 #include <linux/spinlock.h>
33 #include <net/protocol.h>
34 #include <net/route.h>
39 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) && \
40 !defined(HAVE_VLAN_BUG_WORKAROUND)
41 #include <linux/module.h>
43 static int vlan_tso __read_mostly
;
44 module_param(vlan_tso
, int, 0644);
45 MODULE_PARM_DESC(vlan_tso
, "Enable TSO for VLAN packets");
50 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
51 static bool dev_supports_vlan_tx(struct net_device
*dev
)
53 #if defined(HAVE_VLAN_BUG_WORKAROUND)
54 return dev
->features
& NETIF_F_HW_VLAN_TX
;
56 /* Assume that the driver is buggy. */
61 int rpl_dev_queue_xmit(struct sk_buff
*skb
)
66 if (vlan_tx_tag_present(skb
) && !dev_supports_vlan_tx(skb
->dev
)) {
69 features
= netif_skb_features(skb
);
72 features
&= ~(NETIF_F_TSO
| NETIF_F_TSO6
|
73 NETIF_F_UFO
| NETIF_F_FSO
);
75 skb
= __vlan_put_tag(skb
, skb
->vlan_proto
, vlan_tx_tag_get(skb
));
80 if (netif_needs_gso(skb
, features
)) {
83 nskb
= skb_gso_segment(skb
, features
);
85 if (unlikely(skb_cloned(skb
) &&
86 pskb_expand_head(skb
, 0, 0, GFP_ATOMIC
)))
89 skb_shinfo(skb
)->gso_type
&= ~SKB_GSO_DODGY
;
103 err
= dev_queue_xmit(skb
);
111 return dev_queue_xmit(skb
);
117 #endif /* kernel version < 2.6.37 */
119 static __be16
__skb_network_protocol(struct sk_buff
*skb
)
121 __be16 type
= skb
->protocol
;
122 int vlan_depth
= ETH_HLEN
;
124 while (type
== htons(ETH_P_8021Q
) || type
== htons(ETH_P_8021AD
)) {
127 if (unlikely(!pskb_may_pull(skb
, vlan_depth
+ VLAN_HLEN
)))
130 vh
= (struct vlan_hdr
*)(skb
->data
+ vlan_depth
);
131 type
= vh
->h_vlan_encapsulated_proto
;
132 vlan_depth
+= VLAN_HLEN
;
138 static struct sk_buff
*tnl_skb_gso_segment(struct sk_buff
*skb
,
139 netdev_features_t features
,
142 struct iphdr
*iph
= ip_hdr(skb
);
143 int pkt_hlen
= skb_inner_network_offset(skb
); /* inner l2 + tunnel hdr. */
144 int mac_offset
= skb_inner_mac_offset(skb
);
145 struct sk_buff
*skb1
= skb
;
146 struct sk_buff
*segs
;
147 __be16 proto
= skb
->protocol
;
148 char cb
[sizeof(skb
->cb
)];
150 /* setup whole inner packet to get protocol. */
151 __skb_pull(skb
, mac_offset
);
152 skb
->protocol
= __skb_network_protocol(skb
);
154 /* setup l3 packet to gso, to get around segmentation bug on older kernel.*/
155 __skb_pull(skb
, (pkt_hlen
- mac_offset
));
156 skb_reset_mac_header(skb
);
157 skb_reset_network_header(skb
);
158 skb_reset_transport_header(skb
);
160 /* From 3.9 kernel skb->cb is used by skb gso. Therefore
161 * make copy of it to restore it back. */
162 memcpy(cb
, skb
->cb
, sizeof(cb
));
164 segs
= __skb_gso_segment(skb
, 0, tx_path
);
165 if (!segs
|| IS_ERR(segs
))
170 __skb_push(skb
, pkt_hlen
);
171 skb_reset_mac_header(skb
);
172 skb_reset_network_header(skb
);
173 skb_set_transport_header(skb
, sizeof(struct iphdr
));
176 memcpy(ip_hdr(skb
), iph
, pkt_hlen
);
177 memcpy(skb
->cb
, cb
, sizeof(cb
));
178 if (OVS_GSO_CB(skb
)->fix_segment
)
179 OVS_GSO_CB(skb
)->fix_segment(skb
);
181 skb
->protocol
= proto
;
189 int rpl_ip_local_out(struct sk_buff
*skb
)
191 int ret
= NETDEV_TX_OK
;
194 if (skb_is_gso(skb
)) {
199 skb
= tnl_skb_gso_segment(skb
, 0, false);
200 if (!skb
|| IS_ERR(skb
))
202 } else if (skb
->ip_summed
== CHECKSUM_PARTIAL
) {
205 err
= skb_checksum_help(skb
);
211 struct sk_buff
*next_skb
= skb
->next
;
219 iph
->id
= htons(id
++);
221 memset(IPCB(skb
), 0, sizeof(*IPCB(skb
)));
224 err
= ip_local_out(skb
);
225 if (unlikely(net_xmit_eval(err
)))