mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +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
|
1.11.x 2.6.18 to 3.8
|
||||||
2.0.x 2.6.32 to 3.10
|
2.0.x 2.6.32 to 3.10
|
||||||
2.1.x 2.6.32 to 3.11
|
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
|
Open vSwitch userspace should also work with the Linux kernel module
|
||||||
built into Linux 3.3 and later.
|
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
|
- 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'
|
log file (it will terminate instead). Please use 'ovs-appctl vlog/reopen'
|
||||||
instead.
|
instead.
|
||||||
- Support for Linux kernels up to 3.12. On Kernel 3.12 OVS uses tunnel
|
- Support for Linux kernels up to 3.13. From Kernel 3.12 onwards OVS uses
|
||||||
API for GRE and VXLAN.
|
tunnel API for GRE and VXLAN.
|
||||||
- Added DPDK support.
|
- Added DPDK support.
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
|
|||||||
AC_MSG_RESULT([$kversion])
|
AC_MSG_RESULT([$kversion])
|
||||||
|
|
||||||
if test "$version" -ge 3; then
|
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
|
: # Linux 3.x
|
||||||
else
|
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
|
fi
|
||||||
else
|
else
|
||||||
if test "$version" -le 1 || test "$patchlevel" -le 5 || test "$sublevel" -le 31; then
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_PARALLEL_OPS
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
|
||||||
#define SET_PARALLEL_OPS .parallel_ops = true,
|
#define GROUP_ID(grp) 0
|
||||||
#else
|
#else
|
||||||
#define SET_PARALLEL_OPS
|
#define GROUP_ID(grp) ((grp)->id)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
|
||||||
|
@ -64,20 +64,36 @@
|
|||||||
|
|
||||||
int ovs_net_id __read_mostly;
|
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.
|
/* Check if need to build a reply message.
|
||||||
* OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
|
* OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
|
||||||
static bool ovs_must_notify(struct genl_info *info,
|
static bool ovs_must_notify(struct genl_info *info,
|
||||||
const struct genl_multicast_group *grp)
|
const struct genl_multicast_group *grp)
|
||||||
{
|
{
|
||||||
return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
|
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,
|
static void ovs_notify(struct genl_family *family, struct genl_multicast_group *grp,
|
||||||
struct genl_multicast_group *grp)
|
struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
genl_notify(skb, genl_info_net(info), info->snd_portid,
|
genl_notify(family, skb, genl_info_net(info),
|
||||||
grp->id, info->nlhdr, GFP_KERNEL);
|
info->snd_portid, GROUP_ID(grp), info->nlhdr, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,16 +290,6 @@ out:
|
|||||||
u64_stats_update_end(&stats->sync);
|
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,
|
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
|
||||||
const struct dp_upcall_info *upcall_info)
|
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,
|
static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats,
|
||||||
struct ovs_dp_megaflow_stats *mega_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)
|
static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
|
||||||
{
|
{
|
||||||
return NLMSG_ALIGN(sizeof(struct ovs_header))
|
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)
|
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;
|
return 0;
|
||||||
|
|
||||||
err_unlock_ovs:
|
err_unlock_ovs:
|
||||||
@ -1023,7 +1021,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
|||||||
ovs_unlock();
|
ovs_unlock();
|
||||||
|
|
||||||
if (reply)
|
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)
|
if (old_acts)
|
||||||
ovs_nla_free_flow_actions(old_acts);
|
ovs_nla_free_flow_actions(old_acts);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1135,11 +1133,11 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
|||||||
OVS_FLOW_CMD_DEL);
|
OVS_FLOW_CMD_DEL);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
BUG_ON(err < 0);
|
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 {
|
} else {
|
||||||
netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
|
genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0,
|
||||||
ovs_dp_flow_multicast_group.id,
|
GROUP_ID(&ovs_dp_flow_multicast_group), PTR_ERR(reply));
|
||||||
PTR_ERR(reply));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1187,6 +1185,12 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
return skb->len;
|
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[] = {
|
static struct genl_ops dp_flow_genl_ops[] = {
|
||||||
{ .cmd = OVS_FLOW_CMD_NEW,
|
{ .cmd = OVS_FLOW_CMD_NEW,
|
||||||
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
|
.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] = {
|
static struct genl_family dp_flow_genl_family = {
|
||||||
[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 = {
|
|
||||||
.id = GENL_ID_GENERATE,
|
.id = GENL_ID_GENERATE,
|
||||||
.hdrsize = sizeof(struct ovs_header),
|
.hdrsize = sizeof(struct ovs_header),
|
||||||
.name = OVS_DATAPATH_FAMILY,
|
.name = OVS_FLOW_FAMILY,
|
||||||
.version = OVS_DATAPATH_VERSION,
|
.version = OVS_FLOW_VERSION,
|
||||||
.maxattr = OVS_DP_ATTR_MAX,
|
.maxattr = OVS_FLOW_ATTR_MAX,
|
||||||
.netnsok = true,
|
.netnsok = true,
|
||||||
SET_PARALLEL_OPS
|
.parallel_ops = true,
|
||||||
};
|
.ops = dp_flow_genl_ops,
|
||||||
|
.n_ops = ARRAY_SIZE(dp_flow_genl_ops),
|
||||||
static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
|
.mcgrps = &ovs_dp_flow_multicast_group,
|
||||||
.name = OVS_DATAPATH_MCGROUP
|
.n_mcgrps = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t ovs_dp_cmd_msg_size(void)
|
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;
|
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),
|
dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!dp->ports) {
|
if (!dp->ports) {
|
||||||
@ -1411,7 +1415,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
|||||||
|
|
||||||
ovs_unlock();
|
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;
|
return 0;
|
||||||
|
|
||||||
err_destroy_ports_array:
|
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);
|
__dp_destroy(dp);
|
||||||
|
|
||||||
ovs_unlock();
|
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;
|
return 0;
|
||||||
|
|
||||||
err_unlock_free:
|
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);
|
BUG_ON(err < 0);
|
||||||
|
|
||||||
ovs_unlock();
|
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;
|
return 0;
|
||||||
|
|
||||||
err_unlock_free:
|
err_unlock_free:
|
||||||
@ -1573,6 +1577,12 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
return skb->len;
|
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[] = {
|
static struct genl_ops dp_datapath_genl_ops[] = {
|
||||||
{ .cmd = OVS_DP_CMD_NEW,
|
{ .cmd = OVS_DP_CMD_NEW,
|
||||||
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
|
.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] = {
|
static struct genl_family dp_datapath_genl_family = {
|
||||||
[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 = {
|
|
||||||
.id = GENL_ID_GENERATE,
|
.id = GENL_ID_GENERATE,
|
||||||
.hdrsize = sizeof(struct ovs_header),
|
.hdrsize = sizeof(struct ovs_header),
|
||||||
.name = OVS_VPORT_FAMILY,
|
.name = OVS_DATAPATH_FAMILY,
|
||||||
.version = OVS_VPORT_VERSION,
|
.version = OVS_DATAPATH_VERSION,
|
||||||
.maxattr = OVS_VPORT_ATTR_MAX,
|
.maxattr = OVS_DP_ATTR_MAX,
|
||||||
.netnsok = true,
|
.netnsok = true,
|
||||||
SET_PARALLEL_OPS
|
.parallel_ops = true,
|
||||||
};
|
.ops = dp_datapath_genl_ops,
|
||||||
|
.n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
|
||||||
struct genl_multicast_group ovs_dp_vport_multicast_group = {
|
.mcgrps = &ovs_dp_datapath_multicast_group,
|
||||||
.name = OVS_VPORT_MCGROUP
|
.n_mcgrps = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Called with ovs_mutex or RCU read lock. */
|
/* 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);
|
BUG_ON(err < 0);
|
||||||
ovs_unlock();
|
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;
|
return 0;
|
||||||
|
|
||||||
exit_unlock_free:
|
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);
|
BUG_ON(err < 0);
|
||||||
ovs_unlock();
|
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;
|
return 0;
|
||||||
|
|
||||||
exit_unlock_free:
|
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_dp_detach_port(vport);
|
||||||
ovs_unlock();
|
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;
|
return 0;
|
||||||
|
|
||||||
exit_unlock_free:
|
exit_unlock_free:
|
||||||
@ -1947,6 +1948,15 @@ out:
|
|||||||
return skb->len;
|
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[] = {
|
static struct genl_ops dp_vport_genl_ops[] = {
|
||||||
{ .cmd = OVS_VPORT_CMD_NEW,
|
{ .cmd = OVS_VPORT_CMD_NEW,
|
||||||
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
|
.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 dp_vport_genl_family = {
|
||||||
struct genl_family *family;
|
.id = GENL_ID_GENERATE,
|
||||||
struct genl_ops *ops;
|
.hdrsize = sizeof(struct ovs_header),
|
||||||
int n_ops;
|
.name = OVS_VPORT_FAMILY,
|
||||||
struct genl_multicast_group *group;
|
.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[] = {
|
static struct genl_family *dp_genl_families[] = {
|
||||||
{ &dp_datapath_genl_family,
|
&dp_datapath_genl_family,
|
||||||
dp_datapath_genl_ops, ARRAY_SIZE(dp_datapath_genl_ops),
|
&dp_vport_genl_family,
|
||||||
&ovs_dp_datapath_multicast_group },
|
&dp_flow_genl_family,
|
||||||
{ &dp_vport_genl_family,
|
&dp_packet_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 void dp_unregister_genl(int n_families)
|
static void dp_unregister_genl(int n_families)
|
||||||
@ -1998,36 +2007,25 @@ static void dp_unregister_genl(int n_families)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < n_families; 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)
|
static int dp_register_genl(void)
|
||||||
{
|
{
|
||||||
int n_registered;
|
|
||||||
int err;
|
int err;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
n_registered = 0;
|
|
||||||
for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
|
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,
|
err = genl_register_family(dp_genl_families[i]);
|
||||||
f->n_ops);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto error;
|
goto error;
|
||||||
n_registered++;
|
|
||||||
|
|
||||||
if (f->group) {
|
|
||||||
err = genl_register_mc_group(f->family, f->group);
|
|
||||||
if (err)
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
dp_unregister_genl(n_registered);
|
dp_unregister_genl(i);
|
||||||
return err;
|
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 notifier_block ovs_dp_device_notifier;
|
||||||
|
extern struct genl_family dp_vport_genl_family;
|
||||||
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
|
extern struct genl_multicast_group ovs_dp_vport_multicast_group;
|
||||||
|
|
||||||
void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
|
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;
|
struct datapath *dp;
|
||||||
|
|
||||||
dp = vport->dp;
|
dp = vport->dp;
|
||||||
notify = ovs_vport_cmd_build_info(vport, 0, 0,
|
notify = ovs_vport_cmd_build_info(vport, 0, 0, OVS_VPORT_CMD_DEL);
|
||||||
OVS_VPORT_CMD_DEL);
|
|
||||||
ovs_dp_detach_port(vport);
|
ovs_dp_detach_port(vport);
|
||||||
if (IS_ERR(notify)) {
|
if (IS_ERR(notify)) {
|
||||||
netlink_set_err(ovs_dp_get_net(dp)->genl_sock, 0,
|
genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
|
||||||
ovs_dp_vport_multicast_group.id,
|
GROUP_ID(&ovs_dp_vport_multicast_group),
|
||||||
PTR_ERR(notify));
|
PTR_ERR(notify));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
|
genlmsg_multicast_netns(&dp_vport_genl_family,
|
||||||
ovs_dp_vport_multicast_group.id,
|
ovs_dp_get_net(dp), notify, 0,
|
||||||
|
GROUP_ID(&ovs_dp_vport_multicast_group),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
#include <net/genetlink.h>
|
#include <net/genetlink.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
/* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||||
*
|
|
||||||
* This is not (yet) in any upstream kernel. */
|
#undef genl_notify
|
||||||
void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, u32 group,
|
|
||||||
struct nlmsghdr *nlh, gfp_t flags)
|
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;
|
struct sock *sk = net->genl_sock;
|
||||||
int report = 0;
|
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);
|
report = nlmsg_report(nlh);
|
||||||
|
|
||||||
nlmsg_notify(sk, skb, portid, group, report, flags);
|
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 */
|
#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 */
|
#endif /* _LINUX_U64_STATS_SYNC_WRAPPER_H */
|
||||||
|
@ -17,8 +17,84 @@
|
|||||||
#define portid pid
|
#define portid pid
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||||
u32 group, struct nlmsghdr *nlh, gfp_t flags);
|
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)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
|
||||||
static inline struct sk_buff *genlmsg_new_unicast(size_t payload,
|
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
|
#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
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/net.h>
|
#include <linux/net.h>
|
||||||
#include <net/checksum.h>
|
#include <net/checksum.h>
|
||||||
|
#include <net/ip.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
@ -38,6 +39,7 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
|
||||||
bool __net_get_random_once(void *buf, int nbytes, bool *done,
|
bool __net_get_random_once(void *buf, int nbytes, bool *done,
|
||||||
atomic_t *done_key)
|
atomic_t *done_key)
|
||||||
{
|
{
|
||||||
@ -58,3 +60,4 @@ bool __net_get_random_once(void *buf, int nbytes, bool *done,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -163,7 +163,7 @@ static __be64 instance_id_to_tunnel_id(__u8 *iid)
|
|||||||
/* Compute source UDP port for outgoing packet.
|
/* Compute source UDP port for outgoing packet.
|
||||||
* Currently we use the flow hash.
|
* 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);
|
u32 hash = skb_get_rxhash(skb);
|
||||||
unsigned int range;
|
unsigned int range;
|
||||||
@ -177,7 +177,7 @@ static u16 get_src_port(struct sk_buff *skb)
|
|||||||
sizeof(*pkt_key) / sizeof(u32), 0);
|
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;
|
range = (high - low) + 1;
|
||||||
return (((u64) hash * range) >> 32) + low;
|
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,
|
static void lisp_build_header(const struct vport *vport,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct net *net = ovs_dp_get_net(vport->dp);
|
||||||
struct lisp_port *lisp_port = lisp_vport(vport);
|
struct lisp_port *lisp_port = lisp_vport(vport);
|
||||||
struct udphdr *udph = udp_hdr(skb);
|
struct udphdr *udph = udp_hdr(skb);
|
||||||
struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
|
struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
|
||||||
const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
|
const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
|
||||||
|
|
||||||
udph->dest = lisp_port->dst_port;
|
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->check = 0;
|
||||||
udph->len = htons(skb->len - skb_transport_offset(skb));
|
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)
|
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);
|
struct vxlan_port *vxlan_port = vxlan_vport(vport);
|
||||||
__be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
|
__be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
@ -172,7 +173,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
|
|||||||
|
|
||||||
skb->local_df = 1;
|
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);
|
src_port = vxlan_src_port(port_min, port_max, skb);
|
||||||
|
|
||||||
err = vxlan_xmit_skb(vxlan_port->vs, rt, 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;
|
struct vport *vport;
|
||||||
size_t alloc_size;
|
size_t alloc_size;
|
||||||
|
int i;
|
||||||
|
|
||||||
alloc_size = sizeof(struct vport);
|
alloc_size = sizeof(struct vport);
|
||||||
if (priv_size) {
|
if (priv_size) {
|
||||||
@ -145,6 +146,12 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops,
|
|||||||
return ERR_PTR(-ENOMEM);
|
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);
|
spin_lock_init(&vport->stats_lock);
|
||||||
|
|
||||||
return vport;
|
return vport;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user