* [PATCH net-next 22/22] net: hsr: fix return type of ndo_start_xmit function
From: YueHaibing @ 2018-09-20 12:33 UTC (permalink / raw)
To: davem, dmitry.tarnyagin, wg, mkl, michal.simek, hsweeten,
madalin.bucur, pantelis.antoniou, claudiu.manoil, leoyang.li,
linux, sammy, ralf, nico, steve.glendinning, f.fainelli,
grygorii.strashko, w-kwok2, m-karicheri2, t.sailer, jreuter, kys,
haiyangz, wei.liu2, paul.durrant, arvid.brodin, pshelar
Cc: dev, linux-mips, xen-devel, netdev, linux-usb, YueHaibing,
linux-kernel, linux-can, devel, linux-hams, linux-omap,
linuxppc-dev, linux-arm-kernel
In-Reply-To: <20180920123306.14772-1-yuehaibing@huawei.com>
The method ndo_start_xmit() is defined as returning an 'netdev_tx_t',
which is a typedef for an enum type, so make sure the implementation in
this driver has returns 'netdev_tx_t' value, and change the function
return type to netdev_tx_t.
Found by coccinelle.
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
net/hsr/hsr_device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index b8cd43c..a067150 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -233,7 +233,7 @@ static netdev_features_t hsr_fix_features(struct net_device *dev,
}
-static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct hsr_priv *hsr = netdev_priv(dev);
struct hsr_port *master;
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] brcm80211: remove redundant condition check before debugfs_remove_recursive
From: zhong jiang @ 2018-09-20 12:37 UTC (permalink / raw)
To: Kalle Valo
Cc: davem, hante.meuleman, franky.lin, arend.vanspriel,
linux-wireless, brcm80211-dev-list.pdl, netdev, linux-kernel
In-Reply-To: <877ejg1hcd.fsf@kamboji.qca.qualcomm.com>
On 2018/9/20 20:30, Kalle Valo wrote:
> zhong jiang <zhongjiang@huawei.com> writes:
>
>> On 2018/9/20 20:07, Kalle Valo wrote:
>>> zhong jiang <zhongjiang@huawei.com> wrote:
>>>
>>>> debugfs_remove_recursive has taken IS_ERR_OR_NULL into account. So just
>>>> remove the condition check before debugfs_remove_recursive.
>>>>
>>>> Signed-off-by: zhong jiang <zhongjiang@huawei.com>
>>> It seems you already submitted an identical patch four days earlier:
>>>
>>> https://patchwork.kernel.org/patch/10593061/
>>>
>>> Why the duplicate? Please ALWAYS add a changelog and increase the version number:
>> I am sorry for that. Maybe I send the patch earlier, but I remeber I
>> should forget to cc to
>> netdev@vger.kernel.org and LMLK. So I repost it. Plese ingore the current patch.
> Even then please increase the version number and mention in the change
> log why you sent a new version. Otherwise you will make maintainers
> confused and wasting time with asking what has changed.
>
Get it and will keep it in mind . Thanks
Sincerely,
zhong jiang
^ permalink raw reply
* Re: [PATCH 0/2] net/sched: Add hardware specific counters to TC actions
From: Eelco Chaudron @ 2018-09-20 7:14 UTC (permalink / raw)
To: Jakub Kicinski
Cc: David Miller, netdev, jhs, xiyou.wangcong, jiri, simon.horman,
Marcelo Ricardo Leitner, louis.peens, Paolo, Davide Caratti
In-Reply-To: <20180829201211.6c58b827@cakuba.netronome.com>
On 29 Aug 2018, at 20:12, Jakub Kicinski wrote:
> On Wed, 29 Aug 2018 11:43:47 +0200, Eelco Chaudron wrote:
>> On 23 Aug 2018, at 20:14, Jakub Kicinski wrote:
>>
>>> On Mon, 20 Aug 2018 16:03:40 +0200, Eelco Chaudron wrote:
>>>> On 17 Aug 2018, at 13:27, Jakub Kicinski wrote:
>>>>> On Thu, 16 Aug 2018 14:02:44 +0200, Eelco Chaudron wrote:
>>>>>> On 11 Aug 2018, at 21:06, David Miller wrote:
>>>>>>
>>>>>>> From: Jakub Kicinski <jakub.kicinski@netronome.com>
>>>>>>> Date: Thu, 9 Aug 2018 20:26:08 -0700
>>>>>>>
>>>>>>>> It is not immediately clear why this is needed. The memory and
>>>>>>>> updating two sets of counters won't come for free, so perhaps a
>>>>>>>> stronger justification than troubleshooting is due? :S
>>>>>>>>
>>>>>>>> Netdev has counters for fallback vs forwarded traffic, so you'd
>>>>>>>> know
>>>>>>>> that traffic hits the SW datapath, plus the rules which are
>>>>>>>> in_hw
>>>>>>>> will
>>>>>>>> most likely not match as of today for flower (assuming
>>>>>>>> correctness).
>>>>>>
>>>>>> I strongly believe that these counters are a requirement for a
>>>>>> mixed
>>>>>> software/hardware (flow) based forwarding environment. The global
>>>>>> counters will not help much here as you might have chosen to have
>>>>>> certain traffic forwarded by software.
>>>>>>
>>>>>> These counters are probably the only option you have to figure
>>>>>> out
>>>>>> why
>>>>>> forwarding is not as fast as expected, and you want to blame the
>>>>>> TC
>>>>>> offload NIC.
>>>>>
>>>>> The suggested debugging flow would be:
>>>>> (1) check the global counter for fallback are incrementing;
>>>>> (2) find a flow with high stats but no in_hw flag set.
>>>>>
>>>>> The in_hw indication should be sufficient in most cases (unless
>>>>> there
>>>>> are shared blocks between netdevs of different ASICs...).
>>>>
>>>> I guess the aim is to find miss behaving hardware, i.e. having the
>>>> in_hw
>>>> flag set, but flows still coming to the kernel.
>>>
>>> For misbehaving hardware in_hw will not work indeed. Whether we
>>> need
>>> these extra always-on stats for such use case could be debated :)
>>>
>>>>>>>> I'm slightly concerned about potential performance impact,
>>>>>>>> would
>>>>>>>> you
>>>>>>>> be able to share some numbers for non-trivial number of flows
>>>>>>>> (100k
>>>>>>>> active?)?
>>>>>>>
>>>>>>> Agreed, features used for diagnostics cannot have a harmful
>>>>>>> penalty
>>>>>>> for fast path performance.
>>>>>>
>>>>>> Fast path performance is not affected as these counters are not
>>>>>> incremented there. They are only incremented by the nic driver
>>>>>> when
>>>>>> they
>>>>>> gather their statistics from hardware.
>>>>>
>>>>> Not by much, you are adding state to performance-critical
>>>>> structures,
>>>>> though, for what is effectively debugging purposes.
>>>>>
>>>>> I was mostly talking about the HW offload stat updates (sorry for
>>>>> not
>>>>> being clear).
>>>>>
>>>>> We can have some hundreds of thousands active offloaded flows,
>>>>> each
>>>>> of
>>>>> them can have multiple actions, and stats have to be updated
>>>>> multiple
>>>>> times per second and dumped probably around once a second, too.
>>>>> On
>>>>> a
>>>>> busy system the stats will get evicted from cache between each
>>>>> round.
>>>>>
>>>>> But I'm speculating let's see if I can get some numbers on it (if
>>>>> you
>>>>> could get some too, that would be great!).
>>>>
>>>> I’ll try to measure some of this later this week/early next week.
>>>
>>> I asked Louis to run some tests while I'm travelling, and he reports
>>> that my worry about reporting the extra stats was unfounded. Update
>>> function does not show up in traces at all. It seems under stress
>>> (generated with stress-ng) the thread dumping the stats in userspace
>>> (in OvS it would be the revalidator) actually consumes less CPU in
>>> __gnet_stats_copy_basic (0.4% less for ~2.0% total).
>>>
>>> Would this match with your results? I'm not sure why dumping would
>>> be
>>> faster with your change..
>>
>> Tested with OVS and https://github.com/chaudron/ovs_perf using 300K
>> TC
>> rules installed in HW.
>>
>> For __gnet_stats_copy_basic() being faster I have (had) a theory. Now
>> this function is called twice, and I assumed the first call would
>> cache
>> memory and the second call would be faster.
>>
>> Sampling a lot of perf data, I get an average of 1115ns with the base
>> kernel and 954ns with the fix applied, so about ~14%.
>>
>> Thought I would perf tcf_action_copy_stats() as it is the place
>> updating
>> the additional counter. But even in this case, I see a better
>> performance with the patch applied.
>>
>> In average 13581ns with the fix, vs base kernel at 1391ns, so about
>> 2.3%.
>>
>> I guess the changes to the tc_action structure got better cache
>> alignment.
>
> Interesting you could reproduce the speed up too! +1 for the guess.
> Seems like my caution about slowing down SW paths to support HW
> offload
> landed on a very unfortunate patch :)
Is there anything else blocking from getting this into net-next?
I still think this patch is beneficial for the full user experience, and
I’ve got requests from QA and others for this.
^ permalink raw reply
* Re: [PATCH net-next v2 05/10] net: sched: use Qdisc rcu API instead of relying on rtnl lock
From: Vlad Buslov @ 2018-09-20 7:20 UTC (permalink / raw)
To: Cong Wang
Cc: Linux Kernel Network Developers, Jamal Hadi Salim, Jiri Pirko,
David Miller, Stephen Hemminger, Kirill Tkhai, Nicolas Dichtel,
Greg KH, mark.rutland, Leon Romanovsky, Paul E. McKenney,
Florian Westphal, David Ahern, christian, lucien xin,
Jakub Kicinski, Jiri Benc
In-Reply-To: <CAM_iQpVKEU_RqxDPaTEo2KShKNATsHGJEa64afT-m6iadptNGw@mail.gmail.com>
On Wed 19 Sep 2018 at 22:04, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Mon, Sep 17, 2018 at 12:19 AM Vlad Buslov <vladbu@mellanox.com> wrote:
>> +static void tcf_qdisc_put(struct Qdisc *q, bool rtnl_held)
>> +{
>> + if (!q)
>> + return;
>> +
>> + if (rtnl_held)
>> + qdisc_put(q);
>> + else
>> + qdisc_put_unlocked(q);
>> +}
>
> This is very ugly. You should know whether RTNL is held or
> not when calling it.
>
> What's more, all of your code passes true, so why do you
> need a parameter for rtnl_held?
It passes true because currently rule update handlers still registered
as locked. This is a preparation for next patch set where this would be
changed to proper variable that depends on qdics and classifier type.
^ permalink raw reply
* [PATCH] smc: generic netlink family should be __ro_after_init
From: Johannes Berg @ 2018-09-20 7:27 UTC (permalink / raw)
To: linux-s390; +Cc: netdev, Ursula Braun, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
The generic netlink family is only initialized during module init,
so it should be __ro_after_init like all other generic netlink
families.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/smc/smc_pnet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index 01c6ce042a1c..7cb3e4f07c10 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -461,7 +461,7 @@ static const struct genl_ops smc_pnet_ops[] = {
};
/* SMC_PNETID family definition */
-static struct genl_family smc_pnet_nl_family = {
+static struct genl_family smc_pnet_nl_family __ro_after_init = {
.hdrsize = 0,
.name = SMCR_GENL_FAMILY_NAME,
.version = SMCR_GENL_FAMILY_VERSION,
--
2.14.4
^ permalink raw reply related
* Re: [PATCH net-next v2 08/10] net: sched: protect block idr with spinlock
From: Vlad Buslov @ 2018-09-20 7:36 UTC (permalink / raw)
To: Cong Wang
Cc: Linux Kernel Network Developers, Jamal Hadi Salim, Jiri Pirko,
David Miller, Stephen Hemminger, Kirill Tkhai, Nicolas Dichtel,
Greg KH, mark.rutland, Leon Romanovsky, Paul E. McKenney,
Florian Westphal, David Ahern, christian, lucien xin,
Jakub Kicinski, Jiri Benc
In-Reply-To: <CAM_iQpVVKJtLJpjepPE=cpi2=3paxYp7yKvOz6PV6imjYi8BPQ@mail.gmail.com>
On Wed 19 Sep 2018 at 22:09, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Mon, Sep 17, 2018 at 12:19 AM Vlad Buslov <vladbu@mellanox.com> wrote:
>> @@ -482,16 +483,25 @@ static int tcf_block_insert(struct tcf_block *block, struct net *net,
>> struct netlink_ext_ack *extack)
>> {
>> struct tcf_net *tn = net_generic(net, tcf_net_id);
>> + int err;
>> +
>> + idr_preload(GFP_KERNEL);
>> + spin_lock(&tn->idr_lock);
>> + err = idr_alloc_u32(&tn->idr, block, &block->index, block->index,
>> + GFP_NOWAIT);
>
>
> Why GFP_NOWAIT rather than GFP_ATOMIC here?
I checked how idr_preload is used in kernel and in most places following
allocation uses GFP_NOWAIT (including idr-test.c). You suggest I should
change it to GFP_ATOMIC?
^ permalink raw reply
* Re: [PATCH net-next v5 06/20] zinc: ChaCha20 MIPS32r2 implementation
From: Jason A. Donenfeld @ 2018-09-20 13:19 UTC (permalink / raw)
To: paul.burton
Cc: LKML, Netdev, Linux Crypto Mailing List, David Miller,
Greg Kroah-Hartman, René van Dorst, Samuel Neves,
Andrew Lutomirski, Jean-Philippe Aumasson, Ralf Baechle, jhogan,
linux-mips
In-Reply-To: <20180918202549.ogfyunppxaha7sfu@pburton-laptop>
Hi Paul,
Thanks a bunch for the review.
On Tue, Sep 18, 2018 at 10:25 PM Paul Burton <paul.burton@mips.com> wrote:
> Should this be .set reorder?
Nice catch. Fixed here:
https://git.zx2c4.com/WireGuard/commit/?id=23d97fc333cf85dd07445a9d21a28cbef47c553c
But then...
> Even better - could we not just place the addiu before the bne & drop
> the .set noreorder, allowing the assembler to fill the delay slot with
> the addiu? Likewise in many other places throughout the patch.
>
> That would be more future proof - particularly if we ever want to adjust
> this for use with the nanoMIPS ISA which has no delay slots. It may also
> allow the assembler the choice to use compact branches (ie. branches
> without visible delay slots) when targeting MIPS32r6. I know neither of
> these will currently build this code, but I think avoiding all the
> noreorder blocks would be a nice cleanup just for the sake of
> readability anyway.
Great idea. Rene has committed that here:
https://git.zx2c4.com/WireGuard/commit/?id=5c153a59ac3aa58a3ff17c69fee63d599e5f2758
These will be in the v6 patchset whenever that's posted, and it's
already been merged into the dev tree:
https://git.kernel.org/pub/scm/linux/kernel/git/zx2c4/linux.git/log/?h=jd/wireguard
Regards,
Jason
^ permalink raw reply
* [PATCH bpf-next] samples/bpf: fix compilation failure
From: Prashant Bhole @ 2018-09-20 7:52 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann; +Cc: Prashant Bhole, netdev
following commit:
commit d58e468b1112 ("flow_dissector: implements flow dissector BPF hook")
added struct bpf_flow_keys which conflicts with the struct with
same name in sockex2_kern.c and sockex3_kern.c
similar to commit:
commit 534e0e52bc23 ("samples/bpf: fix a compilation failure")
we tried the rename it "flow_keys" but it also conflicted with struct
having same name in include/net/flow_dissector.h. Hence renaming the
struct to "flow_key_record". Also, this commit doesn't fix the
compilation error completely because the similar struct is present in
sockex3_kern.c. Hence renaming it in both files sockex3_user.c and
sockex3_kern.c
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
---
samples/bpf/sockex2_kern.c | 11 ++++++-----
samples/bpf/sockex3_kern.c | 8 ++++----
samples/bpf/sockex3_user.c | 4 ++--
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c
index f58acfc92556..f2f9dbc021b0 100644
--- a/samples/bpf/sockex2_kern.c
+++ b/samples/bpf/sockex2_kern.c
@@ -14,7 +14,7 @@ struct vlan_hdr {
__be16 h_vlan_encapsulated_proto;
};
-struct bpf_flow_keys {
+struct flow_key_record {
__be32 src;
__be32 dst;
union {
@@ -59,7 +59,7 @@ static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off)
}
static inline __u64 parse_ip(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
- struct bpf_flow_keys *flow)
+ struct flow_key_record *flow)
{
__u64 verlen;
@@ -83,7 +83,7 @@ static inline __u64 parse_ip(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto
}
static inline __u64 parse_ipv6(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
- struct bpf_flow_keys *flow)
+ struct flow_key_record *flow)
{
*ip_proto = load_byte(skb,
nhoff + offsetof(struct ipv6hdr, nexthdr));
@@ -96,7 +96,8 @@ static inline __u64 parse_ipv6(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_pro
return nhoff;
}
-static inline bool flow_dissector(struct __sk_buff *skb, struct bpf_flow_keys *flow)
+static inline bool flow_dissector(struct __sk_buff *skb,
+ struct flow_key_record *flow)
{
__u64 nhoff = ETH_HLEN;
__u64 ip_proto;
@@ -198,7 +199,7 @@ struct bpf_map_def SEC("maps") hash_map = {
SEC("socket2")
int bpf_prog2(struct __sk_buff *skb)
{
- struct bpf_flow_keys flow = {};
+ struct flow_key_record flow = {};
struct pair *value;
u32 key;
diff --git a/samples/bpf/sockex3_kern.c b/samples/bpf/sockex3_kern.c
index 95907f8d2b17..c527b57d3ec8 100644
--- a/samples/bpf/sockex3_kern.c
+++ b/samples/bpf/sockex3_kern.c
@@ -61,7 +61,7 @@ struct vlan_hdr {
__be16 h_vlan_encapsulated_proto;
};
-struct bpf_flow_keys {
+struct flow_key_record {
__be32 src;
__be32 dst;
union {
@@ -88,7 +88,7 @@ static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off)
}
struct globals {
- struct bpf_flow_keys flow;
+ struct flow_key_record flow;
};
struct bpf_map_def SEC("maps") percpu_map = {
@@ -114,14 +114,14 @@ struct pair {
struct bpf_map_def SEC("maps") hash_map = {
.type = BPF_MAP_TYPE_HASH,
- .key_size = sizeof(struct bpf_flow_keys),
+ .key_size = sizeof(struct flow_key_record),
.value_size = sizeof(struct pair),
.max_entries = 1024,
};
static void update_stats(struct __sk_buff *skb, struct globals *g)
{
- struct bpf_flow_keys key = g->flow;
+ struct flow_key_record key = g->flow;
struct pair *value;
value = bpf_map_lookup_elem(&hash_map, &key);
diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c
index 22f74d0e1493..9d02e0404719 100644
--- a/samples/bpf/sockex3_user.c
+++ b/samples/bpf/sockex3_user.c
@@ -13,7 +13,7 @@
#define PARSE_IP_PROG_FD (prog_fd[0])
#define PROG_ARRAY_FD (map_fd[0])
-struct flow_keys {
+struct flow_key_record {
__be32 src;
__be32 dst;
union {
@@ -64,7 +64,7 @@ int main(int argc, char **argv)
(void) f;
for (i = 0; i < 5; i++) {
- struct flow_keys key = {}, next_key;
+ struct flow_key_record key = {}, next_key;
struct pair value;
sleep(1);
--
2.17.1
^ permalink raw reply related
* Re: [PATCH iproute2 v2 0/3] testsuite: make alltests fixes
From: Phil Sutter @ 2018-09-20 8:02 UTC (permalink / raw)
To: Petr Vorel; +Cc: netdev, Stephen Hemminger, Luca Boccassi
In-Reply-To: <20180919233624.18494-1-petr.vorel@gmail.com>
Hi Petr,
On Thu, Sep 20, 2018 at 01:36:21AM +0200, Petr Vorel wrote:
> here are simply fixes to restore 'make alltests'.
> Currently it does not run.
Yeah, that testsuite definitely deserves some love.
Just one nit: The one-line summary in Fixes: tags should be enclosed in
quotes and parens, e.g.:
| Fixes: deadbeef ("foo bar")
Cheers, Phil
^ permalink raw reply
* Re: [PATCH v3 net-next 07/12] net: ethernet: Add helper to remove a supported link mode
From: Simon Horman @ 2018-09-20 8:05 UTC (permalink / raw)
To: Andrew Lunn
Cc: David Miller, netdev, Florian Fainelli, Sergei Shtylyov,
linux-renesas-soc
In-Reply-To: <20180919123200.GB26940@lunn.ch>
On Wed, Sep 19, 2018 at 02:32:00PM +0200, Andrew Lunn wrote:
> > > And here also.
> >
> > Thanks for raising this, I noticed it too.
> >
> > > Looking at the code, i see:
> > >
> > > /* E-MAC init function */
> > > static void ravb_emac_init(struct net_device *ndev)
> > > {
> > > struct ravb_private *priv = netdev_priv(ndev);
> > >
> > > /* Receive frame limit set register */
> > > ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR);
> > >
> > > /* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */
> > > ravb_write(ndev, ECMR_ZPF | (priv->duplex ? ECMR_DM : 0) |
> > > (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) |
> > > ECMR_TE | ECMR_RE, ECMR);
> > >
> > > Does this mean Pause is not supported in the hardware?
> >
> > According to my reading of the documentation Pause is supported by the
> > hardware and the above code seems to conflict with the comment (possibly
> > both the code and comment predate the current documentation). My reading of
> > the documentation is that the above unconditionally _enables_ receiving and
> > sending Pause frames with time parameter value 0.
>
> Hi Simon
>
> We should first prove that this additional Pause is causing the
> issue. After that, we can decide if we want to add Pause support to
> the driver. Please could you test this patch.
Hi Andrew,
thanks for your patch. I agree with the approach you have taken here,
however, unfortunately this patch does not seem to resolve the problem that
I have observed.
With this patch on top of net-next ([1] & [2]) I see:
[1] net-next as of two days ago, the version used when reporting
results earlier in this thread
cf7d97e1e54d ("net: mdio: remove duplicated include from mdio_bus.c")
# mii-tool -vv eth0
Using SIOCGMIIPHY=0x8947
eth0: no link
registers for MII PHY 0:
1140 7949 0022 1622 0981 c1e1 000d 0000
0000 0300 0000 0000 0000 0000 0000 3000
0000 0000 0000 0000 7002 0000 0000 0200
0000 0000 0000 0500 0000 0000 0000 0000
product info: vendor 00:08:85, model 34 rev 2
basic mode: autonegotiation enabled
basic status: no link
capabilities: 1000baseT-HD 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
advertising: 100baseTx-FD 100baseTx-HD
link partner: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
[2] net-next as of this morning
faa08325b429 ("isdn/hisax: Remove unnecessary parenthesis")
# mii-tool -vv eth0
Using SIOCGMIIPHY=0x8947
eth0: no link
registers for MII PHY 0:
1140 7949 0022 1622 0981 c1e1 000d 0000
0000 0300 0000 0000 0000 0000 0000 3000
0000 0000 0000 0000 6002 0000 0000 0200
0000 0000 0000 0500 0000 0000 0000 0000
product info: vendor 00:08:85, model 34 rev 2
basic mode: autonegotiation enabled
basic status: no link
capabilities: 1000baseT-HD 1000baseT-FD 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
advertising: 100baseTx-FD 100baseTx-HD
link partner: 100baseTx-FD 100baseTx-HD 10baseT-FD 10baseT-HD
I note a difference in the 3rd line of hex output: 7002 vs 6002
but I am unsure if that is relevant.
^ permalink raw reply
* Re: [RFC 4/5] netlink: prepare validate extack setting for recursion
From: Johannes Berg @ 2018-09-20 8:14 UTC (permalink / raw)
To: Marcelo Ricardo Leitner; +Cc: netdev
In-Reply-To: <20180919211048.GN4590@localhost.localdomain>
On Wed, 2018-09-19 at 18:10 -0300, Marcelo Ricardo Leitner wrote:
> > FWIW, if you do think that there's a need for distinguishing this, then
> > I'd argue that perhaps the right way to address this would be to extend
> > this all the way to userspace and have two separate attributes for
> > errors and warnings in the extended ACK message?
>
> Likely, yes. And perhaps even support multiple messages. That way we
> could, for example, parse all attributes and return a list of the all
> the offending ones, instead of returning one at a time. Net benefit?
> Not clear.. over engineering? Possibly.
Not sure I'd want to continue parsing after hitting something that's
considered garbage? It might be that the attribute length field is
corrupted and the data is actually fine, or something, and then
continuing to parse would just lead to more errors over and over again.
Also, I'd worry about being able to "blow up" the message, if we get a
text & bad attribute for everything that's wrong, it's pretty easy to
create a sort of "message amplification" and we'd probably have to
defend against that in terms of limiting memory allocation for all the
possible errors etc. Not sure I'd want to go there.
> I agree with you that in general we should not need this.
:-)
> > I'm still not really sure what the use case for a warning is, so not
> > sure I can really comment on this.
>
> Good point. From iproute POV, a warning is a non-fatal message. From
> an user perspective, that probably translates are nothing because in
> the end the command actually worked. :-)
>
> Seriously, I do think it's more of a hint for developers than anyone
> else.
I guess we also have the (ratelimited) messages from the kernel, like
the one saying you have extra bytes after your attributes at the end of
the message. Not sure which makes more sense, depends on the specific
case you'd use this in I guess.
Anyway - we got into this discussion because of all the extra recursion
stuff I was adding. With the change suggested by David we don't need
that now at all, so I guess it'd be better to propose a patch if you (or
perhaps I will see a need later) need such a facility for multiple
messages or multiple message levels?
johannes
^ permalink raw reply
* Re: [PATCH net-next 13/22] net: xen-netback: fix return type of ndo_start_xmit function
From: Wei Liu @ 2018-09-20 14:05 UTC (permalink / raw)
To: YueHaibing
Cc: davem, dmitry.tarnyagin, wg, mkl, michal.simek, hsweeten,
madalin.bucur, pantelis.antoniou, claudiu.manoil, leoyang.li,
linux, sammy, ralf, nico, steve.glendinning, f.fainelli,
grygorii.strashko, w-kwok2, m-karicheri2, t.sailer, jreuter, kys,
haiyangz, wei.liu2, paul.durrant, arvid.brodin, pshelar,
linux-kernel, netdev, linux-can, linux-arm-kernel
In-Reply-To: <20180920123306.14772-14-yuehaibing@huawei.com>
On Thu, Sep 20, 2018 at 08:32:57PM +0800, YueHaibing wrote:
> The method ndo_start_xmit() is defined as returning an 'netdev_tx_t',
> which is a typedef for an enum type, so make sure the implementation in
> this driver has returns 'netdev_tx_t' value, and change the function
> return type to netdev_tx_t.
>
> Found by coccinelle.
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
^ permalink raw reply
* Re: [PATCH v2 net-next] ravb: remove tx buffer addr 4byte alilgnment restriction for R-Car Gen3
From: Sergei Shtylyov @ 2018-09-20 8:36 UTC (permalink / raw)
To: David Miller, horms+renesas
Cc: magnus.damm, netdev, linux-renesas-soc, kazuya.mizuguchi.ks
In-Reply-To: <20180919.210836.924996973074874493.davem@davemloft.net>
On 9/20/2018 7:08 AM, David Miller wrote:
>> From: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>>
>> This patch sets from two descriptor to one descriptor because R-Car Gen3
>> does not have the 4 bytes alignment restriction of the transmission buffer.
>>
>> Signed-off-by: Kazuya Mizuguchi <kazuya.mizuguchi.ks@renesas.com>
>> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
>> ---
>> v2 [Simon Horman]
>> * As per review by Sergi Shtylyov
>> - Use reverse xmas tree for variable declarations
>> - Use > rather than >= for conditions
>> - Dropped unnecessary parentheses
>> - Don't allocate memory for tx_align when it will not be used
>> - But, kept NUM_TX_DESC_GEN[23] as I see some value in
>> the self-documentation provided by these #defines
>>
>> v1 [Kazuya Mizuguchi]
>
> Applied, thanks.
Mhm, I was just going to re-review the patch...
MBR, Sergei
^ permalink raw reply
* Re: [PATCH bpf-next 2/3] bpf: emit RECORD_MMAP events for bpf prog load/unload
From: Peter Zijlstra @ 2018-09-20 8:44 UTC (permalink / raw)
To: Alexei Starovoitov; +Cc: David S . Miller, daniel, acme, netdev, kernel-team
In-Reply-To: <20180919223935.999270-3-ast@kernel.org>
On Wed, Sep 19, 2018 at 03:39:34PM -0700, Alexei Starovoitov wrote:
> void bpf_prog_kallsyms_del(struct bpf_prog *fp)
> {
> + unsigned long symbol_start, symbol_end;
> + /* mmap_record.filename cannot be NULL and has to be u64 aligned */
> + char buf[sizeof(u64)] = {};
> +
> if (!bpf_prog_kallsyms_candidate(fp))
> return;
>
> spin_lock_bh(&bpf_lock);
> bpf_prog_ksym_node_del(fp->aux);
> spin_unlock_bh(&bpf_lock);
> + bpf_get_prog_addr_region(fp, &symbol_start, &symbol_end);
> + perf_event_mmap_bpf_prog(symbol_start, symbol_end - symbol_start,
> + buf, sizeof(buf));
> }
So perf doesn't normally issue unmap events.. We've talked about doing
that, but so far it's never really need needed I think.
I feels a bit weird to start issuing unmap events for this.
^ permalink raw reply
* [PATCH] mISDN: remove redundant null pointer check before kfree_skb
From: zhong jiang @ 2018-09-20 14:27 UTC (permalink / raw)
To: davem; +Cc: isdn, dvlasenk, gregkh, netdev, linux-kernel
kfree_skb has taken the null pointer into account. hence it is safe
to remove the redundant null pointer check before kfree_skb.
Signed-off-by: zhong jiang <zhongjiang@huawei.com>
---
drivers/isdn/mISDN/socket.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 18c0a12..15d3ca3 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -236,8 +236,7 @@ static void mISDN_sock_unlink(struct mISDN_sock_list *l, struct sock *sk)
}
done:
- if (skb)
- kfree_skb(skb);
+ kfree_skb(skb);
release_sock(sk);
return err;
}
--
1.7.12.4
^ permalink raw reply related
* Re: [PATCH 00/21] SMMU enablement for NXP LS1043A and LS1046A
From: Laurentiu Tudor @ 2018-09-20 14:33 UTC (permalink / raw)
To: Robin Murphy, devicetree@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org
Cc: Roy Pledge, Leo Li, shawnguo@kernel.org, davem@davemloft.net,
Madalin-cristian Bucur
In-Reply-To: <c2acecc8-5357-6cbe-f93c-00d71470dff5@arm.com>
On 20.09.2018 14:49, Robin Murphy wrote:
> On 20/09/18 11:38, Laurentiu Tudor wrote:
>>
>>
>> On 19.09.2018 17:37, Robin Murphy wrote:
>>> On 19/09/18 15:18, Laurentiu Tudor wrote:
>>>> Hi Robin,
>>>>
>>>> On 19.09.2018 16:25, Robin Murphy wrote:
>>>>> Hi Laurentiu,
>>>>>
>>>>> On 19/09/18 13:35, laurentiu.tudor@nxp.com wrote:
>>>>>> From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
>>>>>>
>>>>>> This patch series adds SMMU support for NXP LS1043A and LS1046A chips
>>>>>> and consists mostly in important driver fixes and the required device
>>>>>> tree updates. It touches several subsystems and consists of three
>>>>>> main
>>>>>> parts:
>>>>>> - changes in soc/drivers/fsl/qbman drivers adding iommu
>>>>>> mapping of
>>>>>> reserved memory areas, fixes and defered probe support
>>>>>> - changes in drivers/net/ethernet/freescale/dpaa_eth drivers
>>>>>> consisting in misc dma mapping related fixes and probe ordering
>>>>>> - addition of the actual arm smmu device tree node together with
>>>>>> various adjustments to the device trees
>>>>>>
>>>>>> Performance impact
>>>>>>
>>>>>> Running iperf benchmarks in a back-to-back setup (both sides
>>>>>> having smmu enabled) on a 10GBps port show an important
>>>>>> networking performance degradation of around %40 (9.48Gbps
>>>>>> linerate vs 5.45Gbps). If you need performance but without
>>>>>> SMMU support you can use "iommu.passthrough=1" to disable
>>>>>> SMMU.
>
> I should have said before - thanks for the numbers there as well. Always
> good to add another datapoint to my collection. If you're interested
> I've added SMMUv2 support to the "non-strict mode" series (of which I
> should be posting v8 soon), so it might be fun to see how well that
> works on MMU-500 in the real world.
Hmm, I think I gave those a try some weeks ago and vaguely remember that
I did see improvements. Can't remember the numbers off the top of my
head but I'll re-test with the latest spin and update the numbers.
>>>>>>
>>>>>> USB issue and workaround
>>>>>>
>>>>>> There's a problem with the usb controllers in these chips
>>>>>> generating smaller, 40-bit wide dma addresses instead of the
>>>>>> 48-bit
>>>>>> supported at the smmu input. So you end up in a situation
>>>>>> where the
>>>>>> smmu is mapped with 48-bit address translations, but the
>>>>>> device
>>>>>> generates transactions with clipped 40-bit addresses, thus
>>>>>> smmu
>>>>>> context faults are triggered. I encountered a similar
>>>>>> situation for
>>>>>> mmc that I managed to fix in software [1] however for USB I
>>>>>> did not
>>>>>> find a proper place in the code to add a similar fix. The only
>>>>>> workaround I found was to add this kernel parameter which
>>>>>> limits the
>>>>>> usb dma to 32-bit size: "xhci-hcd.quirks=0x800000".
>>>>>> This workaround if far from ideal, so any suggestions for a
>>>>>> code
>>>>>> based workaround in this area would be greatly appreciated.
>>>>>
>>>>> If you have a nominally-64-bit device with a
>>>>> narrower-than-the-main-interconnect link in front of it, that should
>>>>> already be fixed in 4.19-rc by bus_dma_mask picking up DT dma-ranges,
>>>>> provided the interconnect hierarchy can be described appropriately (or
>>>>> at least massaged sufficiently to satisfy the binding), e.g.:
>>>>>
>>>>> / {
>>>>> ...
>>>>>
>>>>> soc {
>>>>> ranges;
>>>>> dma-ranges = <0 0 10000 0>;
>>>>>
>>>>> dev_48bit { ... };
>>>>>
>>>>> periph_bus {
>>>>> ranges;
>>>>> dma-ranges = <0 0 100 0>;
>>>>>
>>>>> dev_40bit { ... };
>>>>> };
>>>>> };
>>>>> };
>>>>>
>>>>> and if that fails to work as expected (except for PCI hosts where
>>>>> handling dma-ranges properly still needs sorting out), please do
>>>>> let us
>>>>> know ;)
>>>>>
>>>>
>>>> Just to confirm, Is this [1] the change I was supposed to test?
>>>
>>> Not quite - dma-ranges is only valid for nodes representing a bus, so
>>> putting it directly in the USB device nodes doesn't work (FWIW that's
>>> why PCI is broken, because the parser doesn't expect the
>>> bus-as-leaf-node case). That's teh point of that intermediate simple-bus
>>> node represented by "periph_bus" in my example (sorry, I should have put
>>> compatibles in to make it clearer) - often that's actually true to life
>>> (i.e. "soc" is something like a CCI and "periph_bus" is something like
>>> an AXI NIC gluing a bunch of lower-bandwidth DMA masters to one of the
>>> CCI ports) but at worst it's just a necessary evil to make the binding
>>> happy (if it literally only represents the point-to-point link between
>>> the device master port and interconnect slave port).
>>>
>>
>> Quick update: so I adjusted to device tree according to your example and
>> it works so now I can get rid of that nasty kernel arg based workaround,
>> yey! :-)
>
> Cool! In fact, judging by the block diagrams on the website, the "basic
> peripherals and interconnect" section hanging off the side of the CCI
> implies that probably is true to the real topology as I imagined, so it
> doesn't even count as a horrible hack :)
Indeed, on this chip there's a NoC lumping behind it several low-speed
devices such as usb, sata, esdhc.
>> Thanks a lot, that was really helpful.
>
> No problem. FWIW if you ever come to doing ACPI support for these SoCs,
> the equivalent is merely a case of setting the device memory address
> size limit field appropriately for all the named components.
>
Thanks, I'll keep this in mind. If i remember correctly, there are
people over here working on UEFI + ACPI support for some LS chips but
progress appears to be slow.
---
Best Regards, Laurentiu
^ permalink raw reply
* [PATCH][next-next][v2] netlink: avoid to allocate full skb when sending to many devices
From: Li RongQing @ 2018-09-20 8:54 UTC (permalink / raw)
To: netdev
if skb->head is vmalloc address, when this skb is delivered, full
allocation for this skb is required, if there are many devices,
the full allocation will be called for every devices
now if it is vmalloc, allocate a new skb, whose data is not vmalloc
address, and use new allocated skb to clone and send, to avoid to
allocate full skb everytime.
Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
net/netlink/af_netlink.c | 37 ++++++++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 7 deletions(-)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e3a0538ec0be..a5b1bf706526 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -279,21 +279,25 @@ static bool netlink_filter_tap(const struct sk_buff *skb)
}
static int __netlink_deliver_tap_skb(struct sk_buff *skb,
- struct net_device *dev)
+ struct net_device *dev, bool alloc, bool last)
{
struct sk_buff *nskb;
struct sock *sk = skb->sk;
int ret = -ENOMEM;
- if (!net_eq(dev_net(dev), sock_net(sk)))
+ if (!net_eq(dev_net(dev), sock_net(sk))) {
+ if (last && alloc)
+ consume_skb(skb);
return 0;
+ }
dev_hold(dev);
- if (is_vmalloc_addr(skb->head))
- nskb = netlink_to_full_skb(skb, GFP_ATOMIC);
+ if (unlikely(last && alloc))
+ nskb = skb;
else
nskb = skb_clone(skb, GFP_ATOMIC);
+
if (nskb) {
nskb->dev = dev;
nskb->protocol = htons((u16) sk->sk_protocol);
@@ -303,6 +307,8 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
ret = dev_queue_xmit(nskb);
if (unlikely(ret > 0))
ret = net_xmit_errno(ret);
+ } else if (alloc) {
+ kfree_skb(skb);
}
dev_put(dev);
@@ -311,16 +317,33 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb,
static void __netlink_deliver_tap(struct sk_buff *skb, struct netlink_tap_net *nn)
{
+ struct netlink_tap *tmp, *next;
+ bool alloc = false;
int ret;
- struct netlink_tap *tmp;
if (!netlink_filter_tap(skb))
return;
- list_for_each_entry_rcu(tmp, &nn->netlink_tap_all, list) {
- ret = __netlink_deliver_tap_skb(skb, tmp->dev);
+ tmp = list_first_or_null_rcu(&nn->netlink_tap_all,
+ struct netlink_tap, list);
+ if (!tmp)
+ return;
+
+ if (is_vmalloc_addr(skb->head)) {
+ skb = netlink_to_full_skb(skb, GFP_ATOMIC);
+ if (!skb)
+ return;
+ alloc = true;
+ }
+
+ while (tmp) {
+ next = list_next_or_null_rcu(&nn->netlink_tap_all, &tmp->list,
+ struct netlink_tap, list);
+
+ ret = __netlink_deliver_tap_skb(skb, tmp->dev, alloc, !next);
if (unlikely(ret))
break;
+ tmp = next;
}
}
--
2.16.2
^ permalink raw reply related
* RE: [PATCH net-next 17/22] hv_netvsc: fix return type of ndo_start_xmit function
From: Haiyang Zhang @ 2018-09-20 14:40 UTC (permalink / raw)
To: YueHaibing, davem@davemloft.net, dmitry.tarnyagin@lockless.no,
wg@grandegger.com, mkl@pengutronix.de, michal.simek@xilinx.com,
hsweeten@visionengravers.com, madalin.bucur@nxp.com,
pantelis.antoniou@gmail.com, claudiu.manoil@nxp.com,
leoyang.li@nxp.com, linux@armlinux.org.uk, sammy@sammy.net,
ralf@linux-mips.org, nico@fluxnic.net,
steve.glendinning@shawell.net
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
linux-can@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linuxppc-dev@lists.ozlabs.org, linux-mips@linux-mips.org,
linux-omap@vger.kernel.org, linux-hams@vger.kernel.org,
devel@linuxdriverproject.org, linux-usb@vger.kernel.org,
xen-devel@lists.xenproject.org, dev@openvswitch.org
In-Reply-To: <20180920123306.14772-18-yuehaibing@huawei.com>
> -----Original Message-----
> From: YueHaibing <yuehaibing@huawei.com>
> Sent: Thursday, September 20, 2018 8:33 AM
> To: davem@davemloft.net; dmitry.tarnyagin@lockless.no;
> wg@grandegger.com; mkl@pengutronix.de; michal.simek@xilinx.com;
> hsweeten@visionengravers.com; madalin.bucur@nxp.com;
> pantelis.antoniou@gmail.com; claudiu.manoil@nxp.com; leoyang.li@nxp.com;
> linux@armlinux.org.uk; sammy@sammy.net; ralf@linux-mips.org;
> nico@fluxnic.net; steve.glendinning@shawell.net; f.fainelli@gmail.com;
> grygorii.strashko@ti.com; w-kwok2@ti.com; m-karicheri2@ti.com;
> t.sailer@alumni.ethz.ch; jreuter@yaina.de; KY Srinivasan <kys@microsoft.com>;
> Haiyang Zhang <haiyangz@microsoft.com>; wei.liu2@citrix.com;
> paul.durrant@citrix.com; arvid.brodin@alten.se; pshelar@ovn.org
> Cc: linux-kernel@vger.kernel.org; netdev@vger.kernel.org; linux-
> can@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linuxppc-
> dev@lists.ozlabs.org; linux-mips@linux-mips.org; linux-omap@vger.kernel.org;
> linux-hams@vger.kernel.org; devel@linuxdriverproject.org; linux-
> usb@vger.kernel.org; xen-devel@lists.xenproject.org; dev@openvswitch.org;
> YueHaibing <yuehaibing@huawei.com>
> Subject: [PATCH net-next 17/22] hv_netvsc: fix return type of ndo_start_xmit
> function
>
> The method ndo_start_xmit() is defined as returning an 'netdev_tx_t', which is
> a typedef for an enum type, so make sure the implementation in this driver has
> returns 'netdev_tx_t' value, and change the function return type to netdev_tx_t.
>
> Found by coccinelle.
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> drivers/net/hyperv/netvsc_drv.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
> index 3af6d8d..056c472 100644
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c
> @@ -511,7 +511,8 @@ static int netvsc_vf_xmit(struct net_device *net, struct
> net_device *vf_netdev,
> return rc;
> }
>
> -static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
> +static netdev_tx_t
> +netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
> {
> struct net_device_context *net_device_ctx = netdev_priv(net);
> struct hv_netvsc_packet *packet = NULL; @@ -528,8 +529,11 @@
> static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
> */
> vf_netdev = rcu_dereference_bh(net_device_ctx->vf_netdev);
> if (vf_netdev && netif_running(vf_netdev) &&
> - !netpoll_tx_running(net))
> - return netvsc_vf_xmit(net, vf_netdev, skb);
> + !netpoll_tx_running(net)) {
> + ret = netvsc_vf_xmit(net, vf_netdev, skb);
> + if (ret)
> + return NETDEV_TX_BUSY;
For error case, please just return NETDEV_TX_OK. We are not sure if the
error can go away after retrying, returning NETDEV_TX_BUSY may cause
infinite retry from the upper layer.
Thanks,
- Haiyang
^ permalink raw reply
* [PATCH net-next 0/5] vrf: allow simultaneous service instances in default and other VRFs
From: Mike Manning @ 2018-09-20 8:58 UTC (permalink / raw)
To: netdev
Services currently have to be VRF-aware if they are using an unbound
socket. One cannot have multiple service instances running in the
default and other VRFs for services that are not VRF-aware and listen
on an unbound socket. This is because there is no way of isolating
packets received in the default VRF from those arriving in other VRFs.
This series provides this isolation subject to the existing kernel
parameter net.ipv4.tcp_l3mdev_accept not being set, given that this is
documented as allowing a single service instance to work across all
VRF domains. The functionality applies to UDP & TCP services, for IPv4
and IPv6, in particular adding VRF table handling for IPv6 multicast.
Example of running ssh instances in default and blue VRF:
$ /usr/sbin/sshd -D
$ ip vrf exec vrf-blue /usr/sbin/sshd
$ ss -ta | egrep 'State|ssh'
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0%vrf-blue:ssh 0.0.0.0:*
LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:*
ESTAB 0 0 192.168.122.220:ssh 192.168.122.1:50282
LISTEN 0 128 [::]%vrf-blue:ssh [::]:*
LISTEN 0 128 [::]:ssh [::]:*
ESTAB 0 0 [3000::2]%vrf-blue:ssh [3000::9]:45896
ESTAB 0 0 [2000::2]:ssh [2000::9]:46398
Dewi Morgan (1):
ipv6: do not drop vrf udp multicast packets
Mike Manning (1):
ipv6: allow link-local and multicast packets inside vrf
Patrick Ruddy (1):
ipv6: add vrf table handling code for ipv6 mcast
Robert Shearman (2):
net: allow binding socket in a VRF when there's an unbound socket
ipv4: Allow sending multicast packets on specific i/f using VRF socket
Documentation/networking/vrf.txt | 9 ++++----
drivers/net/vrf.c | 30 ++++++++++++++++--------
include/net/inet6_hashtables.h | 5 ++--
include/net/inet_hashtables.h | 21 +++++++++++------
include/net/inet_sock.h | 13 +++++++++++
net/core/sock.c | 2 ++
net/ipv4/datagram.c | 2 +-
net/ipv4/inet_connection_sock.c | 13 ++++++++---
net/ipv4/inet_hashtables.c | 34 +++++++++++++++++-----------
net/ipv4/ip_sockglue.c | 3 +++
net/ipv4/ping.c | 2 +-
net/ipv4/raw.c | 6 ++---
net/ipv4/udp.c | 17 ++++++--------
net/ipv6/datagram.c | 5 +++-
net/ipv6/inet6_hashtables.c | 14 +++++-------
net/ipv6/ip6_input.c | 46 +++++++++++++++++++++++++++++++++----
net/ipv6/ip6mr.c | 49 ++++++++++++++++++++++++++++++----------
net/ipv6/ipv6_sockglue.c | 5 +++-
net/ipv6/raw.c | 6 ++---
net/ipv6/udp.c | 22 ++++++++----------
20 files changed, 208 insertions(+), 96 deletions(-)
--
2.11.0
^ permalink raw reply
* [PATCH net-next 3/5] ipv4: Allow sending multicast packets on specific i/f using VRF socket
From: Mike Manning @ 2018-09-20 8:58 UTC (permalink / raw)
To: netdev; +Cc: Robert Shearman
In-Reply-To: <20180920085848.17721-1-mmanning@vyatta.att-mail.com>
From: Robert Shearman <rshearma@vyatta.att-mail.com>
It is useful to be able to use the same socket for listening in a
specific VRF, as for sending multicast packets out of a specific
interface. However, the bound device on the socket currently takes
precedence and results in the packets not being sent.
Relax the condition on overriding the output interface to use for
sending packets out of UDP, raw and ping sockets to allow multicast
packets to be sent using the specified multicast interface.
Signed-off-by: Robert Shearman <rshearma@vyatta.att-mail.com>
Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
---
net/ipv4/datagram.c | 2 +-
net/ipv4/ping.c | 2 +-
net/ipv4/raw.c | 2 +-
net/ipv4/udp.c | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index f915abff1350..300921417f89 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -42,7 +42,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
oif = sk->sk_bound_dev_if;
saddr = inet->inet_saddr;
if (ipv4_is_multicast(usin->sin_addr.s_addr)) {
- if (!oif)
+ if (!oif || netif_index_is_l3_master(sock_net(sk), oif))
oif = inet->mc_index;
if (!saddr)
saddr = inet->mc_addr;
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 8d7aaf118a30..7ccb5f87f70b 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -779,7 +779,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
}
if (ipv4_is_multicast(daddr)) {
- if (!ipc.oif)
+ if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
ipc.oif = inet->mc_index;
if (!saddr)
saddr = inet->mc_addr;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 8a0d568d7aec..c55ef53d87a8 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -608,7 +608,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
tos |= RTO_ONLINK;
if (ipv4_is_multicast(daddr)) {
- if (!ipc.oif)
+ if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
ipc.oif = inet->mc_index;
if (!saddr)
saddr = inet->mc_addr;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 3d59ab47a85d..f81097843031 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1039,7 +1039,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
}
if (ipv4_is_multicast(daddr)) {
- if (!ipc.oif)
+ if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
ipc.oif = inet->mc_index;
if (!saddr)
saddr = inet->mc_addr;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 2/5] ipv6: allow link-local and multicast packets inside vrf
From: Mike Manning @ 2018-09-20 8:58 UTC (permalink / raw)
To: netdev
In-Reply-To: <20180920085848.17721-1-mmanning@vyatta.att-mail.com>
Packets that are multicast or to link-local addresses are not enslaved
to the vrf of the socket that they are received on. This is needed for
NDISC, but breaks applications that rely on receiving such packets when
in a VRF. Also to make IPv6 consistent with IPv4 which does handle
multicast packets as being enslaved, modify the VRF driver to do the
same for IPv6. As a result, the multicast address check needs to verify
the address against the enslaved rather than the l3mdev device.
Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
---
drivers/net/vrf.c | 19 +++++++++----------
net/ipv6/ip6_input.c | 19 ++++++++++++++++++-
net/ipv6/ipv6_sockglue.c | 2 +-
3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index f93547f257fb..9d817c19f3b4 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -981,24 +981,23 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
struct sk_buff *skb)
{
int orig_iif = skb->skb_iif;
- bool need_strict;
+ bool need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
+ bool is_ndisc = ipv6_ndisc_frame(skb);
- /* loopback traffic; do not push through packet taps again.
- * Reset pkt_type for upper layers to process skb
+ /* loopback, multicast & non-ND link-local traffic; do not push through
+ * packet taps again. Reset pkt_type for upper layers to process skb
*/
- if (skb->pkt_type == PACKET_LOOPBACK) {
+ if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) {
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
- skb->pkt_type = PACKET_HOST;
+ if (skb->pkt_type == PACKET_LOOPBACK)
+ skb->pkt_type = PACKET_HOST;
goto out;
}
- /* if packet is NDISC or addressed to multicast or link-local
- * then keep the ingress interface
- */
- need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
- if (!ipv6_ndisc_frame(skb) && !need_strict) {
+ /* if packet is NDISC then keep the ingress interface */
+ if (!is_ndisc) {
vrf_rx_stats(vrf_dev, skb->len);
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 96577e742afd..108f5f88ec98 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -432,15 +432,32 @@ EXPORT_SYMBOL_GPL(ip6_input);
int ip6_mc_input(struct sk_buff *skb)
{
+ int sdif = inet6_sdif(skb);
const struct ipv6hdr *hdr;
+ struct net_device *dev;
bool deliver;
__IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev),
__in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST,
skb->len);
+ /* skb->dev passed may be master dev for vrfs. */
+ if (sdif) {
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(dev_net(skb->dev), sdif);
+ if (!dev) {
+ rcu_read_unlock();
+ kfree_skb(skb);
+ return -ENODEV;
+ }
+ } else {
+ dev = skb->dev;
+ }
+
hdr = ipv6_hdr(skb);
- deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
+ deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr, NULL);
+ if (sdif)
+ rcu_read_unlock();
#ifdef CONFIG_IPV6_MROUTE
/*
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 7dfbc797b130..4ebd395dd3df 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -486,7 +486,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
retv = -EFAULT;
break;
}
- if (sk->sk_bound_dev_if && pkt.ipi6_ifindex != sk->sk_bound_dev_if)
+ if (!sk_dev_equal_l3scope(sk, pkt.ipi6_ifindex))
goto e_inval;
np->sticky_pktinfo.ipi6_ifindex = pkt.ipi6_ifindex;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 5/5] ipv6: add vrf table handling code for ipv6 mcast
From: Mike Manning @ 2018-09-20 8:58 UTC (permalink / raw)
To: netdev; +Cc: Patrick Ruddy
In-Reply-To: <20180920085848.17721-1-mmanning@vyatta.att-mail.com>
From: Patrick Ruddy <pruddy@vyatta.att-mail.com>
The code to obtain the correct table for the incoming interface was
missing for IPv6. This has been added along with the table creation
notification to fib rules for the RTNL_FAMILY_IP6MR address family.
Signed-off-by: Patrick Ruddy <pruddy@vyatta.att-mail.com>
Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
---
drivers/net/vrf.c | 11 +++++++++++
net/ipv6/ip6mr.c | 49 +++++++++++++++++++++++++++++++++++++------------
2 files changed, 48 insertions(+), 12 deletions(-)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 9d817c19f3b4..21ad4b1d7f03 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -1214,8 +1214,19 @@ static int vrf_add_fib_rules(const struct net_device *dev)
goto ipmr_err;
#endif
+#if IS_ENABLED(CONFIG_IPV6_MROUTE_MULTIPLE_TABLES)
+ err = vrf_fib_rule(dev, RTNL_FAMILY_IP6MR, true);
+ if (err < 0)
+ goto ip6mr_err;
+#endif
+
return 0;
+#if IS_ENABLED(CONFIG_IPV6_MROUTE_MULTIPLE_TABLES)
+ip6mr_err:
+ vrf_fib_rule(dev, RTNL_FAMILY_IPMR, false);
+#endif
+
#if IS_ENABLED(CONFIG_IP_MROUTE_MULTIPLE_TABLES)
ipmr_err:
vrf_fib_rule(dev, AF_INET6, false);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index d0b7e0249c13..1ecc88456dc5 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -85,7 +85,8 @@ static struct mr_table *ip6mr_new_table(struct net *net, u32 id);
static void ip6mr_free_table(struct mr_table *mrt);
static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
- struct sk_buff *skb, struct mfc6_cache *cache);
+ struct net_device *dev, struct sk_buff *skb,
+ struct mfc6_cache *cache);
static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
mifi_t mifi, int assert);
static void mr6_netlink_event(struct mr_table *mrt, struct mfc6_cache *mfc,
@@ -138,6 +139,9 @@ static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
.flags = FIB_LOOKUP_NOREF,
};
+ /* update flow if oif or iif point to device enslaved to l3mdev */
+ l3mdev_update_flow(net, flowi6_to_flowi(flp6));
+
err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
flowi6_to_flowi(flp6), 0, &arg);
if (err < 0)
@@ -164,7 +168,9 @@ static int ip6mr_rule_action(struct fib_rule *rule, struct flowi *flp,
return -EINVAL;
}
- mrt = ip6mr_get_table(rule->fr_net, rule->table);
+ arg->table = fib_rule_get_table(rule, arg);
+
+ mrt = ip6mr_get_table(rule->fr_net, arg->table);
if (!mrt)
return -EAGAIN;
res->mrt = mrt;
@@ -1014,7 +1020,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr_table *mrt,
}
rtnl_unicast(skb, net, NETLINK_CB(skb).portid);
} else
- ip6_mr_forward(net, mrt, skb, c);
+ ip6_mr_forward(net, mrt, skb->dev, skb, c);
}
}
@@ -1120,7 +1126,7 @@ static int ip6mr_cache_report(struct mr_table *mrt, struct sk_buff *pkt,
/* Queue a packet for resolution. It gets locked cache entry! */
static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
- struct sk_buff *skb)
+ struct sk_buff *skb, struct net_device *dev)
{
struct mfc6_cache *c;
bool found = false;
@@ -1180,6 +1186,10 @@ static int ip6mr_cache_unresolved(struct mr_table *mrt, mifi_t mifi,
kfree_skb(skb);
err = -ENOBUFS;
} else {
+ if (dev) {
+ skb->dev = dev;
+ skb->skb_iif = dev->ifindex;
+ }
skb_queue_tail(&c->_c.mfc_un.unres.unresolved, skb);
err = 0;
}
@@ -2043,11 +2053,12 @@ static int ip6mr_find_vif(struct mr_table *mrt, struct net_device *dev)
}
static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
- struct sk_buff *skb, struct mfc6_cache *c)
+ struct net_device *dev, struct sk_buff *skb,
+ struct mfc6_cache *c)
{
int psend = -1;
int vif, ct;
- int true_vifi = ip6mr_find_vif(mrt, skb->dev);
+ int true_vifi = ip6mr_find_vif(mrt, dev);
vif = c->_c.mfc_parent;
c->_c.mfc_un.res.pkt++;
@@ -2073,7 +2084,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
/*
* Wrong interface: drop packet and (maybe) send PIM assert.
*/
- if (mrt->vif_table[vif].dev != skb->dev) {
+ if (mrt->vif_table[vif].dev != dev) {
c->_c.mfc_un.res.wrong_if++;
if (true_vifi >= 0 && mrt->mroute_do_assert &&
@@ -2146,6 +2157,7 @@ static void ip6_mr_forward(struct net *net, struct mr_table *mrt,
int ip6_mr_input(struct sk_buff *skb)
{
+ struct rtable *rt = skb_rtable(skb);
struct mfc6_cache *cache;
struct net *net = dev_net(skb->dev);
struct mr_table *mrt;
@@ -2154,6 +2166,19 @@ int ip6_mr_input(struct sk_buff *skb)
.flowi6_mark = skb->mark,
};
int err;
+ struct net_device *dev;
+
+ /* skb->dev passed in is the master dev for vrfs.
+ * Get the proper interface that does have a vif associated with it.
+ */
+ dev = skb->dev;
+ if (netif_is_l3_master(skb->dev)) {
+ dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
+ if (!dev) {
+ kfree_skb(skb);
+ return -ENODEV;
+ }
+ }
err = ip6mr_fib_lookup(net, &fl6, &mrt);
if (err < 0) {
@@ -2165,7 +2190,7 @@ int ip6_mr_input(struct sk_buff *skb)
cache = ip6mr_cache_find(mrt,
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
if (!cache) {
- int vif = ip6mr_find_vif(mrt, skb->dev);
+ int vif = ip6mr_find_vif(mrt, dev);
if (vif >= 0)
cache = ip6mr_cache_find_any(mrt,
@@ -2179,9 +2204,9 @@ int ip6_mr_input(struct sk_buff *skb)
if (!cache) {
int vif;
- vif = ip6mr_find_vif(mrt, skb->dev);
+ vif = ip6mr_find_vif(mrt, dev);
if (vif >= 0) {
- int err = ip6mr_cache_unresolved(mrt, vif, skb);
+ int err = ip6mr_cache_unresolved(mrt, vif, skb, dev);
read_unlock(&mrt_lock);
return err;
@@ -2191,7 +2216,7 @@ int ip6_mr_input(struct sk_buff *skb)
return -ENODEV;
}
- ip6_mr_forward(net, mrt, skb, cache);
+ ip6_mr_forward(net, mrt, dev, skb, cache);
read_unlock(&mrt_lock);
@@ -2257,7 +2282,7 @@ int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm,
iph->saddr = rt->rt6i_src.addr;
iph->daddr = rt->rt6i_dst.addr;
- err = ip6mr_cache_unresolved(mrt, vif, skb2);
+ err = ip6mr_cache_unresolved(mrt, vif, skb2, dev);
read_unlock(&mrt_lock);
return err;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 4/5] ipv6: do not drop vrf udp multicast packets
From: Mike Manning @ 2018-09-20 8:58 UTC (permalink / raw)
To: netdev; +Cc: Dewi Morgan
In-Reply-To: <20180920085848.17721-1-mmanning@vyatta.att-mail.com>
From: Dewi Morgan <morgand@vyatta.att-mail.com>
For bound udp sockets in a vrf, also check the sdif to get the index
for ingress devices enslaved to an l3mdev. Verify the multicast address
against the enslaved rather than the l3mdev device.
Signed-off-by: Dewi Morgan <morgand@vyatta.att-mail.com>
Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
---
net/ipv6/ip6_input.c | 27 ++++++++++++++++++++++++---
net/ipv6/udp.c | 8 +++++---
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 108f5f88ec98..fc60f297d95b 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -325,9 +325,12 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
{
const struct inet6_protocol *ipprot;
struct inet6_dev *idev;
+ struct net_device *dev;
unsigned int nhoff;
+ int sdif = inet6_sdif(skb);
int nexthdr;
bool raw;
+ bool deliver;
bool have_final = false;
/*
@@ -371,9 +374,27 @@ static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *sk
skb_postpull_rcsum(skb, skb_network_header(skb),
skb_network_header_len(skb));
hdr = ipv6_hdr(skb);
- if (ipv6_addr_is_multicast(&hdr->daddr) &&
- !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
- &hdr->saddr) &&
+
+ /* skb->dev passed may be master dev for vrfs. */
+ if (sdif) {
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(dev_net(skb->dev),
+ sdif);
+ if (!dev) {
+ rcu_read_unlock();
+ kfree_skb(skb);
+ return -ENODEV;
+ }
+ } else {
+ dev = skb->dev;
+ }
+
+ deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr,
+ &hdr->saddr);
+ if (sdif)
+ rcu_read_unlock();
+
+ if (ipv6_addr_is_multicast(&hdr->daddr) && !deliver &&
!ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
goto discard;
}
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e22b7dd78c9b..35f71b7a1070 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -637,7 +637,7 @@ static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
__be16 loc_port, const struct in6_addr *loc_addr,
__be16 rmt_port, const struct in6_addr *rmt_addr,
- int dif, unsigned short hnum)
+ int dif, int sdif, unsigned short hnum)
{
struct inet_sock *inet = inet_sk(sk);
@@ -649,7 +649,7 @@ static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
(inet->inet_dport && inet->inet_dport != rmt_port) ||
(!ipv6_addr_any(&sk->sk_v6_daddr) &&
!ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) ||
- (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) ||
+ !inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif) ||
(!ipv6_addr_any(&sk->sk_v6_rcv_saddr) &&
!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)))
return false;
@@ -683,6 +683,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
unsigned int offset = offsetof(typeof(*sk), sk_node);
unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
int dif = inet6_iif(skb);
+ int sdif = inet6_sdif(skb);
struct hlist_node *node;
struct sk_buff *nskb;
@@ -697,7 +698,8 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) {
if (!__udp_v6_is_mcast_sock(net, sk, uh->dest, daddr,
- uh->source, saddr, dif, hnum))
+ uh->source, saddr, dif, sdif,
+ hnum))
continue;
/* If zero checksum and no_check is not on for
* the socket then skip it.
--
2.11.0
^ permalink raw reply related
* [PATCH net-next 1/5] net: allow binding socket in a VRF when there's an unbound socket
From: Mike Manning @ 2018-09-20 8:58 UTC (permalink / raw)
To: netdev; +Cc: Robert Shearman
In-Reply-To: <20180920085848.17721-1-mmanning@vyatta.att-mail.com>
From: Robert Shearman <rshearma@vyatta.att-mail.com>
There is no easy way currently for applications that want to receive
packets in the default VRF to be isolated from packets arriving in
VRFs, which makes using VRF-unaware applications in a VRF-aware system
a potential security risk.
So change the inet socket lookup to avoid packets arriving on a device
enslaved to an l3mdev from matching unbound sockets by removing the
wildcard for non sk_bound_dev_if and instead relying on check against
the secondary device index, which will be 0 when the input device is
not enslaved to an l3mdev and so match against an unbound socket and
not match when the input device is enslaved.
The existing net.ipv4.tcp_l3mdev_accept & net.ipv4.udp_l3mdev_accept
sysctls, which are documented as allowing the working across all VRF
domains, can be used to also work in the default VRF by causing
unbound sockets to match against packets arriving on a device
enslaved to an l3mdev.
Change the socket binding to take the l3mdev into account to allow an
unbound socket to not conflict sockets bound to an l3mdev given the
datapath isolation now guaranteed.
Signed-off-by: Robert Shearman <rshearma@vyatta.att-mail.com>
Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
---
Documentation/networking/vrf.txt | 9 +++++----
include/net/inet6_hashtables.h | 5 ++---
include/net/inet_hashtables.h | 21 ++++++++++++++-------
include/net/inet_sock.h | 13 +++++++++++++
net/core/sock.c | 2 ++
net/ipv4/inet_connection_sock.c | 13 ++++++++++---
net/ipv4/inet_hashtables.c | 34 +++++++++++++++++++++-------------
net/ipv4/ip_sockglue.c | 3 +++
net/ipv4/raw.c | 4 ++--
net/ipv4/udp.c | 15 ++++++---------
net/ipv6/datagram.c | 5 ++++-
net/ipv6/inet6_hashtables.c | 14 ++++++--------
net/ipv6/ipv6_sockglue.c | 3 +++
net/ipv6/raw.c | 6 +++---
net/ipv6/udp.c | 14 +++++---------
15 files changed, 99 insertions(+), 62 deletions(-)
diff --git a/Documentation/networking/vrf.txt b/Documentation/networking/vrf.txt
index 8ff7b4c8f91b..d4b129402d57 100644
--- a/Documentation/networking/vrf.txt
+++ b/Documentation/networking/vrf.txt
@@ -103,6 +103,11 @@ VRF device:
or to specify the output device using cmsg and IP_PKTINFO.
+By default the scope of the port bindings for unbound sockets is
+limited to the default VRF. That is, it will not be matched by packets
+arriving on interfaces enslaved to an l3mdev and processes may bind to
+the same port if they bind to an l3mdev.
+
TCP & UDP services running in the default VRF context (ie., not bound
to any VRF device) can work across all VRF domains by enabling the
tcp_l3mdev_accept and udp_l3mdev_accept sysctl options:
@@ -112,10 +117,6 @@ tcp_l3mdev_accept and udp_l3mdev_accept sysctl options:
netfilter rules on the VRF device can be used to limit access to services
running in the default VRF context as well.
-The default VRF does not have limited scope with respect to port bindings.
-That is, if a process does a wildcard bind to a port in the default VRF it
-owns the port across all VRF domains within the network namespace.
-
################################################################################
Using iproute2 for VRFs
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 6e91e38a31da..9db98af46985 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -115,9 +115,8 @@ int inet6_hash(struct sock *sk);
((__sk)->sk_family == AF_INET6) && \
ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \
ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \
- (!(__sk)->sk_bound_dev_if || \
- ((__sk)->sk_bound_dev_if == (__dif)) || \
- ((__sk)->sk_bound_dev_if == (__sdif))) && \
+ (((__sk)->sk_bound_dev_if == (__dif)) || \
+ ((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 9141e95529e7..ec279bcd0958 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -79,6 +79,7 @@ struct inet_ehash_bucket {
struct inet_bind_bucket {
possible_net_t ib_net;
+ int l3mdev;
unsigned short port;
signed char fastreuse;
signed char fastreuseport;
@@ -188,10 +189,18 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
hashinfo->ehash_locks = NULL;
}
+static inline bool inet_sk_bound_dev_eq(struct net *net, int bound_dev_if,
+ int dif, int sdif)
+{
+ if (!bound_dev_if)
+ return !sdif || net->ipv4.sysctl_tcp_l3mdev_accept;
+ return bound_dev_if == dif || bound_dev_if == sdif;
+}
+
struct inet_bind_bucket *
inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
struct inet_bind_hashbucket *head,
- const unsigned short snum);
+ const unsigned short snum, int l3mdev);
void inet_bind_bucket_destroy(struct kmem_cache *cachep,
struct inet_bind_bucket *tb);
@@ -282,9 +291,8 @@ static inline struct sock *inet_lookup_listener(struct net *net,
#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_addrpair == (__cookie)) && \
- (!(__sk)->sk_bound_dev_if || \
- ((__sk)->sk_bound_dev_if == (__dif)) || \
- ((__sk)->sk_bound_dev_if == (__sdif))) && \
+ (((__sk)->sk_bound_dev_if == (__dif)) || \
+ ((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#else /* 32-bit arch */
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
@@ -294,9 +302,8 @@ static inline struct sock *inet_lookup_listener(struct net *net,
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_daddr == (__saddr)) && \
((__sk)->sk_rcv_saddr == (__daddr)) && \
- (!(__sk)->sk_bound_dev_if || \
- ((__sk)->sk_bound_dev_if == (__dif)) || \
- ((__sk)->sk_bound_dev_if == (__sdif))) && \
+ (((__sk)->sk_bound_dev_if == (__dif)) || \
+ ((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#endif /* 64-bit arch */
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index e03b93360f33..92e0aa3958f6 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -130,6 +130,19 @@ static inline int inet_request_bound_dev_if(const struct sock *sk,
return sk->sk_bound_dev_if;
}
+static inline int inet_sk_bound_l3mdev(const struct sock *sk)
+{
+#ifdef CONFIG_NET_L3_MASTER_DEV
+ struct net *net = sock_net(sk);
+
+ if (!net->ipv4.sysctl_tcp_l3mdev_accept)
+ return l3mdev_master_ifindex_by_index(net,
+ sk->sk_bound_dev_if);
+#endif
+
+ return 0;
+}
+
static inline struct ip_options_rcu *ireq_opt_deref(const struct inet_request_sock *ireq)
{
return rcu_dereference_check(ireq->ireq_opt,
diff --git a/net/core/sock.c b/net/core/sock.c
index 3730eb855095..da1cbb88a6bf 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -567,6 +567,8 @@ static int sock_setbindtodevice(struct sock *sk, char __user *optval,
lock_sock(sk);
sk->sk_bound_dev_if = index;
+ if (sk->sk_prot->rehash)
+ sk->sk_prot->rehash(sk);
sk_dst_reset(sk);
release_sock(sk);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index dfd5009f96ef..97bba5b3d69f 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -183,7 +183,9 @@ inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *
int i, low, high, attempt_half;
struct inet_bind_bucket *tb;
u32 remaining, offset;
+ int l3mdev;
+ l3mdev = inet_sk_bound_l3mdev(sk);
attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0;
other_half_scan:
inet_get_local_port_range(net, &low, &high);
@@ -219,7 +221,8 @@ inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *
hinfo->bhash_size)];
spin_lock_bh(&head->lock);
inet_bind_bucket_for_each(tb, &head->chain)
- if (net_eq(ib_net(tb), net) && tb->port == port) {
+ if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
+ tb->port == port) {
if (!inet_csk_bind_conflict(sk, tb, false, false))
goto success;
goto next_port;
@@ -293,6 +296,9 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
struct net *net = sock_net(sk);
struct inet_bind_bucket *tb = NULL;
kuid_t uid = sock_i_uid(sk);
+ int l3mdev;
+
+ l3mdev = inet_sk_bound_l3mdev(sk);
if (!port) {
head = inet_csk_find_open_port(sk, &tb, &port);
@@ -306,11 +312,12 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
hinfo->bhash_size)];
spin_lock_bh(&head->lock);
inet_bind_bucket_for_each(tb, &head->chain)
- if (net_eq(ib_net(tb), net) && tb->port == port)
+ if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
+ tb->port == port)
goto tb_found;
tb_not_found:
tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
- net, head, port);
+ net, head, port, l3mdev);
if (!tb)
goto fail_unlock;
tb_found:
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index f5c9ef2586de..2ec684057ebd 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -65,12 +65,14 @@ static u32 sk_ehashfn(const struct sock *sk)
struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
struct net *net,
struct inet_bind_hashbucket *head,
- const unsigned short snum)
+ const unsigned short snum,
+ int l3mdev)
{
struct inet_bind_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
if (tb) {
write_pnet(&tb->ib_net, net);
+ tb->l3mdev = l3mdev;
tb->port = snum;
tb->fastreuse = 0;
tb->fastreuseport = 0;
@@ -135,6 +137,7 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
table->bhash_size);
struct inet_bind_hashbucket *head = &table->bhash[bhash];
struct inet_bind_bucket *tb;
+ int l3mdev;
spin_lock(&head->lock);
tb = inet_csk(sk)->icsk_bind_hash;
@@ -143,6 +146,8 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
return -ENOENT;
}
if (tb->port != port) {
+ l3mdev = inet_sk_bound_l3mdev(sk);
+
/* NOTE: using tproxy and redirecting skbs to a proxy
* on a different listener port breaks the assumption
* that the listener socket's icsk_bind_hash is the same
@@ -150,12 +155,13 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
* create a new bind bucket for the child here. */
inet_bind_bucket_for_each(tb, &head->chain) {
if (net_eq(ib_net(tb), sock_net(sk)) &&
- tb->port == port)
+ tb->l3mdev == l3mdev && tb->port == port)
break;
}
if (!tb) {
tb = inet_bind_bucket_create(table->bind_bucket_cachep,
- sock_net(sk), head, port);
+ sock_net(sk), head, port,
+ l3mdev);
if (!tb) {
spin_unlock(&head->lock);
return -ENOMEM;
@@ -229,6 +235,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
{
int score = -1;
struct inet_sock *inet = inet_sk(sk);
+ bool dev_match;
if (net_eq(sock_net(sk), net) && inet->inet_num == hnum &&
!ipv6_only_sock(sk)) {
@@ -239,15 +246,12 @@ static inline int compute_score(struct sock *sk, struct net *net,
return -1;
score += 4;
}
- if (sk->sk_bound_dev_if || exact_dif) {
- bool dev_match = (sk->sk_bound_dev_if == dif ||
- sk->sk_bound_dev_if == sdif);
+ dev_match = inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
+ dif, sdif);
+ if (!dev_match)
+ return -1;
+ score += 4;
- if (!dev_match)
- return -1;
- if (sk->sk_bound_dev_if)
- score += 4;
- }
if (sk->sk_incoming_cpu == raw_smp_processor_id())
score++;
}
@@ -675,6 +679,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
u32 remaining, offset;
int ret, i, low, high;
static u32 hint;
+ int l3mdev;
if (port) {
head = &hinfo->bhash[inet_bhashfn(net, port,
@@ -693,6 +698,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
return ret;
}
+ l3mdev = inet_sk_bound_l3mdev(sk);
+
inet_get_local_port_range(net, &low, &high);
high++; /* [32768, 60999] -> [32768, 61000[ */
remaining = high - low;
@@ -719,7 +726,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
* the established check is already unique enough.
*/
inet_bind_bucket_for_each(tb, &head->chain) {
- if (net_eq(ib_net(tb), net) && tb->port == port) {
+ if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
+ tb->port == port) {
if (tb->fastreuse >= 0 ||
tb->fastreuseport >= 0)
goto next_port;
@@ -732,7 +740,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
}
tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
- net, head, port);
+ net, head, port, l3mdev);
if (!tb) {
spin_unlock_bh(&head->lock);
return -ENOMEM;
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index c0fe5ad996f2..026971314c43 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -892,6 +892,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
dev_put(dev);
err = -EINVAL;
+ if (!sk->sk_bound_dev_if && midx)
+ break;
+
if (sk->sk_bound_dev_if &&
mreq.imr_ifindex != sk->sk_bound_dev_if &&
(!midx || midx != sk->sk_bound_dev_if))
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 33df4d76db2d..8a0d568d7aec 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -70,6 +70,7 @@
#include <net/snmp.h>
#include <net/tcp_states.h>
#include <net/inet_common.h>
+#include <net/inet_hashtables.h>
#include <net/checksum.h>
#include <net/xfrm.h>
#include <linux/rtnetlink.h>
@@ -131,8 +132,7 @@ struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
if (net_eq(sock_net(sk), net) && inet->inet_num == num &&
!(inet->inet_daddr && inet->inet_daddr != raddr) &&
!(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
- !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif &&
- sk->sk_bound_dev_if != sdif))
+ inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif))
goto found; /* gotcha */
}
sk = NULL;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index f4e35b2ff8b8..3d59ab47a85d 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -371,6 +371,7 @@ static int compute_score(struct sock *sk, struct net *net,
{
int score;
struct inet_sock *inet;
+ bool dev_match;
if (!net_eq(sock_net(sk), net) ||
udp_sk(sk)->udp_port_hash != hnum ||
@@ -398,15 +399,11 @@ static int compute_score(struct sock *sk, struct net *net,
score += 4;
}
- if (sk->sk_bound_dev_if || exact_dif) {
- bool dev_match = (sk->sk_bound_dev_if == dif ||
- sk->sk_bound_dev_if == sdif);
-
- if (!dev_match)
- return -1;
- if (sk->sk_bound_dev_if)
- score += 4;
- }
+ dev_match = inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
+ dif, sdif);
+ if (!dev_match)
+ return -1;
+ score += 4;
if (sk->sk_incoming_cpu == raw_smp_processor_id())
score++;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 1ede7a16a0be..4813293d4fad 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -782,7 +782,10 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
if (src_info->ipi6_ifindex) {
if (fl6->flowi6_oif &&
- src_info->ipi6_ifindex != fl6->flowi6_oif)
+ src_info->ipi6_ifindex != fl6->flowi6_oif &&
+ (sk->sk_bound_dev_if != fl6->flowi6_oif ||
+ !sk_dev_equal_l3scope(
+ sk, src_info->ipi6_ifindex)))
return -EINVAL;
fl6->flowi6_oif = src_info->ipi6_ifindex;
}
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 3d7c7460a0c5..5eeeba7181a1 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -99,6 +99,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
const int dif, const int sdif, bool exact_dif)
{
int score = -1;
+ bool dev_match;
if (net_eq(sock_net(sk), net) && inet_sk(sk)->inet_num == hnum &&
sk->sk_family == PF_INET6) {
@@ -109,15 +110,12 @@ static inline int compute_score(struct sock *sk, struct net *net,
return -1;
score++;
}
- if (sk->sk_bound_dev_if || exact_dif) {
- bool dev_match = (sk->sk_bound_dev_if == dif ||
- sk->sk_bound_dev_if == sdif);
+ dev_match = inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
+ dif, sdif);
+ if (!dev_match)
+ return -1;
+ score++;
- if (!dev_match)
- return -1;
- if (sk->sk_bound_dev_if)
- score++;
- }
if (sk->sk_incoming_cpu == raw_smp_processor_id())
score++;
}
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index c0cac9cc3a28..7dfbc797b130 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -626,6 +626,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
rcu_read_unlock();
+ if (!sk->sk_bound_dev_if && midx)
+ goto e_inval;
+
if (sk->sk_bound_dev_if &&
sk->sk_bound_dev_if != val &&
(!midx || midx != sk->sk_bound_dev_if))
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 413d98bf24f4..2f61a9f1a2b2 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,6 +49,7 @@
#include <net/transp_v6.h>
#include <net/udp.h>
#include <net/inet_common.h>
+#include <net/inet_hashtables.h>
#include <net/tcp_states.h>
#if IS_ENABLED(CONFIG_IPV6_MIP6)
#include <net/mip6.h>
@@ -86,9 +87,8 @@ struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
!ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
continue;
- if (sk->sk_bound_dev_if &&
- sk->sk_bound_dev_if != dif &&
- sk->sk_bound_dev_if != sdif)
+ if (!inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
+ dif, sdif))
continue;
if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 83f4c77c79d8..e22b7dd78c9b 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -117,6 +117,7 @@ static int compute_score(struct sock *sk, struct net *net,
{
int score;
struct inet_sock *inet;
+ bool dev_match;
if (!net_eq(sock_net(sk), net) ||
udp_sk(sk)->udp_port_hash != hnum ||
@@ -144,15 +145,10 @@ static int compute_score(struct sock *sk, struct net *net,
score++;
}
- if (sk->sk_bound_dev_if || exact_dif) {
- bool dev_match = (sk->sk_bound_dev_if == dif ||
- sk->sk_bound_dev_if == sdif);
-
- if (!dev_match)
- return -1;
- if (sk->sk_bound_dev_if)
- score++;
- }
+ dev_match = inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif);
+ if (!dev_match)
+ return -1;
+ score++;
if (sk->sk_incoming_cpu == raw_smp_processor_id())
score++;
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net-next 17/22] hv_netvsc: fix return type of ndo_start_xmit function
From: Stephen Hemminger @ 2018-09-20 14:43 UTC (permalink / raw)
To: YueHaibing
Cc: dmitry.tarnyagin, madalin.bucur, linux-mips, linux,
pantelis.antoniou, t.sailer, dev, f.fainelli, arvid.brodin,
michal.simek, pshelar, m-karicheri2, xen-devel, jreuter, sammy,
grygorii.strashko, w-kwok2, haiyangz, steve.glendinning,
linux-can, claudiu.manoil, paul.durrant, mkl, linux-hams,
linux-omap, linux-arm-kernel, wei.liu2, nico, netdev, linux-usb,
linux-kernel, ralf, leoyang.li, wg, devel, linuxppc-dev, da
In-Reply-To: <20180920123306.14772-18-yuehaibing@huawei.com>
On Thu, 20 Sep 2018 20:33:01 +0800
YueHaibing <yuehaibing@huawei.com> wrote:
> The method ndo_start_xmit() is defined as returning an 'netdev_tx_t',
> which is a typedef for an enum type, so make sure the implementation in
> this driver has returns 'netdev_tx_t' value, and change the function
> return type to netdev_tx_t.
>
> Found by coccinelle.
>
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
> drivers/net/hyperv/netvsc_drv.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
> index 3af6d8d..056c472 100644
> --- a/drivers/net/hyperv/netvsc_drv.c
> +++ b/drivers/net/hyperv/netvsc_drv.c
> @@ -511,7 +511,8 @@ static int netvsc_vf_xmit(struct net_device *net, struct net_device *vf_netdev,
> return rc;
> }
>
> -static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
> +static netdev_tx_t
> +netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
> {
> struct net_device_context *net_device_ctx = netdev_priv(net);
> struct hv_netvsc_packet *packet = NULL;
> @@ -528,8 +529,11 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
> */
> vf_netdev = rcu_dereference_bh(net_device_ctx->vf_netdev);
> if (vf_netdev && netif_running(vf_netdev) &&
> - !netpoll_tx_running(net))
> - return netvsc_vf_xmit(net, vf_netdev, skb);
> + !netpoll_tx_running(net)) {
> + ret = netvsc_vf_xmit(net, vf_netdev, skb);
> + if (ret)
> + return NETDEV_TX_BUSY;
> + }
Sorry, the new code is wrong. It will fall through if ret == 0 (NETDEV_TX_OK)
Please review and test your patches.
^ 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