1 From a4c2305b6190ce24ceaafb9f85fc5a67787fb71d Mon Sep 17 00:00:00 2001
2 From: Donald Dugger <n0ano@n0ano.com>
3 Date: Mon, 9 May 2016 05:14:12 +0000
4 Subject: [PATCH] Add Linux 4.4 support
6 A bit cleaner than my previous patch.
7 http://patchwork.ozlabs.org/patch/595969/
9 Though I couldn't figure out a clean solution for ip6_local_out(),
10 genl_notify(), and vport-vxlan
12 Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
14 Note that this patch has been rejected for the upstream OVS tree as
15 the maintainers feel a different apporach (backporting all Linux
16 patches that affect the OVS code). We'll just use this patch until
17 the official OVS tree is updated to support Linux 4.4.
21 Signed-off-by: Don Dugger <n0ano@n0ano.com>
24 datapath/actions.c | 6 ++++--
25 datapath/datapath.c | 6 +++++-
26 datapath/linux/compat/include/linux/netfilter_ipv6.h | 2 +-
27 datapath/linux/compat/include/net/ip.h | 19 ++++++++++++++++---
28 datapath/linux/compat/include/net/ip6_tunnel.h | 4 ++++
29 datapath/linux/compat/include/net/vxlan.h | 10 ++++++++++
30 datapath/linux/compat/stt.c | 6 ++++++
31 datapath/vport-vxlan.c | 5 +++++
32 9 files changed, 53 insertions(+), 9 deletions(-)
34 diff --git a/acinclude.m4 b/acinclude.m4
35 index 23015fe..22e75ec 100644
38 @@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
39 AC_MSG_RESULT([$kversion])
41 if test "$version" -ge 4; then
42 - if test "$version" = 4 && test "$patchlevel" -le 3; then
43 + if test "$version" = 4 && test "$patchlevel" -le 4; then
46 - 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)])
47 + 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)])
49 elif test "$version" = 3 && test "$patchlevel" -ge 10; then
51 diff --git a/datapath/actions.c b/datapath/actions.c
52 index dcf8591..242e710 100644
53 --- a/datapath/actions.c
54 +++ b/datapath/actions.c
55 @@ -702,7 +702,8 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
56 skb_dst_set_noref(skb, &ovs_dst);
57 IPCB(skb)->frag_max_size = mru;
59 - ip_do_fragment(skb->sk, skb, ovs_vport_output);
60 + ip_do_fragment(NET_ARG(dev_net(ovs_dst.dev))
61 + skb->sk, skb, ovs_vport_output);
62 refdst_drop(orig_dst);
63 } else if (ethertype == htons(ETH_P_IPV6)) {
64 const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
65 @@ -723,7 +724,8 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
66 skb_dst_set_noref(skb, &ovs_rt.dst);
67 IP6CB(skb)->frag_max_size = mru;
69 - v6ops->fragment(skb->sk, skb, ovs_vport_output);
70 + v6ops->fragment(NET_ARG(dev_net(ovs_rt.dst.dev))
71 + skb->sk, skb, ovs_vport_output);
72 refdst_drop(orig_dst);
74 WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
75 diff --git a/datapath/datapath.c b/datapath/datapath.c
76 index 5bec072..ba19c01 100644
77 --- a/datapath/datapath.c
78 +++ b/datapath/datapath.c
79 @@ -95,8 +95,12 @@ static bool ovs_must_notify(struct genl_family *family, struct genl_info *info,
80 static void ovs_notify(struct genl_family *family, struct genl_multicast_group *grp,
81 struct sk_buff *skb, struct genl_info *info)
83 - genl_notify(family, skb, genl_info_net(info),
84 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
85 + genl_notify(family, skb, info, GROUP_ID(grp), GFP_KERNEL);
87 + genl_notify(family, skb, genl_info_net(info),
88 info->snd_portid, GROUP_ID(grp), info->nlhdr, GFP_KERNEL);
93 diff --git a/datapath/linux/compat/include/linux/netfilter_ipv6.h b/datapath/linux/compat/include/linux/netfilter_ipv6.h
94 index 8d896fb..9f64002 100644
95 --- a/datapath/linux/compat/include/linux/netfilter_ipv6.h
96 +++ b/datapath/linux/compat/include/linux/netfilter_ipv6.h
98 * the callback parameter needs to be in the form that older kernels accept.
99 * We don't backport the other ipv6_ops as they're currently unused by OVS. */
100 struct ovs_nf_ipv6_ops {
101 - int (*fragment)(struct sock *sk, struct sk_buff *skb,
102 + int (*fragment)(NET_ARG(net) struct sock *sk, struct sk_buff *skb,
103 int (*output)(OVS_VPORT_OUTPUT_PARAMS));
105 #define nf_ipv6_ops ovs_nf_ipv6_ops
106 diff --git a/datapath/linux/compat/include/net/ip.h b/datapath/linux/compat/include/net/ip.h
107 index c283ad0..483662c 100644
108 --- a/datapath/linux/compat/include/net/ip.h
109 +++ b/datapath/linux/compat/include/net/ip.h
110 @@ -59,8 +59,20 @@ static inline unsigned int rpl_ip_skb_dst_mtu(const struct sk_buff *skb)
111 #define ip_skb_dst_mtu rpl_ip_skb_dst_mtu
112 #endif /* HAVE_IP_SKB_DST_MTU */
114 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
115 +#define NET_PARAM(x) struct net *x,
116 +#define NET_ARG(x) x,
117 +#define NET_DEV_NET(x) dev_net(x)
118 +#define NET_DECLARE_INIT(x,y)
120 +#define NET_PARAM(x)
122 +#define NET_DEV_NET(x)
123 +#define NET_DECLARE_INIT(x,y) struct net *x = y;
126 #ifdef HAVE_IP_FRAGMENT_TAKES_SOCK
127 -#define OVS_VPORT_OUTPUT_PARAMS struct sock *sock, struct sk_buff *skb
128 +#define OVS_VPORT_OUTPUT_PARAMS NET_PARAM(net) struct sock *sock, struct sk_buff *skb
130 #define OVS_VPORT_OUTPUT_PARAMS struct sk_buff *skb
132 @@ -82,12 +94,13 @@ static inline bool ip_defrag_user_in_between(u32 user,
135 #ifndef HAVE_IP_DO_FRAGMENT
136 -static inline int rpl_ip_do_fragment(struct sock *sk, struct sk_buff *skb,
137 +static inline int rpl_ip_do_fragment(NET_PARAM(net) struct sock *sk, struct sk_buff *skb,
138 int (*output)(OVS_VPORT_OUTPUT_PARAMS))
140 unsigned int mtu = ip_skb_dst_mtu(skb);
141 struct iphdr *iph = ip_hdr(skb);
142 struct rtable *rt = skb_rtable(skb);
143 + NET_DECLARE_INIT(net, dev_net(dev));
144 struct net_device *dev = rt->dst.dev;
146 if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) ||
147 @@ -95,7 +108,7 @@ static inline int rpl_ip_do_fragment(struct sock *sk, struct sk_buff *skb,
148 IPCB(skb)->frag_max_size > mtu))) {
150 pr_warn("Dropping packet in ip_do_fragment()\n");
151 - IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
152 + IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS);
156 diff --git a/datapath/linux/compat/include/net/ip6_tunnel.h b/datapath/linux/compat/include/net/ip6_tunnel.h
157 index ce65087..eacf9ca 100644
158 --- a/datapath/linux/compat/include/net/ip6_tunnel.h
159 +++ b/datapath/linux/compat/include/net/ip6_tunnel.h
160 @@ -17,11 +17,15 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
162 pkt_len = skb->len - skb_inner_network_offset(skb);
163 /* TODO: Fix GSO for ipv6 */
164 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
165 + err = ip6_local_out(dev_net(dev), sk, skb);
167 #ifdef HAVE_IP6_LOCAL_OUT_SK
168 err = ip6_local_out_sk(sk, skb);
170 err = ip6_local_out(skb);
172 +#endif /* >= kernel 4.4 */
173 if (net_xmit_eval(err) != 0)
174 pkt_len = net_xmit_eval(err);
176 diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
177 index 75a5a7a..589cc0d 100644
178 --- a/datapath/linux/compat/include/net/vxlan.h
179 +++ b/datapath/linux/compat/include/net/vxlan.h
180 @@ -218,10 +218,20 @@ struct vxlan_dev {
181 struct net_device *rpl_vxlan_dev_create(struct net *net, const char *name,
182 u8 name_assign_type, struct vxlan_config *conf);
184 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
185 +static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan,
186 + unsigned short family)
188 + if (family == AF_INET6)
189 + return inet_sk(vxlan->vn6_sock->sock->sk)->inet_sport;
190 + return inet_sk(vxlan->vn4_sock->sock->sk)->inet_sport;
193 static inline __be16 vxlan_dev_dst_port(struct vxlan_dev *vxlan)
195 return inet_sk(vxlan->vn_sock->sock->sk)->inet_sport;
199 static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
200 netdev_features_t features)
201 diff --git a/datapath/linux/compat/stt.c b/datapath/linux/compat/stt.c
202 index 86d225e..6b1e3a3 100644
203 --- a/datapath/linux/compat/stt.c
204 +++ b/datapath/linux/compat/stt.c
205 @@ -1544,7 +1544,11 @@ static void clean_percpu(struct work_struct *work)
208 #ifdef HAVE_NF_HOOKFN_ARG_OPS
209 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
210 +#define FIRST_PARAM void *priv
212 #define FIRST_PARAM const struct nf_hook_ops *ops
213 +#endif /* >= kernel 4.4 */
215 #define FIRST_PARAM unsigned int hooknum
217 @@ -1592,7 +1596,9 @@ static unsigned int nf_ip_hook(FIRST_PARAM, struct sk_buff *skb, LAST_PARAM)
219 static struct nf_hook_ops nf_hook_ops __read_mostly = {
221 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,4,0)
222 .owner = THIS_MODULE,
225 .hooknum = NF_INET_LOCAL_IN,
227 diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
228 index c05f5d4..3cbb568 100644
229 --- a/datapath/vport-vxlan.c
230 +++ b/datapath/vport-vxlan.c
231 @@ -153,7 +153,12 @@ static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
233 struct vxlan_dev *vxlan = netdev_priv(vport->dev);
234 struct net *net = ovs_dp_get_net(vport->dp);
235 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
236 + unsigned short family = ip_tunnel_info_af(upcall->egress_tun_info);
237 + __be16 dst_port = vxlan_dev_dst_port(vxlan, family);
239 __be16 dst_port = vxlan_dev_dst_port(vxlan);