mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
datapath: Add support for kernels 3.13
Add support for building the in-tree kernel datapath for Linux kernels up to 3.13. There were some changes in the netlink area which required adding new compatibility code for this layer. Also, some new per-cpu stats initialization code was added. Based on patch from Kyle Mestery. Signed-off-by: Kyle Mestery <mestery@noironetworks.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Kyle Mestery <mestery@noironetworks.com>
This commit is contained in:
parent
1839c35676
commit
cb25142c50
2
FAQ
2
FAQ
@ -149,7 +149,7 @@ A: The following table lists the Linux kernel versions against which the
|
||||
1.11.x 2.6.18 to 3.8
|
||||
2.0.x 2.6.32 to 3.10
|
||||
2.1.x 2.6.32 to 3.11
|
||||
2.2.x 2.6.32 to 3.12
|
||||
2.2.x 2.6.32 to 3.13
|
||||
|
||||
Open vSwitch userspace should also work with the Linux kernel module
|
||||
built into Linux 3.3 and later.
|
||||
|
4
NEWS
4
NEWS
@ -13,8 +13,8 @@ Post-v2.1.0
|
||||
- Upon the receipt of a SIGHUP signal, ovs-vswitchd no longer reopens its
|
||||
log file (it will terminate instead). Please use 'ovs-appctl vlog/reopen'
|
||||
instead.
|
||||
- Support for Linux kernels up to 3.12. On Kernel 3.12 OVS uses tunnel
|
||||
API for GRE and VXLAN.
|
||||
- Support for Linux kernels up to 3.13. From Kernel 3.12 onwards OVS uses
|
||||
tunnel API for GRE and VXLAN.
|
||||
- Added DPDK support.
|
||||
|
||||
|
||||
|
@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
|
||||
AC_MSG_RESULT([$kversion])
|
||||
|
||||
if test "$version" -ge 3; then
|
||||
if test "$version" = 3 && test "$patchlevel" -le 12; then
|
||||
if test "$version" = 3 && test "$patchlevel" -le 13; then
|
||||
: # Linux 3.x
|
||||
else
|
||||
AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.12.x is not supported])
|
||||
AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version newer than 3.13.x is not supported])
|
||||
fi
|
||||
else
|
||||
if test "$version" -le 1 || test "$patchlevel" -le 5 || test "$sublevel" -le 31; then
|
||||
|
@ -32,10 +32,10 @@ static inline void skb_clear_rxhash(struct sk_buff *skb)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_PARALLEL_OPS
|
||||
#define SET_PARALLEL_OPS .parallel_ops = true,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
|
||||
#define GROUP_ID(grp) 0
|
||||
#else
|
||||
#define SET_PARALLEL_OPS
|
||||
#define GROUP_ID(grp) ((grp)->id)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
|
||||
|
@ -64,20 +64,36 @@
|
||||
|
||||
int ovs_net_id __read_mostly;
|
||||
|
||||
static struct genl_family dp_packet_genl_family;
|
||||
static struct genl_family dp_flow_genl_family;
|
||||
static struct genl_family dp_datapath_genl_family;
|
||||
|
||||
static struct genl_multicast_group ovs_dp_flow_multicast_group = {
|
||||
.name = OVS_FLOW_MCGROUP
|
||||
};
|
||||
|
||||
static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
|
||||
.name = OVS_DATAPATH_MCGROUP
|
||||
};
|
||||
|
||||
struct genl_multicast_group ovs_dp_vport_multicast_group = {
|
||||
.name = OVS_VPORT_MCGROUP
|
||||
};
|
||||
|
||||
/* Check if need to build a reply message.
|
||||
* OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
|
||||
static bool ovs_must_notify(struct genl_info *info,
|
||||
const struct genl_multicast_group *grp)
|
||||
{
|
||||
return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
|
||||
netlink_has_listeners(genl_info_net(info)->genl_sock, grp->id);
|
||||
netlink_has_listeners(genl_info_net(info)->genl_sock, GROUP_ID(grp));
|
||||
}
|
||||
|
||||
static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
|
||||
struct genl_multicast_group *grp)
|
||||
static void ovs_notify(struct genl_family *family, struct genl_multicast_group *grp,
|
||||
struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
genl_notify(skb, genl_info_net(info), info->snd_portid,
|
||||
grp->id, info->nlhdr, GFP_KERNEL);
|
||||
genl_notify(family, skb, genl_info_net(info),
|
||||
info->snd_portid, GROUP_ID(grp), info->nlhdr, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -274,16 +290,6 @@ out:
|
||||
u64_stats_update_end(&stats->sync);
|
||||
}
|
||||
|
||||
static struct genl_family dp_packet_genl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = sizeof(struct ovs_header),
|
||||
.name = OVS_PACKET_FAMILY,
|
||||
.version = OVS_PACKET_VERSION,
|
||||
.maxattr = OVS_PACKET_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
SET_PARALLEL_OPS
|
||||
};
|
||||
|
||||
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
|
||||
const struct dp_upcall_info *upcall_info)
|
||||
{
|
||||
@ -601,6 +607,18 @@ static struct genl_ops dp_packet_genl_ops[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct genl_family dp_packet_genl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = sizeof(struct ovs_header),
|
||||
.name = OVS_PACKET_FAMILY,
|
||||
.version = OVS_PACKET_VERSION,
|
||||
.maxattr = OVS_PACKET_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
.parallel_ops = true,
|
||||
.ops = dp_packet_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(dp_packet_genl_ops),
|
||||
};
|
||||
|
||||
static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats,
|
||||
struct ovs_dp_megaflow_stats *mega_stats)
|
||||
{
|
||||
@ -632,26 +650,6 @@ static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats,
|
||||
}
|
||||
}
|
||||
|
||||
static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
|
||||
[OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
|
||||
[OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
|
||||
[OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static struct genl_family dp_flow_genl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = sizeof(struct ovs_header),
|
||||
.name = OVS_FLOW_FAMILY,
|
||||
.version = OVS_FLOW_VERSION,
|
||||
.maxattr = OVS_FLOW_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
SET_PARALLEL_OPS
|
||||
};
|
||||
|
||||
static struct genl_multicast_group ovs_dp_flow_multicast_group = {
|
||||
.name = OVS_FLOW_MCGROUP
|
||||
};
|
||||
|
||||
static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
|
||||
{
|
||||
return NLMSG_ALIGN(sizeof(struct ovs_header))
|
||||
@ -914,7 +912,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
if (reply)
|
||||
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
|
||||
ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
err_unlock_ovs:
|
||||
@ -1023,7 +1021,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
ovs_unlock();
|
||||
|
||||
if (reply)
|
||||
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
|
||||
ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
|
||||
if (old_acts)
|
||||
ovs_nla_free_flow_actions(old_acts);
|
||||
return 0;
|
||||
@ -1135,11 +1133,11 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
||||
OVS_FLOW_CMD_DEL);
|
||||
rcu_read_unlock();
|
||||
BUG_ON(err < 0);
|
||||
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
|
||||
ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
|
||||
} else {
|
||||
netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
|
||||
ovs_dp_flow_multicast_group.id,
|
||||
PTR_ERR(reply));
|
||||
genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0,
|
||||
GROUP_ID(&ovs_dp_flow_multicast_group), PTR_ERR(reply));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1187,6 +1185,12 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
|
||||
[OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
|
||||
[OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
|
||||
[OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
static struct genl_ops dp_flow_genl_ops[] = {
|
||||
{ .cmd = OVS_FLOW_CMD_NEW,
|
||||
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
|
||||
@ -1211,24 +1215,18 @@ static struct genl_ops dp_flow_genl_ops[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
|
||||
[OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
|
||||
[OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
|
||||
[OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static struct genl_family dp_datapath_genl_family = {
|
||||
static struct genl_family dp_flow_genl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = sizeof(struct ovs_header),
|
||||
.name = OVS_DATAPATH_FAMILY,
|
||||
.version = OVS_DATAPATH_VERSION,
|
||||
.maxattr = OVS_DP_ATTR_MAX,
|
||||
.name = OVS_FLOW_FAMILY,
|
||||
.version = OVS_FLOW_VERSION,
|
||||
.maxattr = OVS_FLOW_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
SET_PARALLEL_OPS
|
||||
};
|
||||
|
||||
static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
|
||||
.name = OVS_DATAPATH_MCGROUP
|
||||
.parallel_ops = true,
|
||||
.ops = dp_flow_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(dp_flow_genl_ops),
|
||||
.mcgrps = &ovs_dp_flow_multicast_group,
|
||||
.n_mcgrps = 1,
|
||||
};
|
||||
|
||||
static size_t ovs_dp_cmd_msg_size(void)
|
||||
@ -1361,6 +1359,12 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
goto err_destroy_table;
|
||||
}
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
struct dp_stats_percpu *dpath_stats;
|
||||
dpath_stats = per_cpu_ptr(dp->stats_percpu, i);
|
||||
u64_stats_init(&dpath_stats->sync);
|
||||
}
|
||||
|
||||
dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
|
||||
GFP_KERNEL);
|
||||
if (!dp->ports) {
|
||||
@ -1411,7 +1415,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
ovs_unlock();
|
||||
|
||||
ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
|
||||
ovs_notify(&dp_datapath_genl_family, &ovs_dp_datapath_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
err_destroy_ports_array:
|
||||
@ -1480,7 +1484,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
||||
__dp_destroy(dp);
|
||||
|
||||
ovs_unlock();
|
||||
ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
|
||||
ovs_notify(&dp_datapath_genl_family, &ovs_dp_datapath_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
err_unlock_free:
|
||||
@ -1512,7 +1516,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
BUG_ON(err < 0);
|
||||
|
||||
ovs_unlock();
|
||||
ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
|
||||
ovs_notify(&dp_datapath_genl_family, &ovs_dp_datapath_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
err_unlock_free:
|
||||
@ -1573,6 +1577,12 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
|
||||
[OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
|
||||
[OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
|
||||
[OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static struct genl_ops dp_datapath_genl_ops[] = {
|
||||
{ .cmd = OVS_DP_CMD_NEW,
|
||||
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
|
||||
@ -1597,27 +1607,18 @@ static struct genl_ops dp_datapath_genl_ops[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
|
||||
[OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
|
||||
[OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
|
||||
[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct genl_family dp_vport_genl_family = {
|
||||
static struct genl_family dp_datapath_genl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = sizeof(struct ovs_header),
|
||||
.name = OVS_VPORT_FAMILY,
|
||||
.version = OVS_VPORT_VERSION,
|
||||
.maxattr = OVS_VPORT_ATTR_MAX,
|
||||
.name = OVS_DATAPATH_FAMILY,
|
||||
.version = OVS_DATAPATH_VERSION,
|
||||
.maxattr = OVS_DP_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
SET_PARALLEL_OPS
|
||||
};
|
||||
|
||||
struct genl_multicast_group ovs_dp_vport_multicast_group = {
|
||||
.name = OVS_VPORT_MCGROUP
|
||||
.parallel_ops = true,
|
||||
.ops = dp_datapath_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
|
||||
.mcgrps = &ovs_dp_datapath_multicast_group,
|
||||
.n_mcgrps = 1,
|
||||
};
|
||||
|
||||
/* Called with ovs_mutex or RCU read lock. */
|
||||
@ -1783,7 +1784,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
BUG_ON(err < 0);
|
||||
ovs_unlock();
|
||||
|
||||
ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
|
||||
ovs_notify(&dp_vport_genl_family, &ovs_dp_vport_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
exit_unlock_free:
|
||||
@ -1832,7 +1833,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
BUG_ON(err < 0);
|
||||
ovs_unlock();
|
||||
|
||||
ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
|
||||
ovs_notify(&dp_vport_genl_family, &ovs_dp_vport_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
exit_unlock_free:
|
||||
@ -1869,7 +1870,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
||||
ovs_dp_detach_port(vport);
|
||||
ovs_unlock();
|
||||
|
||||
ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
|
||||
ovs_notify(&dp_vport_genl_family, &ovs_dp_vport_multicast_group, reply, info);
|
||||
return 0;
|
||||
|
||||
exit_unlock_free:
|
||||
@ -1947,6 +1948,15 @@ out:
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
|
||||
[OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
|
||||
[OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
|
||||
[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
|
||||
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct genl_ops dp_vport_genl_ops[] = {
|
||||
{ .cmd = OVS_VPORT_CMD_NEW,
|
||||
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
|
||||
@ -1971,26 +1981,25 @@ static struct genl_ops dp_vport_genl_ops[] = {
|
||||
},
|
||||
};
|
||||
|
||||
struct genl_family_and_ops {
|
||||
struct genl_family *family;
|
||||
struct genl_ops *ops;
|
||||
int n_ops;
|
||||
struct genl_multicast_group *group;
|
||||
struct genl_family dp_vport_genl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = sizeof(struct ovs_header),
|
||||
.name = OVS_VPORT_FAMILY,
|
||||
.version = OVS_VPORT_VERSION,
|
||||
.maxattr = OVS_VPORT_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
.parallel_ops = true,
|
||||
.ops = dp_vport_genl_ops,
|
||||
.n_ops = ARRAY_SIZE(dp_vport_genl_ops),
|
||||
.mcgrps = &ovs_dp_vport_multicast_group,
|
||||
.n_mcgrps = 1,
|
||||
};
|
||||
|
||||
static const struct genl_family_and_ops dp_genl_families[] = {
|
||||
{ &dp_datapath_genl_family,
|
||||
dp_datapath_genl_ops, ARRAY_SIZE(dp_datapath_genl_ops),
|
||||
&ovs_dp_datapath_multicast_group },
|
||||
{ &dp_vport_genl_family,
|
||||
dp_vport_genl_ops, ARRAY_SIZE(dp_vport_genl_ops),
|
||||
&ovs_dp_vport_multicast_group },
|
||||
{ &dp_flow_genl_family,
|
||||
dp_flow_genl_ops, ARRAY_SIZE(dp_flow_genl_ops),
|
||||
&ovs_dp_flow_multicast_group },
|
||||
{ &dp_packet_genl_family,
|
||||
dp_packet_genl_ops, ARRAY_SIZE(dp_packet_genl_ops),
|
||||
NULL },
|
||||
static struct genl_family *dp_genl_families[] = {
|
||||
&dp_datapath_genl_family,
|
||||
&dp_vport_genl_family,
|
||||
&dp_flow_genl_family,
|
||||
&dp_packet_genl_family,
|
||||
};
|
||||
|
||||
static void dp_unregister_genl(int n_families)
|
||||
@ -1998,36 +2007,25 @@ static void dp_unregister_genl(int n_families)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_families; i++)
|
||||
genl_unregister_family(dp_genl_families[i].family);
|
||||
genl_unregister_family(dp_genl_families[i]);
|
||||
}
|
||||
|
||||
static int dp_register_genl(void)
|
||||
{
|
||||
int n_registered;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
n_registered = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
|
||||
const struct genl_family_and_ops *f = &dp_genl_families[i];
|
||||
|
||||
err = genl_register_family_with_ops(f->family, f->ops,
|
||||
f->n_ops);
|
||||
err = genl_register_family(dp_genl_families[i]);
|
||||
if (err)
|
||||
goto error;
|
||||
n_registered++;
|
||||
|
||||
if (f->group) {
|
||||
err = genl_register_mc_group(f->family, f->group);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
dp_unregister_genl(n_registered);
|
||||
dp_unregister_genl(i);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -184,6 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
|
||||
}
|
||||
|
||||
extern struct notifier_block ovs_dp_device_notifier;
|
||||
extern struct genl_family dp_vport_genl_family;
|
||||
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
|
||||
|
||||
void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
|
||||
|
@ -31,18 +31,18 @@ static void dp_detach_port_notify(struct vport *vport)
|
||||
struct datapath *dp;
|
||||
|
||||
dp = vport->dp;
|
||||
notify = ovs_vport_cmd_build_info(vport, 0, 0,
|
||||
OVS_VPORT_CMD_DEL);
|
||||
notify = ovs_vport_cmd_build_info(vport, 0, 0, OVS_VPORT_CMD_DEL);
|
||||
ovs_dp_detach_port(vport);
|
||||
if (IS_ERR(notify)) {
|
||||
netlink_set_err(ovs_dp_get_net(dp)->genl_sock, 0,
|
||||
ovs_dp_vport_multicast_group.id,
|
||||
PTR_ERR(notify));
|
||||
genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
|
||||
GROUP_ID(&ovs_dp_vport_multicast_group),
|
||||
PTR_ERR(notify));
|
||||
return;
|
||||
}
|
||||
|
||||
genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
|
||||
ovs_dp_vport_multicast_group.id,
|
||||
genlmsg_multicast_netns(&dp_vport_genl_family,
|
||||
ovs_dp_get_net(dp), notify, 0,
|
||||
GROUP_ID(&ovs_dp_vport_multicast_group),
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
#include <net/genetlink.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
/* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
|
||||
*
|
||||
* This is not (yet) in any upstream kernel. */
|
||||
void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, u32 group,
|
||||
struct nlmsghdr *nlh, gfp_t flags)
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||
|
||||
#undef genl_notify
|
||||
|
||||
void rpl_genl_notify(struct rpl_genl_family *family, struct sk_buff *skb,
|
||||
struct net *net, u32 portid, u32 group,
|
||||
struct nlmsghdr *nlh, gfp_t flags)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
|
||||
struct sock *sk = net->genl_sock;
|
||||
int report = 0;
|
||||
|
||||
@ -14,4 +17,39 @@ void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, u32 group,
|
||||
report = nlmsg_report(nlh);
|
||||
|
||||
nlmsg_notify(sk, skb, portid, group, report, flags);
|
||||
#else
|
||||
genl_notify(skb, net, portid, group, nlh, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
int rpl___genl_register_family(struct rpl_genl_family *f)
|
||||
{
|
||||
int err;
|
||||
|
||||
f->compat_family.id = f->id;
|
||||
f->compat_family.hdrsize = f->hdrsize;
|
||||
strncpy(f->compat_family.name, f->name, GENL_NAMSIZ);
|
||||
f->compat_family.version = f->version;
|
||||
f->compat_family.maxattr = f->maxattr;
|
||||
f->compat_family.netnsok = f->netnsok;
|
||||
#ifdef HAVE_PARALLEL_OPS
|
||||
f->compat_family.parallel_ops = f->parallel_ops;
|
||||
#endif
|
||||
err = genl_register_family_with_ops(&f->compat_family,
|
||||
(struct genl_ops *) f->ops, f->n_ops);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
if (f->mcgrps) {
|
||||
/* Need to Fix GROUP_ID() for more than one group. */
|
||||
BUG_ON(f->n_mcgrps > 1);
|
||||
err = genl_register_mc_group(&f->compat_family,
|
||||
(struct genl_multicast_group *) f->mcgrps);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
error:
|
||||
return err;
|
||||
|
||||
}
|
||||
#endif /* kernel version < 3.13.0 */
|
||||
|
@ -144,4 +144,15 @@ static inline bool u64_stats_fetch_retry_bh(const struct u64_stats_sync *syncp,
|
||||
}
|
||||
|
||||
#endif /* Linux kernel < 2.6.36 */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||
|
||||
#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
|
||||
# define u64_stats_init(syncp) seqcount_init(syncp.seq)
|
||||
#else
|
||||
# define u64_stats_init(syncp) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_U64_STATS_SYNC_WRAPPER_H */
|
||||
|
@ -17,8 +17,84 @@
|
||||
#define portid pid
|
||||
#endif
|
||||
|
||||
extern void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
|
||||
u32 group, struct nlmsghdr *nlh, gfp_t flags);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||
struct rpl_genl_family {
|
||||
struct genl_family compat_family;
|
||||
unsigned int id;
|
||||
unsigned int hdrsize;
|
||||
char name[GENL_NAMSIZ];
|
||||
unsigned int version;
|
||||
unsigned int maxattr;
|
||||
bool netnsok;
|
||||
bool parallel_ops;
|
||||
int (*pre_doit)(const struct genl_ops *ops,
|
||||
struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
void (*post_doit)(const struct genl_ops *ops,
|
||||
struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
struct nlattr ** attrbuf; /* private */
|
||||
const struct genl_ops * ops; /* private */
|
||||
const struct genl_multicast_group *mcgrps; /* private */
|
||||
unsigned int n_ops; /* private */
|
||||
unsigned int n_mcgrps; /* private */
|
||||
unsigned int mcgrp_offset; /* private */
|
||||
struct list_head family_list; /* private */
|
||||
struct module *module;
|
||||
};
|
||||
|
||||
#define genl_family rpl_genl_family
|
||||
#define genl_notify rpl_genl_notify
|
||||
void genl_notify(struct genl_family *family,
|
||||
struct sk_buff *skb, struct net *net, u32 portid, u32 group,
|
||||
struct nlmsghdr *nlh, gfp_t flags);
|
||||
|
||||
static inline void *rpl_genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
|
||||
struct genl_family *family, int flags, u8 cmd)
|
||||
{
|
||||
return genlmsg_put(skb, portid, seq, &family->compat_family, flags, cmd);
|
||||
}
|
||||
|
||||
#define genlmsg_put rpl_genlmsg_put
|
||||
|
||||
static inline int rpl_genl_unregister_family(struct genl_family *family)
|
||||
{
|
||||
return genl_unregister_family(&family->compat_family);
|
||||
}
|
||||
#define genl_unregister_family rpl_genl_unregister_family
|
||||
|
||||
#define genl_set_err rpl_genl_set_err
|
||||
static inline int genl_set_err(struct genl_family *family, struct net *net,
|
||||
u32 portid, u32 group, int code)
|
||||
{
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
|
||||
netlink_set_err(net->genl_sock, portid, group, code);
|
||||
return 0;
|
||||
#else
|
||||
return netlink_set_err(net->genl_sock, portid, group, code);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define genlmsg_multicast_netns rpl_genlmsg_multicast_netns
|
||||
static inline int genlmsg_multicast_netns(struct genl_family *family,
|
||||
struct net *net, struct sk_buff *skb,
|
||||
u32 portid, unsigned int group, gfp_t flags)
|
||||
{
|
||||
return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
|
||||
}
|
||||
|
||||
|
||||
#define __genl_register_family rpl___genl_register_family
|
||||
int rpl___genl_register_family(struct genl_family *family);
|
||||
|
||||
#define genl_register_family rpl_genl_register_family
|
||||
static inline int rpl_genl_register_family(struct genl_family *family)
|
||||
{
|
||||
family->module = THIS_MODULE;
|
||||
return rpl___genl_register_family(family);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
|
||||
static inline struct sk_buff *genlmsg_new_unicast(size_t payload,
|
||||
|
@ -12,4 +12,14 @@ static inline bool ip_is_fragment(const struct iphdr *iph)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||
static inline void rpl_inet_get_local_port_range(struct net *net, int *low,
|
||||
int *high)
|
||||
{
|
||||
inet_get_local_port_range(low, high);
|
||||
}
|
||||
#define inet_get_local_port_range rpl_inet_get_local_port_range
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/net.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/ip.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/percpu.h>
|
||||
@ -38,6 +39,7 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||
bool __net_get_random_once(void *buf, int nbytes, bool *done,
|
||||
atomic_t *done_key)
|
||||
{
|
||||
@ -58,3 +60,4 @@ bool __net_get_random_once(void *buf, int nbytes, bool *done,
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -163,7 +163,7 @@ static __be64 instance_id_to_tunnel_id(__u8 *iid)
|
||||
/* Compute source UDP port for outgoing packet.
|
||||
* Currently we use the flow hash.
|
||||
*/
|
||||
static u16 get_src_port(struct sk_buff *skb)
|
||||
static u16 get_src_port(struct net *net, struct sk_buff *skb)
|
||||
{
|
||||
u32 hash = skb_get_rxhash(skb);
|
||||
unsigned int range;
|
||||
@ -177,7 +177,7 @@ static u16 get_src_port(struct sk_buff *skb)
|
||||
sizeof(*pkt_key) / sizeof(u32), 0);
|
||||
}
|
||||
|
||||
inet_get_local_port_range(&low, &high);
|
||||
inet_get_local_port_range(net, &low, &high);
|
||||
range = (high - low) + 1;
|
||||
return (((u64) hash * range) >> 32) + low;
|
||||
}
|
||||
@ -185,13 +185,14 @@ static u16 get_src_port(struct sk_buff *skb)
|
||||
static void lisp_build_header(const struct vport *vport,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = ovs_dp_get_net(vport->dp);
|
||||
struct lisp_port *lisp_port = lisp_vport(vport);
|
||||
struct udphdr *udph = udp_hdr(skb);
|
||||
struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
|
||||
const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
|
||||
|
||||
udph->dest = lisp_port->dst_port;
|
||||
udph->source = htons(get_src_port(skb));
|
||||
udph->source = htons(get_src_port(net, skb));
|
||||
udph->check = 0;
|
||||
udph->len = htons(skb->len - skb_transport_offset(skb));
|
||||
|
||||
|
@ -139,6 +139,7 @@ error:
|
||||
|
||||
static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = ovs_dp_get_net(vport->dp);
|
||||
struct vxlan_port *vxlan_port = vxlan_vport(vport);
|
||||
__be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
|
||||
struct rtable *rt;
|
||||
@ -172,7 +173,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
|
||||
|
||||
skb->local_df = 1;
|
||||
|
||||
inet_get_local_port_range(&port_min, &port_max);
|
||||
inet_get_local_port_range(net, &port_min, &port_max);
|
||||
src_port = vxlan_src_port(port_min, port_max, skb);
|
||||
|
||||
err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
|
||||
|
@ -122,6 +122,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
|
||||
{
|
||||
struct vport *vport;
|
||||
size_t alloc_size;
|
||||
int i;
|
||||
|
||||
alloc_size = sizeof(struct vport);
|
||||
if (priv_size) {
|
||||
@ -145,6 +146,12 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
struct pcpu_tstats *vport_stats;
|
||||
vport_stats = per_cpu_ptr(vport->percpu_stats, i);
|
||||
u64_stats_init(&vport_stats->syncp);
|
||||
}
|
||||
|
||||
spin_lock_init(&vport->stats_lock);
|
||||
|
||||
return vport;
|
||||
|
Loading…
x
Reference in New Issue
Block a user