* RE: net/usb/ax88179_178a driver broken in linux-3.12
From: David Laight @ 2013-11-19 13:56 UTC (permalink / raw)
To: Mark Lord, Eric Dumazet, Ming Lei, davem, netdev
In-Reply-To: <528B6B5A.8000003@pobox.com>
> From: Mark Lord [mailto:mlord@pobox.com]
> On 13-11-19 05:04 AM, David Laight wrote:
> >
> > Which changes did you revert?
>
> Just the bits that changed how the headroom/tailroom sizes
> were checked and adjusted. See attachment for the revert patch
> I am using here. My mailer unfortunately likes to mangle inline patches.
>
> =========snip===========
> Revert USB 3.0 network driver changes that break the adapter (lockups)
> in 3.12. This just puts back the original code from previous kernels.
>
> Signed-off-by: Mark Lord <mlord@pobox.com>
>
> --- linux/drivers/net/usb/ax88179_178a.c.orig 2013-11-03 18:41:51.000000000 -0500
> +++ linux/drivers/net/usb/ax88179_178a.c 2013-11-17 13:23:39.525734277 -0500
> @@ -1177,18 +1177,31 @@
> int frame_size = dev->maxpacket;
> int mss = skb_shinfo(skb)->gso_size;
> int headroom;
> + int tailroom;
>
> tx_hdr1 = skb->len;
> tx_hdr2 = mss;
> if (((skb->len + 8) % frame_size) == 0)
> tx_hdr2 |= 0x80008000; /* Enable padding */
>
> - headroom = skb_headroom(skb) - 8;
> + headroom = skb_headroom(skb);
> + tailroom = skb_tailroom(skb);
>
> - if ((skb_header_cloned(skb) || headroom < 0) &&
> - pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) {
> + if (!skb_header_cloned(skb) &&
> + !skb_cloned(skb) &&
> + (headroom + tailroom) >= 8) {
> + if (headroom < 8) {
> + skb->data = memmove(skb->head + 8, skb->data, skb->len);
> + skb_set_tail_pointer(skb, skb->len);
> + }
> + } else {
> + struct sk_buff *skb2;
> +
> + skb2 = skb_copy_expand(skb, 8, 0, flags);
> dev_kfree_skb_any(skb);
> - return NULL;
> + skb = skb2;
> + if (!skb)
> + return NULL;
> }
>
> skb_push(skb, 4);
At a guess it will be a difference between pskb_expand_head() and
skb_copy_expand(). The latter probably generates a linear skb.
The extra check for skb_cloned() probably also applies - and forces
a data copy.
Have you tried the patch to xhci-ring.c?
David
^ permalink raw reply
* Please reply urgently
From: Steve Morgan @ 2013-11-19 13:27 UTC (permalink / raw)
[-- Attachment #1: Type: text/plain, Size: 190 bytes --]
Good day,
I am yet to receive your reply on my last email to you.
Please here is an attachment of the email resend in Polish, please read
and reply.
Best Regards
Mr. Steve Morgan
[-- Attachment #2: Dzie__dobry.pdf --]
[-- Type: application/pdf, Size: 186272 bytes --]
^ permalink raw reply
* Re: net/usb/ax88179_178a driver broken in linux-3.12
From: Mark Lord @ 2013-11-19 14:02 UTC (permalink / raw)
To: David Laight, Eric Dumazet, Ming Lei, davem, netdev, Linux Kernel,
stable
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B7431@saturn3.aculab.com>
[-- Attachment #1: Type: text/plain, Size: 1035 bytes --]
On 13-11-19 05:04 AM, David Laight wrote:
>> From: Mark Lord
..
>> except the ax88179_178a driver still does not work in linux-3.12,
>> whereas it works fine in all earlier kernels.
>>
>> That's a regression.
>> And a simple revert (earlier in this thread) fixes it.
>> So.. let's revert it for now, until a proper xhci compatible patch is produced.
...
> There is a patch to xhci-ring.c that should fix the SG problem.
> http://www.spinics.net/lists/linux-usb/msg97176.html
>
> I think it should apply to the 3.12 sources.
I am running with that patch here now (thanks),
and it too appears to prevent the lockups.
But is this patch upstream already?
If yes, then it needs to get pushed out to -stable for 3.12 at least.
If not upstream, then the revert is probably safest for -stable,
rather than new code that has never been upstream before.
Both patches are attached to this email.
One or the other is required for the USB 3.0 network adapters to function in 3.12.
Thanks
--
Mark Lord
Real-Time Remedies Inc.
mlord@pobox.com
[-- Attachment #2: 51_ax88179_178a_revert_3.12_lockups.patch --]
[-- Type: text/x-patch, Size: 1250 bytes --]
Revert USB 3.0 network driver changes that break the adapter (lockups)
in 3.12. This just puts back the original code from previous kernels.
Signed-off-by: Mark Lord <mlord@pobox.com>
--- linux/drivers/net/usb/ax88179_178a.c.orig 2013-11-03 18:41:51.000000000 -0500
+++ linux/drivers/net/usb/ax88179_178a.c 2013-11-17 13:23:39.525734277 -0500
@@ -1177,18 +1177,31 @@
int frame_size = dev->maxpacket;
int mss = skb_shinfo(skb)->gso_size;
int headroom;
+ int tailroom;
tx_hdr1 = skb->len;
tx_hdr2 = mss;
if (((skb->len + 8) % frame_size) == 0)
tx_hdr2 |= 0x80008000; /* Enable padding */
- headroom = skb_headroom(skb) - 8;
+ headroom = skb_headroom(skb);
+ tailroom = skb_tailroom(skb);
- if ((skb_header_cloned(skb) || headroom < 0) &&
- pskb_expand_head(skb, headroom < 0 ? 8 : 0, 0, GFP_ATOMIC)) {
+ if (!skb_header_cloned(skb) &&
+ !skb_cloned(skb) &&
+ (headroom + tailroom) >= 8) {
+ if (headroom < 8) {
+ skb->data = memmove(skb->head + 8, skb->data, skb->len);
+ skb_set_tail_pointer(skb, skb->len);
+ }
+ } else {
+ struct sk_buff *skb2;
+
+ skb2 = skb_copy_expand(skb, 8, 0, flags);
dev_kfree_skb_any(skb);
- return NULL;
+ skb = skb2;
+ if (!skb)
+ return NULL;
}
skb_push(skb, 4);
[-- Attachment #3: 55_usb_xhci_TRB_scatter_gather_fix.patch --]
[-- Type: text/x-patch, Size: 3078 bytes --]
Section 4.11.7.1 of rev 1.0 of the xhci specification states that a link TRB
can only occur at a boundary between underlying USB frames (512 bytes for 480M).
If this isn't done the USB frames aren't formatted correctly and, for example,
the USB3 ethernet ax88179_178a card will stop sending (while still receiving)
when running a netperf tcp transmit test with (say) and 8k buffer.
This should be a candidate for stable, the ax88179_178a driver defaults to
gso and tso enabled so it passes a lot of fragmented skb to the USB stack.
Signed-off-by: David Laight <david.laight@xxxxxxxxxx>
---
Changes for v2:
1) Only act on bulk endpoints.
While isoc endpoints could suffer from the same problem it is much less
likely and can't be fixed by adding NOP TRBs (they would stop data being
sent in the poll interval).
2) When writing the NOP TRB use the count of TRBs instead of scanning for
the link TRB.
drivers/usb/host/xhci-ring.c | 53 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 5480215..c1342dc 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2929,8 +2929,57 @@
}
while (1) {
- if (room_on_ring(xhci, ep_ring, num_trbs))
- break;
+ if (room_on_ring(xhci, ep_ring, num_trbs)) {
+ union xhci_trb *trb = ep_ring->enqueue;
+ unsigned int usable = ep_ring->enq_seg->trbs +
+ TRBS_PER_SEGMENT - 1 - trb;
+ u32 nop_cmd;
+
+ /*
+ * Section 4.11.7.1 TD Fragments states that a link
+ * TRB must only occur at the boundary between
+ * data bursts (eg 512 bytes for 480M).
+ * While it is possible to split a large fragment
+ * we don't know the size yet.
+ * Simplest solution is to fill the trb before the
+ * LINK with nop commands.
+ */
+ if (num_trbs == 1 || num_trbs <= usable || usable == 0)
+ break;
+
+ if (ep_ring->type != TYPE_BULK)
+ /*
+ * While isoc transfers might have a buffer that
+ * crosses a 64k boundary it is unlikely.
+ * Since we can't add NOPs without generating
+ * gaps in the traffic just hope it never
+ * happens at the end of the ring.
+ * This could be fixed by writing a LINK TRB
+ * instead of the first NOP - however the
+ * TRB_TYPE_LINK_LE32() calls would all need
+ * changing to check the ring length. */
+ break;
+
+ if (num_trbs >= TRBS_PER_SEGMENT) {
+ xhci_err(xhci, "Too many fragments %d, max %d\n",
+ num_trbs, TRBS_PER_SEGMENT - 1);
+ return -ENOMEM;
+ }
+
+ nop_cmd = cpu_to_le32(TRB_TYPE(TRB_TR_NOOP) |
+ ep_ring->cycle_state);
+ ep_ring->num_trbs_free -= usable;
+ do {
+ trb->generic.field[0] = 0;
+ trb->generic.field[1] = 0;
+ trb->generic.field[2] = 0;
+ trb->generic.field[3] = nop_cmd;
+ trb++;
+ } while (--usable);
+ ep_ring->enqueue = trb;
+ if (room_on_ring(xhci, ep_ring, num_trbs))
+ break;
+ }
if (ep_ring == xhci->cmd_ring) {
xhci_err(xhci, "Do not support expand command ring\n");
^ permalink raw reply related
* Re: [PATCH net] virtio-net: fix page refcnt leaking when fail to allocate frag skb
From: Eric Dumazet @ 2013-11-19 14:03 UTC (permalink / raw)
To: Jason Wang
Cc: Michael Dalton, mst, netdev, linux-kernel, virtualization,
Eric Dumazet
In-Reply-To: <1384848307-7217-1-git-send-email-jasowang@redhat.com>
On Tue, 2013-11-19 at 16:05 +0800, Jason Wang wrote:
> We need to drop the refcnt of page when we fail to allocate an skb for frag
> list, otherwise it will be leaked. The bug was introduced by commit
> 2613af0ed18a11d5c566a81f9a6510b73180660a ("virtio_net: migrate mergeable rx
> buffers to page frag allocators").
>
> Cc: Michael Dalton <mwdalton@google.com>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Rusty Russell <rusty@rustcorp.com.au>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> The patch was needed for 3.12 stable.
Good catch, but if we return from receive_mergeable() in the 'middle'
of the frags we would need for the current skb, who will
call the virtqueue_get_buf() to flush the remaining frags ?
Don't we also need to call virtqueue_get_buf() like
while (--num_buf) {
buf = virtqueue_get_buf(rq->vq, &len);
if (!buf)
break;
put_page(virt_to_head_page(buf));
}
?
^ permalink raw reply
* BAYFORD CHARITY DONATIONS!!!
From: Crawford, Andrew @ 2013-11-19 14:05 UTC (permalink / raw)
My wife and I won $217 million on Powerball jackpot ticket and we have
decided to donate the sum of £1,500,000.00 GBP to you to help us
promote our charity donation desires. Contact us via (
bayfordg50@gmx.com)
Moje žena a já vyhrál 217.000.000dolar na jízdence jackpot Powerball a
my jsme se rozhodli darovat částku £ 1,500,000.00 GBP na vás, abyste
nám pomohli podpořit naše touhy charitativní dar. Kontaktujte nás
prostřednictvím (bayfordg50@gmx.com)
^ permalink raw reply
* Re: net/usb/ax88179_178a driver broken in linux-3.12
From: Eric Dumazet @ 2013-11-19 14:15 UTC (permalink / raw)
To: Mark Lord; +Cc: David Laight, Ming Lei, davem, netdev, Linux Kernel, stable
In-Reply-To: <528B6F73.7040801@pobox.com>
On Tue, 2013-11-19 at 09:02 -0500, Mark Lord wrote:
> On 13-11-19 05:04 AM, David Laight wrote:
> >> From: Mark Lord
> ..
> >> except the ax88179_178a driver still does not work in linux-3.12,
> >> whereas it works fine in all earlier kernels.
> >>
> >> That's a regression.
> >> And a simple revert (earlier in this thread) fixes it.
> >> So.. let's revert it for now, until a proper xhci compatible patch is produced.
> ...
> > There is a patch to xhci-ring.c that should fix the SG problem.
> > http://www.spinics.net/lists/linux-usb/msg97176.html
> >
> > I think it should apply to the 3.12 sources.
>
> I am running with that patch here now (thanks),
> and it too appears to prevent the lockups.
>
> But is this patch upstream already?
> If yes, then it needs to get pushed out to -stable for 3.12 at least.
>
> If not upstream, then the revert is probably safest for -stable,
> rather than new code that has never been upstream before.
>
> Both patches are attached to this email.
> One or the other is required for the USB 3.0 network adapters to function in 3.12.
I do not see any error in commit f27070158d6754765f2
("ax88179_178a: avoid copy of tx tcp packets")
Quite the contrary in fact...
I suspect a TSO bug, and would rather disable TSO for this nic.
Have you tried to revert 3804fad45411b482
("USBNET: ax88179_178a: enable tso if usb host supports sg dma")
^ permalink raw reply
* net: stmmac: DT clock parameter and behavior?
From: Chen-Yu Tsai @ 2013-11-19 14:17 UTC (permalink / raw)
To: Giuseppe Cavallaro; +Cc: netdev
I am currently porting the Linux stmmac driver to an AllWinner SoC
board. The AllWinner A20 SoC has a GMAC, and the drivers they provided
seems to be an early version of stmmac, with the names replaced.
I assume the IP in the SoC is an early version of dwmac. So far I have
managed to get a running system. I would like to clarify a few details
to clean up the code.
The stmmac core code references a clock named "stmmaceth".
This clock does not seem to be documented in "networking/stmmac.txt"
nor in "devicetree/bindings/net/stmmac.txt".
STMicroelectronics SPEAr board DTs do not mention this clock.
But I do see Altera SoCFPGA and Samsung Exynos DTs defining it.
The latest patch series for dwmac-sti on netdev suggests that this
clock is a 25MHz clock for the phy device. Is this true?
Then the driver does not consider that the dwmac might have a gated
clock that needs to be enabled as well. I ran into problems when
the dwmac was not initialized by the bootloader. I assume this can
be dealt with using AUXDATA and .init/.exit callbacks?
Also, earlier versions of stmmac seemed to only give a warning if
"stmmaceth" clock was not found. But in
6a81c26f net/stmmac: remove conditional compilation of clk code
the behavior changed to failing completely. Was this intended?
Last, given the supported device is actually Synopsys DesignWare
Ethernet MAC, is there any chance the driver could be renamed to dwmac?
Thank You
Chen-Yu Tsai
^ permalink raw reply
* [PATCH 0/9] genetlink: clean up multicast group APIs
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev
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.
johannes
^ permalink raw reply
* [PATCH 5/9] genetlink: remove genl_unregister_mc_group()
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
There are no users of this API remaining, and we'll soon
change group registration to be static (like ops are now)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/genetlink.h | 2 --
net/netlink/genetlink.c | 23 -----------------------
2 files changed, 25 deletions(-)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 9bd52a4c..067569d 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -168,8 +168,6 @@ static inline int _genl_register_family_with_ops(struct genl_family *family,
int genl_unregister_family(struct genl_family *family);
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
-void genl_unregister_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp);
void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
u32 group, struct nlmsghdr *nlh, gfp_t flags);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index bee91a7..6efb0e9 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -265,29 +265,6 @@ static void __genl_unregister_mc_group(struct genl_family *family,
grp->family = NULL;
}
-/**
- * genl_unregister_mc_group - unregister a multicast group
- *
- * Unregisters the specified multicast group and notifies userspace
- * about it. All current listeners on the group are removed.
- *
- * Note: It is not necessary to unregister all multicast groups before
- * unregistering the family, unregistering the family will cause
- * all assigned multicast groups to be unregistered automatically.
- *
- * @family: Generic netlink family the group belongs to.
- * @grp: The group to unregister, must have been registered successfully
- * previously.
- */
-void genl_unregister_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp)
-{
- genl_lock_all();
- __genl_unregister_mc_group(family, grp);
- genl_unlock_all();
-}
-EXPORT_SYMBOL(genl_unregister_mc_group);
-
static void genl_unregister_mc_groups(struct genl_family *family)
{
struct genl_multicast_group *grp, *tmp;
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 2/9] drop_monitor/genetlink: use proper genetlink multicast APIs
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
The drop monitor code is abusing the genetlink API and is
statically using the generic netlink multicast group 1, even
if that group belongs to somebody else (which it invariably
will, since it's not reserved.)
Make the drop monitor code use the proper APIs to reserve a
group ID, but also reserve the group id 1 in generic netlink
code to preserve the userspace API. Since drop monitor can
be a module, don't clear the bit for it on unregistration.
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/core/drop_monitor.c | 13 ++++++++++++-
net/netlink/genetlink.c | 13 ++++++++++---
2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 0efc502..46ee488 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -106,6 +106,10 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
return skb;
}
+static struct genl_multicast_group dm_mcgrp = {
+ .name = "events",
+};
+
static void send_dm_alert(struct work_struct *work)
{
struct sk_buff *skb;
@@ -116,7 +120,7 @@ static void send_dm_alert(struct work_struct *work)
skb = reset_per_cpu_data(data);
if (skb)
- genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+ genlmsg_multicast(skb, 0, dm_mcgrp.id, GFP_KERNEL);
}
/*
@@ -371,6 +375,13 @@ static int __init init_net_drop_monitor(void)
return rc;
}
+ rc = genl_register_mc_group(&net_drop_monitor_family, &dm_mcgrp);
+ if (rc) {
+ pr_err("Failed to register drop monitor mcast group\n");
+ goto out_unreg;
+ }
+ WARN_ON(dm_mcgrp.id != NET_DM_GRP_ALERT);
+
rc = register_netdevice_notifier(&dropmon_net_notifier);
if (rc < 0) {
pr_crit("Failed to register netdevice notifier\n");
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index c68ce73..353909d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -65,8 +65,12 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
* 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 the drop-monitor code
+ * abuses the API and thinks it can statically use group 1.
+ * That group will typically conflict with other groups that
+ * any proper users use.
*/
-static unsigned long mc_group_start = 0x1;
+static unsigned long mc_group_start = 0x3;
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
@@ -160,9 +164,11 @@ int genl_register_mc_group(struct genl_family *family,
genl_lock_all();
- /* special-case our own group */
+ /* special-case our own group and hacks */
if (grp == ¬ify_grp)
id = GENL_ID_CTRL;
+ else if (strcmp(family->name, "NET_DM") == 0)
+ id = 1;
else
id = find_first_zero_bit(mc_groups,
mc_groups_longs * BITS_PER_LONG);
@@ -245,7 +251,8 @@ static void __genl_unregister_mc_group(struct genl_family *family,
rcu_read_unlock();
netlink_table_ungrab();
- clear_bit(grp->id, mc_groups);
+ if (grp->id != 1)
+ clear_bit(grp->id, mc_groups);
list_del(&grp->list);
genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
grp->id = 0;
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 6/9] genetlink: remove family pointer from genl_multicast_group
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
There's no reason to have the family pointer there since it
can just be passed internally where needed, so remove it.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/genetlink.h | 2 --
net/netlink/genetlink.c | 38 ++++++++++++++++++--------------------
2 files changed, 18 insertions(+), 22 deletions(-)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 067569d..d8a8b1f 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -13,10 +13,8 @@
* @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;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 6efb0e9..e9ef640 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -77,7 +77,8 @@ static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_VFS_DQUOT);
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
-static int genl_ctrl_event(int event, void *data);
+static int genl_ctrl_event(int event, struct genl_family *family,
+ struct genl_multicast_group *grp);
static inline unsigned int genl_family_hash(unsigned int id)
{
@@ -235,9 +236,8 @@ int genl_register_mc_group(struct genl_family *family,
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);
+ genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family, grp);
out:
genl_unlock_all();
return err;
@@ -248,7 +248,6 @@ static void __genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp)
{
struct net *net;
- BUG_ON(grp->family != family);
netlink_table_grab();
rcu_read_lock();
@@ -260,9 +259,8 @@ static void __genl_unregister_mc_group(struct genl_family *family,
if (grp->id != 1)
clear_bit(grp->id, mc_groups);
list_del(&grp->list);
- genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, grp);
+ genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family, grp);
grp->id = 0;
- grp->family = NULL;
}
static void genl_unregister_mc_groups(struct genl_family *family)
@@ -364,7 +362,7 @@ int __genl_register_family(struct genl_family *family)
list_add_tail(&family->family_list, genl_family_chain(family->id));
genl_unlock_all();
- genl_ctrl_event(CTRL_CMD_NEWFAMILY, family);
+ genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL);
return 0;
@@ -400,7 +398,7 @@ int genl_unregister_family(struct genl_family *family)
genl_unlock_all();
kfree(family->attrbuf);
- genl_ctrl_event(CTRL_CMD_DELFAMILY, family);
+ genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL);
return 0;
}
@@ -693,7 +691,8 @@ nla_put_failure:
return -EMSGSIZE;
}
-static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 portid,
+static int ctrl_fill_mcgrp_info(struct genl_family *family,
+ struct genl_multicast_group *grp, u32 portid,
u32 seq, u32 flags, struct sk_buff *skb,
u8 cmd)
{
@@ -705,8 +704,8 @@ static int ctrl_fill_mcgrp_info(struct genl_multicast_group *grp, u32 portid,
if (hdr == NULL)
return -1;
- if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, grp->family->name) ||
- nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, grp->family->id))
+ if (nla_put_string(skb, CTRL_ATTR_FAMILY_NAME, family->name) ||
+ nla_put_u16(skb, CTRL_ATTR_FAMILY_ID, family->id))
goto nla_put_failure;
nla_grps = nla_nest_start(skb, CTRL_ATTR_MCAST_GROUPS);
@@ -783,7 +782,8 @@ static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
return skb;
}
-static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp,
+static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_family *family,
+ struct genl_multicast_group *grp,
u32 portid, int seq, u8 cmd)
{
struct sk_buff *skb;
@@ -793,7 +793,7 @@ static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_multicast_group *grp,
if (skb == NULL)
return ERR_PTR(-ENOBUFS);
- err = ctrl_fill_mcgrp_info(grp, portid, seq, 0, skb, cmd);
+ err = ctrl_fill_mcgrp_info(family, grp, portid, seq, 0, skb, cmd);
if (err < 0) {
nlmsg_free(skb);
return ERR_PTR(err);
@@ -855,11 +855,10 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
return genlmsg_reply(msg, info);
}
-static int genl_ctrl_event(int event, void *data)
+static int genl_ctrl_event(int event, struct genl_family *family,
+ struct genl_multicast_group *grp)
{
struct sk_buff *msg;
- struct genl_family *family;
- struct genl_multicast_group *grp;
/* genl is still initialising */
if (!init_net.genl_sock)
@@ -868,14 +867,13 @@ static int genl_ctrl_event(int event, void *data)
switch (event) {
case CTRL_CMD_NEWFAMILY:
case CTRL_CMD_DELFAMILY:
- family = data;
+ WARN_ON(grp);
msg = ctrl_build_family_msg(family, 0, 0, event);
break;
case CTRL_CMD_NEWMCAST_GRP:
case CTRL_CMD_DELMCAST_GRP:
- grp = data;
- family = grp->family;
- msg = ctrl_build_mcgrp_msg(data, 0, 0, event);
+ BUG_ON(!grp);
+ msg = ctrl_build_mcgrp_msg(family, grp, 0, 0, event);
break;
default:
return -EINVAL;
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 3/9] quota/genetlink: use proper genetlink multicast APIs
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
The quota code is abusing the genetlink API and is using
its family ID as the multicast group ID, which is invalid
and may belong to somebody else (and likely will.)
Make the quota code use the correct API, but since this
is already used as-is by userspace, reserve a family ID
for this code and also reserve that group ID to not break
userspace assumptions.
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
fs/quota/netlink.c | 17 +++++++++++++++--
include/uapi/linux/genetlink.h | 1 +
net/netlink/genetlink.c | 10 ++++++++--
3 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
index 16e8abb..aa22fe0 100644
--- a/fs/quota/netlink.c
+++ b/fs/quota/netlink.c
@@ -11,13 +11,23 @@
/* Netlink family structure for quota */
static struct genl_family quota_genl_family = {
- .id = GENL_ID_GENERATE,
+ /*
+ * Needed due to multicast group ID abuse - old code assumed
+ * the family ID was also a valid multicast group ID (which
+ * isn't true) and userspace might thus rely on it. Assign a
+ * static ID for this group to make dealing with that easier.
+ */
+ .id = GENL_ID_VFS_DQUOT,
.hdrsize = 0,
.name = "VFS_DQUOT",
.version = 1,
.maxattr = QUOTA_NL_A_MAX,
};
+static struct genl_multicast_group quota_mcgrp = {
+ .name = "events",
+};
+
/**
* quota_send_warning - Send warning to userspace about exceeded quota
* @type: The quota type: USRQQUOTA, GRPQUOTA,...
@@ -78,7 +88,7 @@ void quota_send_warning(struct kqid qid, dev_t dev,
goto attr_err_out;
genlmsg_end(skb, msg_head);
- genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS);
+ genlmsg_multicast(skb, 0, quota_mcgrp.id, GFP_NOFS);
return;
attr_err_out:
printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
@@ -92,6 +102,9 @@ static int __init quota_init(void)
if (genl_register_family("a_genl_family) != 0)
printk(KERN_ERR
"VFS: Failed to create quota netlink interface.\n");
+ if (genl_register_mc_group("a_genl_family, "a_mcgrp))
+ printk(KERN_ERR
+ "VFS: Failed to register quota mcast group.\n");
return 0;
};
diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h
index c880a41..1af72d82 100644
--- a/include/uapi/linux/genetlink.h
+++ b/include/uapi/linux/genetlink.h
@@ -27,6 +27,7 @@ struct genlmsghdr {
*/
#define GENL_ID_GENERATE 0
#define GENL_ID_CTRL NLMSG_MIN_TYPE
+#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
/**************************************************************************
* Controller
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 353909d..bee91a7 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -69,8 +69,11 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
* abuses the API and thinks it can statically use group 1.
* That group will typically conflict with other groups that
* any proper users use.
+ * Bit 17 is marked as already used since the VFS quota code
+ * also abused this API and relied on family == group ID, we
+ * cater to that by giving it a static family and group ID.
*/
-static unsigned long mc_group_start = 0x3;
+static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_VFS_DQUOT);
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
@@ -130,7 +133,8 @@ static u16 genl_generate_id(void)
int i;
for (i = 0; i <= GENL_MAX_ID - GENL_MIN_ID; i++) {
- if (!genl_family_find_byid(id_gen_idx))
+ if (id_gen_idx != GENL_ID_VFS_DQUOT &&
+ !genl_family_find_byid(id_gen_idx))
return id_gen_idx;
if (++id_gen_idx > GENL_MAX_ID)
id_gen_idx = GENL_MIN_ID;
@@ -169,6 +173,8 @@ int genl_register_mc_group(struct genl_family *family,
id = GENL_ID_CTRL;
else if (strcmp(family->name, "NET_DM") == 0)
id = 1;
+ else if (strcmp(family->name, "VFS_DQUOT") == 0)
+ id = GENL_ID_VFS_DQUOT;
else
id = find_first_zero_bit(mc_groups,
mc_groups_longs * BITS_PER_LONG);
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 7/9] genetlink: add and use genl_set_err()
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Add a static inline to generic netlink to wrap netlink_set_err()
to make it easier to use here - use it in openvswitch (the only
generic netlink user of netlink_set_err()).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/genetlink.h | 14 ++++++++++++++
net/openvswitch/datapath.c | 8 ++++----
net/openvswitch/dp_notify.c | 6 +++---
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index d8a8b1f..11ac77f 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -351,5 +351,19 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
return nlmsg_new(genlmsg_total_size(payload), flags);
}
+/**
+ * genl_set_err - report error to genetlink broadcast listeners
+ * @net: the network namespace to report the error to
+ * @portid: the PORTID of a process that we want to skip (if any)
+ * @group: the broadcast group that will notice the error
+ * @code: error code, must be negative (as usual in kernelspace)
+ *
+ * This function returns the number of broadcast listeners that have set the
+ * NETLINK_RECV_NO_ENOBUFS socket option.
+ */
+static inline int genl_set_err(struct net *net, u32 portid, u32 group, int code)
+{
+ return netlink_set_err(net->genl_sock, portid, group, code);
+}
#endif /* __NET_GENERIC_NETLINK_H */
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 8ec8b73..3e2bb15 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -879,8 +879,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
if (!IS_ERR(reply))
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
else
- netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
- ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
+ genl_set_err(sock_net(skb->sk), 0,
+ ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
return 0;
err_flow_free:
@@ -1326,8 +1326,8 @@ 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(sock_net(skb->sk), 0,
+ ovs_dp_datapath_multicast_group.id, err);
err = 0;
goto unlock;
}
diff --git a/net/openvswitch/dp_notify.c b/net/openvswitch/dp_notify.c
index 5c2dab2..3d55ead 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -34,9 +34,9 @@ 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(ovs_dp_get_net(dp), 0,
+ ovs_dp_vport_multicast_group.id,
+ PTR_ERR(notify));
return;
}
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 1/9] genetlink: only pass array to genl_register_family_with_ops()
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
As suggested by David Miller, make genl_register_family_with_ops()
a macro and pass only the array, evaluating ARRAY_SIZE() in the
macro, this is a little safer.
The openvswitch has some indirection, assing ops/n_ops directly in
that code. This might ultimately just assign the pointers in the
family initializations, saving the struct genl_family_and_ops and
code (once mcast groups are handled differently.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/net/team/team.c | 3 +--
drivers/net/wireless/mac80211_hwsim.c | 3 +--
fs/dlm/netlink.c | 10 ++++++----
include/linux/genl_magic_func.h | 3 +--
include/net/genetlink.h | 8 ++++++--
kernel/taskstats.c | 3 +--
net/core/drop_monitor.c | 3 +--
net/hsr/hsr_netlink.c | 3 +--
net/ieee802154/netlink.c | 3 +--
net/ipv4/tcp_metrics.c | 3 +--
net/irda/irnetlink.c | 3 +--
net/l2tp/l2tp_netlink.c | 7 +------
net/netfilter/ipvs/ip_vs_ctl.c | 2 +-
net/netlabel/netlabel_cipso_v4.c | 2 +-
net/netlabel/netlabel_mgmt.c | 2 +-
net/netlabel/netlabel_unlabeled.c | 2 +-
net/netlink/genetlink.c | 14 ++++++++------
net/nfc/netlink.c | 3 +--
net/openvswitch/datapath.c | 5 +++--
net/tipc/netlink.c | 11 ++++++-----
net/wimax/stack.c | 4 ++--
net/wireless/nl80211.c | 3 +--
22 files changed, 47 insertions(+), 53 deletions(-)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 6390254..f55758b 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2699,8 +2699,7 @@ static int team_nl_init(void)
{
int err;
- err = genl_register_family_with_ops(&team_nl_family, team_nl_ops,
- ARRAY_SIZE(team_nl_ops));
+ err = genl_register_family_with_ops(&team_nl_family, team_nl_ops);
if (err)
return err;
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index cfc3fda..9df7bc9 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2148,8 +2148,7 @@ static int hwsim_init_netlink(void)
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
- rc = genl_register_family_with_ops(&hwsim_genl_family,
- hwsim_ops, ARRAY_SIZE(hwsim_ops));
+ rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops);
if (rc)
goto failure;
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c
index 60a3278..e7cfbaf 100644
--- a/fs/dlm/netlink.c
+++ b/fs/dlm/netlink.c
@@ -74,14 +74,16 @@ static int user_cmd(struct sk_buff *skb, struct genl_info *info)
return 0;
}
-static struct genl_ops dlm_nl_ops = {
- .cmd = DLM_CMD_HELLO,
- .doit = user_cmd,
+static struct genl_ops dlm_nl_ops[] = {
+ {
+ .cmd = DLM_CMD_HELLO,
+ .doit = user_cmd,
+ },
};
int __init dlm_netlink_init(void)
{
- return genl_register_family_with_ops(&family, &dlm_nl_ops, 1);
+ return genl_register_family_with_ops(&family, dlm_nl_ops);
}
void dlm_netlink_exit(void)
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
index 023bc34..4708603 100644
--- a/include/linux/genl_magic_func.h
+++ b/include/linux/genl_magic_func.h
@@ -293,8 +293,7 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
{
- int err = genl_register_family_with_ops(&ZZZ_genl_family,
- ZZZ_genl_ops, ARRAY_SIZE(ZZZ_genl_ops));
+ int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops);
if (err)
return err;
#undef GENL_mc_group
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index e96385d..9bd52a4c 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -152,8 +152,9 @@ static inline int genl_register_family(struct genl_family *family)
*
* Return 0 on success or a negative error code.
*/
-static inline int genl_register_family_with_ops(struct genl_family *family,
- const struct genl_ops *ops, size_t n_ops)
+static inline int _genl_register_family_with_ops(struct genl_family *family,
+ const struct genl_ops *ops,
+ size_t n_ops)
{
family->module = THIS_MODULE;
family->ops = ops;
@@ -161,6 +162,9 @@ static inline int genl_register_family_with_ops(struct genl_family *family,
return __genl_register_family(family);
}
+#define genl_register_family_with_ops(family, ops) \
+ _genl_register_family_with_ops((family), (ops), ARRAY_SIZE(ops))
+
int genl_unregister_family(struct genl_family *family);
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
diff --git a/kernel/taskstats.c b/kernel/taskstats.c
index 76595cd..13d2f7c 100644
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -703,8 +703,7 @@ static int __init taskstats_init(void)
{
int rc;
- rc = genl_register_family_with_ops(&family, taskstats_ops,
- ARRAY_SIZE(taskstats_ops));
+ rc = genl_register_family_with_ops(&family, taskstats_ops);
if (rc)
return rc;
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index f9fe2f2..0efc502 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -365,8 +365,7 @@ static int __init init_net_drop_monitor(void)
}
rc = genl_register_family_with_ops(&net_drop_monitor_family,
- dropmon_ops,
- ARRAY_SIZE(dropmon_ops));
+ dropmon_ops);
if (rc) {
pr_err("Could not create drop monitor netlink family\n");
return rc;
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
index 3b9205d..f182260 100644
--- a/net/hsr/hsr_netlink.c
+++ b/net/hsr/hsr_netlink.c
@@ -414,8 +414,7 @@ int __init hsr_netlink_init(void)
if (rc)
goto fail_rtnl_link_register;
- rc = genl_register_family_with_ops(&hsr_genl_family, hsr_ops,
- ARRAY_SIZE(hsr_ops));
+ rc = genl_register_family_with_ops(&hsr_genl_family, hsr_ops);
if (rc)
goto fail_genl_register_family;
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 3ffcdbb..1a81709 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -129,8 +129,7 @@ int __init ieee802154_nl_init(void)
{
int rc;
- rc = genl_register_family_with_ops(&nl802154_family, ieee8021154_ops,
- ARRAY_SIZE(ieee8021154_ops));
+ rc = genl_register_family_with_ops(&nl802154_family, ieee8021154_ops);
if (rc)
return rc;
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index 8c121b5..0649373 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -1082,8 +1082,7 @@ void __init tcp_metrics_init(void)
if (ret < 0)
goto cleanup;
ret = genl_register_family_with_ops(&tcp_metrics_nl_family,
- tcp_metrics_nl_ops,
- ARRAY_SIZE(tcp_metrics_nl_ops));
+ tcp_metrics_nl_ops);
if (ret < 0)
goto cleanup_subsys;
return;
diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c
index bf5d7d4..a37b81f 100644
--- a/net/irda/irnetlink.c
+++ b/net/irda/irnetlink.c
@@ -149,8 +149,7 @@ static const struct genl_ops irda_nl_ops[] = {
int irda_nl_register(void)
{
- return genl_register_family_with_ops(&irda_nl_family,
- irda_nl_ops, ARRAY_SIZE(irda_nl_ops));
+ return genl_register_family_with_ops(&irda_nl_family, irda_nl_ops);
}
void irda_nl_unregister(void)
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 57db66e..4cfd722 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -887,13 +887,8 @@ EXPORT_SYMBOL_GPL(l2tp_nl_unregister_ops);
static int l2tp_nl_init(void)
{
- int err;
-
pr_info("L2TP netlink interface\n");
- err = genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops,
- ARRAY_SIZE(l2tp_nl_ops));
-
- return err;
+ return genl_register_family_with_ops(&l2tp_nl_family, l2tp_nl_ops);
}
static void l2tp_nl_cleanup(void)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index fc8a04e..3934987 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3666,7 +3666,7 @@ static const struct genl_ops ip_vs_genl_ops[] __read_mostly = {
static int __init ip_vs_genl_register(void)
{
return genl_register_family_with_ops(&ip_vs_genl_family,
- ip_vs_genl_ops, ARRAY_SIZE(ip_vs_genl_ops));
+ ip_vs_genl_ops);
}
static void ip_vs_genl_unregister(void)
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index 7066917..69345ce 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -783,5 +783,5 @@ static const struct genl_ops netlbl_cipsov4_ops[] = {
int __init netlbl_cipsov4_genl_init(void)
{
return genl_register_family_with_ops(&netlbl_cipsov4_gnl_family,
- netlbl_cipsov4_ops, ARRAY_SIZE(netlbl_cipsov4_ops));
+ netlbl_cipsov4_ops);
}
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 7de6f66..8ef83ee 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -779,5 +779,5 @@ static const struct genl_ops netlbl_mgmt_genl_ops[] = {
int __init netlbl_mgmt_genl_init(void)
{
return genl_register_family_with_ops(&netlbl_mgmt_gnl_family,
- netlbl_mgmt_genl_ops, ARRAY_SIZE(netlbl_mgmt_genl_ops));
+ netlbl_mgmt_genl_ops);
}
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 76ee925..43817d7 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1397,7 +1397,7 @@ static const struct genl_ops netlbl_unlabel_genl_ops[] = {
int __init netlbl_unlabel_genl_init(void)
{
return genl_register_family_with_ops(&netlbl_unlabel_gnl_family,
- netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops));
+ netlbl_unlabel_genl_ops);
}
/*
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f54215d..c68ce73 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -906,11 +906,13 @@ static int genl_ctrl_event(int event, void *data)
return 0;
}
-static struct genl_ops genl_ctrl_ops = {
- .cmd = CTRL_CMD_GETFAMILY,
- .doit = ctrl_getfamily,
- .dumpit = ctrl_dumpfamily,
- .policy = ctrl_policy,
+static struct genl_ops genl_ctrl_ops[] = {
+ {
+ .cmd = CTRL_CMD_GETFAMILY,
+ .doit = ctrl_getfamily,
+ .dumpit = ctrl_dumpfamily,
+ .policy = ctrl_policy,
+ },
};
static struct genl_multicast_group notify_grp = {
@@ -954,7 +956,7 @@ static int __init genl_init(void)
for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
INIT_LIST_HEAD(&family_ht[i]);
- err = genl_register_family_with_ops(&genl_ctrl, &genl_ctrl_ops, 1);
+ err = genl_register_family_with_ops(&genl_ctrl, genl_ctrl_ops);
if (err < 0)
goto problem;
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index f558561..fe6760d 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -1536,8 +1536,7 @@ int __init nfc_genl_init(void)
{
int rc;
- rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
- ARRAY_SIZE(nfc_genl_ops));
+ rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops);
if (rc)
return rc;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 91e1c92..8ec8b73 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1817,8 +1817,9 @@ 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;
+ err = genl_register_family(f->family);
if (err)
goto error;
n_registered++;
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 8bcd498..9f72a63 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -76,9 +76,11 @@ static struct genl_family tipc_genl_family = {
.maxattr = 0,
};
-static struct genl_ops tipc_genl_ops = {
- .cmd = TIPC_GENL_CMD,
- .doit = handle_cmd,
+static struct genl_ops tipc_genl_ops[] = {
+ {
+ .cmd = TIPC_GENL_CMD,
+ .doit = handle_cmd,
+ },
};
static int tipc_genl_family_registered;
@@ -87,8 +89,7 @@ int tipc_netlink_start(void)
{
int res;
- res = genl_register_family_with_ops(&tipc_genl_family,
- &tipc_genl_ops, 1);
+ res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops);
if (res) {
pr_err("Failed to register netlink interface\n");
return res;
diff --git a/net/wimax/stack.c b/net/wimax/stack.c
index 47170c9..6328afe 100644
--- a/net/wimax/stack.c
+++ b/net/wimax/stack.c
@@ -597,8 +597,8 @@ int __init wimax_subsys_init(void)
snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name),
"WiMAX");
- result = genl_register_family_with_ops(&wimax_gnl_family, wimax_gnl_ops,
- ARRAY_SIZE(wimax_gnl_ops));
+ result = genl_register_family_with_ops(&wimax_gnl_family,
+ wimax_gnl_ops);
if (unlikely(result < 0)) {
printk(KERN_ERR "cannot register generic netlink family: %d\n",
result);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 58c43c8..1b6c5dd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -11329,8 +11329,7 @@ int nl80211_init(void)
{
int err;
- err = genl_register_family_with_ops(&nl80211_fam,
- nl80211_ops, ARRAY_SIZE(nl80211_ops));
+ err = genl_register_family_with_ops(&nl80211_fam, nl80211_ops);
if (err)
return err;
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 4/9] hsr: don't call genl_unregister_mc_group()
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
There's no need to unregister the multicast group if the
generic netlink family is registered immediately after.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/hsr/hsr_netlink.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
index f182260..908e335 100644
--- a/net/hsr/hsr_netlink.c
+++ b/net/hsr/hsr_netlink.c
@@ -435,9 +435,7 @@ fail_rtnl_link_register:
void __exit hsr_netlink_exit(void)
{
- genl_unregister_mc_group(&hsr_genl_family, &hsr_network_genl_mcgrp);
genl_unregister_family(&hsr_genl_family);
-
rtnl_link_unregister(&hsr_link_ops);
}
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 8/9] genetlink: pass family to functions using groups
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
This doesn't really change anything, but prepares for the
next patch that will change the APIs to pass the group ID
within the family, rather than the global group ID.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/acpi/event.c | 3 +-
drivers/net/team/team.c | 5 +--
drivers/scsi/pmcraid.c | 3 +-
drivers/thermal/thermal_core.c | 3 +-
fs/quota/netlink.c | 2 +-
include/linux/genl_magic_func.h | 3 +-
include/net/genetlink.h | 22 +++++++++----
net/core/drop_monitor.c | 3 +-
net/hsr/hsr_netlink.c | 6 ++--
net/ieee802154/netlink.c | 2 +-
net/netlink/genetlink.c | 12 ++++---
net/nfc/netlink.c | 39 +++++++++++++++--------
net/openvswitch/datapath.c | 35 +++++++++++++--------
net/openvswitch/datapath.h | 1 +
net/openvswitch/dp_notify.c | 5 +--
net/wimax/op-msg.c | 3 +-
net/wimax/stack.c | 3 +-
net/wireless/nl80211.c | 70 ++++++++++++++++++++---------------------
18 files changed, 133 insertions(+), 87 deletions(-)
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 8247fcd..68a8755 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -146,7 +146,8 @@ int acpi_bus_generate_netlink_event(const char *device_class,
return result;
}
- genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&acpi_event_genl_family,
+ skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
return 0;
}
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index f55758b..2721e29 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2677,8 +2677,9 @@ static struct genl_multicast_group team_change_event_mcgrp = {
static int team_nl_send_multicast(struct sk_buff *skb,
struct team *team, u32 portid)
{
- return genlmsg_multicast_netns(dev_net(team->dev), skb, 0,
- team_change_event_mcgrp.id, GFP_KERNEL);
+ return genlmsg_multicast_netns(&team_nl_family, dev_net(team->dev),
+ skb, 0, team_change_event_mcgrp.id,
+ GFP_KERNEL);
}
static int team_nl_send_event_options_get(struct team *team,
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 1eb7b028..2775441 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -1512,7 +1512,8 @@ static int pmcraid_notify_aen(
}
result =
- genlmsg_multicast(skb, 0, pmcraid_event_family.id, GFP_ATOMIC);
+ genlmsg_multicast(&pmcraid_event_family, skb, 0,
+ pmcraid_event_family.id, GFP_ATOMIC);
/* If there are no listeners, genlmsg_multicast may return non-zero
* value.
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4962a6a..2570a94 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1675,7 +1675,8 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
return result;
}
- result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC);
+ result = genlmsg_multicast(&thermal_event_genl_family, skb, 0,
+ thermal_event_mcgrp.id, GFP_ATOMIC);
if (result)
dev_err(&tz->device, "Failed to send netlink event:%d", result);
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
index aa22fe0..a5b5edd 100644
--- a/fs/quota/netlink.c
+++ b/fs/quota/netlink.c
@@ -88,7 +88,7 @@ void quota_send_warning(struct kqid qid, dev_t dev,
goto attr_err_out;
genlmsg_end(skb, msg_head);
- genlmsg_multicast(skb, 0, quota_mcgrp.id, GFP_NOFS);
+ genlmsg_multicast("a_genl_family, skb, 0, quota_mcgrp.id, GFP_NOFS);
return;
attr_err_out:
printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
index 4708603..5b9b8ae 100644
--- a/include/linux/genl_magic_func.h
+++ b/include/linux/genl_magic_func.h
@@ -286,7 +286,8 @@ static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \
if (!group_id) \
return -EINVAL; \
- return genlmsg_multicast(skb, 0, group_id, flags); \
+ return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \
+ group_id, flags); \
}
#include GENL_MAGIC_INCLUDE_FILE
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 11ac77f..60aef0d 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -166,7 +166,8 @@ static inline int _genl_register_family_with_ops(struct genl_family *family,
int genl_unregister_family(struct genl_family *family);
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
-void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
+void genl_notify(struct genl_family *family,
+ struct sk_buff *skb, struct net *net, u32 portid,
u32 group, struct nlmsghdr *nlh, gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
@@ -246,13 +247,15 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
/**
* genlmsg_multicast_netns - multicast a netlink message to a specific netns
+ * @family: the generic netlink family
* @net: the net namespace
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
* @flags: allocation flags
*/
-static inline int genlmsg_multicast_netns(struct net *net, struct sk_buff *skb,
+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);
@@ -260,19 +263,23 @@ static inline int genlmsg_multicast_netns(struct net *net, struct sk_buff *skb,
/**
* genlmsg_multicast - multicast a netlink message to the default netns
+ * @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
* @flags: allocation flags
*/
-static inline int genlmsg_multicast(struct sk_buff *skb, u32 portid,
+static inline int genlmsg_multicast(struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
- return genlmsg_multicast_netns(&init_net, skb, portid, group, flags);
+ return genlmsg_multicast_netns(family, &init_net, skb,
+ portid, group, flags);
}
/**
* genlmsg_multicast_allns - multicast a netlink message to all net namespaces
+ * @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
@@ -280,7 +287,8 @@ static inline int genlmsg_multicast(struct sk_buff *skb, u32 portid,
*
* This function must hold the RTNL or rcu_read_lock().
*/
-int genlmsg_multicast_allns(struct sk_buff *skb, u32 portid,
+int genlmsg_multicast_allns(struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags);
/**
@@ -353,6 +361,7 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
/**
* genl_set_err - report error to genetlink broadcast listeners
+ * @family: the generic netlink family
* @net: the network namespace to report the error to
* @portid: the PORTID of a process that we want to skip (if any)
* @group: the broadcast group that will notice the error
@@ -361,7 +370,8 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option.
*/
-static inline int genl_set_err(struct net *net, u32 portid, u32 group, int code)
+static inline int genl_set_err(struct genl_family *family, struct net *net,
+ u32 portid, u32 group, int code)
{
return netlink_set_err(net->genl_sock, portid, group, code);
}
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 46ee488..1eab1dc 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -120,7 +120,8 @@ static void send_dm_alert(struct work_struct *work)
skb = reset_per_cpu_data(data);
if (skb)
- genlmsg_multicast(skb, 0, dm_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&net_drop_monitor_family, skb, 0,
+ dm_mcgrp.id, GFP_KERNEL);
}
/*
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
index 908e335..0009416 100644
--- a/net/hsr/hsr_netlink.c
+++ b/net/hsr/hsr_netlink.c
@@ -129,7 +129,8 @@ void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN],
goto nla_put_failure;
genlmsg_end(skb, msg_head);
- genlmsg_multicast(skb, 0, hsr_network_genl_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&hsr_genl_family, skb, 0,
+ hsr_network_genl_mcgrp.id, GFP_ATOMIC);
return;
@@ -163,7 +164,8 @@ void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN])
goto nla_put_failure;
genlmsg_end(skb, msg_head);
- genlmsg_multicast(skb, 0, hsr_network_genl_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&hsr_genl_family, skb, 0,
+ hsr_network_genl_mcgrp.id, GFP_ATOMIC);
return;
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 1a81709..5172f46 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -70,7 +70,7 @@ int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group)
if (genlmsg_end(msg, hdr) < 0)
goto out;
- return genlmsg_multicast(msg, 0, group, GFP_ATOMIC);
+ return genlmsg_multicast(&nl802154_family, msg, 0, group, GFP_ATOMIC);
out:
nlmsg_free(msg);
return -ENOBUFS;
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index e9ef640..36e3a86 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -883,11 +883,12 @@ static int genl_ctrl_event(int event, struct genl_family *family,
return PTR_ERR(msg);
if (!family->netnsok) {
- genlmsg_multicast_netns(&init_net, msg, 0,
+ genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0,
GENL_ID_CTRL, GFP_KERNEL);
} else {
rcu_read_lock();
- genlmsg_multicast_allns(msg, 0, GENL_ID_CTRL, GFP_ATOMIC);
+ genlmsg_multicast_allns(&genl_ctrl, msg, 0,
+ GENL_ID_CTRL, GFP_ATOMIC);
rcu_read_unlock();
}
@@ -993,14 +994,15 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
return err;
}
-int genlmsg_multicast_allns(struct sk_buff *skb, u32 portid, unsigned int group,
- gfp_t flags)
+int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
+ u32 portid, unsigned int group, gfp_t flags)
{
return genlmsg_mcast(skb, portid, group, flags);
}
EXPORT_SYMBOL(genlmsg_multicast_allns);
-void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, u32 group,
+void genl_notify(struct genl_family *family,
+ struct sk_buff *skb, struct net *net, u32 portid, u32 group,
struct nlmsghdr *nlh, gfp_t flags)
{
struct sock *sk = net->genl_sock;
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index fe6760d..3092df31 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -194,7 +194,8 @@ int nfc_genl_targets_found(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ return genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_ATOMIC);
nla_put_failure:
genlmsg_cancel(msg, hdr);
@@ -223,7 +224,8 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -255,7 +257,8 @@ int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -285,7 +288,8 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -318,7 +322,8 @@ int nfc_genl_device_added(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -348,7 +353,8 @@ int nfc_genl_device_removed(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -414,7 +420,8 @@ int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list)
genlmsg_end(msg, hdr);
- return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ return genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_ATOMIC);
nla_put_failure:
genlmsg_cancel(msg, hdr);
@@ -448,7 +455,8 @@ int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -479,7 +487,8 @@ int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -600,7 +609,8 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
dev->dep_link_up = true;
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_ATOMIC);
return 0;
@@ -632,7 +642,8 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_ATOMIC);
return 0;
@@ -1137,7 +1148,8 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
return 0;
@@ -1308,7 +1320,8 @@ static void se_io_cb(void *context, u8 *apdu, size_t apdu_len, int err)
genlmsg_end(msg, hdr);
- genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0,
+ nfc_genl_event_mcgrp.id, GFP_KERNEL);
kfree(ctx);
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 3e2bb15..5c19846 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -61,10 +61,11 @@
int ovs_net_id __read_mostly;
-static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
+static void ovs_notify(struct genl_family *family,
+ struct sk_buff *skb, struct genl_info *info,
struct genl_multicast_group *grp)
{
- genl_notify(skb, genl_info_net(info), info->snd_portid,
+ genl_notify(family, skb, genl_info_net(info), info->snd_portid,
grp->id, info->nlhdr, GFP_KERNEL);
}
@@ -877,9 +878,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,
+ &ovs_dp_flow_multicast_group);
else
- genl_set_err(sock_net(skb->sk), 0,
+ genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0,
ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
return 0;
@@ -990,7 +992,8 @@ 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,
+ &ovs_dp_flow_multicast_group);
return 0;
unlock:
ovs_unlock();
@@ -1237,7 +1240,8 @@ 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,
+ &ovs_dp_datapath_multicast_group);
return 0;
err_destroy_local_port:
@@ -1302,7 +1306,8 @@ 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,
+ &ovs_dp_datapath_multicast_group);
return 0;
unlock:
@@ -1326,14 +1331,15 @@ 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);
- genl_set_err(sock_net(skb->sk), 0,
+ genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
ovs_dp_datapath_multicast_group.id, err);
err = 0;
goto unlock;
}
ovs_unlock();
- ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
+ ovs_notify(&dp_datapath_genl_family, reply, info,
+ &ovs_dp_datapath_multicast_group);
return 0;
unlock:
@@ -1425,7 +1431,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 +1601,8 @@ 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,
+ &ovs_dp_vport_multicast_group);
exit_unlock:
ovs_unlock();
@@ -1642,7 +1649,8 @@ 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,
+ &ovs_dp_vport_multicast_group);
return 0;
exit_free:
@@ -1679,7 +1687,8 @@ 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,
+ &ovs_dp_vport_multicast_group);
exit_unlock:
ovs_unlock();
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index d3d14a58..4067ea4 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 3d55ead..f4b66c8 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -34,13 +34,14 @@ static void dp_detach_port_notify(struct vport *vport)
OVS_VPORT_CMD_DEL);
ovs_dp_detach_port(vport);
if (IS_ERR(notify)) {
- genl_set_err(ovs_dp_get_net(dp), 0,
+ genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
ovs_dp_vport_multicast_group.id,
PTR_ERR(notify));
return;
}
- genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
+ genlmsg_multicast_netns(&dp_vport_genl_family,
+ ovs_dp_get_net(dp), notify, 0,
ovs_dp_vport_multicast_group.id,
GFP_KERNEL);
}
diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c
index ff19cbe..f37dd3c 100644
--- a/net/wimax/op-msg.c
+++ b/net/wimax/op-msg.c
@@ -279,7 +279,8 @@ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
d_dump(2, dev, msg, size);
- genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL);
+ genlmsg_multicast(&wimax_gnl_family, skb, 0,
+ wimax_gnl_mcg.id, GFP_KERNEL);
d_printf(1, dev, "CTX: genl multicast done\n");
return 0;
}
diff --git a/net/wimax/stack.c b/net/wimax/stack.c
index 6328afe..1888874 100644
--- a/net/wimax/stack.c
+++ b/net/wimax/stack.c
@@ -177,7 +177,8 @@ int wimax_gnl_re_state_change_send(
goto out;
}
genlmsg_end(report_skb, header);
- genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL);
+ genlmsg_multicast(&wimax_gnl_family, report_skb, 0,
+ wimax_gnl_mcg.id, GFP_KERNEL);
out:
d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n",
wimax_dev, report_skb, result);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1b6c5dd..f20edfd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6868,7 +6868,7 @@ void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
nla_nest_end(skb, data);
genlmsg_end(skb, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
nl80211_testmode_mcgrp.id, gfp);
}
EXPORT_SYMBOL(cfg80211_testmode_event);
@@ -9597,7 +9597,7 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_config_mcgrp.id, GFP_KERNEL);
}
@@ -9707,7 +9707,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
@@ -9726,7 +9726,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
@@ -9745,7 +9745,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
@@ -9764,7 +9764,7 @@ void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
@@ -9782,7 +9782,7 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_scan_mcgrp.id, GFP_KERNEL);
}
@@ -9837,8 +9837,8 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
genlmsg_end(msg, hdr);
rcu_read_lock();
- genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
- GFP_ATOMIC);
+ genlmsg_multicast_allns(&nl80211_fam, msg, 0,
+ nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
rcu_read_unlock();
return;
@@ -9873,7 +9873,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -9961,7 +9961,7 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10017,7 +10017,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10056,7 +10056,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10094,7 +10094,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, GFP_KERNEL);
return;
@@ -10128,7 +10128,7 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10169,7 +10169,7 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10208,7 +10208,7 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10261,8 +10261,8 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
genlmsg_end(msg, hdr);
rcu_read_lock();
- genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
- GFP_ATOMIC);
+ genlmsg_multicast_allns(&nl80211_fam, msg, 0,
+ nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
rcu_read_unlock();
return;
@@ -10307,7 +10307,7 @@ static void nl80211_send_remain_on_chan_event(
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10362,7 +10362,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
return;
}
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
}
EXPORT_SYMBOL(cfg80211_new_sta);
@@ -10392,7 +10392,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10428,7 +10428,7 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10590,7 +10590,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10639,7 +10639,7 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10684,7 +10684,7 @@ static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10742,7 +10742,7 @@ nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10789,7 +10789,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10866,7 +10866,7 @@ void cfg80211_cqm_txe_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10915,7 +10915,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -10962,7 +10962,7 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -11002,7 +11002,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -11154,7 +11154,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -11196,7 +11196,7 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, gfp);
return;
@@ -11279,7 +11279,7 @@ void cfg80211_ft_event(struct net_device *netdev,
genlmsg_end(msg, hdr);
- genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
nl80211_mlme_mcgrp.id, GFP_KERNEL);
}
EXPORT_SYMBOL(cfg80211_ft_event);
--
1.8.4.rc3
^ permalink raw reply related
* [PATCH 9/9] genetlink: make multicast groups const, prevent abuse
From: Johannes Berg @ 2013-11-19 14:19 UTC (permalink / raw)
To: netdev; +Cc: Johannes Berg
In-Reply-To: <1384870779-17571-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Register generic netlink multicast groups as an array with
the family and give them contiguous group IDs. Then instead
of passing the global group ID to the various functions that
send messages, pass the ID relative to the family - for most
families that's just 0 because the only have one group.
This avoids the list_head and ID in each group, adding a new
field for the mcast group ID offset to the family.
At the same time, this allows us to prevent abusing groups
again like the quota and dropmon code did, since we can now
check that a family only uses a group it owns.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/acpi/event.c | 26 ++--
drivers/net/team/team.c | 25 +---
drivers/thermal/thermal_core.c | 24 ++--
fs/quota/netlink.c | 15 +--
include/linux/genl_magic_func.h | 49 +++----
include/net/genetlink.h | 48 ++++---
net/core/drop_monitor.c | 18 +--
net/hsr/hsr_netlink.c | 19 +--
net/ieee802154/ieee802154.h | 6 +-
net/ieee802154/netlink.c | 26 ++--
net/ieee802154/nl-mac.c | 22 +---
net/netlink/genetlink.c | 278 ++++++++++++++++++++++++----------------
net/nfc/netlink.c | 51 +++-----
net/openvswitch/datapath.c | 43 +++----
net/openvswitch/dp_notify.c | 6 +-
net/wimax/op-msg.c | 3 +-
net/wimax/stack.c | 21 ++-
net/wimax/wimax-internal.h | 1 -
net/wireless/nl80211.c | 129 ++++++++-----------
19 files changed, 377 insertions(+), 433 deletions(-)
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index 68a8755..aeb5aa6 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -78,15 +78,17 @@ enum {
#define ACPI_GENL_VERSION 0x01
#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group"
+static const struct genl_multicast_group acpi_event_mcgrps[] = {
+ { .name = ACPI_GENL_MCAST_GROUP_NAME, },
+};
+
static struct genl_family acpi_event_genl_family = {
.id = GENL_ID_GENERATE,
.name = ACPI_GENL_FAMILY_NAME,
.version = ACPI_GENL_VERSION,
.maxattr = ACPI_GENL_ATTR_MAX,
-};
-
-static struct genl_multicast_group acpi_event_mcgrp = {
- .name = ACPI_GENL_MCAST_GROUP_NAME,
+ .mcgrps = acpi_event_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),
};
int acpi_bus_generate_netlink_event(const char *device_class,
@@ -146,8 +148,7 @@ int acpi_bus_generate_netlink_event(const char *device_class,
return result;
}
- genlmsg_multicast(&acpi_event_genl_family,
- skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
return 0;
}
@@ -155,18 +156,7 @@ EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
static int acpi_event_genetlink_init(void)
{
- int result;
-
- result = genl_register_family(&acpi_event_genl_family);
- if (result)
- return result;
-
- result = genl_register_mc_group(&acpi_event_genl_family,
- &acpi_event_mcgrp);
- if (result)
- genl_unregister_family(&acpi_event_genl_family);
-
- return result;
+ return genl_register_family(&acpi_event_genl_family);
}
#else
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 2721e29..0715de5 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2670,16 +2670,15 @@ static const struct genl_ops team_nl_ops[] = {
},
};
-static struct genl_multicast_group team_change_event_mcgrp = {
- .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME,
+static const struct genl_multicast_group team_nl_mcgrps[] = {
+ { .name = TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME, },
};
static int team_nl_send_multicast(struct sk_buff *skb,
struct team *team, u32 portid)
{
return genlmsg_multicast_netns(&team_nl_family, dev_net(team->dev),
- skb, 0, team_change_event_mcgrp.id,
- GFP_KERNEL);
+ skb, 0, 0, GFP_KERNEL);
}
static int team_nl_send_event_options_get(struct team *team,
@@ -2698,22 +2697,8 @@ static int team_nl_send_event_port_get(struct team *team,
static int team_nl_init(void)
{
- int err;
-
- err = genl_register_family_with_ops(&team_nl_family, team_nl_ops);
- if (err)
- return err;
-
- err = genl_register_mc_group(&team_nl_family, &team_change_event_mcgrp);
- if (err)
- goto err_change_event_grp_reg;
-
- return 0;
-
-err_change_event_grp_reg:
- genl_unregister_family(&team_nl_family);
-
- return err;
+ return genl_register_family_with_ops_groups(&team_nl_family, team_nl_ops,
+ team_nl_mcgrps);
}
static void team_nl_fini(void)
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 2570a94..19edd61 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1606,15 +1606,17 @@ exit:
EXPORT_SYMBOL_GPL(thermal_zone_get_zone_by_name);
#ifdef CONFIG_NET
+static const struct genl_multicast_group thermal_event_mcgrps[] = {
+ { .name = THERMAL_GENL_MCAST_GROUP_NAME, },
+};
+
static struct genl_family thermal_event_genl_family = {
.id = GENL_ID_GENERATE,
.name = THERMAL_GENL_FAMILY_NAME,
.version = THERMAL_GENL_VERSION,
.maxattr = THERMAL_GENL_ATTR_MAX,
-};
-
-static struct genl_multicast_group thermal_event_mcgrp = {
- .name = THERMAL_GENL_MCAST_GROUP_NAME,
+ .mcgrps = thermal_event_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(thermal_event_mcgrps),
};
int thermal_generate_netlink_event(struct thermal_zone_device *tz,
@@ -1676,7 +1678,7 @@ int thermal_generate_netlink_event(struct thermal_zone_device *tz,
}
result = genlmsg_multicast(&thermal_event_genl_family, skb, 0,
- thermal_event_mcgrp.id, GFP_ATOMIC);
+ 0, GFP_ATOMIC);
if (result)
dev_err(&tz->device, "Failed to send netlink event:%d", result);
@@ -1686,17 +1688,7 @@ EXPORT_SYMBOL_GPL(thermal_generate_netlink_event);
static int genetlink_init(void)
{
- int result;
-
- result = genl_register_family(&thermal_event_genl_family);
- if (result)
- return result;
-
- result = genl_register_mc_group(&thermal_event_genl_family,
- &thermal_event_mcgrp);
- if (result)
- genl_unregister_family(&thermal_event_genl_family);
- return result;
+ return genl_register_family(&thermal_event_genl_family);
}
static void genetlink_exit(void)
diff --git a/fs/quota/netlink.c b/fs/quota/netlink.c
index a5b5edd..72d2917 100644
--- a/fs/quota/netlink.c
+++ b/fs/quota/netlink.c
@@ -9,6 +9,10 @@
#include <net/netlink.h>
#include <net/genetlink.h>
+static const struct genl_multicast_group quota_mcgrps[] = {
+ { .name = "events", },
+};
+
/* Netlink family structure for quota */
static struct genl_family quota_genl_family = {
/*
@@ -22,10 +26,8 @@ static struct genl_family quota_genl_family = {
.name = "VFS_DQUOT",
.version = 1,
.maxattr = QUOTA_NL_A_MAX,
-};
-
-static struct genl_multicast_group quota_mcgrp = {
- .name = "events",
+ .mcgrps = quota_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(quota_mcgrps),
};
/**
@@ -88,7 +90,7 @@ void quota_send_warning(struct kqid qid, dev_t dev,
goto attr_err_out;
genlmsg_end(skb, msg_head);
- genlmsg_multicast("a_genl_family, skb, 0, quota_mcgrp.id, GFP_NOFS);
+ genlmsg_multicast("a_genl_family, skb, 0, 0, GFP_NOFS);
return;
attr_err_out:
printk(KERN_ERR "VFS: Not enough space to compose quota message!\n");
@@ -102,9 +104,6 @@ static int __init quota_init(void)
if (genl_register_family("a_genl_family) != 0)
printk(KERN_ERR
"VFS: Failed to create quota netlink interface.\n");
- if (genl_register_mc_group("a_genl_family, "a_mcgrp))
- printk(KERN_ERR
- "VFS: Failed to register quota mcast group.\n");
return 0;
};
diff --git a/include/linux/genl_magic_func.h b/include/linux/genl_magic_func.h
index 5b9b8ae..c0894dd 100644
--- a/include/linux/genl_magic_func.h
+++ b/include/linux/genl_magic_func.h
@@ -273,49 +273,40 @@ static struct genl_family ZZZ_genl_family __read_mostly = {
* Magic: define multicast groups
* Magic: define multicast group registration helper
*/
+#define ZZZ_genl_mcgrps CONCAT_(GENL_MAGIC_FAMILY, _genl_mcgrps)
+static const struct genl_multicast_group ZZZ_genl_mcgrps[] = {
+#undef GENL_mc_group
+#define GENL_mc_group(group) { .name = #group, },
+#include GENL_MAGIC_INCLUDE_FILE
+};
+
+enum CONCAT_(GENL_MAGIC_FAMILY, group_ids) {
+#undef GENL_mc_group
+#define GENL_mc_group(group) CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group),
+#include GENL_MAGIC_INCLUDE_FILE
+};
+
#undef GENL_mc_group
#define GENL_mc_group(group) \
-static struct genl_multicast_group \
-CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group) __read_mostly = { \
- .name = #group, \
-}; \
static int CONCAT_(GENL_MAGIC_FAMILY, _genl_multicast_ ## group)( \
struct sk_buff *skb, gfp_t flags) \
{ \
unsigned int group_id = \
- CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id; \
- if (!group_id) \
- return -EINVAL; \
+ CONCAT_(GENL_MAGIC_FAMILY, _group_ ## group); \
return genlmsg_multicast(&ZZZ_genl_family, skb, 0, \
group_id, flags); \
}
#include GENL_MAGIC_INCLUDE_FILE
-int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
-{
- int err = genl_register_family_with_ops(&ZZZ_genl_family, ZZZ_genl_ops);
- if (err)
- return err;
-#undef GENL_mc_group
-#define GENL_mc_group(group) \
- err = genl_register_mc_group(&ZZZ_genl_family, \
- &CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group)); \
- if (err) \
- goto fail; \
- else \
- pr_info("%s: mcg %s: %u\n", #group, \
- __stringify(GENL_MAGIC_FAMILY), \
- CONCAT_(GENL_MAGIC_FAMILY, _mcg_ ## group).id);
-
-#include GENL_MAGIC_INCLUDE_FILE
-
#undef GENL_mc_group
#define GENL_mc_group(group)
- return 0;
-fail:
- genl_unregister_family(&ZZZ_genl_family);
- return err;
+
+int CONCAT_(GENL_MAGIC_FAMILY, _genl_register)(void)
+{
+ return genl_register_family_with_ops_groups(&ZZZ_genl_family, \
+ ZZZ_genl_ops, \
+ ZZZ_genl_mcgrps);
}
void CONCAT_(GENL_MAGIC_FAMILY, _genl_unregister)(void)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 60aef0d..ace4abf 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -10,14 +10,9 @@
/**
* 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
*/
struct genl_multicast_group {
- struct list_head list; /* private */
char name[GENL_NAMSIZ];
- u32 id;
};
struct genl_ops;
@@ -38,7 +33,9 @@ struct genl_info;
* undo operations done by pre_doit, for example release locks
* @attrbuf: buffer to store parsed attributes
* @family_list: family list
- * @mcast_groups: multicast groups list
+ * @mcgrps: multicast groups used by this family (private)
+ * @n_mcgrps: number of multicast groups (private)
+ * @mcgrp_offset: starting number of multicast group IDs in this family
* @ops: the operations supported by this family (private)
* @n_ops: number of operations supported by this family (private)
*/
@@ -58,9 +55,11 @@ struct genl_family {
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 list_head mcast_groups; /* private */
struct module *module;
};
@@ -150,22 +149,30 @@ static inline int genl_register_family(struct genl_family *family)
*
* Return 0 on success or a negative error code.
*/
-static inline int _genl_register_family_with_ops(struct genl_family *family,
- const struct genl_ops *ops,
- size_t n_ops)
+static inline int
+_genl_register_family_with_ops_grps(struct genl_family *family,
+ const struct genl_ops *ops, size_t n_ops,
+ const struct genl_multicast_group *mcgrps,
+ size_t n_mcgrps)
{
family->module = THIS_MODULE;
family->ops = ops;
family->n_ops = n_ops;
+ family->mcgrps = mcgrps;
+ family->n_mcgrps = n_mcgrps;
return __genl_register_family(family);
}
-#define genl_register_family_with_ops(family, ops) \
- _genl_register_family_with_ops((family), (ops), ARRAY_SIZE(ops))
+#define genl_register_family_with_ops(family, ops) \
+ _genl_register_family_with_ops_grps((family), \
+ (ops), ARRAY_SIZE(ops), \
+ NULL, 0)
+#define genl_register_family_with_ops_groups(family, ops, grps) \
+ _genl_register_family_with_ops_grps((family), \
+ (ops), ARRAY_SIZE(ops), \
+ (grps), ARRAY_SIZE(grps))
int genl_unregister_family(struct genl_family *family);
-int genl_register_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp);
void genl_notify(struct genl_family *family,
struct sk_buff *skb, struct net *net, u32 portid,
u32 group, struct nlmsghdr *nlh, gfp_t flags);
@@ -251,13 +258,16 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
* @net: the net namespace
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
- * @group: multicast group id
+ * @group: offset of multicast group in groups array
* @flags: allocation flags
*/
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)
{
+ if (group >= family->n_mcgrps)
+ return -EINVAL;
+ group = family->mcgrp_offset + group;
return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
}
@@ -266,13 +276,16 @@ static inline int genlmsg_multicast_netns(struct genl_family *family,
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
- * @group: multicast group id
+ * @group: offset of multicast group in groups array
* @flags: allocation flags
*/
static inline int genlmsg_multicast(struct genl_family *family,
struct sk_buff *skb, u32 portid,
unsigned int group, gfp_t flags)
{
+ if (group >= family->n_mcgrps)
+ return -EINVAL;
+ group = family->mcgrp_offset + group;
return genlmsg_multicast_netns(family, &init_net, skb,
portid, group, flags);
}
@@ -282,7 +295,7 @@ static inline int genlmsg_multicast(struct genl_family *family,
* @family: the generic netlink family
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
- * @group: multicast group id
+ * @group: offset of multicast group in groups array
* @flags: allocation flags
*
* This function must hold the RTNL or rcu_read_lock().
@@ -365,6 +378,7 @@ static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
* @net: the network namespace to report the error to
* @portid: the PORTID of a process that we want to skip (if any)
* @group: the broadcast group that will notice the error
+ * (this is the offset of the multicast group in the groups array)
* @code: error code, must be negative (as usual in kernelspace)
*
* This function returns the number of broadcast listeners that have set the
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 1eab1dc..9589718 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -106,8 +106,8 @@ static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data)
return skb;
}
-static struct genl_multicast_group dm_mcgrp = {
- .name = "events",
+static struct genl_multicast_group dropmon_mcgrps[] = {
+ { .name = "events", },
};
static void send_dm_alert(struct work_struct *work)
@@ -121,7 +121,7 @@ static void send_dm_alert(struct work_struct *work)
if (skb)
genlmsg_multicast(&net_drop_monitor_family, skb, 0,
- dm_mcgrp.id, GFP_KERNEL);
+ 0, GFP_KERNEL);
}
/*
@@ -369,19 +369,13 @@ static int __init init_net_drop_monitor(void)
return -ENOSPC;
}
- rc = genl_register_family_with_ops(&net_drop_monitor_family,
- dropmon_ops);
+ rc = genl_register_family_with_ops_groups(&net_drop_monitor_family,
+ dropmon_ops, dropmon_mcgrps);
if (rc) {
pr_err("Could not create drop monitor netlink family\n");
return rc;
}
-
- rc = genl_register_mc_group(&net_drop_monitor_family, &dm_mcgrp);
- if (rc) {
- pr_err("Failed to register drop monitor mcast group\n");
- goto out_unreg;
- }
- WARN_ON(dm_mcgrp.id != NET_DM_GRP_ALERT);
+ WARN_ON(net_drop_monitor_family.mcgrp_offset != NET_DM_GRP_ALERT);
rc = register_netdevice_notifier(&dropmon_net_notifier);
if (rc < 0) {
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
index 0009416..5325af8 100644
--- a/net/hsr/hsr_netlink.c
+++ b/net/hsr/hsr_netlink.c
@@ -90,8 +90,8 @@ static struct genl_family hsr_genl_family = {
.maxattr = HSR_A_MAX,
};
-static struct genl_multicast_group hsr_network_genl_mcgrp = {
- .name = "hsr-network",
+static const struct genl_multicast_group hsr_mcgrps[] = {
+ { .name = "hsr-network", },
};
@@ -129,8 +129,7 @@ void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN],
goto nla_put_failure;
genlmsg_end(skb, msg_head);
- genlmsg_multicast(&hsr_genl_family, skb, 0,
- hsr_network_genl_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);
return;
@@ -164,8 +163,7 @@ void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN])
goto nla_put_failure;
genlmsg_end(skb, msg_head);
- genlmsg_multicast(&hsr_genl_family, skb, 0,
- hsr_network_genl_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);
return;
@@ -416,18 +414,13 @@ int __init hsr_netlink_init(void)
if (rc)
goto fail_rtnl_link_register;
- rc = genl_register_family_with_ops(&hsr_genl_family, hsr_ops);
+ rc = genl_register_family_with_ops_groups(&hsr_genl_family, hsr_ops,
+ hsr_mcgrps);
if (rc)
goto fail_genl_register_family;
- rc = genl_register_mc_group(&hsr_genl_family, &hsr_network_genl_mcgrp);
- if (rc)
- goto fail_genl_register_mc_group;
-
return 0;
-fail_genl_register_mc_group:
- genl_unregister_family(&hsr_genl_family);
fail_genl_register_family:
rtnl_link_unregister(&hsr_link_ops);
fail_rtnl_link_register:
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
index 14d5dab..cee4425 100644
--- a/net/ieee802154/ieee802154.h
+++ b/net/ieee802154/ieee802154.h
@@ -54,8 +54,10 @@ int ieee802154_dump_phy(struct sk_buff *skb, struct netlink_callback *cb);
int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info);
int ieee802154_del_iface(struct sk_buff *skb, struct genl_info *info);
-extern struct genl_multicast_group ieee802154_coord_mcgrp;
-extern struct genl_multicast_group ieee802154_beacon_mcgrp;
+enum ieee802154_mcgrp_ids {
+ IEEE802154_COORD_MCGRP,
+ IEEE802154_BEACON_MCGRP,
+};
int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info);
int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info);
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 5172f46..43f1b2b 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -125,25 +125,17 @@ static const struct genl_ops ieee8021154_ops[] = {
ieee802154_dump_iface),
};
-int __init ieee802154_nl_init(void)
-{
- int rc;
-
- rc = genl_register_family_with_ops(&nl802154_family, ieee8021154_ops);
- if (rc)
- return rc;
+static const struct genl_multicast_group ieee802154_mcgrps[] = {
+ [IEEE802154_COORD_MCGRP] = { .name = IEEE802154_MCAST_COORD_NAME, },
+ [IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
+};
- rc = genl_register_mc_group(&nl802154_family, &ieee802154_coord_mcgrp);
- if (rc)
- goto fail;
- rc = genl_register_mc_group(&nl802154_family, &ieee802154_beacon_mcgrp);
- if (rc)
- goto fail;
- return 0;
-fail:
- genl_unregister_family(&nl802154_family);
- return rc;
+int __init ieee802154_nl_init(void)
+{
+ return genl_register_family_with_ops_groups(&nl802154_family,
+ ieee8021154_ops,
+ ieee802154_mcgrps);
}
void __exit ieee802154_nl_exit(void)
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index 28d4930..ba5c1e0 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -39,14 +39,6 @@
#include "ieee802154.h"
-struct genl_multicast_group ieee802154_coord_mcgrp = {
- .name = IEEE802154_MCAST_COORD_NAME,
-};
-
-struct genl_multicast_group ieee802154_beacon_mcgrp = {
- .name = IEEE802154_MCAST_BEACON_NAME,
-};
-
int ieee802154_nl_assoc_indic(struct net_device *dev,
struct ieee802154_addr *addr, u8 cap)
{
@@ -72,7 +64,7 @@ int ieee802154_nl_assoc_indic(struct net_device *dev,
nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
@@ -98,7 +90,7 @@ int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr,
nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
@@ -133,7 +125,7 @@ int ieee802154_nl_disassoc_indic(struct net_device *dev,
}
if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
@@ -157,7 +149,7 @@ int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
dev->dev_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
@@ -183,7 +175,7 @@ int ieee802154_nl_beacon_indic(struct net_device *dev,
nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr) ||
nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
@@ -214,7 +206,7 @@ int ieee802154_nl_scan_confirm(struct net_device *dev,
(edl &&
nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
@@ -238,7 +230,7 @@ int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
dev->dev_addr) ||
nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
goto nla_put_failure;
- return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id);
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
nla_put_failure:
nlmsg_free(msg);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 36e3a86..7dbc4f7 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -69,16 +69,20 @@ static struct list_head family_ht[GENL_FAM_TAB_SIZE];
* abuses the API and thinks it can statically use group 1.
* That group will typically conflict with other groups that
* any proper users use.
+ * Bit 16 is marked as used since it's used for generic netlink
+ * and the code no longer marks pre-reserved IDs as used.
* Bit 17 is marked as already used since the VFS quota code
* also abused this API and relied on family == group ID, we
* cater to that by giving it a static family and group ID.
*/
-static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_VFS_DQUOT);
+static unsigned long mc_group_start = 0x3 | BIT(GENL_ID_CTRL) |
+ BIT(GENL_ID_VFS_DQUOT);
static unsigned long *mc_groups = &mc_group_start;
static unsigned long mc_groups_longs = 1;
static int genl_ctrl_event(int event, struct genl_family *family,
- struct genl_multicast_group *grp);
+ const struct genl_multicast_group *grp,
+ int grp_id);
static inline unsigned int genl_family_hash(unsigned int id)
{
@@ -144,66 +148,110 @@ static u16 genl_generate_id(void)
return 0;
}
-static struct genl_multicast_group notify_grp;
-
-/**
- * genl_register_mc_group - register a multicast group
- *
- * Registers the specified multicast group and notifies userspace
- * about the new group.
- *
- * Returns 0 on success or a negative error code.
- *
- * @family: The generic netlink family the group shall be registered for.
- * @grp: The group to register, must have a name.
- */
-int genl_register_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp)
+static int genl_allocate_reserve_groups(int n_groups, int *first_id)
{
- int id;
unsigned long *new_groups;
- int err = 0;
+ int start = 0;
+ int i;
+ int id;
+ bool fits;
+
+ do {
+ if (start == 0)
+ id = find_first_zero_bit(mc_groups,
+ mc_groups_longs *
+ BITS_PER_LONG);
+ else
+ id = find_next_zero_bit(mc_groups,
+ mc_groups_longs * BITS_PER_LONG,
+ start);
+
+ fits = true;
+ for (i = id;
+ i < min_t(int, id + n_groups,
+ mc_groups_longs * BITS_PER_LONG);
+ i++) {
+ if (test_bit(i, mc_groups)) {
+ start = i;
+ fits = false;
+ break;
+ }
+ }
- BUG_ON(grp->name[0] == '\0');
- BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL);
+ if (id >= mc_groups_longs * BITS_PER_LONG) {
+ unsigned long new_longs = mc_groups_longs +
+ BITS_TO_LONGS(n_groups);
+ size_t nlen = new_longs * sizeof(unsigned long);
+
+ if (mc_groups == &mc_group_start) {
+ new_groups = kzalloc(nlen, GFP_KERNEL);
+ if (!new_groups)
+ return -ENOMEM;
+ mc_groups = new_groups;
+ *mc_groups = mc_group_start;
+ } else {
+ new_groups = krealloc(mc_groups, nlen,
+ GFP_KERNEL);
+ if (!new_groups)
+ return -ENOMEM;
+ mc_groups = new_groups;
+ for (i = 0; i < BITS_TO_LONGS(n_groups); i++)
+ mc_groups[mc_groups_longs + i] = 0;
+ }
+ mc_groups_longs = new_longs;
+ }
+ } while (!fits);
- genl_lock_all();
+ for (i = id; i < id + n_groups; i++)
+ set_bit(i, mc_groups);
+ *first_id = id;
+ return 0;
+}
+
+static struct genl_family genl_ctrl;
+
+static int genl_validate_assign_mc_groups(struct genl_family *family)
+{
+ int first_id;
+ int n_groups = family->n_mcgrps;
+ int err, i;
+ bool groups_allocated = false;
+
+ if (!n_groups)
+ return 0;
+
+ for (i = 0; i < n_groups; i++) {
+ const struct genl_multicast_group *grp = &family->mcgrps[i];
+
+ if (WARN_ON(grp->name[0] == '\0'))
+ return -EINVAL;
+ if (WARN_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL))
+ return -EINVAL;
+ }
/* special-case our own group and hacks */
- if (grp == ¬ify_grp)
- id = GENL_ID_CTRL;
- else if (strcmp(family->name, "NET_DM") == 0)
- id = 1;
- else if (strcmp(family->name, "VFS_DQUOT") == 0)
- id = GENL_ID_VFS_DQUOT;
- else
- id = find_first_zero_bit(mc_groups,
- mc_groups_longs * BITS_PER_LONG);
-
-
- if (id >= mc_groups_longs * BITS_PER_LONG) {
- size_t nlen = (mc_groups_longs + 1) * sizeof(unsigned long);
-
- if (mc_groups == &mc_group_start) {
- new_groups = kzalloc(nlen, GFP_KERNEL);
- if (!new_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++;
+ if (family == &genl_ctrl) {
+ first_id = GENL_ID_CTRL;
+ BUG_ON(n_groups != 1);
+ } else if (strcmp(family->name, "NET_DM") == 0) {
+ first_id = 1;
+ BUG_ON(n_groups != 1);
+ } else if (strcmp(family->name, "VFS_DQUOT") == 0) {
+ first_id = GENL_ID_VFS_DQUOT;
+ BUG_ON(n_groups != 1);
+ } else {
+ groups_allocated = true;
+ err = genl_allocate_reserve_groups(n_groups, &first_id);
+ if (err)
+ return err;
}
+ family->mcgrp_offset = first_id;
+
+ /* if still initializing, can't and don't need to to realloc bitmaps */
+ if (!init_net.genl_sock)
+ return 0;
+
if (family->netnsok) {
struct net *net;
@@ -219,9 +267,7 @@ int genl_register_mc_group(struct genl_family *family,
* number of _possible_ groups has been
* increased on some sockets which is ok.
*/
- rcu_read_unlock();
- netlink_table_ungrab();
- goto out;
+ break;
}
}
rcu_read_unlock();
@@ -229,46 +275,39 @@ int genl_register_mc_group(struct genl_family *family,
} else {
err = netlink_change_ngroups(init_net.genl_sock,
mc_groups_longs * BITS_PER_LONG);
- if (err)
- goto out;
}
- grp->id = id;
- set_bit(id, mc_groups);
- list_add_tail(&grp->list, &family->mcast_groups);
+ if (groups_allocated && err) {
+ for (i = 0; i < family->n_mcgrps; i++)
+ clear_bit(family->mcgrp_offset + i, mc_groups);
+ }
- genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family, grp);
- out:
- genl_unlock_all();
return err;
}
-EXPORT_SYMBOL(genl_register_mc_group);
-static void __genl_unregister_mc_group(struct genl_family *family,
- struct genl_multicast_group *grp)
+static void genl_unregister_mc_groups(struct genl_family *family)
{
struct net *net;
+ int i;
netlink_table_grab();
rcu_read_lock();
- for_each_net_rcu(net)
- __netlink_clear_multicast_users(net->genl_sock, grp->id);
+ for_each_net_rcu(net) {
+ for (i = 0; i < family->n_mcgrps; i++)
+ __netlink_clear_multicast_users(
+ net->genl_sock, family->mcgrp_offset + i);
+ }
rcu_read_unlock();
netlink_table_ungrab();
- if (grp->id != 1)
- clear_bit(grp->id, mc_groups);
- list_del(&grp->list);
- genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family, grp);
- grp->id = 0;
-}
-
-static void genl_unregister_mc_groups(struct genl_family *family)
-{
- struct genl_multicast_group *grp, *tmp;
+ for (i = 0; i < family->n_mcgrps; i++) {
+ int grp_id = family->mcgrp_offset + i;
- list_for_each_entry_safe(grp, tmp, &family->mcast_groups, list)
- __genl_unregister_mc_group(family, grp);
+ if (grp_id != 1)
+ clear_bit(grp_id, mc_groups);
+ genl_ctrl_event(CTRL_CMD_DELMCAST_GRP, family,
+ &family->mcgrps[i], grp_id);
+ }
}
static int genl_validate_ops(struct genl_family *family)
@@ -314,7 +353,7 @@ static int genl_validate_ops(struct genl_family *family)
*/
int __genl_register_family(struct genl_family *family)
{
- int err = -EINVAL;
+ int err = -EINVAL, i;
if (family->id && family->id < GENL_MIN_ID)
goto errout;
@@ -326,8 +365,6 @@ int __genl_register_family(struct genl_family *family)
if (err)
return err;
- INIT_LIST_HEAD(&family->mcast_groups);
-
genl_lock_all();
if (genl_family_find_byname(family->name)) {
@@ -359,10 +396,18 @@ int __genl_register_family(struct genl_family *family)
} else
family->attrbuf = NULL;
+ err = genl_validate_assign_mc_groups(family);
+ if (err)
+ goto errout_locked;
+
list_add_tail(&family->family_list, genl_family_chain(family->id));
genl_unlock_all();
- genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL);
+ /* send all events */
+ genl_ctrl_event(CTRL_CMD_NEWFAMILY, family, NULL, 0);
+ for (i = 0; i < family->n_mcgrps; i++)
+ genl_ctrl_event(CTRL_CMD_NEWMCAST_GRP, family,
+ &family->mcgrps[i], family->mcgrp_offset + i);
return 0;
@@ -398,7 +443,7 @@ int genl_unregister_family(struct genl_family *family)
genl_unlock_all();
kfree(family->attrbuf);
- genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL);
+ genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
return 0;
}
@@ -658,23 +703,26 @@ static int ctrl_fill_info(struct genl_family *family, u32 portid, u32 seq,
nla_nest_end(skb, nla_ops);
}
- if (!list_empty(&family->mcast_groups)) {
- struct genl_multicast_group *grp;
+ if (family->n_mcgrps) {
struct nlattr *nla_grps;
- int idx = 1;
+ int i;
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) {
+ for (i = 0; i < family->n_mcgrps; i++) {
struct nlattr *nest;
+ const struct genl_multicast_group *grp;
- nest = nla_nest_start(skb, idx++);
+ grp = &family->mcgrps[i];
+
+ nest = nla_nest_start(skb, i + 1);
if (nest == NULL)
goto nla_put_failure;
- if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id) ||
+ if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID,
+ family->mcgrp_offset + i) ||
nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
grp->name))
goto nla_put_failure;
@@ -692,9 +740,9 @@ nla_put_failure:
}
static int ctrl_fill_mcgrp_info(struct genl_family *family,
- struct genl_multicast_group *grp, u32 portid,
- u32 seq, u32 flags, struct sk_buff *skb,
- u8 cmd)
+ const struct genl_multicast_group *grp,
+ int grp_id, u32 portid, u32 seq, u32 flags,
+ struct sk_buff *skb, u8 cmd)
{
void *hdr;
struct nlattr *nla_grps;
@@ -716,7 +764,7 @@ static int ctrl_fill_mcgrp_info(struct genl_family *family,
if (nest == NULL)
goto nla_put_failure;
- if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp->id) ||
+ if (nla_put_u32(skb, CTRL_ATTR_MCAST_GRP_ID, grp_id) ||
nla_put_string(skb, CTRL_ATTR_MCAST_GRP_NAME,
grp->name))
goto nla_put_failure;
@@ -782,9 +830,10 @@ static struct sk_buff *ctrl_build_family_msg(struct genl_family *family,
return skb;
}
-static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_family *family,
- struct genl_multicast_group *grp,
- u32 portid, int seq, u8 cmd)
+static struct sk_buff *
+ctrl_build_mcgrp_msg(struct genl_family *family,
+ const struct genl_multicast_group *grp,
+ int grp_id, u32 portid, int seq, u8 cmd)
{
struct sk_buff *skb;
int err;
@@ -793,7 +842,8 @@ static struct sk_buff *ctrl_build_mcgrp_msg(struct genl_family *family,
if (skb == NULL)
return ERR_PTR(-ENOBUFS);
- err = ctrl_fill_mcgrp_info(family, grp, portid, seq, 0, skb, cmd);
+ err = ctrl_fill_mcgrp_info(family, grp, grp_id, portid,
+ seq, 0, skb, cmd);
if (err < 0) {
nlmsg_free(skb);
return ERR_PTR(err);
@@ -856,7 +906,8 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info)
}
static int genl_ctrl_event(int event, struct genl_family *family,
- struct genl_multicast_group *grp)
+ const struct genl_multicast_group *grp,
+ int grp_id)
{
struct sk_buff *msg;
@@ -873,7 +924,7 @@ static int genl_ctrl_event(int event, struct genl_family *family,
case CTRL_CMD_NEWMCAST_GRP:
case CTRL_CMD_DELMCAST_GRP:
BUG_ON(!grp);
- msg = ctrl_build_mcgrp_msg(family, grp, 0, 0, event);
+ msg = ctrl_build_mcgrp_msg(family, grp, grp_id, 0, 0, event);
break;
default:
return -EINVAL;
@@ -884,11 +935,11 @@ static int genl_ctrl_event(int event, struct genl_family *family,
if (!family->netnsok) {
genlmsg_multicast_netns(&genl_ctrl, &init_net, msg, 0,
- GENL_ID_CTRL, GFP_KERNEL);
+ 0, GFP_KERNEL);
} else {
rcu_read_lock();
genlmsg_multicast_allns(&genl_ctrl, msg, 0,
- GENL_ID_CTRL, GFP_ATOMIC);
+ 0, GFP_ATOMIC);
rcu_read_unlock();
}
@@ -904,8 +955,8 @@ static struct genl_ops genl_ctrl_ops[] = {
},
};
-static struct genl_multicast_group notify_grp = {
- .name = "notify",
+static struct genl_multicast_group genl_ctrl_groups[] = {
+ { .name = "notify", },
};
static int __net_init genl_pernet_init(struct net *net)
@@ -945,7 +996,8 @@ static int __init genl_init(void)
for (i = 0; i < GENL_FAM_TAB_SIZE; i++)
INIT_LIST_HEAD(&family_ht[i]);
- err = genl_register_family_with_ops(&genl_ctrl, genl_ctrl_ops);
+ err = genl_register_family_with_ops_groups(&genl_ctrl, genl_ctrl_ops,
+ genl_ctrl_groups);
if (err < 0)
goto problem;
@@ -953,10 +1005,6 @@ static int __init genl_init(void)
if (err)
goto problem;
- err = genl_register_mc_group(&genl_ctrl, ¬ify_grp);
- if (err < 0)
- goto problem;
-
return 0;
problem:
@@ -997,6 +1045,9 @@ static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
int genlmsg_multicast_allns(struct genl_family *family, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
+ if (group >= family->n_mcgrps)
+ return -EINVAL;
+ group = family->mcgrp_offset + group;
return genlmsg_mcast(skb, portid, group, flags);
}
EXPORT_SYMBOL(genlmsg_multicast_allns);
@@ -1011,6 +1062,9 @@ void genl_notify(struct genl_family *family,
if (nlh)
report = nlmsg_report(nlh);
+ if (group >= family->n_mcgrps)
+ return;
+ group = family->mcgrp_offset + group;
nlmsg_notify(sk, skb, portid, group, report, flags);
}
EXPORT_SYMBOL(genl_notify);
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 3092df31..a9b2342 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -30,8 +30,8 @@
#include "nfc.h"
#include "llcp.h"
-static struct genl_multicast_group nfc_genl_event_mcgrp = {
- .name = NFC_GENL_MCAST_EVENT_NAME,
+static const struct genl_multicast_group nfc_genl_mcgrps[] = {
+ { .name = NFC_GENL_MCAST_EVENT_NAME, },
};
static struct genl_family nfc_genl_family = {
@@ -194,8 +194,7 @@ int nfc_genl_targets_found(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- return genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ return genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
nla_put_failure:
genlmsg_cancel(msg, hdr);
@@ -224,8 +223,7 @@ int nfc_genl_target_lost(struct nfc_dev *dev, u32 target_idx)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -257,8 +255,7 @@ int nfc_genl_tm_activated(struct nfc_dev *dev, u32 protocol)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -288,8 +285,7 @@ int nfc_genl_tm_deactivated(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -322,8 +318,7 @@ int nfc_genl_device_added(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -353,8 +348,7 @@ int nfc_genl_device_removed(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -420,8 +414,7 @@ int nfc_genl_llc_send_sdres(struct nfc_dev *dev, struct hlist_head *sdres_list)
genlmsg_end(msg, hdr);
- return genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ return genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
nla_put_failure:
genlmsg_cancel(msg, hdr);
@@ -455,8 +448,7 @@ int nfc_genl_se_added(struct nfc_dev *dev, u32 se_idx, u16 type)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -487,8 +479,7 @@ int nfc_genl_se_removed(struct nfc_dev *dev, u32 se_idx)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -609,8 +600,7 @@ int nfc_genl_dep_link_up_event(struct nfc_dev *dev, u32 target_idx,
dev->dep_link_up = true;
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
return 0;
@@ -642,8 +632,7 @@ int nfc_genl_dep_link_down_event(struct nfc_dev *dev)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_ATOMIC);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_ATOMIC);
return 0;
@@ -1148,8 +1137,7 @@ int nfc_genl_fw_download_done(struct nfc_dev *dev, const char *firmware_name,
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
return 0;
@@ -1320,8 +1308,7 @@ static void se_io_cb(void *context, u8 *apdu, size_t apdu_len, int err)
genlmsg_end(msg, hdr);
- genlmsg_multicast(&nfc_genl_family, msg, 0,
- nfc_genl_event_mcgrp.id, GFP_KERNEL);
+ genlmsg_multicast(&nfc_genl_family, msg, 0, 0, GFP_KERNEL);
kfree(ctx);
@@ -1549,15 +1536,15 @@ int __init nfc_genl_init(void)
{
int rc;
- rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops);
+ rc = genl_register_family_with_ops_groups(&nfc_genl_family,
+ nfc_genl_ops,
+ nfc_genl_mcgrps);
if (rc)
return rc;
- rc = genl_register_mc_group(&nfc_genl_family, &nfc_genl_event_mcgrp);
-
netlink_register_notifier(&nl_notifier);
- return rc;
+ return 0;
}
/**
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 5c19846..1de4d28 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -62,11 +62,10 @@
int ovs_net_id __read_mostly;
static void ovs_notify(struct genl_family *family,
- struct sk_buff *skb, struct genl_info *info,
- struct genl_multicast_group *grp)
+ struct sk_buff *skb, struct genl_info *info)
{
genl_notify(family, skb, genl_info_net(info), info->snd_portid,
- grp->id, info->nlhdr, GFP_KERNEL);
+ 0, info->nlhdr, GFP_KERNEL);
}
/**
@@ -878,11 +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(&dp_flow_genl_family, reply, info,
- &ovs_dp_flow_multicast_group);
+ ovs_notify(&dp_flow_genl_family, reply, info);
else
genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 0,
- ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
+ 0, PTR_ERR(reply));
return 0;
err_flow_free:
@@ -992,8 +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(&dp_flow_genl_family, reply, info,
- &ovs_dp_flow_multicast_group);
+ ovs_notify(&dp_flow_genl_family, reply, info);
return 0;
unlock:
ovs_unlock();
@@ -1240,8 +1237,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
ovs_unlock();
- ovs_notify(&dp_datapath_genl_family, reply, info,
- &ovs_dp_datapath_multicast_group);
+ ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
err_destroy_local_port:
@@ -1306,8 +1302,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info)
__dp_destroy(dp);
ovs_unlock();
- ovs_notify(&dp_datapath_genl_family, reply, info,
- &ovs_dp_datapath_multicast_group);
+ ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
unlock:
@@ -1332,14 +1327,13 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(reply)) {
err = PTR_ERR(reply);
genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
- ovs_dp_datapath_multicast_group.id, err);
+ 0, err);
err = 0;
goto unlock;
}
ovs_unlock();
- ovs_notify(&dp_datapath_genl_family, reply, info,
- &ovs_dp_datapath_multicast_group);
+ ovs_notify(&dp_datapath_genl_family, reply, info);
return 0;
unlock:
@@ -1601,8 +1595,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto exit_unlock;
}
- ovs_notify(&dp_vport_genl_family, reply, info,
- &ovs_dp_vport_multicast_group);
+ ovs_notify(&dp_vport_genl_family, reply, info);
exit_unlock:
ovs_unlock();
@@ -1649,8 +1642,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
BUG_ON(err < 0);
ovs_unlock();
- ovs_notify(&dp_vport_genl_family, reply, info,
- &ovs_dp_vport_multicast_group);
+ ovs_notify(&dp_vport_genl_family, reply, info);
return 0;
exit_free:
@@ -1687,8 +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(&dp_vport_genl_family, reply, info,
- &ovs_dp_vport_multicast_group);
+ ovs_notify(&dp_vport_genl_family, reply, info);
exit_unlock:
ovs_unlock();
@@ -1790,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[] = {
@@ -1828,16 +1819,12 @@ static int dp_register_genl(void)
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/dp_notify.c b/net/openvswitch/dp_notify.c
index f4b66c8..2c631fe 100644
--- a/net/openvswitch/dp_notify.c
+++ b/net/openvswitch/dp_notify.c
@@ -35,15 +35,13 @@ static void dp_detach_port_notify(struct vport *vport)
ovs_dp_detach_port(vport);
if (IS_ERR(notify)) {
genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
- ovs_dp_vport_multicast_group.id,
- PTR_ERR(notify));
+ 0, PTR_ERR(notify));
return;
}
genlmsg_multicast_netns(&dp_vport_genl_family,
ovs_dp_get_net(dp), notify, 0,
- ovs_dp_vport_multicast_group.id,
- GFP_KERNEL);
+ 0, GFP_KERNEL);
}
void ovs_dp_notify_wq(struct work_struct *work)
diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c
index f37dd3c..c278b33 100644
--- a/net/wimax/op-msg.c
+++ b/net/wimax/op-msg.c
@@ -279,8 +279,7 @@ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
d_dump(2, dev, msg, size);
- genlmsg_multicast(&wimax_gnl_family, skb, 0,
- wimax_gnl_mcg.id, GFP_KERNEL);
+ genlmsg_multicast(&wimax_gnl_family, skb, 0, 0, GFP_KERNEL);
d_printf(1, dev, "CTX: genl multicast done\n");
return 0;
}
diff --git a/net/wimax/stack.c b/net/wimax/stack.c
index 1888874..ef2191b 100644
--- a/net/wimax/stack.c
+++ b/net/wimax/stack.c
@@ -116,8 +116,9 @@ struct sk_buff *wimax_gnl_re_state_change_alloc(
dev_err(dev, "RE_STCH: can't create message\n");
goto error_new;
}
- data = genlmsg_put(report_skb, 0, wimax_gnl_mcg.id, &wimax_gnl_family,
- 0, WIMAX_GNL_RE_STATE_CHANGE);
+ /* FIXME: sending a group ID as the seq is wrong */
+ data = genlmsg_put(report_skb, 0, wimax_gnl_family.mcgrp_offset,
+ &wimax_gnl_family, 0, WIMAX_GNL_RE_STATE_CHANGE);
if (data == NULL) {
dev_err(dev, "RE_STCH: can't put data into message\n");
goto error_put;
@@ -177,8 +178,7 @@ int wimax_gnl_re_state_change_send(
goto out;
}
genlmsg_end(report_skb, header);
- genlmsg_multicast(&wimax_gnl_family, report_skb, 0,
- wimax_gnl_mcg.id, GFP_KERNEL);
+ genlmsg_multicast(&wimax_gnl_family, report_skb, 0, 0, GFP_KERNEL);
out:
d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n",
wimax_dev, report_skb, result);
@@ -580,8 +580,8 @@ struct genl_family wimax_gnl_family = {
.maxattr = WIMAX_GNL_ATTR_MAX,
};
-struct genl_multicast_group wimax_gnl_mcg = {
- .name = "msg",
+static const struct genl_multicast_group wimax_gnl_mcgrps[] = {
+ { .name = "msg", },
};
@@ -598,21 +598,18 @@ int __init wimax_subsys_init(void)
snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name),
"WiMAX");
- result = genl_register_family_with_ops(&wimax_gnl_family,
- wimax_gnl_ops);
+ result = genl_register_family_with_ops_groups(&wimax_gnl_family,
+ wimax_gnl_ops,
+ wimax_gnl_mcgrps);
if (unlikely(result < 0)) {
printk(KERN_ERR "cannot register generic netlink family: %d\n",
result);
goto error_register_family;
}
- result = genl_register_mc_group(&wimax_gnl_family, &wimax_gnl_mcg);
- if (result < 0)
- goto error_mc_group;
d_fnend(4, NULL, "() = 0\n");
return 0;
-error_mc_group:
genl_unregister_family(&wimax_gnl_family);
error_register_family:
d_fnend(4, NULL, "() = %d\n", result);
diff --git a/net/wimax/wimax-internal.h b/net/wimax/wimax-internal.h
index 8567d30..b445b82 100644
--- a/net/wimax/wimax-internal.h
+++ b/net/wimax/wimax-internal.h
@@ -86,7 +86,6 @@ void wimax_rfkill_rm(struct wimax_dev *);
/* generic netlink */
extern struct genl_family wimax_gnl_family;
-extern struct genl_multicast_group wimax_gnl_mcg;
/* ops */
int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f20edfd..a1eb210 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -47,6 +47,25 @@ static struct genl_family nl80211_fam = {
.post_doit = nl80211_post_doit,
};
+/* multicast groups */
+enum nl80211_multicast_groups {
+ NL80211_MCGRP_CONFIG,
+ NL80211_MCGRP_SCAN,
+ NL80211_MCGRP_REGULATORY,
+ NL80211_MCGRP_MLME,
+ NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
+};
+
+static const struct genl_multicast_group nl80211_mcgrps[] = {
+ [NL80211_MCGRP_CONFIG] = { .name = "config", },
+ [NL80211_MCGRP_SCAN] = { .name = "scan", },
+ [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", },
+ [NL80211_MCGRP_MLME] = { .name = "mlme", },
+#ifdef CONFIG_NL80211_TESTMODE
+ [NL80211_MCGRP_TESTMODE] = { .name = "testmode", }
+#endif
+};
+
/* returns ERR_PTR values */
static struct wireless_dev *
__cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
@@ -6656,10 +6675,6 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_NL80211_TESTMODE
-static struct genl_multicast_group nl80211_testmode_mcgrp = {
- .name = "testmode",
-};
-
static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6869,7 +6884,7 @@ void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
nla_nest_end(skb, data);
genlmsg_end(skb, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
- nl80211_testmode_mcgrp.id, gfp);
+ NL80211_MCGRP_TESTMODE, gfp);
}
EXPORT_SYMBOL(cfg80211_testmode_event);
#endif
@@ -9566,21 +9581,6 @@ static const struct genl_ops nl80211_ops[] = {
},
};
-static struct genl_multicast_group nl80211_mlme_mcgrp = {
- .name = "mlme",
-};
-
-/* multicast groups */
-static struct genl_multicast_group nl80211_config_mcgrp = {
- .name = "config",
-};
-static struct genl_multicast_group nl80211_scan_mcgrp = {
- .name = "scan",
-};
-static struct genl_multicast_group nl80211_regulatory_mcgrp = {
- .name = "regulatory",
-};
-
/* notification functions */
void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
@@ -9598,7 +9598,7 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_config_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_CONFIG, GFP_KERNEL);
}
static int nl80211_add_scan_req(struct sk_buff *msg,
@@ -9708,7 +9708,7 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
@@ -9727,7 +9727,7 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
@@ -9746,7 +9746,7 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
@@ -9765,7 +9765,7 @@ void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
@@ -9783,7 +9783,7 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_scan_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_SCAN, GFP_KERNEL);
}
/*
@@ -9838,7 +9838,7 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
rcu_read_lock();
genlmsg_multicast_allns(&nl80211_fam, msg, 0,
- nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
+ NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
rcu_read_unlock();
return;
@@ -9874,7 +9874,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -9962,7 +9962,7 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10018,7 +10018,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10057,7 +10057,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10095,7 +10095,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_MLME, GFP_KERNEL);
return;
nla_put_failure:
@@ -10129,7 +10129,7 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10170,7 +10170,7 @@ void cfg80211_notify_new_peer_candidate(struct net_device *dev, const u8 *addr,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10209,7 +10209,7 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10262,7 +10262,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
rcu_read_lock();
genlmsg_multicast_allns(&nl80211_fam, msg, 0,
- nl80211_regulatory_mcgrp.id, GFP_ATOMIC);
+ NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
rcu_read_unlock();
return;
@@ -10308,7 +10308,7 @@ static void nl80211_send_remain_on_chan_event(
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10363,7 +10363,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
}
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
}
EXPORT_SYMBOL(cfg80211_new_sta);
@@ -10393,7 +10393,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10429,7 +10429,7 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10591,7 +10591,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10640,7 +10640,7 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10685,7 +10685,7 @@ static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10743,7 +10743,7 @@ nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10790,7 +10790,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10867,7 +10867,7 @@ void cfg80211_cqm_txe_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10916,7 +10916,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -10963,7 +10963,7 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -11003,7 +11003,7 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -11155,7 +11155,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
free_msg:
@@ -11197,7 +11197,7 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, gfp);
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
@@ -11280,7 +11280,7 @@ void cfg80211_ft_event(struct net_device *netdev,
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ NL80211_MCGRP_MLME, GFP_KERNEL);
}
EXPORT_SYMBOL(cfg80211_ft_event);
@@ -11329,32 +11329,11 @@ int nl80211_init(void)
{
int err;
- err = genl_register_family_with_ops(&nl80211_fam, nl80211_ops);
+ err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
+ nl80211_mcgrps);
if (err)
return err;
- err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
- if (err)
- goto err_out;
-
- err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp);
- if (err)
- goto err_out;
-
- err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
- if (err)
- goto err_out;
-
- err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp);
- if (err)
- goto err_out;
-
-#ifdef CONFIG_NL80211_TESTMODE
- err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp);
- if (err)
- goto err_out;
-#endif
-
err = netlink_register_notifier(&nl80211_netlink_notifier);
if (err)
goto err_out;
--
1.8.4.rc3
^ permalink raw reply related
* Re: [PATCH 2/2] ipv6: use sk_v6_copy_addrs when memcpy struct ipv6_pinfo
From: Eric Dumazet @ 2013-11-19 14:23 UTC (permalink / raw)
To: Daniel Borkmann
Cc: wangweidong, davem, gerrit, kuznet, jmorris, yoshfuji, kaber,
vyasevich, nhorman, dccp, netdev, linux-sctp, dingtianhong
In-Reply-To: <528B4D0B.10204@redhat.com>
On Tue, 2013-11-19 at 12:35 +0100, Daniel Borkmann wrote:
> On 11/19/2013 05:00 AM, Eric Dumazet wrote:
> > On Mon, 2013-11-18 at 19:58 -0800, Eric Dumazet wrote:
> >
> >> But sctp is not tcp ;)
> >>
> >> sctp_copy_sock() is doing some clever/partial copy of the socket, so
> >> please fix it ;)
> >>
> >> No idea why it's not doing the normal copy of the socket.
> >
> > BTW, not doing the full copy means for example that SO_MAX_PACING_RATE
> > is broken for SCTP.
>
> Yep, indeed. Looking into it ...
It might be the time to finally use inet_csk_clone_lock() in SCTP.
^ permalink raw reply
* Re: net/usb/ax88179_178a driver broken in linux-3.12
From: Mark Lord @ 2013-11-19 14:24 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Laight, Ming Lei, davem, netdev, Linux Kernel, stable
In-Reply-To: <1384870550.8604.101.camel@edumazet-glaptop2.roam.corp.google.com>
On 13-11-19 09:15 AM, Eric Dumazet wrote:
> On Tue, 2013-11-19 at 09:02 -0500, Mark Lord wrote:
>> On 13-11-19 05:04 AM, David Laight wrote:
>>>> From: Mark Lord
>> ..
>>>> except the ax88179_178a driver still does not work in linux-3.12,
>>>> whereas it works fine in all earlier kernels.
>>>>
>>>> That's a regression.
>>>> And a simple revert (earlier in this thread) fixes it.
>>>> So.. let's revert it for now, until a proper xhci compatible patch is produced.
>> ...
>>> There is a patch to xhci-ring.c that should fix the SG problem.
>>> http://www.spinics.net/lists/linux-usb/msg97176.html
>>>
>>> I think it should apply to the 3.12 sources.
>>
>> I am running with that patch here now (thanks),
>> and it too appears to prevent the lockups.
>>
>> But is this patch upstream already?
>> If yes, then it needs to get pushed out to -stable for 3.12 at least.
>>
>> If not upstream, then the revert is probably safest for -stable,
>> rather than new code that has never been upstream before.
>>
>
>> Both patches are attached to this email.
>> One or the other is required for the USB 3.0 network adapters to function in 3.12.
>
> I do not see any error in commit f27070158d6754765f2
> ("ax88179_178a: avoid copy of tx tcp packets")
> Quite the contrary in fact...
>
> I suspect a TSO bug, and would rather disable TSO for this nic.
David's explanation for the XHCI issue seems to explain it nicely,
and the patch he linked to does indeed address/fix the issue,
without disabling TSO.
So on the evidence, probably NOT a TSO bug.
--
Mark Lord
Real-Time Remedies Inc.
mlord@pobox.com
^ permalink raw reply
* Re: [PATCH 2/2] ipv6: use sk_v6_copy_addrs when memcpy struct ipv6_pinfo
From: Daniel Borkmann @ 2013-11-19 14:26 UTC (permalink / raw)
To: Eric Dumazet
Cc: wangweidong, davem, gerrit, kuznet, jmorris, yoshfuji, kaber,
vyasevich, nhorman, dccp, netdev, linux-sctp, dingtianhong
In-Reply-To: <1384871001.8604.103.camel@edumazet-glaptop2.roam.corp.google.com>
On 11/19/2013 03:23 PM, Eric Dumazet wrote:
> On Tue, 2013-11-19 at 12:35 +0100, Daniel Borkmann wrote:
>> On 11/19/2013 05:00 AM, Eric Dumazet wrote:
>>> On Mon, 2013-11-18 at 19:58 -0800, Eric Dumazet wrote:
>>>
>>>> But sctp is not tcp ;)
>>>>
>>>> sctp_copy_sock() is doing some clever/partial copy of the socket, so
>>>> please fix it ;)
>>>>
>>>> No idea why it's not doing the normal copy of the socket.
>>>
>>> BTW, not doing the full copy means for example that SO_MAX_PACING_RATE
>>> is broken for SCTP.
>>
>> Yep, indeed. Looking into it ...
>
> It might be the time to finally use inet_csk_clone_lock() in SCTP.
I agree, this would be a good consolidation. We should do that for net-next
if that's possible.
^ permalink raw reply
* Re: [PATCH 1/2] netfilter: synproxy: send mss option to backend
From: Pablo Neira Ayuso @ 2013-11-19 14:35 UTC (permalink / raw)
To: Martin Topholm; +Cc: brouer, kaber, netfilter-devel, netdev
In-Reply-To: <1384439731-16296-2-git-send-email-mph@one.com>
On Thu, Nov 14, 2013 at 03:35:30PM +0100, Martin Topholm wrote:
> When the synproxy_parse_options is called on the client ack the mss
> option will not be present. Consequently mss wont be included in the
> backend syn packet, which falls back to 536 bytes mss.
>
> Therefore XT_SYNPROXY_OPT_MSS is explicitly flagged when recovering mss
> value from cookie.
Applied, thanks Martin.
^ permalink raw reply
* Re: [PATCH 2/2] netfilter: synproxy: correct wscale option passing
From: Pablo Neira Ayuso @ 2013-11-19 14:35 UTC (permalink / raw)
To: Martin Topholm; +Cc: brouer, kaber, netfilter-devel, netdev
In-Reply-To: <1384439731-16296-3-git-send-email-mph@one.com>
On Thu, Nov 14, 2013 at 03:35:31PM +0100, Martin Topholm wrote:
> Timestamp are used to store additional syncookie parameters such as sack,
> ecn, and wscale. The wscale value we need to encode is the client's
> wscale, since we can't recover that later in the session. Next overwrite
> the wscale option so the later synproxy_send_client_synack will send
> the backend's wscale to the client.
Also applied, thanks.
^ permalink raw reply
* RE: net/usb/ax88179_178a driver broken in linux-3.12
From: David Laight @ 2013-11-19 14:43 UTC (permalink / raw)
To: Eric Dumazet, Mark Lord; +Cc: Ming Lei, davem, netdev, Linux Kernel, stable
In-Reply-To: <1384870550.8604.101.camel@edumazet-glaptop2.roam.corp.google.com>
> From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> On Tue, 2013-11-19 at 09:02 -0500, Mark Lord wrote:
> > On 13-11-19 05:04 AM, David Laight wrote:
> > >> From: Mark Lord
> > ..
> > >> except the ax88179_178a driver still does not work in linux-3.12,
> > >> whereas it works fine in all earlier kernels.
I've seen lost packets in IIRC 3.2
> > >> That's a regression.
> > >> And a simple revert (earlier in this thread) fixes it.
> > >> So.. let's revert it for now, until a proper xhci compatible patch is produced.
> > ...
> > > There is a patch to xhci-ring.c that should fix the SG problem.
> > > http://www.spinics.net/lists/linux-usb/msg97176.html
> > >
> > > I think it should apply to the 3.12 sources.
> >
> > I am running with that patch here now (thanks),
> > and it too appears to prevent the lockups.
> >
> > But is this patch upstream already?
> > If yes, then it needs to get pushed out to -stable for 3.12 at least.
Having someone else confirm that there is a bug, and that the
patch fixes it should help it get pushed to -stable.
> > If not upstream, then the revert is probably safest for -stable,
> > rather than new code that has never been upstream before.
> >
>
> > Both patches are attached to this email.
> > One or the other is required for the USB 3.0 network adapters to function in 3.12.
>
> I do not see any error in commit f27070158d6754765f2
> ("ax88179_178a: avoid copy of tx tcp packets")
>
> Quite the contrary in fact...
>
> I suspect a TSO bug, and would rather disable TSO for this nic.
>
> Have you tried to revert 3804fad45411b482
> ("USBNET: ax88179_178a: enable tso if usb host supports sg dma")
It isn't directly a TSO problem.
There has always been a bug in the xhci driver for fragmented buffers.
TSO just means it is given a lot of fragmented buffers.
As well as user-supplied fragmented buffers, the bug affects
internal fragmentation that happens whenever a buffer crosses a 64k
byte boundary (please hw engineers - stop doing this!)
I'm not sure whether usbnet would ever pass buffers that cross 64k
boundaries. I've not seen one - even with TSO. But the rx buffers
are 20k (doesn't seem ideal!) and could also be problematical.
USB mass storage has used SG for ages, the buffers must all be
adequately aligned for the hardware - they won't meet the constraint
for USB3 itself, but the documented restriction may be more severe
than the actual one.
David
^ permalink raw reply
* Re: [PATCH 2/2] ipv6: use sk_v6_copy_addrs when memcpy struct ipv6_pinfo
From: Vlad Yasevich @ 2013-11-19 15:25 UTC (permalink / raw)
To: Eric Dumazet, Daniel Borkmann
Cc: wangweidong, davem, gerrit, kuznet, jmorris, yoshfuji, kaber,
nhorman, dccp, netdev, linux-sctp, dingtianhong
In-Reply-To: <1384871001.8604.103.camel@edumazet-glaptop2.roam.corp.google.com>
On 11/19/2013 09:23 AM, Eric Dumazet wrote:
> On Tue, 2013-11-19 at 12:35 +0100, Daniel Borkmann wrote:
>> On 11/19/2013 05:00 AM, Eric Dumazet wrote:
>>> On Mon, 2013-11-18 at 19:58 -0800, Eric Dumazet wrote:
>>>
>>>> But sctp is not tcp ;)
>>>>
>>>> sctp_copy_sock() is doing some clever/partial copy of the socket, so
>>>> please fix it ;)
>>>>
>>>> No idea why it's not doing the normal copy of the socket.
>>>
>>> BTW, not doing the full copy means for example that SO_MAX_PACING_RATE
>>> is broken for SCTP.
>>
>> Yep, indeed. Looking into it ...
>
> It might be the time to finally use inet_csk_clone_lock() in SCTP.
>
>
I can see sk_clone_lock() since SCTP doesn't use icsk sockets. Need
to study the code a bit.
-vlad
^ permalink raw reply
* Re: [PATCH net] net: sctp: fix copying sk_v6_rcv_saddr in sctp_v6_create_accept_sk
From: Vlad Yasevich @ 2013-11-19 15:38 UTC (permalink / raw)
To: Daniel Borkmann, davem; +Cc: netdev, linux-sctp, Wang Weidong, Eric Dumazet
In-Reply-To: <1384858284-2246-1-git-send-email-dborkman@redhat.com>
On 11/19/2013 05:51 AM, Daniel Borkmann wrote:
> Wang reported an issue that lksctp's test_getname_v6 seems to fail.
>
> The issue is that we do not copy sk_v6_rcv_saddr over to the new
> socket, although the comment above says so regarding rcv_saddr.
>
> Commit 914e1c8b6980 ("sctp: Inherit all socket options from parent
> correctly.") originally moved that over to sctp_copy_sock(), but
> after commit efe4208f47f9 ("ipv6: make lookups simpler and faster")
> this no longer holds and the actual value of sk_v6_rcv_saddr was
> no longer being migrated.
>
> With this patch, the lksctp test suite passes again for IPv6.
>
> Fixes: efe4208f47f9 ("ipv6: make lookups simpler and faster")
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
> Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
> Cc: Eric Dumazet <eric.dumazet@gmail.com>
> ---
> net/sctp/ipv6.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
> index 7567e6f..be08592 100644
> --- a/net/sctp/ipv6.c
> +++ b/net/sctp/ipv6.c
> @@ -661,6 +661,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
> * and getpeername().
> */
> sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
> + newsk->sk_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
>
> sk_refcnt_debug_inc(newsk);
>
>
This fixes the issue for the accept() case, but the bug is still there
in the peeloff case.
I think you should make sctp_copy_sock() use sock_copy() for now. It
looks like it will catch all the cases.
We can then look at possibly getting rid of sctp_copy_sock() for net-next.
-vlad
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox