* Re: ath10k: dump Copy Engine registers during firmware crash
From: Kalle Valo @ 2017-01-19 13:19 UTC (permalink / raw)
To: Kalle Valo; +Cc: ath10k, linux-wireless
In-Reply-To: <148458066842.22029.11182008791835649945.stgit@potku.adurom.net>
Kalle Valo <kvalo@qca.qualcomm.com> wrote:
> From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
>
> Dump Copy Engine source and destination ring addresses.
> This is useful information to debug firmware crashes, assertes or hangs over long run
> assessing the Copy Engine Register status. This also enables dumping CE
> register status in debugfs Crash Dump file.
>
> Screenshot:
>
> ath10k_pci 0000:02:00.0: simulating hard firmware crash
> ath10k_pci 0000:02:00.0: firmware crashed! (uuid 84901ff5-d33c-456e-93ee-0165dea643cf)
> ath10k_pci 0000:02:00.0: qca988x hw2.0 target 0x4100016c chip_id 0x043202ff sub 0000:0000
> ath10k_pci 0000:02:00.0: kconfig debug 1 debugfs 1 tracing 1 dfs 1 testmode 1
> ath10k_pci 0000:02:00.0: firmware ver 10.2.4.70.59-2 api 5 features no-p2p,raw-mode,mfp,allows-mesh-bcast crc32 4159f498
> ath10k_pci 0000:02:00.0: board_file api 1 bmi_id N/A crc32 bebc7c08
> ath10k_pci 0000:02:00.0: htt-ver 2.1 wmi-op 5 htt-op 2 cal otp max-sta 128 raw 0 hwcrypto 1
> ath10k_pci 0000:02:00.0: firmware register dump:
> ath10k_pci 0000:02:00.0: [00]: 0x4100016C 0x00000000 0x009A0F2A 0x00000000
> ath10k_pci 0000:02:00.0: [04]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [08]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [12]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [16]: 0x00000000 0x00000000 0x00000000 0x009A0F2A
> ath10k_pci 0000:02:00.0: [20]: 0x00000000 0x00401930 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [24]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [28]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [32]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [36]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [40]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [44]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [48]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [52]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: [56]: 0x00000000 0x00000000 0x00000000 0x00000000
> ath10k_pci 0000:02:00.0: Copy Engine register dump:
> ath10k_pci 0000:02:00.0: [00]: 0x00057400 7 7 3 3
> ath10k_pci 0000:02:00.0: [01]: 0x00057800 18 18 85 86
> ath10k_pci 0000:02:00.0: [02]: 0x00057c00 49 49 48 49
> ath10k_pci 0000:02:00.0: [03]: 0x00058000 16 16 17 16
> ath10k_pci 0000:02:00.0: [04]: 0x00058400 4 4 44 4
> ath10k_pci 0000:02:00.0: [05]: 0x00058800 12 12 11 12
> ath10k_pci 0000:02:00.0: [06]: 0x00058c00 3 3 3 3
> ath10k_pci 0000:02:00.0: [07]: 0x00059000 0 0 0 0
> ieee80211 phy0: Hardware restart was requested
> ath10k_pci 0000:02:00.0: device successfully recovered
>
> Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
> [kvalo@qca.qualcomm.com: simplify the implementation]
> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
c75c398be6ed ath10k: dump Copy Engine registers during firmware crash
--
https://patchwork.kernel.org/patch/9518985/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: ath10k: prevent sta pointer rcu violation
From: Kalle Valo @ 2017-01-19 13:18 UTC (permalink / raw)
To: Michal Kazior; +Cc: greearb, linux-wireless, Michal Kazior, ath10k, mohammed
In-Reply-To: <1484234070-7431-1-git-send-email-michal.kazior@tieto.com>
Michal Kazior <michal.kazior@tieto.com> wrote:
> Station pointers are RCU protected so driver must
> be extra careful if it tries to store them
> internally for later use outside of the RCU
> section it obtained it in.
>
> It was possible for station teardown to race with
> some htt events. The possible outcome could be a
> use-after-free and a crash.
>
> Only peer-flow-control capable firmware was
> affected (so hardware-wise qca99x0 and qca4019).
>
> This could be done in sta_state() itself via
> explicit synchronize_net() call but there's
> already a convenient sta_pre_rcu_remove() op that
> can be hooked up to avoid extra rcu stall.
>
> The peer->sta pointer itself can't be set to
> NULL/ERR_PTR because it is later used in
> sta_state() for extra sanity checks.
>
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Patch applied to ath-next branch of ath.git, thanks.
0a744d927406 ath10k: prevent sta pointer rcu violation
--
https://patchwork.kernel.org/patch/9513391/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: ath10k: Fix per station tx bit rate reporting
From: Kalle Valo @ 2017-01-19 13:19 UTC (permalink / raw)
To: Mohammed Shafi Shajakhan
Cc: ath10k, mohammed, linux-wireless, Mohammed Shafi Shajakhan
In-Reply-To: <1484303403-8908-1-git-send-email-mohammed@qca.qualcomm.com>
Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com> wrote:
> From: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
>
> Not clearing the previous tx bit rate status
> results in a ambigous tx bit rate reporting to
> mac80211/cfg80211, for example the previous bit
> rate status would have been marked as legacy rate
> , while the current rate would have been an HT/VHT
> rate with the tx bit rate flags set and this results
> in exporting tx bitrate as legacy rate but with HT/VHT
> rate flags set, fix this by clearing the tx bitrate
> status for each event. This also fixes the below
> warning when we do:
>
> iw dev wlan#N station dump
>
> WARNING: net/wireless/util.c:1222 cfg80211
>
> [<c022f104>] (warn_slowpath_null) from [<bf3b9adc>]
> (cfg80211_calculate_bitrate+0x110/0x1f4 [cfg80211])
> [<bf3b9adc>] (cfg80211_calculate_bitrate [cfg80211]) from
> [<bf3dcd54>] (nl80211_put_sta_rate+0x44/0x1dc [cfg80211])
> [<bf3dcd54>] (nl80211_put_sta_rate [cfg80211]) from
> [<bf3cbc34>] (nl80211_set_interface+0x724/0xd70 [cfg80211])
> [<bf3cbc34>] (nl80211_set_interface [cfg80211]) from
> [<bf3d0a18>] (nl80211_dump_station+0xdc/0x100 [cfg80211])
> [<bf3d0a18>] (nl80211_dump_station [cfg80211])
>
> Fixes: cec17c382140 ("ath10k: add per peer htt tx stats support for 10.4")
> Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qti.qualcomm.com>
Patch applied to ath-next branch of ath.git, thanks.
0f8a2b7772f7 ath10k: fix per station tx bit rate reporting
--
https://patchwork.kernel.org/patch/9514989/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v2 01/13] wil6210: add sysfs file for FTM calibration
From: Arend Van Spriel @ 2017-01-19 13:14 UTC (permalink / raw)
To: Lior David, Valo, Kalle, qca_merez
Cc: qca_liord, linux-wireless@vger.kernel.org, wil6210
In-Reply-To: <c066ef7d-f61b-3b3e-1a6c-e2b89de812e9@codeaurora.org>
On 19-1-2017 13:36, Lior David wrote:
> On 1/19/2017 2:24 PM, Valo, Kalle wrote:
>> Maya Erez <qca_merez@qca.qualcomm.com> writes:
>>
>>> From: Lior David <qca_liord@qca.qualcomm.com>
>>>
>>> In fine timing measurements, the calculation is affected by
>>> 2 parts: timing of packets over the air, which is platform
>>> independent, and platform-specific delays, which are dependent
>>> on things like antenna cable length and type.
>>> Add a sysfs file which allows to get/set these platform specific
>>> delays, separated into the TX and RX components.
>>> There are 2 key scenarios where the file can be used:
>>> 1. Calibration - start with some initial values (for example,
>>> the default values at startup), make measurements at a known
>>> distance, then iteratively change the values until the
>>> measurement results match the known distance.
>>> 2. Adjust the delays when platform starts up, based on known
>>> values.
>>>
>>> Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
>>> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
>>
>> Can't this go via nl80211? sysfs is not really supposed to be used for
>> something like this.
>>
> There is no nl80211 API for this (yet?).
So come up with one...?
> Will it be ok to put this in debugfs? Normally this will be in the board
> file (as part of RF configuration) but it will be useful to play
> with these values for debugging/diagnostics.
What is doing the FTM measurements? Is it all done in user-space? That
would mean you also need measurement data exported to user-space. How is
that done? Intel has a FTM api proposal, but it has not been submitted
upstream (yet?).
Regards,
Arend
^ permalink raw reply
* Re: [PATCH] nl80211: fix validation of scheduled scan info for wowlan netdetect
From: Arend Van Spriel @ 2017-01-19 13:08 UTC (permalink / raw)
To: Luca Coelho, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1484827206.2774.12.camel@coelho.fi>
On 19-1-2017 13:00, Luca Coelho wrote:
> On Thu, 2017-01-19 at 10:01 +0000, Arend van Spriel wrote:
>> For wowlan netdetect a separate limit is defined for the number of
>> matchsets. Currently, this limit is ignored and the regular limit
>> for scheduled scan matchsets, ie. struct wiphy::max_match_sets, is
>> used for the net-detect case as well.
>>
>> Cc: Luciano Coelho <luciano.coelho@intel.com>
>> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
>> ---
>
> What?! You don't have the same number of matchsets for both? :P
Actually I have, but your comment mentioned they do not have to be the
same. brcmfmac actually did not set max_nd_match_sets so I was surprised
it worked. That said this patch will result in regression in brcmfmac
:-p Not sure about other drivers supporting net-detect.
Regards,
Arend
> Looks good.
>
> Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
>
> --
> Luca.
>
^ permalink raw reply
* Re: rt2800: remove warning on bcn_num != rt2x00dev->intf_beaconing
From: Kalle Valo @ 2017-01-19 12:48 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: linux-wireless, Helmut Schaa, Daniel Golle
In-Reply-To: <1484319307-10821-1-git-send-email-sgruszka@redhat.com>
Stanislaw Gruszka <sgruszka@redhat.com> wrote:
> Since rt2800pci update beacon settings asynchronously from
> tbtt tasklet, without beacon_skb_mutex protection, number of
> currently active beacons entries can be different than
> number pointed by rt2x00dev->intf_beaconing. Remove warning
> about that inconsistency.
>
> Reported-by: evaxige@qq.com
> Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Patch applied to wireless-drivers-next.git, thanks.
feecb0cb466b rt2800: remove warning on bcn_num != rt2x00dev->intf_beaconing
--
https://patchwork.kernel.org/patch/9515787/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v3 2/2] mmc: pwrseq: add support for Marvell SD8787 chip
From: Ulf Hansson @ 2017-01-19 12:50 UTC (permalink / raw)
To: Matt Ranostay
Cc: Shawn Lin, linux-wireless@vger.kernel.org, Linux Kernel,
linux-mmc@vger.kernel.org, devicetree@vger.kernel.org,
Tony Lindgren
In-Reply-To: <CAJ_EiSSQF_2pRaYdUBbKzbHt=1pn3NBrz8C5B7Dta9x7xqZ8oA@mail.gmail.com>
On 18 January 2017 at 08:50, Matt Ranostay <matt@ranostay.consulting> wrote:
> On Sun, Jan 15, 2017 at 6:35 PM, Shawn Lin <shawn.lin@rock-chips.com> wrote:
>> On 2017/1/16 5:41, Matt Ranostay wrote:
>>>
>>> On Thu, Jan 12, 2017 at 11:16 PM, Shawn Lin <shawn.lin@rock-chips.com>
>>> wrote:
>>>>
>>>> On 2017/1/13 13:29, Matt Ranostay wrote:
>>>>>
>>>>>
>>>>> Allow power sequencing for the Marvell SD8787 Wifi/BT chip.
>>>>> This can be abstracted to other chipsets if needed in the future.
>>>>>
>>>>> Cc: Tony Lindgren <tony@atomide.com>
>>>>> Cc: Ulf Hansson <ulf.hansson@linaro.org>
>>>>> Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
>>>>> ---
>>>>> drivers/mmc/core/Kconfig | 10 ++++
>>>>> drivers/mmc/core/Makefile | 1 +
>>>>> drivers/mmc/core/pwrseq_sd8787.c | 117
>>>>> +++++++++++++++++++++++++++++++++++++++
>>>>> 3 files changed, 128 insertions(+)
>>>>> create mode 100644 drivers/mmc/core/pwrseq_sd8787.c
>>>>>
>>>>> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig
>>>>> index cdfa8520a4b1..fc1ecdaaa9ca 100644
>>>>> --- a/drivers/mmc/core/Kconfig
>>>>> +++ b/drivers/mmc/core/Kconfig
>>>>> @@ -12,6 +12,16 @@ config PWRSEQ_EMMC
>>>>> This driver can also be built as a module. If so, the module
>>>>> will be called pwrseq_emmc.
>>>>>
>>>>> +config PWRSEQ_SD8787
>>>>> + tristate "HW reset support for SD8787 BT + Wifi module"
>>>>> + depends on OF && (MWIFIEX || BT_MRVL_SDIO)
>>>>> + help
>>>>> + This selects hardware reset support for the SD8787 BT + Wifi
>>>>> + module. By default this option is set to n.
>>>>> +
>>>>> + This driver can also be built as a module. If so, the module
>>>>> + will be called pwrseq_sd8787.
>>>>> +
>>>>
>>>>
>>>>
>>>> I don't like this way, as we have a chance to list lots
>>>> configure options here. wifi A,B,C,D...Z, all of them need a
>>>> new section here if needed?
>>>>
>>>> Instead, could you just extent pwrseq_simple.c and add you
>>>> .compatible = "mmc-pwrseq-sd8787", "mmc-pwrseq-simple"?
>>>
>>>
>>> You mean all the chipset pwrseqs linked into the pwrseq-simple module?
>>
>>
>> What I mean was if you just extent the pwrseq-simple a bit, you could
>> just add your chipset pwrseqs linked into the pwrseq-simple. But if you
>> need a different *pattern* of pwrseqs, you should need a new name, for
>> instance, pwrseq-sdio.c etc... But please don't use the name of
>> sd8787? So if I use a wifi named ABC but using the same pwrseq pattenr,
>> should I include your "mmc-pwrseq- sd8787" for that or I need a new
>> mmc-pwrseq-ABC.c?
>
> Ah so pwrseq-sdio.c seems reasonable and having chipsets functions
> defined in a structure. That could be abstracted out for other
> chipsets that could needed in the future.
I think get the idea and it seems reasonable. With that in mind, I
have looked at the code once more and I got some new ideas on how to
adopt pwrseq-simple for your case.
I post the comments separately.
Kind regards
Uffe
^ permalink raw reply
* Re: [v2,10/14] rt2x00: rt2800lib: correctly set HT20/HT40 filter
From: Kalle Valo @ 2017-01-19 12:49 UTC (permalink / raw)
To: Daniel Golle
Cc: linux-wireless, Johannes Berg, Stanislaw Gruszka, roman,
michel.stempin, c.mignanti, evaxige, Felix Fietkau, John Crispin,
Gabor Juhos
In-Reply-To: <20170116030820.GA32255@makrotopia.org>
Daniel Golle <daniel@makrotopia.org> wrote:
> From: Serge Vasilugin <vasilugin@yandex.ru>
>
> Simple patch to correct HT20/HT40 filter setting.
> Tested with Rt3290, Rt3352 and Rt5350
>
> Signed-off-by: Serge Vasilugin <vasilugin@yandex.ru>
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
> Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>
3 patches applied to wireless-drivers-next.git, thanks.
e974f3acafe3 rt2x00: rt2800lib: correctly set HT20/HT40 filter
b8c2db58d5a1 rt2x00: rt2800lib: fix rf id for RT3352
dab38e7d251d rt2x00: rt2800lib: support for for RT3352 with external PA
--
https://patchwork.kernel.org/patch/9518017/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: mwifiex: remove redundant dma padding in AMSDU
From: Kalle Valo @ 2017-01-19 12:48 UTC (permalink / raw)
To: Amitkumar Karwar
Cc: linux-wireless, Cathy Luo, Nishant Sarmukadam, Xinming Hu,
Amitkumar Karwar
In-Reply-To: <1484151084-7241-1-git-send-email-akarwar@marvell.com>
Amitkumar Karwar <akarwar@marvell.com> wrote:
> From: Xinming Hu <huxm@marvell.com>
>
> We already ensure 64 bytes alignment and add padding if required
> during skb_aggr allocation.
>
> Alignment and padding in mwifiex_11n_form_amsdu_txpd() is redundant.
> We may end up accessing more data than allocated size with this.
>
> This patch fixes following issue by removing redundant padding.
>
> [ 370.241338] skbuff: skb_over_panic: text:ffffffffc046946a len:3550
> put:72 head:ffff880000110000 data:ffff8800001100e4 tail:0xec2 end:0xec0 dev:<NULL>
> [ 370.241374] ------------[ cut here ]------------
> [ 370.241382] kernel BUG at net/core/skbuff.c:104!
> 370.244032] Call Trace:
> [ 370.244041] [<ffffffff8c3df5ec>] skb_put+0x44/0x45
> [ 370.244055] [<ffffffffc046946a>]
> mwifiex_11n_aggregate_pkt+0x1e9/0xa50 [mwifiex]
> [ 370.244067] [<ffffffffc0467c16>] mwifiex_wmm_process_tx+0x44a/0x6b7
> [mwifiex]
> [ 370.244074] [<ffffffffc0411eb8>] ? 0xffffffffc0411eb8
> [ 370.244084] [<ffffffffc046116b>] mwifiex_main_process+0x476/0x5a5
> [mwifiex]
> [ 370.244098] [<ffffffffc0461298>] mwifiex_main_process+0x5a3/0x5a5
> [mwifiex]
> [ 370.244113] [<ffffffff8be7e9ff>] process_one_work+0x1a4/0x309
> [ 370.244123] [<ffffffff8be7f4ca>] worker_thread+0x20c/0x2ee
> [ 370.244130] [<ffffffff8be7f2be>] ? rescuer_thread+0x383/0x383
> [ 370.244136] [<ffffffff8be7f2be>] ? rescuer_thread+0x383/0x383
> [ 370.244143] [<ffffffff8be83742>] kthread+0x11c/0x124
> [ 370.244150] [<ffffffff8be83626>] ? kthread_parkme+0x24/0x24
> [ 370.244157] [<ffffffff8c4da1ef>] ret_from_fork+0x3f/0x70
> [ 370.244168] [<ffffffff8be83626>] ? kthread_parkme+0x24/0x24
>
> Fixes: 84b313b35f8158d ("mwifiex: make tx packet 64 byte DMA aligned")
> Signed-off-by: Xinming Hu <huxm@marvell.com>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Patch applied to wireless-drivers-next.git, thanks.
5f0a221f59ad mwifiex: remove redundant dma padding in AMSDU
--
https://patchwork.kernel.org/patch/9510541/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [1/3] rtlwifi: Download firmware as bytes rather than as dwords
From: Kalle Valo @ 2017-01-19 12:47 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless, Larry Finger, Ping-Ke Shih
In-Reply-To: <20170109230058.22758-2-Larry.Finger@lwfinger.net>
Larry Finger <Larry.Finger@lwfinger.net> wrote:
> The firmware is read from disk as a little-endian byte string. The code
> that loads the firmware into the device transfers it as 4-byte quantities.
> The routines that write multi-byte quantities on BE hardware assume that
> the data are in CPU order, and automatically do the conversion to the LE
> order required by the device. As a result, the firmware is transmitted
> incorrectly. Rather than do multiple byte swaps on the data, the download
> routine is revised to transmit bytes rather than dwords. Although the
> number of I/O operations is increased, the firmware is not often loaded.
>
> All drivers have the same bug, and use essentially the same code to
> download firmware. These routines have been moved into rtlwifi.
>
> Some CamelCase variables have been renamed.
>
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> Cc: Ping-Ke Shih <pkshih@realtek.com>
Failed to apply:
fatal: sha1 information is lacking or useless (drivers/net/wireless/realtek/rtlwifi/efuse.c).
error: could not build fake ancestor
Applying: rtlwifi: Download firmware as bytes rather than as dwords
Patch failed at 0001 rtlwifi: Download firmware as bytes rather than as dwords
The copy of the patch that failed is found in: .git/rebase-apply/patch
3 patches set to Changes Requested.
9506051 [1/3] rtlwifi: Download firmware as bytes rather than as dwords
9506053 [2/3] rtlwifi: rtl8192cu: Calculate descriptor checksum correctly for BE
9506055 [3/3] rtlwifi: rtl8192cu: Convert driver to use common macros
--
https://patchwork.kernel.org/patch/9506051/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: libertas: fix improper return value
From: Kalle Valo @ 2017-01-19 12:39 UTC (permalink / raw)
To: Pan Bian
Cc: Andreas Kemnade, Johannes Berg, libertas-dev, linux-wireless,
netdev, linux-kernel, Pan Bian
In-Reply-To: <1480760857-4549-1-git-send-email-bianpan2016@163.com>
Pan Bian <bianpan2016@163.com> wrote:
> Function lbs_cmd_802_11_sleep_params() always return 0, even if the call
> to lbs_cmd_with_response() fails. In this case, the parameter @sp will
> keep uninitialized. Because the return value is 0, its caller (say
> lbs_sleepparams_read()) will not detect the error, and will copy the
> uninitialized stack memory to user sapce, resulting in stack information
> leak. To avoid the bug, this patch returns variable ret (which takes
> the return value of lbs_cmd_with_response()) instead of 0.
>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=188451
>
> Signed-off-by: Pan Bian <bianpan2016@163.com>
Patch applied to wireless-drivers-next.git, thanks.
259010c509b6 libertas: fix improper return value
--
https://patchwork.kernel.org/patch/9459597/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: brcmfmac: make brcmf_of_probe more generic
From: Kalle Valo @ 2017-01-19 12:45 UTC (permalink / raw)
To: Rafał Miłecki
Cc: Arend van Spriel, Franky Lin, Hante Meuleman,
Pieter-Paul Giesberts, Franky Lin, linux-wireless,
brcm80211-dev-list.pdl, Rafał Miłecki
In-Reply-To: <20170107224345.3079-1-zajec5@gmail.com>
Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
>
> We may want to use Open Firmware for other devices than just SDIO ones.
> In future we may want to support more Broadcom properties so there is
> really no reason for such limitation.
>
> Call brcmf_of_probe for all kind of devices & move extra conditions to
> the body of that funcion.
>
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Patch applied to wireless-drivers-next.git, thanks.
e457a8a01a19 brcmfmac: make brcmf_of_probe more generic
--
https://patchwork.kernel.org/patch/9503295/
Documentation about submitting wireless patches and checking status
from patchwork:
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply
* Re: [PATCH v2 01/13] wil6210: add sysfs file for FTM calibration
From: Lior David @ 2017-01-19 12:36 UTC (permalink / raw)
To: Valo, Kalle, qca_merez; +Cc: qca_liord, linux-wireless@vger.kernel.org, wil6210
In-Reply-To: <871svzp79p.fsf@kamboji.qca.qualcomm.com>
On 1/19/2017 2:24 PM, Valo, Kalle wrote:
> Maya Erez <qca_merez@qca.qualcomm.com> writes:
>
>> From: Lior David <qca_liord@qca.qualcomm.com>
>>
>> In fine timing measurements, the calculation is affected by
>> 2 parts: timing of packets over the air, which is platform
>> independent, and platform-specific delays, which are dependent
>> on things like antenna cable length and type.
>> Add a sysfs file which allows to get/set these platform specific
>> delays, separated into the TX and RX components.
>> There are 2 key scenarios where the file can be used:
>> 1. Calibration - start with some initial values (for example,
>> the default values at startup), make measurements at a known
>> distance, then iteratively change the values until the
>> measurement results match the known distance.
>> 2. Adjust the delays when platform starts up, based on known
>> values.
>>
>> Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
>> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
>
> Can't this go via nl80211? sysfs is not really supposed to be used for
> something like this.
>
There is no nl80211 API for this (yet?).
Will it be ok to put this in debugfs? Normally this will be in the board
file (as part of RF configuration) but it will be useful to play
with these values for debugging/diagnostics.
Thanks,
Lior
^ permalink raw reply
* Re: [PATCH v2 01/13] wil6210: add sysfs file for FTM calibration
From: Valo, Kalle @ 2017-01-19 12:24 UTC (permalink / raw)
To: qca_merez; +Cc: qca_liord, linux-wireless@vger.kernel.org, wil6210
In-Reply-To: <1484226365-10433-2-git-send-email-qca_merez@qca.qualcomm.com>
Maya Erez <qca_merez@qca.qualcomm.com> writes:
> From: Lior David <qca_liord@qca.qualcomm.com>
>
> In fine timing measurements, the calculation is affected by
> 2 parts: timing of packets over the air, which is platform
> independent, and platform-specific delays, which are dependent
> on things like antenna cable length and type.
> Add a sysfs file which allows to get/set these platform specific
> delays, separated into the TX and RX components.
> There are 2 key scenarios where the file can be used:
> 1. Calibration - start with some initial values (for example,
> the default values at startup), make measurements at a known
> distance, then iteratively change the values until the
> measurement results match the known distance.
> 2. Adjust the delays when platform starts up, based on known
> values.
>
> Signed-off-by: Lior David <qca_liord@qca.qualcomm.com>
> Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Can't this go via nl80211? sysfs is not really supposed to be used for
something like this.
--=20
Kalle Valo=
^ permalink raw reply
* Re: [PATCH] nl80211: fix validation of scheduled scan info for wowlan netdetect
From: Luca Coelho @ 2017-01-19 12:00 UTC (permalink / raw)
To: Arend van Spriel, Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1484820088-24448-1-git-send-email-arend.vanspriel@broadcom.com>
On Thu, 2017-01-19 at 10:01 +0000, Arend van Spriel wrote:
> For wowlan netdetect a separate limit is defined for the number of
> matchsets. Currently, this limit is ignored and the regular limit
> for scheduled scan matchsets, ie. struct wiphy::max_match_sets, is
> used for the net-detect case as well.
>
> Cc: Luciano Coelho <luciano.coelho@intel.com>
> Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> ---
What?! You don't have the same number of matchsets for both? :P
Looks good.
Reviewed-by: Luca Coelho <luciano.coelho@intel.com>
--
Luca.
^ permalink raw reply
* [PATCH] rtlwifi: rtl8192x: Enabling and disabling hardware interrupts after enabling local irq flags
From: Bharat Kumar Gogada @ 2017-01-19 10:14 UTC (permalink / raw)
To: Larry.Finger, chaoming_li, linux-wireless, linux-kernel
Cc: kvalo, netdev, rgummal, Bharat Kumar Gogada
-Realtek 8192CE chipset maintains local irq flags after enabling/disabling
hardware interrupts.
-Hardware interrupts are enabled before enabling the local irq
flags(these flags are being checked in interrupt handler),
leading to race condition on some RP, where the irq line between
bridge and GIC goes high at ASSERT_INTx and goes low only
at DEASSERT_INTx. In this kind of RP by the time ASSERT_INTx is seen
irq_enable flag is still set to false, resulting in continuous
interrupts seen by CPU as DEASSERT_INTx cannot be sent since
flag is still false and making CPU stall.
-Changing the sequence of setting these irq flags.
Signed-off-by: Bharat Kumar Gogada <bharatku@xilinx.com>
---
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
index a47be73..143766c4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/hw.c
@@ -1306,9 +1306,9 @@ void rtl92ce_enable_interrupt(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ rtlpci->irq_enabled = true;
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
- rtlpci->irq_enabled = true;
}
void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1316,9 +1316,9 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+ rtlpci->irq_enabled = false;
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- rtlpci->irq_enabled = false;
}
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
--
2.1.1
^ permalink raw reply related
* [PATCH] nl80211: fix validation of scheduled scan info for wowlan netdetect
From: Arend van Spriel @ 2017-01-19 10:01 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Arend van Spriel, Luciano Coelho
For wowlan netdetect a separate limit is defined for the number of
matchsets. Currently, this limit is ignored and the regular limit
for scheduled scan matchsets, ie. struct wiphy::max_match_sets, is
used for the net-detect case as well.
Cc: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
---
net/wireless/nl80211.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b4e7bdd..df0675d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6852,7 +6852,7 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
static struct cfg80211_sched_scan_request *
nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
- struct nlattr **attrs)
+ struct nlattr **attrs, int max_match_sets)
{
struct cfg80211_sched_scan_request *request;
struct nlattr *attr;
@@ -6917,7 +6917,7 @@ static int nl80211_abort_scan(struct sk_buff *skb, struct genl_info *info)
if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
n_match_sets = 1;
- if (n_match_sets > wiphy->max_match_sets)
+ if (n_match_sets > max_match_sets)
return ERR_PTR(-EINVAL);
if (attrs[NL80211_ATTR_IE])
@@ -7217,7 +7217,8 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
return -EINPROGRESS;
sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
- info->attrs);
+ info->attrs,
+ rdev->wiphy.max_match_sets);
err = PTR_ERR_OR_ZERO(sched_scan_req);
if (err)
@@ -10030,7 +10031,8 @@ static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
if (err)
goto out;
- trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb);
+ trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb,
+ wowlan->max_nd_match_sets);
err = PTR_ERR_OR_ZERO(trig->nd_config);
if (err)
trig->nd_config = NULL;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH net-next v4] bridge: multicast to unicast
From: Nikolay Aleksandrov @ 2017-01-19 9:53 UTC (permalink / raw)
To: Linus Lüssing, netdev
Cc: David S . Miller, Stephen Hemminger, Felix Fietkau, bridge,
linux-kernel, linux-wireless
In-Reply-To: <20170119024510.3284-1-linus.luessing@c0d3.blue>
On 19/01/17 03:45, Linus Lüssing wrote:
> From: Felix Fietkau <nbd@nbd.name>
>
> Implements an optional, per bridge port flag and feature to deliver
> multicast packets to any host on the according port via unicast
> individually. This is done by copying the packet per host and
> changing the multicast destination MAC to a unicast one accordingly.
>
> multicast-to-unicast works on top of the multicast snooping feature of
> the bridge. Which means unicast copies are only delivered to hosts which
> are interested in it and signalized this via IGMP/MLD reports
> previously.
>
> This feature is intended for interface types which have a more reliable
> and/or efficient way to deliver unicast packets than broadcast ones
> (e.g. wifi).
>
> However, it should only be enabled on interfaces where no IGMPv2/MLDv1
> report suppression takes place. This feature is disabled by default.
>
> The initial patch and idea is from Felix Fietkau.
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
> [linus.luessing@c0d3.blue: various bug + style fixes, commit message]
> Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
>
> ---
>
> This feature is used and enabled by default in OpenWRT and LEDE for AP
> interfaces for more than a year now to allow both a more robust multicast
> delivery and multicast at higher rates (e.g. multicast streaming).
>
> In OpenWRT/LEDE the IGMP/MLD report suppression issue is overcome by
> the network daemon enabling AP isolation and by that separating all STAs.
> Delivery of STA-to-STA IP mulitcast is made possible again by
> enabling and utilizing the bridge hairpin mode, which considers the
> incoming port as a potential outgoing port, too.
>
> Hairpin-mode is performed after multicast snooping, therefore leading to
> only deliver reports to STAs running a multicast router.
>
> Changes in v4:
> * readd "From: Felix Fietkau [...]" (missed it again in v3)
>
> Changes in v3:
> * fix an uninitialized variable bug introduced in br_multicast_flood()
> in v2, found by kbuild test bot
>
> Changes in v2:
> * netlink support (thanks Nik!)
> * fixed switching between multicast_to_unicast on/off
> -> even after toggling an already existing entry would
> stale in its mode and would never be replaced
> -> new extra check in br_port_group_equal)
> * reduced checks in br_multicast_flood() from two to one
> to address fast-path concerns (thanks Nik!)
> * rev-christmas tree ordering (thanks Nik!)
> * removed "net_bridge_port_group::unicast", using
> ::flags instead (thanks Nik!)
> * BR_MULTICAST_TO_UCAST -> BR_MULTICAST_TO_UNICAST
> (BR_MULTICAST_FLAST_LEAVE has the same length anyway)
> * simplified maybe_deliver_addr()
> (no return, no "prev" paramater -> was a NOP anyway)
> * added "From: Felix Fietkau [...]"
> * added "Signed-off-by: Felix Fietkau [...]"
> ---
> include/linux/if_bridge.h | 1 +
> include/uapi/linux/if_link.h | 1 +
> net/bridge/br_forward.c | 37 ++++++++++++++++-
> net/bridge/br_mdb.c | 2 +-
> net/bridge/br_multicast.c | 96 ++++++++++++++++++++++++++++++++------------
> net/bridge/br_netlink.c | 5 +++
> net/bridge/br_private.h | 8 ++--
> net/bridge/br_sysfs_if.c | 2 +
> 8 files changed, 121 insertions(+), 31 deletions(-)
>
Looks good to me,
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
^ permalink raw reply
* [PATCH] brcmfmac: drop duplicated core selection from brcmf_pcie_attach
From: Rafał Miłecki @ 2017-01-19 9:51 UTC (permalink / raw)
To: Kalle Valo
Cc: Arend van Spriel, Franky Lin, Hante Meuleman,
Pieter-Paul Giesberts, Franky Lin, linux-wireless,
brcm80211-dev-list.pdl, Rafał Miłecki, Hante Meuleman
From: Rafał Miłecki <rafal@milecki.pl>
It was left after reworking PCIe reset in commit 07fe2e38c7fd
("brcmfmac: Reset PCIE devices after recognition.").
Cc: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 19db8f2..6fae4cf 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -601,7 +601,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
{
u32 config;
- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
/* BAR1 window may not be sized properly */
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
--
2.10.1
^ permalink raw reply related
* Re: [3/3] rtlwifi: Enable debug mask to be set from sysfs
From: Kalle Valo @ 2017-01-19 8:57 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless, Ping-Ke Shih
In-Reply-To: <5aefd440-1b6f-1791-d85b-e71464c47620@lwfinger.net>
Larry Finger <Larry.Finger@lwfinger.net> writes:
> On 01/18/2017 08:49 AM, Kalle Valo wrote:
>> Larry Finger <Larry.Finger@lwfinger.net> wrote:
>>> The previous commit changes the debug system to use a mask to select
>>> which components are to be debugged. Now, we add the necessary code
>>> to change the mask from sysfs.
>>>
>>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>>> Cc: Ping-Ke Shih <pkshih@realtek.com>
>>
>> There's already a generic sysfs interface to change module parameters in
>> /sys/module/<driver>/parameters, drivers should not have a private interface for
>> that.
>
> Kalle,
>
> I was not aware of that part of sysfs. I will respin the patch as well
> as remove the old code that set the debug level.
Good, thanks. I dropped the whole series now and assume that you will
send v2.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v3] brcmfmac: fix incorrect event channel deduction
From: Kalle Valo @ 2017-01-19 8:48 UTC (permalink / raw)
To: Gavin Li
Cc: Arend Van Spriel, Franky Lin, Hante Meuleman, linux-wireless,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER, Stable,
Gavin Li, Rafał Miłecki
In-Reply-To: <CA+GxvY43AbKOVJFWAxHg1Gku=LD-dveHY8m6=zPPu9qR4+r=Fg@mail.gmail.com>
Gavin Li <gavinli@thegavinli.com> writes:
> I think calling this a performance regression is a bit understated; my
> download speed jumped from 1Mbit/s back up to 40MBit/s after applying
> the patch due to the sheer amount of packets being incorrectly
> processed.
>
> In addition, processing arbitrary data frames as firmware events might
> be a security vulnerability.
You should always mention valuable information like this in the commit
log, don't make us maintainers (and others) guessing the symptoms and
impact.
--
Kalle Valo
^ permalink raw reply
* Re: [PATCH v3] brcmfmac: fix incorrect event channel deduction
From: Kalle Valo @ 2017-01-19 8:55 UTC (permalink / raw)
To: Gavin Li
Cc: Arend Van Spriel, Franky Lin, Gavin Li, Hante Meuleman,
Rafał Miłecki, Stable, linux-wireless,
open list:BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
In-Reply-To: <CA+GxvY6ho89L-Ye7MrbtVM=i+Ck8YSH7JaSG1p=WzH5u_Be0_A@mail.gmail.com>
Gavin Li <gavinli@thegavinli.com> writes:
> Should I make a v4 patch with an updated log?
No need, I'll just copy your description of the bug to the commit log
before I commit it.
--
Kalle Valo
^ permalink raw reply
* [PATCH net-next v4] bridge: multicast to unicast
From: Linus Lüssing @ 2017-01-19 2:45 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Stephen Hemminger, Felix Fietkau,
Nikolay Aleksandrov, bridge, linux-kernel, linux-wireless,
Linus Lüssing
From: Felix Fietkau <nbd@nbd.name>
Implements an optional, per bridge port flag and feature to deliver
multicast packets to any host on the according port via unicast
individually. This is done by copying the packet per host and
changing the multicast destination MAC to a unicast one accordingly.
multicast-to-unicast works on top of the multicast snooping feature of
the bridge. Which means unicast copies are only delivered to hosts which
are interested in it and signalized this via IGMP/MLD reports
previously.
This feature is intended for interface types which have a more reliable
and/or efficient way to deliver unicast packets than broadcast ones
(e.g. wifi).
However, it should only be enabled on interfaces where no IGMPv2/MLDv1
report suppression takes place. This feature is disabled by default.
The initial patch and idea is from Felix Fietkau.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
[linus.luessing@c0d3.blue: various bug + style fixes, commit message]
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
This feature is used and enabled by default in OpenWRT and LEDE for AP
interfaces for more than a year now to allow both a more robust multicast
delivery and multicast at higher rates (e.g. multicast streaming).
In OpenWRT/LEDE the IGMP/MLD report suppression issue is overcome by
the network daemon enabling AP isolation and by that separating all STAs.
Delivery of STA-to-STA IP mulitcast is made possible again by
enabling and utilizing the bridge hairpin mode, which considers the
incoming port as a potential outgoing port, too.
Hairpin-mode is performed after multicast snooping, therefore leading to
only deliver reports to STAs running a multicast router.
Changes in v4:
* readd "From: Felix Fietkau [...]" (missed it again in v3)
Changes in v3:
* fix an uninitialized variable bug introduced in br_multicast_flood()
in v2, found by kbuild test bot
Changes in v2:
* netlink support (thanks Nik!)
* fixed switching between multicast_to_unicast on/off
-> even after toggling an already existing entry would
stale in its mode and would never be replaced
-> new extra check in br_port_group_equal)
* reduced checks in br_multicast_flood() from two to one
to address fast-path concerns (thanks Nik!)
* rev-christmas tree ordering (thanks Nik!)
* removed "net_bridge_port_group::unicast", using
::flags instead (thanks Nik!)
* BR_MULTICAST_TO_UCAST -> BR_MULTICAST_TO_UNICAST
(BR_MULTICAST_FLAST_LEAVE has the same length anyway)
* simplified maybe_deliver_addr()
(no return, no "prev" paramater -> was a NOP anyway)
* added "From: Felix Fietkau [...]"
* added "Signed-off-by: Felix Fietkau [...]"
---
include/linux/if_bridge.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/bridge/br_forward.c | 37 ++++++++++++++++-
net/bridge/br_mdb.c | 2 +-
net/bridge/br_multicast.c | 96 ++++++++++++++++++++++++++++++++------------
net/bridge/br_netlink.c | 5 +++
net/bridge/br_private.h | 8 ++--
net/bridge/br_sysfs_if.c | 2 +
8 files changed, 121 insertions(+), 31 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index c6587c0..debc9d5 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -46,6 +46,7 @@ struct br_ip_list {
#define BR_LEARNING_SYNC BIT(9)
#define BR_PROXYARP_WIFI BIT(10)
#define BR_MCAST_FLOOD BIT(11)
+#define BR_MULTICAST_TO_UNICAST BIT(12)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6b13e59..4e59565 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -321,6 +321,7 @@ enum {
IFLA_BRPORT_MULTICAST_ROUTER,
IFLA_BRPORT_PAD,
IFLA_BRPORT_MCAST_FLOOD,
+ IFLA_BRPORT_MCAST_TO_UCAST,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 7cb41ae..a6c8a27 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -174,6 +174,29 @@ static struct net_bridge_port *maybe_deliver(
return p;
}
+static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
+ const unsigned char *addr, bool local_orig)
+{
+ struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+ const unsigned char *src = eth_hdr(skb)->h_source;
+
+ if (!should_deliver(p, skb))
+ return;
+
+ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
+ if (skb->dev == p->dev && ether_addr_equal(src, addr))
+ return;
+
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb) {
+ dev->stats.tx_dropped++;
+ return;
+ }
+
+ memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
+ __br_forward(p, skb, local_orig);
+}
+
/* called under rcu_read_lock */
void br_flood(struct net_bridge *br, struct sk_buff *skb,
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig)
@@ -241,10 +264,20 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
NULL;
- port = (unsigned long)lport > (unsigned long)rport ?
- lport : rport;
+ if ((unsigned long)lport > (unsigned long)rport) {
+ port = lport;
+
+ if (p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) {
+ maybe_deliver_addr(lport, skb, p->eth_addr,
+ local_orig);
+ goto delivered;
+ }
+ } else {
+ port = rport;
+ }
prev = maybe_deliver(prev, port, skb, local_orig);
+delivered:
if (IS_ERR(prev))
goto out;
if (prev == port)
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 7dbc80d..056e6ac 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -531,7 +531,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
break;
}
- p = br_multicast_new_port_group(port, group, *pp, state);
+ p = br_multicast_new_port_group(port, group, *pp, state, NULL);
if (unlikely(!p))
return -ENOMEM;
rcu_assign_pointer(*pp, p);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b30e77e..b127bb7 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -43,12 +43,14 @@ static void br_multicast_add_router(struct net_bridge *br,
static void br_ip4_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid);
+ __u16 vid,
+ const unsigned char *src);
+
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid);
+ __u16 vid, const unsigned char *src);
#endif
unsigned int br_mdb_rehash_seq;
@@ -711,7 +713,8 @@ struct net_bridge_port_group *br_multicast_new_port_group(
struct net_bridge_port *port,
struct br_ip *group,
struct net_bridge_port_group __rcu *next,
- unsigned char flags)
+ unsigned char flags,
+ const unsigned char *src)
{
struct net_bridge_port_group *p;
@@ -726,12 +729,39 @@ struct net_bridge_port_group *br_multicast_new_port_group(
hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p);
+
+ if ((port->flags & BR_MULTICAST_TO_UNICAST) && src) {
+ memcpy(p->eth_addr, src, ETH_ALEN);
+ p->flags |= MDB_PG_FLAGS_MCAST_TO_UCAST;
+ }
+
return p;
}
+static bool br_port_group_equal(struct net_bridge_port_group *p,
+ struct net_bridge_port *port,
+ const unsigned char *src)
+{
+ if (p->port != port)
+ return false;
+
+ if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) !=
+ !(port->flags & BR_MULTICAST_TO_UNICAST))
+ return false;
+
+ if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST))
+ return true;
+
+ if (!src)
+ return false;
+
+ return ether_addr_equal(src, p->eth_addr);
+}
+
static int br_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
- struct br_ip *group)
+ struct br_ip *group,
+ const unsigned char *src)
{
struct net_bridge_port_group __rcu **pp;
struct net_bridge_port_group *p;
@@ -758,13 +788,13 @@ static int br_multicast_add_group(struct net_bridge *br,
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port == port)
+ if (br_port_group_equal(p, port, src))
goto found;
if ((unsigned long)p->port < (unsigned long)port)
break;
}
- p = br_multicast_new_port_group(port, group, *pp, 0);
+ p = br_multicast_new_port_group(port, group, *pp, 0, src);
if (unlikely(!p))
goto err;
rcu_assign_pointer(*pp, p);
@@ -783,7 +813,8 @@ static int br_multicast_add_group(struct net_bridge *br,
static int br_ip4_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
@@ -794,14 +825,15 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
br_group.proto = htons(ETH_P_IP);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, &br_group, src);
}
#if IS_ENABLED(CONFIG_IPV6)
static int br_ip6_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
@@ -812,7 +844,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br,
br_group.proto = htons(ETH_P_IPV6);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, &br_group, src);
}
#endif
@@ -1081,6 +1113,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src;
struct igmpv3_report *ih;
struct igmpv3_grec *grec;
int i;
@@ -1121,12 +1154,14 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
continue;
}
+ src = eth_hdr(skb)->h_source;
if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
type == IGMPV3_MODE_IS_INCLUDE) &&
ntohs(grec->grec_nsrcs) == 0) {
- br_ip4_multicast_leave_group(br, port, group, vid);
+ br_ip4_multicast_leave_group(br, port, group, vid, src);
} else {
- err = br_ip4_multicast_add_group(br, port, group, vid);
+ err = br_ip4_multicast_add_group(br, port, group, vid,
+ src);
if (err)
break;
}
@@ -1141,6 +1176,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src = eth_hdr(skb)->h_source;
struct icmp6hdr *icmp6h;
struct mld2_grec *grec;
int i;
@@ -1192,10 +1228,11 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
ntohs(*nsrcs) == 0) {
br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
- vid);
+ vid, src);
} else {
err = br_ip6_multicast_add_group(br, port,
- &grec->grec_mca, vid);
+ &grec->grec_mca, vid,
+ src);
if (err)
break;
}
@@ -1511,7 +1548,8 @@ br_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
struct br_ip *group,
struct bridge_mcast_other_query *other_query,
- struct bridge_mcast_own_query *own_query)
+ struct bridge_mcast_own_query *own_query,
+ const unsigned char *src)
{
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
@@ -1535,7 +1573,7 @@ br_multicast_leave_group(struct net_bridge *br,
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port != port)
+ if (!br_port_group_equal(p, port, src))
continue;
rcu_assign_pointer(*pp, p->next);
@@ -1566,7 +1604,7 @@ br_multicast_leave_group(struct net_bridge *br,
for (p = mlock_dereference(mp->ports, br);
p != NULL;
p = mlock_dereference(p->next, br)) {
- if (p->port != port)
+ if (!br_port_group_equal(p, port, src))
continue;
if (!hlist_unhashed(&p->mglist) &&
@@ -1617,7 +1655,8 @@ br_multicast_leave_group(struct net_bridge *br,
static void br_ip4_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1632,14 +1671,15 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
br_group.vid = vid;
br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
- own_query);
+ own_query, src);
}
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1654,7 +1694,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
br_group.vid = vid;
br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
- own_query);
+ own_query, src);
}
#endif
@@ -1712,6 +1752,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct igmphdr *ih;
int err;
@@ -1731,13 +1772,14 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
}
ih = igmp_hdr(skb);
+ src = eth_hdr(skb)->h_source;
BR_INPUT_SKB_CB(skb)->igmp = ih->type;
switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT:
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip4_multicast_add_group(br, port, ih->group, vid);
+ err = br_ip4_multicast_add_group(br, port, ih->group, vid, src);
break;
case IGMPV3_HOST_MEMBERSHIP_REPORT:
err = br_ip4_multicast_igmp3_report(br, port, skb_trimmed, vid);
@@ -1746,7 +1788,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
err = br_ip4_multicast_query(br, port, skb_trimmed, vid);
break;
case IGMP_HOST_LEAVE_MESSAGE:
- br_ip4_multicast_leave_group(br, port, ih->group, vid);
+ br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
break;
}
@@ -1766,6 +1808,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct mld_msg *mld;
int err;
@@ -1785,8 +1828,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
switch (mld->mld_type) {
case ICMPV6_MGM_REPORT:
+ src = eth_hdr(skb)->h_source;
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid);
+ err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid,
+ src);
break;
case ICMPV6_MLD2_REPORT:
err = br_ip6_multicast_mld2_report(br, port, skb_trimmed, vid);
@@ -1795,7 +1840,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
err = br_ip6_multicast_query(br, port, skb_trimmed, vid);
break;
case ICMPV6_MGM_REDUCTION:
- br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
+ src = eth_hdr(skb)->h_source;
+ br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
break;
}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 71c7453..6c087cd 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -123,6 +123,7 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ + nla_total_size(1) /* IFLA_BRPORT_MCAST_TO_UCAST */
+ nla_total_size(1) /* IFLA_BRPORT_LEARNING */
+ nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */
+ nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
@@ -173,6 +174,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
!!(p->flags & BR_ROOT_BLOCK)) ||
nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE,
!!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
+ nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
+ !!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
!!(p->flags & BR_FLOOD)) ||
@@ -586,6 +589,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_PROXYARP] = { .type = NLA_U8 },
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 },
+ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 },
};
/* Change the state of the port and notify spanning tree */
@@ -636,6 +640,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
+ br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..f7db79f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -166,8 +166,9 @@ struct net_bridge_fdb_entry
struct rcu_head rcu;
};
-#define MDB_PG_FLAGS_PERMANENT BIT(0)
-#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_PERMANENT BIT(0)
+#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_MCAST_TO_UCAST BIT(2)
struct net_bridge_port_group {
struct net_bridge_port *port;
@@ -177,6 +178,7 @@ struct net_bridge_port_group {
struct timer_list timer;
struct br_ip addr;
unsigned char flags;
+ unsigned char eth_addr[ETH_ALEN];
};
struct net_bridge_mdb_entry
@@ -599,7 +601,7 @@ void br_multicast_free_pg(struct rcu_head *head);
struct net_bridge_port_group *
br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
struct net_bridge_port_group __rcu *next,
- unsigned char flags);
+ unsigned char flags, const unsigned char *src);
void br_mdb_init(void);
void br_mdb_uninit(void);
void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 8bd5696..05e8946 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -188,6 +188,7 @@ static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
store_multicast_router);
BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
+BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST);
#endif
static const struct brport_attribute *brport_attrs[] = {
@@ -214,6 +215,7 @@ static const struct brport_attribute *brport_attrs[] = {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
&brport_attr_multicast_router,
&brport_attr_multicast_fast_leave,
+ &brport_attr_multicast_to_unicast,
#endif
&brport_attr_proxyarp,
&brport_attr_proxyarp_wifi,
--
2.1.4
^ permalink raw reply related
* RE: [PATCH v9] Add new mac80211 driver mwlwifi.
From: David Lin @ 2017-01-19 1:22 UTC (permalink / raw)
To: Johannes Berg, Kalle Valo
Cc: linux-wireless@vger.kernel.org, Chor Teck Law, James Lin,
Pete Hsieh
In-Reply-To: <1484126730.23671.5.camel@sipsolutions.net>
PiBKb2hhbm5lcyBCZXJnIFttYWlsdG86am9oYW5uZXNAc2lwc29sdXRpb25zLm5ldF0gd3JvdGU6
DQo+IE9uIFR1ZSwgMjAxNy0wMS0xMCBhdCAwMTozMiArMDAwMCwgRGF2aWQgTGluIHdyb3RlOg0K
PiANCj4gPiA+IFRoZSBvbmx5IHRoaW5nIHRoYXQgcmVhbGx5IHNlZW1zIHF1ZXN0aW9uYWJsZSB0
byBtZSBpcyB0aGUgd2hvbGUNCj4gPiA+IGJlYWNvbiBwYXJzaW5nIChhbmQgYXBwYXJlbnQgcmVi
dWlsZGluZyBpbiBmaXJtd2FyZT8pLiBJdCdzIHZlcnkgb2RkDQo+ID4gPiB0aGF0IHlvdSBjb3Vs
ZCBkbyB0aGF0LCB3aXRoIGEgc29mdG1hYyBkZXZpY2Ugd2hlcmUgYWxsIHRoZQ0KPiA+ID4gYXV0
aGVudGljYXRpb24gYW5kIGFzc29jaWF0aW9uIGlzIGhhbmRsZWQgYnkgaG9zdGFwZCBhbnl3YXks
IGFuZCB5b3UNCj4gPiA+IGNhbid0IHBvc3NpYmx5IHByZXRlbmQgdG8gaGFuZGxlIGV2ZXJ5dGhp
bmcgaG9zdGFwZCBtaWdodCB0aHJvdyBhdA0KPiA+ID4geW91IC0gdGhpcyB3aWxsIG1lYW4gdGhh
dCB5b3UnbGwgaGF2ZSBmZWF0dXJlcyBob3N0YXBkIGFuZCBldmVyeQ0KPiA+ID4gb3RoZXIgbWFj
ODAyMTEgc3VwcG9ydHMgdGhhdCB5b3Ugd2lsbCBzaWxlbnRseSBkcm9wIGFmYWljdCAtIHdoaWNo
DQo+ID4gPiBpcyByYXRoZXIgdW5leHBlY3RlZC4NCj4gPiA+DQo+ID4gPiBGaXJzdCwgeW91J3Jl
IHBhcnNpbmcgdGhlIGRhdGEgb2J0YWluZWQgZnJvbSBob3N0YXBkLCBpbg0KPiA+ID4gbXdsX2Z3
Y21kX3BhcnNlX2JlYWNvbigpLCBhbmQgdGhlbiB5b3Ugc2VuZCB0aGVtIGFsbCB0byB0aGUgZmly
bXdhcmUNCj4gPiA+IGluIG13bF9md2NtZF9zZXRfaWVzKCksIGJ1dCBvbmx5IHRoZSB0aGluZ3Mg
eW91IGFjdHVhbGx5IHVuZGVyc3Rvb2QuDQo+ID4gPiBOZXcgaGlnaGVyLWxldmVsIGZlYXR1cmVz
IHlvdSBkb24ndCB1bmRlcnN0YW5kLCBvciB2ZW5kb3IgYmVhY29uIElFcw0KPiA+ID4gdGhhdCBh
cmVuJ3QgV01NLCB3b3VsZCBiZSBjb21wbGV0ZWx5IGRyb3BwZWQuDQo+ID4gPg0KPiA+ID4gSSdt
IG5vdCB2ZXJ5IGhhcHB5IHdpdGggdGhhdCBiZWhhdmlvdXIuDQo+ID4gPg0KPiA+ID4gV2h5IGRv
ZXMgdGhlIGZpcm13YXJlIHJlcXVpcmUgdGhpcz8gV2h5IG5vdCBqdXN0IHBhY2sgYWxsIElFcyBp
bnRvDQo+ID4gPiB0aGUgcGNtZC0+aWVfbGlzdF9sZW5fcHJvcHJpZXRhcnksIGFuZCBsZWF2ZSBl
dmVyeXRoaW5nIGVsc2UgMD8gT3INCj4gPiA+IC0gaWYgcGVyaGFwcyBmaXJtd2FyZSBmb3Igc29t
ZSByZWFzb24gcmVxdWlyZXMgSFQvVkhUIHRvIGJlIHRyZWF0ZWQNCj4gPiA+IHNwZWNpYWxseSwg
b25seSBwYXJzZSBvdXQgdGhlIG9uZXMgdGhhdCBhcmUgcmVhbGx5IG5lZWRlZCBzcGVjaWFsbHkN
Cj4gPiA+IGFuZCBsZWF2ZSBldmVyeXRoaW5nIGVsc2UgaW4gdGhlIGllX2xpc3RfbGVuX3Byb3By
aWV0YXJ5Pw0KPiA+ID4NCj4gPiA+IEFsc28sIHRoaXMgaXMgZHJvcHBpbmcgYWxsIHRoZSBlbmNy
eXB0aW9uIHN0dWZmIC0gZXZlbiB0aG9zZSBhcmUNCj4gPiA+IGV4dGVuc2libGUgYnR3LCBhbmQg
aG9zdGFwZCBtaWdodCBkbyBzby4gSGF2aW5nIHRoZSBmaXJtd2FyZSByZWJ1aWxkDQo+ID4gPiB0
aG9zZSBvdXQgb2Ygb3V0LW9mLWJhbmQgaW5mb3JtYXRpb24gaXMgdmVyeSB1bmV4cGVjdGVkIGZv
ciBhDQo+ID4gPiBtYWM4MDIxMSBkcml2ZXIuDQo+ID4gPg0KPiA+DQo+ID4gVGhpcyBkcml2ZXIg
anVzdCBleHRyYWN0cyBuZWVkZWQgSUVzIHdoaWNoIGlzIHVzZWQgZm9yIHRoZSBob3N0DQo+ID4g
Y29tbWFuZCBvZiBmaXJtd2FyZS4gSSB0aGluayB3ZSB3aWxsIG5vdCBzdXBwb3J0IG90aGVyIHZl
bmRvciBJRXMuDQo+ID4gQW5kIGlmIG5lZWRlZCwgd2UgY2FuIGFkZCB0aGVtIHRvIHBjbWQtPmll
X2xpc3RfcHJvcHJpZXRhcnkuDQo+IA0KPiBTdXJlLCBJIHNlZSB0aGF0IHlvdSdyZSBkb2luZyB0
aGlzLiBJdCBzdGlsbCBtYWtlcyBubyBzZW5zZSB0aG91Z2gsIHNpbmNlIGFsbA0KPiBtYW5hZ2Vt
ZW50IGZyYW1lcyBhcmUgaGFuZGxlZCBieSBob3N0YXBkIGFueXdheS4gSXQgd291bGQgbWFrZSBz
b21lDQo+IHNlbnNlIGlmIHlvdSBhY3R1YWxseSB3ZXJlIGdvaW5nIHRvIGhhbmRsZSBhc3NvY2lh
dGlvbiBpbiB0aGUgZmlybXdhcmUsIGJ1dCBpdA0KPiBtYWtlcyBubyBzZW5zZSBoZXJlLCBhcyBm
YXIgYXMgSSBjYW4gdGVsbC4NCj4gDQo+IEknbSBub3Qgc3VyZSBob3cgaGFyZCBhIGxpbmUgSSBz
aG91bGQgZHJhdyBoZXJlLCBidXQgSSdsbCB3YXJuIHlvdSBub3cgdGhhdCBJDQo+IHdvbid0IHRh
a2UgdGhpcyBpbnRvIGNvbnNpZGVyYXRpb24gd2hlbiBhZGRpbmcgbmV3IGZlYXR1cmVzIHRvIG1h
YzgwMjExLCBhbmQNCj4gY2VydGFpbmx5IEpvdW5pIHdvbid0IHRha2UgaXQgaW50byBhY2NvdW50
IHdoZW4gYWRkaW5nIG5ldyBmZWF0dXJlcyB0byBob3N0YXBkLA0KPiBzbyB0aGF0IHN1Y2ggbmV3
IGZlYXR1cmVzIHdpbGwgdGhlbiBTSUxFTlRMWSBhbmQgVU5FWFBFQ1RFRExZIChkdWUgdG8NCj4g
bWFjODAyMTEpIG5vdCB3b3JrIHdpdGggeW91ciBkcml2ZXIuDQo+IA0KPiBJIHN0cm9uZ2x5IGFk
dmlzZSB5b3UgdG8gcmVjb25zaWRlciB0aGlzIGFuZCB0cnkgdG8gcGFzcyB0aHJvdWdoIGFsbCB0
aGUgSUVzIHNvDQo+IHRoYXQgbmV3bHkgYWRkZWQgZmVhdHVyZXMgdGhhdCBzaG91bGRuJ3QgcmVx
dWlyZSBmaXJtd2FyZSBpbnRlcmFjdGlvbiAoc2luY2UNCj4gaG9zdGFwZCBpcyBoYW5kbGluZyBh
bGwgdGhlIGFzc29jaWF0aW9uIGhhbmRzaGFrZSBhbmQgSUVzIHRvIGFkdmVydGlzZSB0aGUNCj4g
ZmVhdHVyZSkgd2lsbCBhdXRvbWF0aWNhbGx5IGFuZCBjbGVhbmx5IHdvcmsuDQo+IA0KPiBJZiB5
b3UgcmVhbGx5IGNhbid0IGRvIHRoYXQsIGZvciBzb21lIHJlYXNvbiwgdGhlbiBmb3IgbXkgYmVu
ZWZpdCBhcyB0aGUNCj4gbWFjODAyMTEgbWFpbnRhaW5lciBhbmQgZnV0dXJlIG1haW50YWluZXJz
IG9mIHlvdXIgZHJpdmVyLCBJJ2QgbGlrZSB0byBoYXZlDQo+IGRvY3VtZW50YXRpb24gaW4gdGhl
IGRyaXZlciBhcyB0byB3aHkgdGhlIGZpcm13YXJlIG5lZWRzIHRoZSBkcml2ZXIgdG8gc3BsaXQN
Cj4gdXAgYWxsIHRob3NlIElFcyBhbmQgd2hhdCBpdCBkb2VzIHdpdGggdGhlbS4gQWZ0ZXIgYWxs
LCBhIGNvbW1vbi1zZW5zZSBhbmFseXNpcw0KPiB3b3VsZCBzdWdnZXN0IHRoYXQgdGhlIGZpcm13
YXJlIGhhcyBubyBuZWVkIGZvciBpdCwgc2luY2UgYWxsIGNvbmZpZ3VyYXRpb24NCj4gc2hvdWxk
IGNvbWUgdGhyb3VnaCBvdGhlciBwbGFjZXMgYW5kIGFsbCBJRXMgYXJlIGp1c3QgZm9yIGdvaW5n
IG91dCBvbiB0aGUgYWlyLg0KPiANCg0KLSBUaGUgb2JqZWN0aXZlIGlzIHRvIHVzZSB0aGUgc2Ft
ZSBwcm9kdWN0aW9uIGZpcm13YXJlIGJpbmFyeSBmb3IgYm90aCB0aGUgb3BlbiBzb3VyY2UgYW5k
IHByb3ByaWV0YXJ5IGRyaXZlci4gU2FtZSBpbnRlcmZhY2UgaXMgY3VycmVudGx5IHVzZWQgYnkg
cHJvcHJpZXRhcnkgZHJpdmVyIGZvciBoaXN0b3JpY2FsbHkgcmVhc29uLCB3aGlsZSB0aGUgb3Bl
biBzb3VyY2UgSEFMIGlzIGFkYXB0aW5nIHRvIGl0IGZvciB0aGUgZXhpc3Rpbmcgc2hpcHBpbmcg
cHJvZHVjdC4NCi0gV2Ugd2lsbCBtYWtlIGNoYW5nZXMgYW5kIGNsZWFuIHRoaW5ncyB1cCBpbiBm
dXR1cmUuIEkgd2lsbCBzcGVuZCBlZmZvcnQgdG8gY29udGludWUgaXRzIG1haW50ZW5hbmNlIGFu
ZCBjbGVhbi11cC4NCg0KVGhhbmtzLA0KRGF2aWQNCg0KPiBqb2hhbm5lcw0K
^ permalink raw reply
* [PATCH net-next v3] bridge: multicast to unicast
From: Linus Lüssing @ 2017-01-19 0:23 UTC (permalink / raw)
To: netdev
Cc: David S . Miller, Stephen Hemminger, Felix Fietkau,
Nikolay Aleksandrov, bridge, linux-kernel, linux-wireless,
Linus Lüssing
Implements an optional, per bridge port flag and feature to deliver
multicast packets to any host on the according port via unicast
individually. This is done by copying the packet per host and
changing the multicast destination MAC to a unicast one accordingly.
multicast-to-unicast works on top of the multicast snooping feature of
the bridge. Which means unicast copies are only delivered to hosts which
are interested in it and signalized this via IGMP/MLD reports
previously.
This feature is intended for interface types which have a more reliable
and/or efficient way to deliver unicast packets than broadcast ones
(e.g. wifi).
However, it should only be enabled on interfaces where no IGMPv2/MLDv1
report suppression takes place. This feature is disabled by default.
The initial patch and idea is from Felix Fietkau.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
[linus.luessing@c0d3.blue: various bug + style fixes, commit message]
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
This feature is used and enabled by default in OpenWRT and LEDE for AP
interfaces for more than a year now to allow both a more robust multicast
delivery and multicast at higher rates (e.g. multicast streaming).
In OpenWRT/LEDE the IGMP/MLD report suppression issue is overcome by
the network daemon enabling AP isolation and by that separating all STAs.
Delivery of STA-to-STA IP mulitcast is made possible again by
enabling and utilizing the bridge hairpin mode, which considers the
incoming port as a potential outgoing port, too.
Hairpin-mode is performed after multicast snooping, therefore leading to
only deliver reports to STAs running a multicast router.
Changes in v3:
* fix an uninitialized variable bug introduced in br_multicast_flood()
in v2, found by kbuild test bot
Changes in v2:
* netlink support (thanks Nik!)
* fixed switching between multicast_to_unicast on/off
-> even after toggling an already existing entry would
stale in its mode and would never be replaced
-> new extra check in br_port_group_equal)
* reduced checks in br_multicast_flood() from two to one
to address fast-path concerns (thanks Nik!)
* rev-christmas tree ordering (thanks Nik!)
* removed "net_bridge_port_group::unicast", using
::flags instead (thanks Nik!)
* BR_MULTICAST_TO_UCAST -> BR_MULTICAST_TO_UNICAST
(BR_MULTICAST_FLAST_LEAVE has the same length anyway)
* simplified maybe_deliver_addr()
(no return, no "prev" paramater -> was a NOP anyway)
* added "From: Felix Fietkau [...]"
* added "Signed-off-by: Felix Fietkau [...]"
---
include/linux/if_bridge.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/bridge/br_forward.c | 37 ++++++++++++++++-
net/bridge/br_mdb.c | 2 +-
net/bridge/br_multicast.c | 96 ++++++++++++++++++++++++++++++++------------
net/bridge/br_netlink.c | 5 +++
net/bridge/br_private.h | 8 ++--
net/bridge/br_sysfs_if.c | 2 +
8 files changed, 121 insertions(+), 31 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index c6587c0..debc9d5 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -46,6 +46,7 @@ struct br_ip_list {
#define BR_LEARNING_SYNC BIT(9)
#define BR_PROXYARP_WIFI BIT(10)
#define BR_MCAST_FLOOD BIT(11)
+#define BR_MULTICAST_TO_UNICAST BIT(12)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 6b13e59..4e59565 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -321,6 +321,7 @@ enum {
IFLA_BRPORT_MULTICAST_ROUTER,
IFLA_BRPORT_PAD,
IFLA_BRPORT_MCAST_FLOOD,
+ IFLA_BRPORT_MCAST_TO_UCAST,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 7cb41ae..a6c8a27 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -174,6 +174,29 @@ static struct net_bridge_port *maybe_deliver(
return p;
}
+static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
+ const unsigned char *addr, bool local_orig)
+{
+ struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+ const unsigned char *src = eth_hdr(skb)->h_source;
+
+ if (!should_deliver(p, skb))
+ return;
+
+ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
+ if (skb->dev == p->dev && ether_addr_equal(src, addr))
+ return;
+
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb) {
+ dev->stats.tx_dropped++;
+ return;
+ }
+
+ memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
+ __br_forward(p, skb, local_orig);
+}
+
/* called under rcu_read_lock */
void br_flood(struct net_bridge *br, struct sk_buff *skb,
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig)
@@ -241,10 +264,20 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
NULL;
- port = (unsigned long)lport > (unsigned long)rport ?
- lport : rport;
+ if ((unsigned long)lport > (unsigned long)rport) {
+ port = lport;
+
+ if (p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) {
+ maybe_deliver_addr(lport, skb, p->eth_addr,
+ local_orig);
+ goto delivered;
+ }
+ } else {
+ port = rport;
+ }
prev = maybe_deliver(prev, port, skb, local_orig);
+delivered:
if (IS_ERR(prev))
goto out;
if (prev == port)
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 7dbc80d..056e6ac 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -531,7 +531,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
break;
}
- p = br_multicast_new_port_group(port, group, *pp, state);
+ p = br_multicast_new_port_group(port, group, *pp, state, NULL);
if (unlikely(!p))
return -ENOMEM;
rcu_assign_pointer(*pp, p);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index b30e77e..b127bb7 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -43,12 +43,14 @@ static void br_multicast_add_router(struct net_bridge *br,
static void br_ip4_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid);
+ __u16 vid,
+ const unsigned char *src);
+
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid);
+ __u16 vid, const unsigned char *src);
#endif
unsigned int br_mdb_rehash_seq;
@@ -711,7 +713,8 @@ struct net_bridge_port_group *br_multicast_new_port_group(
struct net_bridge_port *port,
struct br_ip *group,
struct net_bridge_port_group __rcu *next,
- unsigned char flags)
+ unsigned char flags,
+ const unsigned char *src)
{
struct net_bridge_port_group *p;
@@ -726,12 +729,39 @@ struct net_bridge_port_group *br_multicast_new_port_group(
hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p);
+
+ if ((port->flags & BR_MULTICAST_TO_UNICAST) && src) {
+ memcpy(p->eth_addr, src, ETH_ALEN);
+ p->flags |= MDB_PG_FLAGS_MCAST_TO_UCAST;
+ }
+
return p;
}
+static bool br_port_group_equal(struct net_bridge_port_group *p,
+ struct net_bridge_port *port,
+ const unsigned char *src)
+{
+ if (p->port != port)
+ return false;
+
+ if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST) !=
+ !(port->flags & BR_MULTICAST_TO_UNICAST))
+ return false;
+
+ if (!(p->flags & MDB_PG_FLAGS_MCAST_TO_UCAST))
+ return true;
+
+ if (!src)
+ return false;
+
+ return ether_addr_equal(src, p->eth_addr);
+}
+
static int br_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
- struct br_ip *group)
+ struct br_ip *group,
+ const unsigned char *src)
{
struct net_bridge_port_group __rcu **pp;
struct net_bridge_port_group *p;
@@ -758,13 +788,13 @@ static int br_multicast_add_group(struct net_bridge *br,
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port == port)
+ if (br_port_group_equal(p, port, src))
goto found;
if ((unsigned long)p->port < (unsigned long)port)
break;
}
- p = br_multicast_new_port_group(port, group, *pp, 0);
+ p = br_multicast_new_port_group(port, group, *pp, 0, src);
if (unlikely(!p))
goto err;
rcu_assign_pointer(*pp, p);
@@ -783,7 +813,8 @@ static int br_multicast_add_group(struct net_bridge *br,
static int br_ip4_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
@@ -794,14 +825,15 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
br_group.proto = htons(ETH_P_IP);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, &br_group, src);
}
#if IS_ENABLED(CONFIG_IPV6)
static int br_ip6_multicast_add_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
@@ -812,7 +844,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br,
br_group.proto = htons(ETH_P_IPV6);
br_group.vid = vid;
- return br_multicast_add_group(br, port, &br_group);
+ return br_multicast_add_group(br, port, &br_group, src);
}
#endif
@@ -1081,6 +1113,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src;
struct igmpv3_report *ih;
struct igmpv3_grec *grec;
int i;
@@ -1121,12 +1154,14 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
continue;
}
+ src = eth_hdr(skb)->h_source;
if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
type == IGMPV3_MODE_IS_INCLUDE) &&
ntohs(grec->grec_nsrcs) == 0) {
- br_ip4_multicast_leave_group(br, port, group, vid);
+ br_ip4_multicast_leave_group(br, port, group, vid, src);
} else {
- err = br_ip4_multicast_add_group(br, port, group, vid);
+ err = br_ip4_multicast_add_group(br, port, group, vid,
+ src);
if (err)
break;
}
@@ -1141,6 +1176,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
struct sk_buff *skb,
u16 vid)
{
+ const unsigned char *src = eth_hdr(skb)->h_source;
struct icmp6hdr *icmp6h;
struct mld2_grec *grec;
int i;
@@ -1192,10 +1228,11 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
ntohs(*nsrcs) == 0) {
br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
- vid);
+ vid, src);
} else {
err = br_ip6_multicast_add_group(br, port,
- &grec->grec_mca, vid);
+ &grec->grec_mca, vid,
+ src);
if (err)
break;
}
@@ -1511,7 +1548,8 @@ br_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
struct br_ip *group,
struct bridge_mcast_other_query *other_query,
- struct bridge_mcast_own_query *own_query)
+ struct bridge_mcast_own_query *own_query,
+ const unsigned char *src)
{
struct net_bridge_mdb_htable *mdb;
struct net_bridge_mdb_entry *mp;
@@ -1535,7 +1573,7 @@ br_multicast_leave_group(struct net_bridge *br,
for (pp = &mp->ports;
(p = mlock_dereference(*pp, br)) != NULL;
pp = &p->next) {
- if (p->port != port)
+ if (!br_port_group_equal(p, port, src))
continue;
rcu_assign_pointer(*pp, p->next);
@@ -1566,7 +1604,7 @@ br_multicast_leave_group(struct net_bridge *br,
for (p = mlock_dereference(mp->ports, br);
p != NULL;
p = mlock_dereference(p->next, br)) {
- if (p->port != port)
+ if (!br_port_group_equal(p, port, src))
continue;
if (!hlist_unhashed(&p->mglist) &&
@@ -1617,7 +1655,8 @@ br_multicast_leave_group(struct net_bridge *br,
static void br_ip4_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
__be32 group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1632,14 +1671,15 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
br_group.vid = vid;
br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
- own_query);
+ own_query, src);
}
#if IS_ENABLED(CONFIG_IPV6)
static void br_ip6_multicast_leave_group(struct net_bridge *br,
struct net_bridge_port *port,
const struct in6_addr *group,
- __u16 vid)
+ __u16 vid,
+ const unsigned char *src)
{
struct br_ip br_group;
struct bridge_mcast_own_query *own_query;
@@ -1654,7 +1694,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
br_group.vid = vid;
br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
- own_query);
+ own_query, src);
}
#endif
@@ -1712,6 +1752,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct igmphdr *ih;
int err;
@@ -1731,13 +1772,14 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
}
ih = igmp_hdr(skb);
+ src = eth_hdr(skb)->h_source;
BR_INPUT_SKB_CB(skb)->igmp = ih->type;
switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMPV2_HOST_MEMBERSHIP_REPORT:
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip4_multicast_add_group(br, port, ih->group, vid);
+ err = br_ip4_multicast_add_group(br, port, ih->group, vid, src);
break;
case IGMPV3_HOST_MEMBERSHIP_REPORT:
err = br_ip4_multicast_igmp3_report(br, port, skb_trimmed, vid);
@@ -1746,7 +1788,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
err = br_ip4_multicast_query(br, port, skb_trimmed, vid);
break;
case IGMP_HOST_LEAVE_MESSAGE:
- br_ip4_multicast_leave_group(br, port, ih->group, vid);
+ br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
break;
}
@@ -1766,6 +1808,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
u16 vid)
{
struct sk_buff *skb_trimmed = NULL;
+ const unsigned char *src;
struct mld_msg *mld;
int err;
@@ -1785,8 +1828,10 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
switch (mld->mld_type) {
case ICMPV6_MGM_REPORT:
+ src = eth_hdr(skb)->h_source;
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
- err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid);
+ err = br_ip6_multicast_add_group(br, port, &mld->mld_mca, vid,
+ src);
break;
case ICMPV6_MLD2_REPORT:
err = br_ip6_multicast_mld2_report(br, port, skb_trimmed, vid);
@@ -1795,7 +1840,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
err = br_ip6_multicast_query(br, port, skb_trimmed, vid);
break;
case ICMPV6_MGM_REDUCTION:
- br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
+ src = eth_hdr(skb)->h_source;
+ br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
break;
}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 71c7453..6c087cd 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -123,6 +123,7 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(1) /* IFLA_BRPORT_GUARD */
+ nla_total_size(1) /* IFLA_BRPORT_PROTECT */
+ nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ + nla_total_size(1) /* IFLA_BRPORT_MCAST_TO_UCAST */
+ nla_total_size(1) /* IFLA_BRPORT_LEARNING */
+ nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */
+ nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
@@ -173,6 +174,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
!!(p->flags & BR_ROOT_BLOCK)) ||
nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE,
!!(p->flags & BR_MULTICAST_FAST_LEAVE)) ||
+ nla_put_u8(skb, IFLA_BRPORT_MCAST_TO_UCAST,
+ !!(p->flags & BR_MULTICAST_TO_UNICAST)) ||
nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) ||
nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
!!(p->flags & BR_FLOOD)) ||
@@ -586,6 +589,7 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
[IFLA_BRPORT_PROXYARP] = { .type = NLA_U8 },
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 },
+ [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 },
};
/* Change the state of the port and notify spanning tree */
@@ -636,6 +640,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING);
br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
+ br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_TO_UCAST, BR_MULTICAST_TO_UNICAST);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..f7db79f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -166,8 +166,9 @@ struct net_bridge_fdb_entry
struct rcu_head rcu;
};
-#define MDB_PG_FLAGS_PERMANENT BIT(0)
-#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_PERMANENT BIT(0)
+#define MDB_PG_FLAGS_OFFLOAD BIT(1)
+#define MDB_PG_FLAGS_MCAST_TO_UCAST BIT(2)
struct net_bridge_port_group {
struct net_bridge_port *port;
@@ -177,6 +178,7 @@ struct net_bridge_port_group {
struct timer_list timer;
struct br_ip addr;
unsigned char flags;
+ unsigned char eth_addr[ETH_ALEN];
};
struct net_bridge_mdb_entry
@@ -599,7 +601,7 @@ void br_multicast_free_pg(struct rcu_head *head);
struct net_bridge_port_group *
br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
struct net_bridge_port_group __rcu *next,
- unsigned char flags);
+ unsigned char flags, const unsigned char *src);
void br_mdb_init(void);
void br_mdb_uninit(void);
void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 8bd5696..05e8946 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -188,6 +188,7 @@ static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
store_multicast_router);
BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
+BRPORT_ATTR_FLAG(multicast_to_unicast, BR_MULTICAST_TO_UNICAST);
#endif
static const struct brport_attribute *brport_attrs[] = {
@@ -214,6 +215,7 @@ static const struct brport_attribute *brport_attrs[] = {
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
&brport_attr_multicast_router,
&brport_attr_multicast_fast_leave,
+ &brport_attr_multicast_to_unicast,
#endif
&brport_attr_proxyarp,
&brport_attr_proxyarp_wifi,
--
2.1.4
^ permalink raw reply related
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