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/version.h>
21 #include <linux/module.h>
23 #include <linux/if_tunnel.h>
24 #include <linux/if_vlan.h>
25 #include <linux/icmp.h>
28 #include <linux/ipv6.h>
29 #include <linux/kernel.h>
30 #include <linux/kmod.h>
31 #include <linux/netdevice.h>
32 #include <linux/skbuff.h>
33 #include <linux/spinlock.h>
38 #include <net/protocol.h>
39 #include <net/route.h>
44 #ifdef OVS_USE_COMPAT_GSO_SEGMENTATION
45 /* Strictly this is not needed and will be optimised out
46 * as this code is guarded by if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0).
47 * It is here to make things explicit should the compatibility
48 * code be extended in some way prior extending its life-span
51 static bool supports_mpls_gso(void)
53 /* MPLS GSO was introduced in v3.11, however it was not correctly
54 * activated using mpls_features until v3.19. */
55 #ifdef OVS_USE_COMPAT_GSO_SEGMENTATION
62 int rpl_dev_queue_xmit(struct sk_buff *skb)
70 /* Avoid traversing any VLAN tags that are present to determine if
71 * the ethtype is MPLS. Instead compare the mac_len (end of L2) and
72 * skb_network_offset() (beginning of L3) whose inequality will
73 * indicate the presence of an MPLS label stack. */
74 if (skb->mac_len != skb_network_offset(skb) && !supports_mpls_gso())
80 features = netif_skb_features(skb);
82 /* As of v3.11 the kernel provides an mpls_features field in
83 * struct net_device which allows devices to advertise which
84 * features its supports for MPLS. This value defaults to
85 * NETIF_F_SG and as of v3.19.
87 * This compatibility code is intended for kernels older
88 * than v3.19 that do not support MPLS GSO and do not
89 * use mpls_features. Thus this code uses NETIF_F_SG
90 * directly in place of mpls_features.
93 features &= NETIF_F_SG;
95 if (netif_needs_gso(skb, features)) {
98 nskb = skb_gso_segment(skb, features);
100 if (unlikely(skb_cloned(skb) &&
101 pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
104 skb_shinfo(skb)->gso_type &= ~SKB_GSO_DODGY;
118 err = dev_queue_xmit(skb);
126 return dev_queue_xmit(skb);
132 EXPORT_SYMBOL_GPL(rpl_dev_queue_xmit);
133 #endif /* OVS_USE_COMPAT_GSO_SEGMENTATION */
135 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
136 static __be16 __skb_network_protocol(struct sk_buff *skb)
138 __be16 type = skb->protocol;
139 int vlan_depth = ETH_HLEN;
141 while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
144 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
147 vh = (struct vlan_hdr *)(skb->data + vlan_depth);
148 type = vh->h_vlan_encapsulated_proto;
149 vlan_depth += VLAN_HLEN;
152 if (eth_p_mpls(type))
153 type = ovs_skb_get_inner_protocol(skb);
158 static struct sk_buff *tnl_skb_gso_segment(struct sk_buff *skb,
159 netdev_features_t features,
161 sa_family_t sa_family)
163 void *iph = skb_network_header(skb);
164 int pkt_hlen = skb_inner_network_offset(skb); /* inner l2 + tunnel hdr. */
165 int mac_offset = skb_inner_mac_offset(skb);
166 int outer_l3_offset = skb_network_offset(skb);
167 int outer_l4_offset = skb_transport_offset(skb);
168 struct sk_buff *skb1 = skb;
169 struct dst_entry *dst = skb_dst(skb);
170 struct sk_buff *segs;
171 __be16 proto = skb->protocol;
172 char cb[sizeof(skb->cb)];
174 OVS_GSO_CB(skb)->ipv6 = (sa_family == AF_INET6);
175 /* setup whole inner packet to get protocol. */
176 __skb_pull(skb, mac_offset);
177 skb->protocol = __skb_network_protocol(skb);
179 /* setup l3 packet to gso, to get around segmentation bug on older kernel.*/
180 __skb_pull(skb, (pkt_hlen - mac_offset));
181 skb_reset_mac_header(skb);
182 skb_reset_network_header(skb);
183 skb_reset_transport_header(skb);
185 /* From 3.9 kernel skb->cb is used by skb gso. Therefore
186 * make copy of it to restore it back. */
187 memcpy(cb, skb->cb, sizeof(cb));
189 skb->encapsulation = 0;
191 /* We are handling offloads by segmenting l3 packet, so
192 * no need to call OVS compat segmentation function. */
194 #ifdef HAVE___SKB_GSO_SEGMENT
195 #undef __skb_gso_segment
196 segs = __skb_gso_segment(skb, 0, tx_path);
198 #undef skb_gso_segment
199 segs = skb_gso_segment(skb, 0);
202 if (!segs || IS_ERR(segs))
207 __skb_push(skb, pkt_hlen);
208 skb_reset_mac_header(skb);
209 skb_set_network_header(skb, outer_l3_offset);
210 skb_set_transport_header(skb, outer_l4_offset);
213 memcpy(skb_network_header(skb), iph, pkt_hlen);
214 memcpy(skb->cb, cb, sizeof(cb));
216 skb->protocol = proto;
218 dst = dst_clone(dst);
220 skb_dst_set(skb, dst);
221 OVS_GSO_CB(skb)->fix_segment(skb);
230 static int output_ip(struct sk_buff *skb)
232 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
235 return ip_local_out(skb);
238 int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
240 if (!OVS_GSO_CB(skb)->fix_segment)
241 return output_ip(skb);
243 if (skb_is_gso(skb)) {
247 skb = tnl_skb_gso_segment(skb, 0, false, AF_INET);
248 if (!skb || IS_ERR(skb))
249 return NET_XMIT_DROP;
251 id = ntohs(ip_hdr(skb)->id);
253 struct sk_buff *next_skb = skb->next;
256 ip_hdr(skb)->id = htons(id++);
258 ret = output_ip(skb);
262 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
265 err = skb_checksum_help(skb);
267 return NET_XMIT_DROP;
270 return output_ip(skb);
272 EXPORT_SYMBOL_GPL(rpl_ip_local_out);
274 static int output_ipv6(struct sk_buff *skb)
276 memset(IP6CB(skb), 0, sizeof (*IP6CB(skb)));
278 return ip6_local_out(skb);
281 int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
284 if (!OVS_GSO_CB(skb)->fix_segment)
285 return output_ipv6(skb);
287 if (skb_is_gso(skb)) {
290 skb = tnl_skb_gso_segment(skb, 0, false, AF_INET6);
291 if (!skb || IS_ERR(skb))
292 return NET_XMIT_DROP;
295 struct sk_buff *next_skb = skb->next;
298 ret = output_ipv6(skb);
302 } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
305 err = skb_checksum_help(skb);
307 return NET_XMIT_DROP;
310 return output_ipv6(skb);
312 EXPORT_SYMBOL_GPL(rpl_ip6_local_out);