summaryrefslogtreecommitdiffstats
path: root/patches/ovs/0001-Add-Linux-4.4-support.patch
blob: a580bc267e0fffe64614a2ce11ef385398b03ad2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
From a4c2305b6190ce24ceaafb9f85fc5a67787fb71d Mon Sep 17 00:00:00 2001
From: Donald Dugger <n0ano@n0ano.com>
Date: Mon, 9 May 2016 05:14:12 +0000
Subject: [PATCH] Add Linux 4.4 support

A bit cleaner than my previous patch.
  http://patchwork.ozlabs.org/patch/595969/

Though I couldn't figure out a clean solution for ip6_local_out(),
genl_notify(), and vport-vxlan

Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>

Note that this patch has been rejected for the upstream OVS tree as
the maintainers feel a different apporach (backporting all Linux
patches that affect the OVS code).  We'll just use this patch until
the official OVS tree is updated to support Linux 4.4.

Upstream status: NA

Signed-off-by: Don Dugger <n0ano@n0ano.com>
---
 acinclude.m4                                         |  4 ++--
 datapath/actions.c                                   |  6 ++++--
 datapath/datapath.c                                  |  6 +++++-
 datapath/linux/compat/include/linux/netfilter_ipv6.h |  2 +-
 datapath/linux/compat/include/net/ip.h               | 19 ++++++++++++++++---
 datapath/linux/compat/include/net/ip6_tunnel.h       |  4 ++++
 datapath/linux/compat/include/net/vxlan.h            | 10 ++++++++++
 datapath/linux/compat/stt.c                          |  6 ++++++
 datapath/vport-vxlan.c                               |  5 +++++
 9 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index 23015fe..22e75ec 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
     AC_MSG_RESULT([$kversion])
 
     if test "$version" -ge 4; then
-       if test "$version" = 4 && test "$patchlevel" -le 3; then
+       if test "$version" = 4 && test "$patchlevel" -le 4; then
           : # Linux 4.x
        else
-          AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.3.x is not supported (please refer to the FAQ for advice)])
+          AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 4.4.x is not supported (please refer to the FAQ for advice)])
        fi
     elif test "$version" = 3 && test "$patchlevel" -ge 10; then
        : # Linux 3.x
diff --git a/datapath/actions.c b/datapath/actions.c
index dcf8591..242e710 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -702,7 +702,8 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
 		skb_dst_set_noref(skb, &ovs_dst);
 		IPCB(skb)->frag_max_size = mru;
 
-		ip_do_fragment(skb->sk, skb, ovs_vport_output);
+		ip_do_fragment(NET_ARG(dev_net(ovs_dst.dev))
+			skb->sk, skb, ovs_vport_output);
 		refdst_drop(orig_dst);
 	} else if (ethertype == htons(ETH_P_IPV6)) {
 		const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
@@ -723,7 +724,8 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
 		skb_dst_set_noref(skb, &ovs_rt.dst);
 		IP6CB(skb)->frag_max_size = mru;
 
-		v6ops->fragment(skb->sk, skb, ovs_vport_output);
+		v6ops->fragment(NET_ARG(dev_net(ovs_rt.dst.dev))
+			skb->sk, skb, ovs_vport_output);
 		refdst_drop(orig_dst);
 	} else {
 		WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 5bec072..ba19c01 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -95,8 +95,12 @@ static bool ovs_must_notify(struct genl_family *family, struct genl_info *info,
 static void ovs_notify(struct genl_family *family, struct genl_multicast_group *grp,
 		       struct sk_buff *skb, struct genl_info *info)
 {
-	genl_notify(family, skb, genl_info_net(info),
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+	genl_notify(family, skb, info, GROUP_ID(grp), GFP_KERNEL);
+#else
+	genl_notify(family, skb, genl_info_net(info),
 		    info->snd_portid, GROUP_ID(grp), info->nlhdr, GFP_KERNEL);
+#endif
 }
 
 /**
diff --git a/datapath/linux/compat/include/linux/netfilter_ipv6.h b/datapath/linux/compat/include/linux/netfilter_ipv6.h
index 8d896fb..9f64002 100644
--- a/datapath/linux/compat/include/linux/netfilter_ipv6.h
+++ b/datapath/linux/compat/include/linux/netfilter_ipv6.h
@@ -13,7 +13,7 @@
  * the callback parameter needs to be in the form that older kernels accept.
  * We don't backport the other ipv6_ops as they're currently unused by OVS. */
 struct ovs_nf_ipv6_ops {
-	int (*fragment)(struct sock *sk, struct sk_buff *skb,
+	int (*fragment)(NET_ARG(net) struct sock *sk, struct sk_buff *skb,
 			int (*output)(OVS_VPORT_OUTPUT_PARAMS));
 };
 #define nf_ipv6_ops ovs_nf_ipv6_ops
diff --git a/datapath/linux/compat/include/net/ip.h b/datapath/linux/compat/include/net/ip.h
index c283ad0..483662c 100644
--- a/datapath/linux/compat/include/net/ip.h
+++ b/datapath/linux/compat/include/net/ip.h
@@ -59,8 +59,20 @@ static inline unsigned int rpl_ip_skb_dst_mtu(const struct sk_buff *skb)
 #define ip_skb_dst_mtu rpl_ip_skb_dst_mtu
 #endif /* HAVE_IP_SKB_DST_MTU */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+#define NET_PARAM(x) struct net *x,
+#define NET_ARG(x) x,
+#define NET_DEV_NET(x) dev_net(x)
+#define NET_DECLARE_INIT(x,y)
+#else
+#define NET_PARAM(x)
+#define NET_ARG(x)
+#define NET_DEV_NET(x)
+#define NET_DECLARE_INIT(x,y) struct net *x = y;
+#endif
+
 #ifdef HAVE_IP_FRAGMENT_TAKES_SOCK
-#define OVS_VPORT_OUTPUT_PARAMS struct sock *sock, struct sk_buff *skb
+#define OVS_VPORT_OUTPUT_PARAMS NET_PARAM(net) struct sock *sock, struct sk_buff *skb
 #else
 #define OVS_VPORT_OUTPUT_PARAMS struct sk_buff *skb
 #endif
@@ -82,12 +94,13 @@ static inline bool ip_defrag_user_in_between(u32 user,
 #endif /* < v4.2 */
 
 #ifndef HAVE_IP_DO_FRAGMENT
-static inline int rpl_ip_do_fragment(struct sock *sk, struct sk_buff *skb,
+static inline int rpl_ip_do_fragment(NET_PARAM(net) struct sock *sk, struct sk_buff *skb,
 				     int (*output)(OVS_VPORT_OUTPUT_PARAMS))
 {
 	unsigned int mtu = ip_skb_dst_mtu(skb);
 	struct iphdr *iph = ip_hdr(skb);
 	struct rtable *rt = skb_rtable(skb);
+	NET_DECLARE_INIT(net, dev_net(dev));
 	struct net_device *dev = rt->dst.dev;
 
 	if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) ||
@@ -95,7 +108,7 @@ static inline int rpl_ip_do_fragment(struct sock *sk, struct sk_buff *skb,
 		      IPCB(skb)->frag_max_size > mtu))) {
 
 		pr_warn("Dropping packet in ip_do_fragment()\n");
-		IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+		IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS);
 		kfree_skb(skb);
 		return -EMSGSIZE;
 	}
diff --git a/datapath/linux/compat/include/net/ip6_tunnel.h b/datapath/linux/compat/include/net/ip6_tunnel.h
index ce65087..eacf9ca 100644
--- a/datapath/linux/compat/include/net/ip6_tunnel.h
+++ b/datapath/linux/compat/include/net/ip6_tunnel.h
@@ -17,11 +17,15 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
 
 	pkt_len = skb->len - skb_inner_network_offset(skb);
 	/* TODO: Fix GSO for ipv6 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+	err = ip6_local_out(dev_net(dev), sk, skb);
+#else
 #ifdef HAVE_IP6_LOCAL_OUT_SK
 	err = ip6_local_out_sk(sk, skb);
 #else
 	err = ip6_local_out(skb);
 #endif
+#endif /* >= kernel 4.4 */
 	if (net_xmit_eval(err) != 0)
 		pkt_len = net_xmit_eval(err);
 	else
diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
index 75a5a7a..589cc0d 100644
--- a/datapath/linux/compat/include/net/vxlan.h
+++ b/datapath/linux/compat/include/net/vxlan.h
@@ -218,10 +218,20 @@ struct vxlan_dev {
 struct net_device *rpl_vxlan_dev_create(struct net *net, const char *name,
 				    u8 name_assign_type, struct vxlan_config *conf);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan,
+					unsigned short family)
+{
+	if (family == AF_INET6)
+		return inet_sk(vxlan->vn6_sock->sock->sk)->inet_sport;
+	return inet_sk(vxlan->vn4_sock->sock->sk)->inet_sport;
+}
+#else
 static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan)
 {
 	return inet_sk(vxlan->vn_sock->sock->sk)->inet_sport;
 }
+#endif
 
 static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
 						     netdev_features_t features)
diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c
index 86d225e..6b1e3a3 100644
--- a/datapath/linux/compat/stt.c
+++ b/datapath/linux/compat/stt.c
@@ -1544,7 +1544,11 @@ static void clean_percpu(struct work_struct *work)
 }
 
 #ifdef HAVE_NF_HOOKFN_ARG_OPS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+#define FIRST_PARAM void *priv
+#else
 #define FIRST_PARAM const struct nf_hook_ops *ops
+#endif /* >= kernel 4.4 */
 #else
 #define FIRST_PARAM unsigned int hooknum
 #endif
@@ -1592,7 +1596,9 @@ static unsigned int nf_ip_hook(FIRST_PARAM, struct sk_buff *skb, LAST_PARAM)
 
 static struct nf_hook_ops nf_hook_ops __read_mostly = {
 	.hook           = nf_ip_hook,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
 	.owner          = THIS_MODULE,
+#endif
 	.pf             = NFPROTO_IPV4,
 	.hooknum        = NF_INET_LOCAL_IN,
 	.priority       = INT_MAX,
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
index c05f5d4..3cbb568 100644
--- a/datapath/vport-vxlan.c
+++ b/datapath/vport-vxlan.c
@@ -153,7 +153,12 @@ static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
 {
 	struct vxlan_dev *vxlan = netdev_priv(vport->dev);
 	struct net *net = ovs_dp_get_net(vport->dp);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
+	unsigned short family = ip_tunnel_info_af(upcall->egress_tun_info);
+	__be16 dst_port = vxlan_dev_dst_port(vxlan, family);
+#else
 	__be16 dst_port = vxlan_dev_dst_port(vxlan);
+#endif
 	__be16 src_port;
 	int port_min;
 	int port_max;
-- 
1.9.1