summaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-11-19 16:39:42 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-19 16:39:42 -0500
commit091e0662ee2c37867ad918ce7b6ddd17f0e090e2 (patch)
treee5a066d8f83d8822d448421019a4503f361295f9 /net/openvswitch
parentdbde497966804e63a38fdedc1e3815e77097efc2 (diff)
parent2a94fe48f32ccf7321450a2cc07f2b724a444e5b (diff)
downloadlinux-091e0662ee2c37867ad918ce7b6ddd17f0e090e2.tar.bz2
Merge branch 'genetlink_mcast'
Johannes Berg says: ==================== genetlink: clean up multicast group APIs The generic netlink multicast group registration doesn't have to be dynamic, and can thus be simplified just like I did with the ops. This removes some complexity in registration code. Additionally, two users of generic netlink already use multicast groups in a wrong way, add workarounds for those two to keep the userspace API working, but at the same time make them not clash with other users of multicast groups as might happen now. While making it all a bit easier, also prevent such abuse by adding checks to the APIs so each family can only use the groups it owns. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/datapath.c49
-rw-r--r--net/openvswitch/datapath.h1
-rw-r--r--net/openvswitch/dp_notify.c11
3 files changed, 29 insertions, 32 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 91e1c927a465..1de4d281e3f1 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -61,11 +61,11 @@
int ovs_net_id __read_mostly;
-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 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,
+ 0, info->nlhdr, GFP_KERNEL);
}
/**
@@ -877,10 +877,10 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
ovs_unlock();
if (!IS_ERR(reply))
- ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
+ ovs_notify(&dp_flow_genl_family, 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,
+ 0, PTR_ERR(reply));
return 0;
err_flow_free:
@@ -990,7 +990,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
ovs_flow_free(flow, true);
ovs_unlock();
- ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
+ ovs_notify(&dp_flow_genl_family, reply, info);
return 0;
unlock:
ovs_unlock();
@@ -1237,7 +1237,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, reply, info);
return 0;
err_destroy_local_port:
@@ -1302,7 +1302,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, reply, info);
return 0;
unlock:
@@ -1326,14 +1326,14 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
info->snd_seq, OVS_DP_CMD_NEW);
if (IS_ERR(reply)) {
err = PTR_ERR(reply);
- netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
- ovs_dp_datapath_multicast_group.id, err);
+ genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
+ 0, err);
err = 0;
goto unlock;
}
ovs_unlock();
- ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
+ ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
unlock:
@@ -1425,7 +1425,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
};
-static struct genl_family dp_vport_genl_family = {
+struct genl_family dp_vport_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = sizeof(struct ovs_header),
.name = OVS_VPORT_FAMILY,
@@ -1595,7 +1595,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto exit_unlock;
}
- ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
+ ovs_notify(&dp_vport_genl_family, reply, info);
exit_unlock:
ovs_unlock();
@@ -1642,7 +1642,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, reply, info);
return 0;
exit_free:
@@ -1679,7 +1679,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
err = 0;
ovs_dp_detach_port(vport);
- ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
+ ovs_notify(&dp_vport_genl_family, reply, info);
exit_unlock:
ovs_unlock();
@@ -1781,7 +1781,7 @@ struct genl_family_and_ops {
struct genl_family *family;
const struct genl_ops *ops;
int n_ops;
- struct genl_multicast_group *group;
+ const struct genl_multicast_group *group;
};
static const struct genl_family_and_ops dp_genl_families[] = {
@@ -1817,17 +1817,14 @@ static int dp_register_genl(void)
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);
+ f->family->ops = f->ops;
+ f->family->n_ops = f->n_ops;
+ f->family->mcgrps = f->group;
+ f->family->n_mcgrps = f->group ? 1 : 0;
+ err = genl_register_family(f->family);
if (err)
goto error;
n_registered++;
-
- if (f->group) {
- err = genl_register_mc_group(f->family, f->group);
- if (err)
- goto error;
- }
}
return 0;
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index d3d14a58aa91..4067ea41be28 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -177,6 +177,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 *);
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c
index 5c2dab276109..2c631fe76be1 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -34,15 +34,14 @@ static void dp_detach_port_notify(struct vport *vport)
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,
+ 0, PTR_ERR(notify));
return;
}
- genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
- ovs_dp_vport_multicast_group.id,
- GFP_KERNEL);
+ genlmsg_multicast_netns(&dp_vport_genl_family,
+ ovs_dp_get_net(dp), notify, 0,
+ 0, GFP_KERNEL);
}
void ovs_dp_notify_wq(struct work_struct *work)