[ovs-dev] [PATCH] datapath: Add support for 3.6 kernel.

Pravin B Shelar pshelar at nicira.com
Sat Oct 27 20:07:35 UTC 2012


Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 datapath/datapath.c                           |   50 ++++++++++++-------------
 datapath/linux/compat/include/linux/netlink.h |    6 +++
 datapath/linux/compat/include/net/genetlink.h |    8 ++++
 datapath/tunnel.c                             |   35 +++++++++--------
 datapath/vport-capwap.c                       |    5 ++-
 5 files changed, 63 insertions(+), 41 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index 65f4dc8..a28096e 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -61,8 +61,8 @@
 #include "vport-internal_dev.h"
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \
-    LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
-#error Kernels before 2.6.18 or after 3.5 are not supported by this version of Open vSwitch.
+    LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+#error Kernels before 2.6.18 or after 3.6 are not supported by this version of Open vSwitch.
 #endif
 
 #define REHASH_FLOW_INTERVAL (10 * 60 * HZ)
@@ -1080,7 +1080,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 		/* Put flow in bucket. */
 		ovs_flow_tbl_insert(table, flow, &key, key_len);
 
-		reply = ovs_flow_cmd_build_info(flow, dp, info->snd_pid,
+		reply = ovs_flow_cmd_build_info(flow, dp, genl_info_port_id(info),
 						info->snd_seq,
 						OVS_FLOW_CMD_NEW);
 	} else {
@@ -1118,7 +1118,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 			ovs_flow_deferred_free_acts(old_acts);
 		}
 
-		reply = ovs_flow_cmd_build_info(flow, dp, info->snd_pid,
+		reply = ovs_flow_cmd_build_info(flow, dp, genl_info_port_id(info),
 					       info->snd_seq, OVS_FLOW_CMD_NEW);
 
 		/* Clear stats. */
@@ -1130,7 +1130,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 	}
 
 	if (!IS_ERR(reply))
-		genl_notify(reply, genl_info_net(info), info->snd_pid,
+		genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 			   ovs_dp_flow_multicast_group.id, info->nlhdr,
 			   GFP_KERNEL);
 	else
@@ -1171,7 +1171,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
 	if (!flow)
 		return -ENOENT;
 
-	reply = ovs_flow_cmd_build_info(flow, dp, info->snd_pid,
+	reply = ovs_flow_cmd_build_info(flow, dp, genl_info_port_id(info),
 					info->snd_seq, OVS_FLOW_CMD_NEW);
 	if (IS_ERR(reply))
 		return PTR_ERR(reply);
@@ -1213,13 +1213,13 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
 
 	ovs_flow_tbl_remove(table, flow);
 
-	err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_pid,
+	err = ovs_flow_cmd_fill_info(flow, dp, reply, genl_info_port_id(info),
 				     info->snd_seq, 0, OVS_FLOW_CMD_DEL);
 	BUG_ON(err < 0);
 
 	ovs_flow_deferred_free(flow);
 
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_flow_multicast_group.id, info->nlhdr, GFP_KERNEL);
 	return 0;
 }
@@ -1247,7 +1247,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
 			break;
 
 		if (ovs_flow_cmd_fill_info(flow, dp, skb,
-					   NETLINK_CB(cb->skb).pid,
+					   NETLINK_CB_PORT_ID(cb->skb),
 					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
 					   OVS_FLOW_CMD_NEW) < 0)
 			break;
@@ -1448,7 +1448,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
 		goto err_destroy_ports_array;
 	}
 
-	reply = ovs_dp_cmd_build_info(dp, info->snd_pid,
+	reply = ovs_dp_cmd_build_info(dp, genl_info_port_id(info),
 				      info->snd_seq, OVS_DP_CMD_NEW);
 	err = PTR_ERR(reply);
 	if (IS_ERR(reply))
@@ -1460,7 +1460,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
 	rtnl_unlock();
 
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_datapath_multicast_group.id, info->nlhdr,
 		    GFP_KERNEL);
 	return 0;
@@ -1527,7 +1527,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(dp))
 		return err;
 
-	reply = ovs_dp_cmd_build_info(dp, info->snd_pid,
+	reply = ovs_dp_cmd_build_info(dp, genl_info_port_id(info),
 				      info->snd_seq, OVS_DP_CMD_DEL);
 	err = PTR_ERR(reply);
 	if (IS_ERR(reply))
@@ -1535,7 +1535,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
 
 	__dp_destroy(dp);
 
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_datapath_multicast_group.id, info->nlhdr,
 		    GFP_KERNEL);
 
@@ -1556,7 +1556,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(dp))
 		return PTR_ERR(dp);
 
-	reply = ovs_dp_cmd_build_info(dp, info->snd_pid,
+	reply = ovs_dp_cmd_build_info(dp, genl_info_port_id(info),
 				      info->snd_seq, OVS_DP_CMD_NEW);
 	if (IS_ERR(reply)) {
 		err = PTR_ERR(reply);
@@ -1565,7 +1565,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
 		return 0;
 	}
 
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_datapath_multicast_group.id, info->nlhdr,
 		    GFP_KERNEL);
 
@@ -1586,7 +1586,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(dp))
 		return PTR_ERR(dp);
 
-	reply = ovs_dp_cmd_build_info(dp, info->snd_pid,
+	reply = ovs_dp_cmd_build_info(dp, genl_info_port_id(info),
 				      info->snd_seq, OVS_DP_CMD_NEW);
 	if (IS_ERR(reply))
 		return PTR_ERR(reply);
@@ -1603,7 +1603,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
 
 	list_for_each_entry(dp, &ovs_net->dps, list_node) {
 		if (i >= skip &&
-		    ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).pid,
+		    ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB_PORT_ID(cb->skb),
 					 cb->nlh->nlmsg_seq, NLM_F_MULTI,
 					 OVS_DP_CMD_NEW) < 0)
 			break;
@@ -1848,7 +1848,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
 
 	err = change_vport(vport, a);
 	if (!err) {
-		reply = ovs_vport_cmd_build_info(vport, info->snd_pid,
+		reply = ovs_vport_cmd_build_info(vport, genl_info_port_id(info),
 						 info->snd_seq,
 						 OVS_VPORT_CMD_NEW);
 		if (IS_ERR(reply))
@@ -1858,7 +1858,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
 		ovs_dp_detach_port(vport);
 		goto exit_unlock;
 	}
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_vport_multicast_group.id, info->nlhdr, GFP_KERNEL);
 
 exit_unlock:
@@ -1898,7 +1898,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
 	if (!err && a[OVS_VPORT_ATTR_UPCALL_PID])
 		vport->upcall_pid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]);
 
-	reply = ovs_vport_cmd_build_info(vport, info->snd_pid, info->snd_seq,
+	reply = ovs_vport_cmd_build_info(vport, genl_info_port_id(info), info->snd_seq,
 					 OVS_VPORT_CMD_NEW);
 	if (IS_ERR(reply)) {
 		netlink_set_err(GENL_SOCK(sock_net(skb->sk)), 0,
@@ -1906,7 +1906,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
 		goto exit_unlock;
 	}
 
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_vport_multicast_group.id, info->nlhdr, GFP_KERNEL);
 
 exit_unlock:
@@ -1937,7 +1937,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
 		goto exit_unlock;
 	}
 
-	reply = ovs_vport_cmd_build_info(vport, info->snd_pid, info->snd_seq,
+	reply = ovs_vport_cmd_build_info(vport, genl_info_port_id(info), info->snd_seq,
 					 OVS_VPORT_CMD_DEL);
 	err = PTR_ERR(reply);
 	if (IS_ERR(reply))
@@ -1945,7 +1945,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
 
 	ovs_dp_detach_port(vport);
 
-	genl_notify(reply, genl_info_net(info), info->snd_pid,
+	genl_notify(reply, genl_info_net(info), genl_info_port_id(info),
 		    ovs_dp_vport_multicast_group.id, info->nlhdr, GFP_KERNEL);
 
 exit_unlock:
@@ -1972,7 +1972,7 @@ static int ovs_vport_cmd_get(struct sk_buff *skb, struct genl_info *info)
 	if (IS_ERR(vport))
 		goto exit_unlock;
 
-	reply = ovs_vport_cmd_build_info(vport, info->snd_pid, info->snd_seq,
+	reply = ovs_vport_cmd_build_info(vport, genl_info_port_id(info), info->snd_seq,
 					 OVS_VPORT_CMD_NEW);
 	err = PTR_ERR(reply);
 	if (IS_ERR(reply))
@@ -2008,7 +2008,7 @@ static int ovs_vport_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
 		hlist_for_each_entry_rcu(vport, n, &dp->ports[i], dp_hash_node) {
 			if (j >= skip &&
 			    ovs_vport_cmd_fill_info(vport, skb,
-						    NETLINK_CB(cb->skb).pid,
+						    NETLINK_CB_PORT_ID(cb->skb),
 						    cb->nlh->nlmsg_seq,
 						    NLM_F_MULTI,
 						    OVS_VPORT_CMD_NEW) < 0)
diff --git a/datapath/linux/compat/include/linux/netlink.h b/datapath/linux/compat/include/linux/netlink.h
index 44a2073..73af1cb 100644
--- a/datapath/linux/compat/include/linux/netlink.h
+++ b/datapath/linux/compat/include/linux/netlink.h
@@ -32,4 +32,10 @@ static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
 }
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+#define NETLINK_CB_PORT_ID(skb) (NETLINK_CB((skb)).portid)
+#else
+#define NETLINK_CB_PORT_ID(skb) (NETLINK_CB((skb)).pid)
+#endif
+
 #endif
diff --git a/datapath/linux/compat/include/net/genetlink.h b/datapath/linux/compat/include/net/genetlink.h
index af7d5fd..a4fc431 100644
--- a/datapath/linux/compat/include/net/genetlink.h
+++ b/datapath/linux/compat/include/net/genetlink.h
@@ -171,6 +171,14 @@ static inline struct net *genl_info_net(struct genl_info *info)
 }
 #endif
 
+static inline u32 genl_info_port_id(struct genl_info *info)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+	return info->snd_portid;
+#else
+	return info->snd_pid;
+#endif
+}
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
 #define genlmsg_unicast(ignore_net, skb, pid)   genlmsg_unicast(skb, pid)
 #endif
diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 5b74877..04ff55f 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -701,32 +701,35 @@ static bool check_mtu(struct sk_buff *skb,
 	return true;
 }
 
-static struct rtable *find_route(const struct tnl_mutable_config *mutable,
-				   __be32 saddr, __be32 daddr, u8 ipproto,
-				   u8 tos)
+static struct rtable *find_route(struct net *net,
+		__be32 *saddr, __be32 daddr, u8 ipproto,
+		u8 tos)
 {
+	struct rtable *rt;
 	/* Tunnel configuration keeps DSCP part of TOS bits, But Linux
 	 * router expect RT_TOS bits only. */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
 	struct flowi fl = { .nl_u = { .ip4_u = {
 					.daddr = daddr,
-					.saddr = saddr,
+					.saddr = *saddr,
 					.tos   = RT_TOS(tos) } },
 					.proto = ipproto };
-	struct rtable *rt;
 
-	if (unlikely(ip_route_output_key(port_key_get_net(&mutable->key), &rt, &fl)))
+	if (unlikely(ip_route_output_key(net, &rt, &fl)))
 		return ERR_PTR(-EADDRNOTAVAIL);
-
+	*saddr = fl.nl_u.ip4_u.saddr;
 	return rt;
 #else
 	struct flowi4 fl = { .daddr = daddr,
-			     .saddr = saddr,
+			     .saddr = *saddr,
 			     .flowi4_tos = RT_TOS(tos),
 			     .flowi4_proto = ipproto };
 
-	return ip_route_output_key(port_key_get_net(&mutable->key), &fl);
+	rt = ip_route_output_key(net, &fl);
+	if (!IS_ERR(rt))
+		*saddr = fl.saddr;
+	return rt;
 #endif
 }
 
@@ -947,7 +950,8 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
 	}
 
 	/* Route lookup */
-	rt = find_route(mutable, saddr, daddr, tnl_vport->tnl_ops->ipproto, tos);
+	rt = find_route(port_key_get_net(&mutable->key), &saddr, daddr,
+			  tnl_vport->tnl_ops->ipproto, tos);
 	if (IS_ERR(rt))
 		goto error_free;
 
@@ -1007,10 +1011,9 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
 		iph = ip_hdr(skb);
 		iph->version	= 4;
 		iph->ihl	= sizeof(struct iphdr) >> 2;
-		iph->frag_off	= htons(IP_DF);
 		iph->protocol	= tnl_vport->tnl_ops->ipproto;
-		iph->daddr	= rt->rt_dst;
-		iph->saddr	= rt->rt_src;
+		iph->daddr	= daddr;
+		iph->saddr	= saddr;
 		iph->tos	= tos;
 		iph->ttl	= ttl;
 		iph->frag_off	= frag_off;
@@ -1106,9 +1109,11 @@ static int tnl_set_config(struct net *net, struct nlattr *options,
 	if (ipv4_is_multicast(mutable->key.daddr)) {
 		struct net_device *dev;
 		struct rtable *rt;
+		__be32 saddr = mutable->key.saddr;
 
-		rt = find_route(mutable, mutable->key.saddr, mutable->key.daddr,
-				  tnl_ops->ipproto, mutable->tos);
+		rt = find_route(port_key_get_net(&mutable->key),
+			     &saddr, mutable->key.daddr,
+			     tnl_ops->ipproto, mutable->tos);
 		if (IS_ERR(rt))
 			return -EADDRNOTAVAIL;
 		dev = rt_dst(rt).dev;
diff --git a/datapath/vport-capwap.c b/datapath/vport-capwap.c
index e466323..83c4b03 100644
--- a/datapath/vport-capwap.c
+++ b/datapath/vport-capwap.c
@@ -791,8 +791,11 @@ static struct sk_buff *defrag(struct sk_buff *skb, bool frag_last)
 	struct frag_queue *fq;
 
 	if (atomic_read(&ns_frag_state->mem) > ns_frag_state->high_thresh)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+		inet_frag_evictor(ns_frag_state, &frag_state, true);
+#else
 		inet_frag_evictor(ns_frag_state, &frag_state);
-
+#endif
 	match.daddr = iph->daddr;
 	match.saddr = iph->saddr;
 	match.id = cwh->frag_id;
-- 
1.7.10




More information about the dev mailing list