[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