* [RFC 0/3] netlink/generic netlink multicast group rework
@ 2007-07-04 14:30 Johannes Berg
2007-07-04 14:30 ` [RFC 1/3] netlink: allocate group bitmaps dynamically Johannes Berg
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Johannes Berg @ 2007-07-04 14:30 UTC (permalink / raw)
To: netdev; +Cc: hadi, Patrick McHardy
This is just a repost of the patches that I posted previously
because they were buried deeply in the ACPI thread and I'm
hoping that now other people will also take a look.
johannes
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC 1/3] netlink: allocate group bitmaps dynamically
2007-07-04 14:30 [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
@ 2007-07-04 14:30 ` Johannes Berg
2007-07-04 14:30 ` [RFC 2/3] netlink: allow removing multicast groups Johannes Berg
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2007-07-04 14:30 UTC (permalink / raw)
To: netdev; +Cc: hadi, Patrick McHardy
[-- Attachment #1: 053-netlink-groups.patch --]
[-- Type: text/plain, Size: 5234 bytes --]
Allow changing the number of groups for a netlink family
after it has been created, use RCU to protect the listeners
bitmap keeping netlink_has_listeners() lock-free.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/linux/netlink.h | 1
net/netlink/af_netlink.c | 86 +++++++++++++++++++++++++++++++++++------------
2 files changed, 66 insertions(+), 21 deletions(-)
--- wireless-dev.orig/net/netlink/af_netlink.c 2007-07-04 00:43:55.297749881 +0200
+++ wireless-dev/net/netlink/af_netlink.c 2007-07-04 01:12:17.046331215 +0200
@@ -62,6 +62,7 @@
#include <net/netlink.h>
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
+#define NLGRPLONGS(x) (NLGRPSZ(x)/sizeof(unsigned long))
struct netlink_sock {
/* struct sock has to be the first member of netlink_sock */
@@ -314,10 +315,12 @@ netlink_update_listeners(struct sock *sk
unsigned long mask;
unsigned int i;
- for (i = 0; i < NLGRPSZ(tbl->groups)/sizeof(unsigned long); i++) {
+ for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
mask = 0;
- sk_for_each_bound(sk, node, &tbl->mc_list)
- mask |= nlk_sk(sk)->groups[i];
+ sk_for_each_bound(sk, node, &tbl->mc_list) {
+ if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
+ mask |= nlk_sk(sk)->groups[i];
+ }
tbl->listeners[i] = mask;
}
/* this function is only called with the netlink table "grabbed", which
@@ -555,26 +558,37 @@ netlink_update_subscriptions(struct sock
nlk->subscriptions = subscriptions;
}
-static int netlink_alloc_groups(struct sock *sk)
+static int netlink_realloc_groups(struct sock *sk)
{
struct netlink_sock *nlk = nlk_sk(sk);
unsigned int groups;
+ unsigned long *new_groups;
int err = 0;
netlink_lock_table();
groups = nl_table[sk->sk_protocol].groups;
if (!nl_table[sk->sk_protocol].registered)
err = -ENOENT;
- netlink_unlock_table();
if (err)
- return err;
+ goto out_unlock;
- nlk->groups = kzalloc(NLGRPSZ(groups), GFP_KERNEL);
- if (nlk->groups == NULL)
- return -ENOMEM;
+ if (nlk->ngroups >= groups)
+ goto out_unlock;
+
+ new_groups = krealloc(nlk->groups, NLGRPSZ(groups), GFP_KERNEL);
+ if (new_groups == NULL) {
+ err = -ENOMEM;
+ goto out_unlock;
+ }
+ memset((char*)new_groups + NLGRPSZ(nlk->ngroups), 0,
+ NLGRPSZ(groups) - NLGRPSZ(nlk->ngroups));
+
+ nlk->groups = new_groups;
nlk->ngroups = groups;
- return 0;
+ out_unlock:
+ netlink_unlock_table();
+ return err;
}
static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
@@ -591,11 +605,9 @@ static int netlink_bind(struct socket *s
if (nladdr->nl_groups) {
if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
- if (nlk->groups == NULL) {
- err = netlink_alloc_groups(sk);
- if (err)
- return err;
- }
+ err = netlink_realloc_groups(sk);
+ if (err)
+ return err;
}
if (nlk->pid) {
@@ -839,10 +851,18 @@ retry:
int netlink_has_listeners(struct sock *sk, unsigned int group)
{
int res = 0;
+ unsigned long *listeners;
BUG_ON(!(nlk_sk(sk)->flags & NETLINK_KERNEL_SOCKET));
+
+ rcu_read_lock();
+ listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
+
if (group - 1 < nl_table[sk->sk_protocol].groups)
- res = test_bit(group - 1, nl_table[sk->sk_protocol].listeners);
+ res = test_bit(group - 1, listeners);
+
+ rcu_read_unlock();
+
return res;
}
EXPORT_SYMBOL_GPL(netlink_has_listeners);
@@ -1037,11 +1057,9 @@ static int netlink_setsockopt(struct soc
if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
- if (nlk->groups == NULL) {
- err = netlink_alloc_groups(sk);
- if (err)
- return err;
- }
+ err = netlink_realloc_groups(sk);
+ if (err)
+ return err;
if (!val || val - 1 >= nlk->ngroups)
return -EINVAL;
netlink_table_grab();
@@ -1328,6 +1346,32 @@ out_sock_release:
return NULL;
}
+int netlink_change_ngroups(int unit, unsigned int groups)
+{
+ unsigned long *listeners, old = NULL;
+ int err = 0;
+
+ netlink_table_grab();
+ if (NLGRPSZ(nl_table[unit].groups) < NLGRPSZ(groups)) {
+ listeners = kzalloc(NLGRPSZ(groups), GFP_ATOMIC);
+ if (!listeners) {
+ err = -ENOMEM;
+ goto out_ungrab;
+ }
+ old = nl_table[unit].listeners;
+ memcpy(listeners, old, NLGRPSZ(nl_table[unit].groups));
+ rcu_assign_pointer(nl_table[unit].listeners, listeners);
+ }
+ nl_table[unit].groups = groups;
+
+ out_ungrab:
+ netlink_table_ungrab();
+ synchronize_rcu();
+ kfree(old);
+ return err;
+}
+EXPORT_SYMBOL(netlink_change_ngroups);
+
void netlink_set_nonroot(int protocol, unsigned int flags)
{
if ((unsigned int)protocol < MAX_LINKS)
--- wireless-dev.orig/include/linux/netlink.h 2007-07-04 00:43:20.437749881 +0200
+++ wireless-dev/include/linux/netlink.h 2007-07-04 01:10:34.986331215 +0200
@@ -161,6 +161,7 @@ extern struct sock *netlink_kernel_creat
void (*input)(struct sock *sk, int len),
struct mutex *cb_mutex,
struct module *module);
+extern int netlink_change_ngroups(int unit, unsigned int groups);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
--
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC 2/3] netlink: allow removing multicast groups
2007-07-04 14:30 [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
2007-07-04 14:30 ` [RFC 1/3] netlink: allocate group bitmaps dynamically Johannes Berg
@ 2007-07-04 14:30 ` Johannes Berg
2007-07-04 14:30 ` [RFC 3/3] generic netlink: dynamic " Johannes Berg
2007-07-16 8:48 ` [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
3 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2007-07-04 14:30 UTC (permalink / raw)
To: netdev; +Cc: hadi, Patrick McHardy
[-- Attachment #1: 054-netlink-mc-groups.patch --]
[-- Type: text/plain, Size: 3370 bytes --]
Allow kicking listeners out of a multicast group when necessary
(for example if that group is going to be removed.)
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/linux/netlink.h | 1 +
net/netlink/af_netlink.c | 47 ++++++++++++++++++++++++++++++++++-------------
2 files changed, 35 insertions(+), 13 deletions(-)
--- wireless-dev.orig/include/linux/netlink.h 2007-07-04 00:43:12.727749881 +0200
+++ wireless-dev/include/linux/netlink.h 2007-07-04 00:43:13.277749881 +0200
@@ -162,6 +162,7 @@ extern struct sock *netlink_kernel_creat
struct mutex *cb_mutex,
struct module *module);
extern int netlink_change_ngroups(int unit, unsigned int groups);
+extern void netlink_clear_multicast_users(int unit, unsigned int group);
extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
extern int netlink_has_listeners(struct sock *sk, unsigned int group);
extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
--- wireless-dev.orig/net/netlink/af_netlink.c 2007-07-04 00:43:12.727749881 +0200
+++ wireless-dev/net/netlink/af_netlink.c 2007-07-04 00:43:13.277749881 +0200
@@ -1027,6 +1027,24 @@ void netlink_set_err(struct sock *ssk, u
read_unlock(&nl_table_lock);
}
+static void netlink_update_socket_mc(struct netlink_sock *nlk,
+ unsigned int group,
+ int is_new)
+{
+ int old, new = !!is_new, subscriptions;
+
+ netlink_table_grab();
+ old = test_bit(group - 1, nlk->groups);
+ subscriptions = nlk->subscriptions - old + new;
+ if (new)
+ __set_bit(group - 1, nlk->groups);
+ else
+ __clear_bit(group - 1, nlk->groups);
+ netlink_update_subscriptions(&nlk->sk, subscriptions);
+ netlink_update_listeners(&nlk->sk);
+ netlink_table_ungrab();
+}
+
static int netlink_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
@@ -1052,9 +1070,6 @@ static int netlink_setsockopt(struct soc
break;
case NETLINK_ADD_MEMBERSHIP:
case NETLINK_DROP_MEMBERSHIP: {
- unsigned int subscriptions;
- int old, new = optname == NETLINK_ADD_MEMBERSHIP ? 1 : 0;
-
if (!netlink_capable(sock, NL_NONROOT_RECV))
return -EPERM;
err = netlink_realloc_groups(sk);
@@ -1062,16 +1077,8 @@ static int netlink_setsockopt(struct soc
return err;
if (!val || val - 1 >= nlk->ngroups)
return -EINVAL;
- netlink_table_grab();
- old = test_bit(val - 1, nlk->groups);
- subscriptions = nlk->subscriptions - old + new;
- if (new)
- __set_bit(val - 1, nlk->groups);
- else
- __clear_bit(val - 1, nlk->groups);
- netlink_update_subscriptions(sk, subscriptions);
- netlink_update_listeners(sk);
- netlink_table_ungrab();
+ netlink_update_socket_mc(nlk, val,
+ optname == NETLINK_ADD_MEMBERSHIP);
err = 0;
break;
}
@@ -1372,6 +1379,20 @@ int netlink_change_ngroups(int unit, uns
}
EXPORT_SYMBOL(netlink_change_ngroups);
+void netlink_clear_multicast_users(int unit, unsigned int group)
+{
+ struct sock *sk;
+ struct hlist_node *node;
+
+ read_lock(&nl_table_lock);
+
+ sk_for_each_bound(sk, node, &nl_table[unit].mc_list)
+ netlink_update_socket_mc(nlk_sk(sk), group, 0);
+
+ read_unlock(&nl_table_lock);
+}
+EXPORT_SYMBOL(netlink_clear_multicast_users);
+
void netlink_set_nonroot(int protocol, unsigned int flags)
{
if ((unsigned int)protocol < MAX_LINKS)
--
^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC 3/3] generic netlink: dynamic multicast groups
2007-07-04 14:30 [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
2007-07-04 14:30 ` [RFC 1/3] netlink: allocate group bitmaps dynamically Johannes Berg
2007-07-04 14:30 ` [RFC 2/3] netlink: allow removing multicast groups Johannes Berg
@ 2007-07-04 14:30 ` Johannes Berg
2007-07-16 8:48 ` [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
3 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2007-07-04 14:30 UTC (permalink / raw)
To: netdev; +Cc: hadi, Patrick McHardy
[-- Attachment #1: 055-genl-multicast-groups.patch --]
[-- Type: text/plain, Size: 10370 bytes --]
Introduce API to dynamically register and unregister multicast groups.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
include/linux/genetlink.h | 13 +++
include/net/genetlink.h | 22 +++++
net/netlink/genetlink.c | 190 ++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 218 insertions(+), 7 deletions(-)
--- wireless-dev.orig/include/net/genetlink.h 2007-07-04 00:41:56.067749881 +0200
+++ wireless-dev/include/net/genetlink.h 2007-07-04 00:43:13.837749881 +0200
@@ -5,6 +5,22 @@
#include <net/netlink.h>
/**
+ * struct genl_multicast_group - generic netlink multicast group
+ * @name: name of the multicast group, names are per-family
+ * @id: multicast group ID, assigned by the core, to use with
+ * genlmsg_multicast().
+ * @list: list entry for linking
+ * @family: pointer to family, need not be set before registering
+ */
+struct genl_multicast_group
+{
+ struct genl_family *family; /* private */
+ struct list_head list; /* private */
+ char name[GENL_NAMSIZ];
+ u32 id;
+};
+
+/**
* struct genl_family - generic netlink family
* @id: protocol family idenfitier
* @hdrsize: length of user specific header in bytes
@@ -14,6 +30,7 @@
* @attrbuf: buffer to store parsed attributes
* @ops_list: list of all assigned operations
* @family_list: family list
+ * @mcast_groups: multicast groups list
*/
struct genl_family
{
@@ -25,6 +42,7 @@ struct genl_family
struct nlattr ** attrbuf; /* private */
struct list_head ops_list; /* private */
struct list_head family_list; /* private */
+ struct list_head mcast_groups; /* private */
};
/**
@@ -73,6 +91,10 @@ extern int genl_register_family(struct g
extern int genl_unregister_family(struct genl_family *family);
extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
+extern int genl_register_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp);
+extern void genl_unregister_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp);
extern struct sock *genl_sock;
--- wireless-dev.orig/net/netlink/genetlink.c 2007-07-04 00:41:56.217749881 +0200
+++ wireless-dev/net/netlink/genetlink.c 2007-07-04 00:43:13.837749881 +0200
@@ -3,6 +3,7 @@
*
* Authors: Jamal Hadi Salim
* Thomas Graf <tgraf@suug.ch>
+ * Johannes Berg <johannes@sipsolutions.net>
*/
#include <linux/module.h>
@@ -13,6 +14,7 @@
#include <linux/string.h>
#include <linux/skbuff.h>
#include <linux/mutex.h>
+#include <linux/bitmap.h>
#include <net/sock.h>
#include <net/genetlink.h>
@@ -42,6 +44,17 @@ static void genl_unlock(void)
#define GENL_FAM_TAB_MASK (GENL_FAM_TAB_SIZE - 1)
static struct list_head family_ht[GENL_FAM_TAB_SIZE];
+/*
+ * Bitmap of multicast groups that are currently in use.
+ *
+ * To avoid an allocation at boot of just one unsigned long,
+ * declare it global instead.
+ * Bit 0 is marked as already used since group 0 is invalid,
+ * bit 1 is marked as already used since group 1 is the controller group.
+ */
+static unsigned long mc_group_start = 0x3;
+static unsigned long *mc_groups = &mc_group_start;
+static unsigned long mc_groups_longs = 1;
static int genl_ctrl_event(int event, void *data);
@@ -116,6 +129,77 @@ static inline u16 genl_generate_id(void)
return id_gen_idx;
}
+int genl_register_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp)
+{
+ int id = find_first_zero_bit(mc_groups,
+ mc_groups_longs * BITS_PER_LONG);
+ unsigned long *new_groups;
+ size_t nlen = (mc_groups_longs + 1) * sizeof(unsigned long);
+ int err;
+
+ genl_lock();
+
+ if (id >= mc_groups_longs * BITS_PER_LONG) {
+ if (mc_groups == &mc_group_start) {
+ new_groups = kzalloc(nlen, GFP_KERNEL);
+ if (!mc_groups) {
+ err = -ENOMEM;
+ goto out;
+ }
+ mc_groups = new_groups;
+ *mc_groups = mc_group_start;
+ } else {
+ new_groups = krealloc(mc_groups, nlen, GFP_KERNEL);
+ if (!new_groups) {
+ err = -ENOMEM;
+ goto out;
+ }
+ mc_groups = new_groups;
+ mc_groups[mc_groups_longs] = 0;
+ }
+ mc_groups_longs++;
+ }
+
+ err = netlink_change_ngroups(NETLINK_GENERIC,
+ sizeof(unsigned long) * NETLINK_GENERIC);
+ if (err)
+ goto out;
+
+ grp->id = id;
+ set_bit(id, mc_groups);
+ list_add_tail(&grp->list, &family->mcast_groups);
+ grp->family = family;
+
+ genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, grp);
+ out:
+ genl_unlock();
+ return 0;
+}
+EXPORT_SYMBOL(genl_register_mc_group);
+
+void genl_unregister_mc_group(struct genl_family *family,
+ struct genl_multicast_group *grp)
+{
+ BUG_ON(grp->family != family);
+ genl_lock();
+ netlink_clear_multicast_users(NETLINK_GENERIC, grp->id);
+ clear_bit(grp->id, mc_groups);
+ list_del(&grp->list);
+ genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
+ grp->id = 0;
+ grp->family = NULL;
+ genl_unlock();
+}
+
+static void genl_unregister_mc_groups(struct genl_family *family)
+{
+ struct genl_multicast_group *grp, *tmp;
+
+ list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list)
+ genl_unregister_mc_group(family, grp);
+}
+
/**
* genl_register_ops - register generic netlink operations
* @family: generic netlink family
@@ -216,6 +300,7 @@ int genl_register_family(struct genl_fam
goto errout;
INIT_LIST_HEAD(&family->ops_list);
+ INIT_LIST_HEAD(&family->mcast_groups);
genl_lock();
@@ -275,6 +360,8 @@ int genl_unregister_family(struct genl_f
{
struct genl_family *rc;
+ genl_unregister_mc_groups(family);
+
genl_lock();
list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
@@ -410,6 +497,67 @@ static int ctrl_fill_info(struct genl_fa
nla_nest_end(skb, nla_ops);
}
+ if (!list_empty(&family->mcast_groups)) {
+ struct genl_multicast_group *grp;
+ struct nlattr *nla_grps;
+ int idx = 1;
+
+ nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);
+ if (nla_grps == NULL)
+ goto nla_put_failure;
+
+ list_for_each_entry(grp, &family->mcast_groups, list) {
+ struct nlattr *nest;
+
+ nest = nla_nest_start(skb, idx++);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id);
+ NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME,
+ grp->name);
+
+ nla_nest_end(skb, nest);
+ }
+ nla_nest_end(skb, nla_grps);
+ }
+
+ return genlmsg_end(skb, hdr);
+
+nla_put_failure:
+ return genlmsg_cancel(skb, hdr);
+}
+
+static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 pid,
+ u32 seq, u32 flags, struct sk_buff *skb,
+ u8 cmd)
+{
+ void *hdr;
+ struct nlattr *nla_grps;
+ struct nlattr *nest;
+
+ hdr = genlmsg_put(skb, pid, seq, &genl_ctrl, flags, cmd);
+ if (hdr == NULL)
+ return -1;
+
+ NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name);
+ NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id);
+
+ nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);
+ if (nla_grps == NULL)
+ goto nla_put_failure;
+
+ nest = nla_nest_start(skb, 1);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ NLA_PUT_U32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id);
+ NLA_PUT_STRING(skb, CTRL_ATTR_MCAST_GRP_NAME,
+ grp->name);
+
+ nla_nest_end(skb, nest);
+ nla_nest_end(skb, nla_grps);
+
return genlmsg_end(skb, hdr);
nla_put_failure:
@@ -453,8 +601,8 @@ errout:
return skb->len;
}
-static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
- int seq, u8 cmd)
+static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
+ u32 pid, int seq, u8 cmd)
{
struct sk_buff *skb;
int err;
@@ -472,6 +620,25 @@ static struct sk_buff *ctrl_build_msg(st
return skb;
}
+static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp,
+ u32 pid, int seq, u8 cmd)
+{
+ struct sk_buff *skb;
+ int err;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (skb == NULL)
+ return ERR_PTR(-ENOBUFS);
+
+ err = ctrl_fill_mcgrp_info(grp, pid, seq, 0, skb, cmd);
+ if (err < 0) {
+ nlmsg_free(skb);
+ return ERR_PTR(err);
+ }
+
+ return skb;
+}
+
static const struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] = {
[CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 },
[CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING,
@@ -501,8 +668,8 @@ static int ctrl_getfamily(struct sk_buff
goto errout;
}
- msg = ctrl_build_msg(res, info->snd_pid, info->snd_seq,
- CTRL_CMD_NEWFAMILY);
+ msg = ctrl_build_family_msg(res, info->snd_pid, info->snd_seq,
+ CTRL_CMD_NEWFAMILY);
if (IS_ERR(msg)) {
err = PTR_ERR(msg);
goto errout;
@@ -523,7 +690,15 @@ static int genl_ctrl_event(int event, vo
switch (event) {
case CTRL_CMD_NEWFAMILY:
case CTRL_CMD_DELFAMILY:
- msg = ctrl_build_msg(data, 0, 0, event);
+ msg = ctrl_build_family_msg(data, 0, 0, event);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL);
+ break;
+ case CTRL_CMD_NEWMCAST_GRP:
+ case CTRL_CMD_DELMCAST_GRP:
+ msg = ctrl_build_mcgrp_msg(data, 0, 0, event);
if (IS_ERR(msg))
return PTR_ERR(msg);
@@ -557,8 +732,9 @@ static int __init genl_init(void)
goto errout_register;
netlink_set_nonroot(NETLINK_GENERIC, NL_NONROOT_RECV);
- genl_sock = netlink_kernel_create(NETLINK_GENERIC, GENL_MAX_ID,
- genl_rcv, NULL, THIS_MODULE);
+ /* only one static multicast group */
+ genl_sock = netlink_kernel_create(NETLINK_GENERIC, 1, genl_rcv,
+ NULL, THIS_MODULE);
if (genl_sock == NULL)
panic("GENL: Cannot initialize generic netlink\n");
--- wireless-dev.orig/include/linux/genetlink.h 2007-07-04 00:41:56.097749881 +0200
+++ wireless-dev/include/linux/genetlink.h 2007-07-04 00:43:13.867749881 +0200
@@ -39,6 +39,9 @@ enum {
CTRL_CMD_NEWOPS,
CTRL_CMD_DELOPS,
CTRL_CMD_GETOPS,
+ CTRL_CMD_NEWMCAST_GRP,
+ CTRL_CMD_DELMCAST_GRP,
+ CTRL_CMD_GETMCAST_GRP, /* unused */
__CTRL_CMD_MAX,
};
@@ -52,6 +55,7 @@ enum {
CTRL_ATTR_HDRSIZE,
CTRL_ATTR_MAXATTR,
CTRL_ATTR_OPS,
+ CTRL_ATTR_MCAST_GROUPS,
__CTRL_ATTR_MAX,
};
@@ -66,4 +70,13 @@ enum {
#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
+enum {
+ CTRL_ATTR_MCAST_GRP_UNSPEC,
+ CTRL_ATTR_MCAST_GRP_NAME,
+ CTRL_ATTR_MCAST_GRP_ID,
+ __CTRL_ATTR_MCAST_GRP_MAX,
+};
+
+#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
+
#endif /* __LINUX_GENERIC_NETLINK_H */
--
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC 0/3] netlink/generic netlink multicast group rework
2007-07-04 14:30 [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
` (2 preceding siblings ...)
2007-07-04 14:30 ` [RFC 3/3] generic netlink: dynamic " Johannes Berg
@ 2007-07-16 8:48 ` Johannes Berg
2007-07-16 13:42 ` Patrick McHardy
3 siblings, 1 reply; 7+ messages in thread
From: Johannes Berg @ 2007-07-16 8:48 UTC (permalink / raw)
To: netdev; +Cc: hadi, Patrick McHardy
[-- Attachment #1: Type: text/plain, Size: 666 bytes --]
On Wed, 2007-07-04 at 16:30 +0200, Johannes Berg wrote:
> This is just a repost of the patches that I posted previously
> because they were buried deeply in the ACPI thread and I'm
> hoping that now other people will also take a look.
Ping? Has anybody had a chance to look into this? I've been running
regular work on my notebook with this ever since posting and it all
works fine; the ACPI people would like to see this in to base the ACPI
notification on it. I don't care all that much right now but if they
don't base their acpi notification on it then these patches will need to
be updated to give acpi a stable family/multicast number.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC 0/3] netlink/generic netlink multicast group rework
2007-07-16 8:48 ` [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
@ 2007-07-16 13:42 ` Patrick McHardy
2007-07-17 10:28 ` Johannes Berg
0 siblings, 1 reply; 7+ messages in thread
From: Patrick McHardy @ 2007-07-16 13:42 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev, hadi
Johannes Berg wrote:
> On Wed, 2007-07-04 at 16:30 +0200, Johannes Berg wrote:
>
>>This is just a repost of the patches that I posted previously
>>because they were buried deeply in the ACPI thread and I'm
>>hoping that now other people will also take a look.
>
>
> Ping? Has anybody had a chance to look into this?
Sorry, I'm behind with my plans. I'll try to get to it ASAP,
but I don't want to stand in your way until then. So here's
a preliminary ACK based on my first swift review, in case
I notice something later I can just send a patch on top.
Jamal also asked me to add:
Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC 0/3] netlink/generic netlink multicast group rework
2007-07-16 13:42 ` Patrick McHardy
@ 2007-07-17 10:28 ` Johannes Berg
0 siblings, 0 replies; 7+ messages in thread
From: Johannes Berg @ 2007-07-17 10:28 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev, hadi
[-- Attachment #1: Type: text/plain, Size: 586 bytes --]
On Mon, 2007-07-16 at 15:42 +0200, Patrick McHardy wrote:
> Sorry, I'm behind with my plans. I'll try to get to it ASAP,
> but I don't want to stand in your way until then.
Don't want to hurry you or anything, just thought maybe it had dropped
off.
> So here's
> a preliminary ACK based on my first swift review, in case
> I notice something later I can just send a patch on top.
Just let me know if you find any problems, I can fix them as well. For
now I'll resend for inclusion then I guess and see that the ACPI guys
get a ping to update their code.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2007-07-17 10:29 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-04 14:30 [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
2007-07-04 14:30 ` [RFC 1/3] netlink: allocate group bitmaps dynamically Johannes Berg
2007-07-04 14:30 ` [RFC 2/3] netlink: allow removing multicast groups Johannes Berg
2007-07-04 14:30 ` [RFC 3/3] generic netlink: dynamic " Johannes Berg
2007-07-16 8:48 ` [RFC 0/3] netlink/generic netlink multicast group rework Johannes Berg
2007-07-16 13:42 ` Patrick McHardy
2007-07-17 10:28 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).