* Re: [PATCH v2] net: amd-xgbe: Get rid of custom hex_dump_to_buffer()
From: David Miller @ 2017-12-20 18:05 UTC (permalink / raw)
To: andriy.shevchenko; +Cc: thomas.lendacky, netdev
In-Reply-To: <20171219212215.11561-1-andriy.shevchenko@linux.intel.com>
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Tue, 19 Dec 2017 23:22:15 +0200
> Get rid of yet another custom hex_dump_to_buffer().
>
> The output is slightly changed, i.e. each byte followed by white space.
>
> Note, we don't use print_hex_dump() here since the original code uses
> nedev_dbg().
>
> Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Applied to net-next.
^ permalink raw reply
* Re: RCU callback crashes
From: John Fastabend @ 2017-12-20 18:04 UTC (permalink / raw)
To: Jakub Kicinski, Jiri Pirko; +Cc: netdev@vger.kernel.org, Cong Wang
In-Reply-To: <20171219223404.03786d66@cakuba.netronome.com>
On 12/19/2017 10:34 PM, Jakub Kicinski wrote:
> On Tue, 19 Dec 2017 22:22:27 -0800, Jakub Kicinski wrote:
>>>> I get this:
>>>
>>> Could you try to run it with kasan on?
>>
>> I didn't manage to reproduce it with KASAN on so far :( Even enabling
>> object debugging to get the second splat in my email (which is more
>> useful) actually makes the crash go away, I only see the warning...
>
> Ah, no object debug but KASAN on produces this:
>
@Jakub, This is with mq and pfifo_fast I guess?
> [ 39.268209] BUG: KASAN: use-after-free in cpu_needs_another_gp+0x246/0x2b0
> [ 39.275965] Read of size 8 at addr ffff8803aa64f138 by task swapper/13/0
> [ 39.283524]
> [ 39.285256] CPU: 13 PID: 0 Comm: swapper/13 Not tainted 4.15.0-rc3-perf-00955-g1d0b01347dd5-dirty #8
> [ 39.295535] Hardware name: Dell Inc. PowerEdge R730/072T6D, BIOS 2.3.4 11/08/2016
> [ 39.303969] Call Trace:
> [ 39.306769] <IRQ>
> [ 39.309088] dump_stack+0xa6/0x118
> [ 39.312957] ? _atomic_dec_and_lock+0xe8/0xe8
> [ 39.317895] ? cpu_needs_another_gp+0x246/0x2b0
> [ 39.323030] print_address_description+0x6a/0x270
> [ 39.328380] ? cpu_needs_another_gp+0x246/0x2b0
> [ 39.333510] kasan_report+0x23f/0x350
> [ 39.337672] cpu_needs_another_gp+0x246/0x2b0
> ...
> [ 39.383026] rcu_process_callbacks+0x1a0/0x620
> ...
> [ 39.426713] __do_softirq+0x17f/0x4de
> ...
> [ 39.463841] irq_exit+0xe1/0xf0
> [ 39.467437] smp_apic_timer_interrupt+0xd9/0x290
> [ 39.472685] ? smp_call_function_single_interrupt+0x230/0x230
> [ 39.479195] ? smp_reschedule_interrupt+0x240/0x240
> [ 39.484736] apic_timer_interrupt+0x8c/0xa0
> [ 39.489497] </IRQ>
> [ 39.491929] RIP: 0010:cpuidle_enter_state+0x12a/0x510
> [ 39.497660] RSP: 0018:ffff88086bf9fd08 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff11
> [ 39.506228] RAX: 0000000000000000 RBX: ffffe8ffffb060e0 RCX: ffffffff921329f5
> [ 39.514291] RDX: dffffc0000000000 RSI: dffffc0000000000 RDI: ffff88086f3246e8
> [ 39.522354] RBP: 1ffff1010d7f3fa6 R08: fffffbfff2742768 R09: fffffbfff2742768
> [ 39.530418] R10: ffff88086bf9fcc8 R11: fffffbfff2742767 R12: 0000000924148b4b
> [ 39.538480] R13: 0000000000000004 R14: 0000000000000004 R15: ffffffff9383eb80
> [ 39.546545] ? sched_idle_set_state+0x25/0x30
> [ 39.551502] ? cpuidle_enter_state+0x106/0x510
> [ 39.556556] ? cpuidle_enter_s2idle+0x130/0x130
> [ 39.561706] ? rcu_eqs_enter_common.constprop.62+0xd1/0x1e0
> [ 39.568037] ? rcu_gp_init+0xf70/0xf70
> [ 39.572331] ? sched_set_stop_task+0x160/0x160
> [ 39.577384] do_idle+0x1af/0x200
> [ 39.581076] cpu_startup_entry+0xd2/0xe0
> [ 39.585545] ? cpu_in_idle+0x20/0x20
> [ 39.589626] ? _raw_spin_trylock+0xe0/0xe0
> [ 39.594292] ? memcpy+0x34/0x50
> [ 39.597890] start_secondary+0x271/0x2b0
> [ 39.602361] ? set_cpu_sibling_map+0x840/0x840
> [ 39.607416] secondary_startup_64+0xa5/0xb0
> [ 39.612180]
> [ 39.613929] Allocated by task 1358:
> [ 39.617914] __kmalloc_node+0x183/0x2c0
> [ 39.622290] qdisc_alloc+0xbd/0x3f0
> [ 39.626274] qdisc_create+0xd8/0x720
> [ 39.630355] tc_modify_qdisc+0x657/0x910
> [ 39.634826] rtnetlink_rcv_msg+0x37c/0x7e0
> [ 39.639491] netlink_rcv_skb+0x122/0x230
> [ 39.643960] netlink_unicast+0x2ae/0x360
> [ 39.648443] netlink_sendmsg+0x5d5/0x620
> [ 39.652915] sock_sendmsg+0x64/0x80
> [ 39.656900] ___sys_sendmsg+0x4a8/0x500
> [ 39.661272] __sys_sendmsg+0xa9/0x140
> [ 39.665450] entry_SYSCALL_64_fastpath+0x1e/0x81
> [ 39.670695]
> [ 39.672441] Freed by task 1370:
> [ 39.676052] kfree+0x8d/0x1c0
> [ 39.679454] qdisc_graft+0x208/0x670
> [ 39.683535] tc_get_qdisc+0x229/0x350
> [ 39.687713] rtnetlink_rcv_msg+0x37c/0x7e0
> [ 39.692411] netlink_rcv_skb+0x122/0x230
> [ 39.696881] netlink_unicast+0x2ae/0x360
> [ 39.701350] netlink_sendmsg+0x5d5/0x620
> [ 39.705819] sock_sendmsg+0x64/0x80
> [ 39.709801] ___sys_sendmsg+0x4a8/0x500
> [ 39.714172] __sys_sendmsg+0xa9/0x140
> [ 39.718351] entry_SYSCALL_64_fastpath+0x1e/0x81
> [ 39.723597]
> [ 39.725347] The buggy address belongs to the object at ffff8803aa64ef80
> [ 39.725347] which belongs to the cache kmalloc-512 of size 512
> [ 39.739453] The buggy address is located 440 bytes inside of
> [ 39.739453] 512-byte region [ffff8803aa64ef80, ffff8803aa64f180)
> [ 39.752684] The buggy address belongs to the page:
> [ 39.758127] page:0000000042b3124b count:1 mapcount:0 mapping: (null) index:0x0 compound_mapcount: 0
> [ 39.769222] flags: 0x2ffff0000008100(slab|head)
> [ 39.774365] raw: 02ffff0000008100 0000000000000000 0000000000000000 0000000180190019
> [ 39.783129] raw: dead000000000100 dead000000000200 ffff8803afc0ed80 0000000000000000
> [ 39.791986] page dumped because: kasan: bad access detected
> [ 39.798300]
> [ 39.800063] Memory state around the buggy address:
> [ 39.805503] ffff8803aa64f000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [ 39.813684] ffff8803aa64f080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [ 39.821866] >ffff8803aa64f100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [ 39.830045] ^
> [ 39.835778] ffff8803aa64f180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 39.843958] ffff8803aa64f200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>
So with lockless qdisc support we really do need to wait a
RCU grace period before free'ing the qdisc. I missed this initially
in the lockless qdisc set but we need to revert this,
commit 752fbcc33405d6f8249465e4b2c4e420091bb825
Author: Cong Wang <xiyou.wangcong@gmail.com>
Date: Tue Sep 19 13:15:42 2017 -0700
net_sched: no need to free qdisc in RCU callback
gen estimator has been rewritten in commit 1c0d32fde5bd
("net_sched: gen_estimator: complete rewrite of rate estimators"),
the caller no longer needs to wait for a grace period. So this
patch gets rid of it.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Thanks,
John
^ permalink raw reply
* Re: [PATCH net-next] net: Clarify dev_weight documentation for LRO and GRO_HW.
From: David Miller @ 2017-12-20 18:04 UTC (permalink / raw)
To: michael.chan; +Cc: netdev
In-Reply-To: <1513717976-24263-1-git-send-email-michael.chan@broadcom.com>
From: Michael Chan <michael.chan@broadcom.com>
Date: Tue, 19 Dec 2017 16:12:56 -0500
> Reported-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Applied, thanks a lot.
^ permalink raw reply
* Re: [PATCH net V2] net: always reevalulate autoflowlabel setting for reset packet
From: David Miller @ 2017-12-20 18:03 UTC (permalink / raw)
To: shli; +Cc: netdev, Kernel-team, shli, kafai
In-Reply-To: <b44762a8392137c6008e2f7490cbd0853f0015ac.1513716787.git.shli@fb.com>
From: Shaohua Li <shli@kernel.org>
Date: Tue, 19 Dec 2017 12:58:21 -0800
> From: Shaohua Li <shli@fb.com>
>
> ipv6_pinfo.autoflowlabel is set in sock creation. Later if we change
> sysctl.ip6.auto_flowlabels, the ipv6_pinfo.autoflowlabel isn't changed,
> so the sock will keep the old behavior in terms of auto flowlabel. Reset
> packet is suffering from this problem, because reset packset is sent
> from a special control socket, which is created at boot time. Since
> sysctl.ipv6.auto_flowlabels is 2 by default, the control socket will
> always have its ipv6_pinfo.autoflowlabel set, even after user set
> sysctl.ipv6.auto_flowlabels to 1, so reset packset will always have
> flowlabel.
>
> To fix this, we always reevaluate autoflowlabel setting for reset
> packet. Normal sock has the same issue too, but since the
> sysctl.ipv6.auto_flowlabels is usually set at host startup, this isn't a
> big issue for normal sock.
>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Signed-off-by: Shaohua Li <shli@fb.com>
This definitely goes into the category of hack.
Special casing resets is not the answer.
What about normal user sockets openned before the sysctl setting is
modified?
No user is going to be happy about this nice little surprise.
What you're saying is that we should specially treat the kernel
sockets that emit resets, in response to this sysctl setting being
modified.
But that is not what you are doing. You are treating all sockets
in the system in this way, and only for reset packets. That's
really terrible.
^ permalink raw reply
* Re: [for-next 07/11] net/mlx5: E-Switch, Create generic header struct to be used by representors
From: David Miller @ 2017-12-20 17:58 UTC (permalink / raw)
To: saeedm; +Cc: dledford, netdev, linux-rdma, leonro, markb
In-Reply-To: <20171219203340.2600-8-saeedm@mellanox.com>
From: Saeed Mahameed <saeedm@mellanox.com>
Date: Tue, 19 Dec 2017 12:33:36 -0800
> +static int esw_offloads_load_reps(struct mlx5_eswitch *esw, int nvports)
> +{
> + u8 rep_type = 0;
> + int err;
> +
> + while (rep_type < NUM_REP_TYPES) {
> + err = esw_offloads_load_reps_type(esw, nvports,
> + rep_type);
> + if (err)
> + goto err_reps;
> + rep_type++;
> + }
Please, don't obfuscate what is a normal for() loop:
for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
Thanks.
^ permalink raw reply
* Re: [for-next 01/11] net/mlx5: E-Switch, Refactor vport representors initialization
From: David Miller @ 2017-12-20 17:57 UTC (permalink / raw)
To: saeedm-VPRAkNaXOzVWk0Htik3J/w
Cc: dledford-H+wXaHxf7aLQT0dZR+AlfA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, leonro-VPRAkNaXOzVWk0Htik3J/w,
markb-VPRAkNaXOzVWk0Htik3J/w
In-Reply-To: <20171219203340.2600-2-saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
From: Saeed Mahameed <saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Date: Tue, 19 Dec 2017 12:33:30 -0800
> +int esw_offloads_init_reps(struct mlx5_eswitch *esw)
> +{
> + struct mlx5_core_dev *dev = esw->dev;
> + struct mlx5_esw_offload *offloads;
> + struct mlx5_eswitch_rep *rep;
> + int total_vfs = MLX5_TOTAL_VPORTS(dev);
> + u8 hw_id[ETH_ALEN];
> + int vport;
Reverse christmas-tree please.
> + esw->offloads.vport_reps =
> + kcalloc(total_vfs, sizeof(struct mlx5_eswitch_rep),
> + GFP_KERNEL);
That looks really unpleasant:
x = kcalloc(y,
z, GFP_KERNEL);
would look so much nicer.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [pull request][for-next 00/11] Mellanox, mlx5 E-Switch updates 2017-12-19
From: David Miller @ 2017-12-20 17:56 UTC (permalink / raw)
To: saeedm-VPRAkNaXOzVWk0Htik3J/w
Cc: dledford-H+wXaHxf7aLQT0dZR+AlfA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-rdma-u79uwXL29TY76Z2rM5mHXA, leonro-VPRAkNaXOzVWk0Htik3J/w
In-Reply-To: <20171219203340.2600-1-saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
From: Saeed Mahameed <saeedm-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Date: Tue, 19 Dec 2017 12:33:29 -0800
> This patchset is based on rc4 and I see that net-next is still on rc3, i hope
> this is not a problem.
If it doesn't pull cleanly into net-next, then it would be a problem.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next 0/2] netdevsim: couple of build warning fixes
From: David Miller @ 2017-12-20 17:51 UTC (permalink / raw)
To: jakub.kicinski; +Cc: netdev, oss-drivers
In-Reply-To: <20171219201043.18851-1-jakub.kicinski@netronome.com>
From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Tue, 19 Dec 2017 12:10:41 -0800
> This series fixes two harmless build warning about a symbol which
> should be static and an unused variable.
Series applied, thanks Jakub.
^ permalink raw reply
* Re: [PATCH net-next] selftests: rtnetlink: add gretap test cases
From: David Miller @ 2017-12-20 17:49 UTC (permalink / raw)
To: u9012063; +Cc: netdev, fw
In-Reply-To: <1513708622-111607-1-git-send-email-u9012063@gmail.com>
From: William Tu <u9012063@gmail.com>
Date: Tue, 19 Dec 2017 10:37:02 -0800
> Add test cases for gretap and ip6gretap, native mode
> and external (collect metadata) mode.
>
> Signed-off-by: William Tu <u9012063@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH v1] net: pasemi: Replace mac address parsing
From: David Miller @ 2017-12-20 17:48 UTC (permalink / raw)
To: andriy.shevchenko; +Cc: keescook, edumazet, netdev
In-Reply-To: <20171219183103.74530-1-andriy.shevchenko@linux.intel.com>
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Tue, 19 Dec 2017 20:31:03 +0200
> Replace sscanf() with mac_pton().
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Applied to net-next.
^ permalink raw reply
* Re: [PATCH v1] net: bonding: Replace mac address parsing
From: David Miller @ 2017-12-20 17:48 UTC (permalink / raw)
To: andriy.shevchenko; +Cc: j.vosburgh, vfalico, andy, netdev
In-Reply-To: <20171219182044.5678-1-andriy.shevchenko@linux.intel.com>
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Tue, 19 Dec 2017 20:20:44 +0200
> Replace sscanf() with mac_pton().
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Applied to net-next.
^ permalink raw reply
* Re: [PATCH v1] bridge: Use helpers to handle MAC address
From: David Miller @ 2017-12-20 17:46 UTC (permalink / raw)
To: andriy.shevchenko; +Cc: stephen, bridge, netdev
In-Reply-To: <20171219181053.86320-1-andriy.shevchenko@linux.intel.com>
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Tue, 19 Dec 2017 20:10:53 +0200
> Use
> %pM to print MAC
> mac_pton() to convert it from ASCII to binary format, and
> ether_addr_copy() to copy.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Applied to net-next
^ permalink raw reply
* Re: [PATCH net v3] ipv4: Fix use-after-free when flushing FIB tables
From: Alexander Duyck @ 2017-12-20 17:46 UTC (permalink / raw)
To: Ido Schimmel
Cc: Netdev, David Miller, Duyck, Alexander H, David Ahern,
Fengguang Wu, mlxsw
In-Reply-To: <20171220173419.11259-1-idosch@mellanox.com>
On Wed, Dec 20, 2017 at 9:34 AM, Ido Schimmel <idosch@mellanox.com> wrote:
> Since commit 0ddcf43d5d4a ("ipv4: FIB Local/MAIN table collapse") the
> local table uses the same trie allocated for the main table when custom
> rules are not in use.
>
> When a net namespace is dismantled, the main table is flushed and freed
> (via an RCU callback) before the local table. In case the callback is
> invoked before the local table is iterated, a use-after-free can occur.
>
> Fix this by iterating over the FIB tables in reverse order, so that the
> main table is always freed after the local table.
>
> v3: Reworded comment according to Alex's suggestion.
> v2: Add a comment to make the fix more explicit per Dave's and Alex's
> feedback.
>
> Fixes: 0ddcf43d5d4a ("ipv4: FIB Local/MAIN table collapse")
> Signed-off-by: Ido Schimmel <idosch@mellanox.com>
> Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Acked-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
> net/ipv4/fib_frontend.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
> index f52d27a422c3..08259d078b1c 100644
> --- a/net/ipv4/fib_frontend.c
> +++ b/net/ipv4/fib_frontend.c
> @@ -1298,14 +1298,19 @@ static int __net_init ip_fib_net_init(struct net *net)
>
> static void ip_fib_net_exit(struct net *net)
> {
> - unsigned int i;
> + int i;
>
> rtnl_lock();
> #ifdef CONFIG_IP_MULTIPLE_TABLES
> RCU_INIT_POINTER(net->ipv4.fib_main, NULL);
> RCU_INIT_POINTER(net->ipv4.fib_default, NULL);
> #endif
> - for (i = 0; i < FIB_TABLE_HASHSZ; i++) {
> + /* Destroy the tables in reverse order to guarantee that the
> + * local table, ID 255, is destroyed before the main table, ID
> + * 254. This is necessary as the local table may contain
> + * references to data contained in the main table.
> + */
> + for (i = FIB_TABLE_HASHSZ - 1; i >= 0; i--) {
> struct hlist_head *head = &net->ipv4.fib_table_hash[i];
> struct hlist_node *tmp;
> struct fib_table *tb;
> --
> 2.14.3
>
^ permalink raw reply
* Re: [PATCH v1] net: dwc-xlgmac: Get rid of custom hex_dump_to_buffer()
From: David Miller @ 2017-12-20 17:45 UTC (permalink / raw)
To: andriy.shevchenko; +Cc: jiedeng, Jose.Abreu, netdev
In-Reply-To: <20171219180306.13409-1-andriy.shevchenko@linux.intel.com>
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Date: Tue, 19 Dec 2017 20:03:06 +0200
> + hex_dump_to_buffer(&skb->data[i], len, 32, 1, buffer, 128, false);
Please make the changes here that were requested for the amd-xgbe version of
this patch. In particular, use "sizeof(buffer)" instead of the magic constant 128.
Thank you.
^ permalink raw reply
* Re: [PATCH] net: Fix double free and memory corruption in get_net_ns_by_id()
From: David Miller @ 2017-12-20 17:43 UTC (permalink / raw)
To: ebiederm
Cc: netdev, ktkhai, security, secalert, eric.dumazet, stephen,
nicolas.dichtel
In-Reply-To: <87d13aaaqr.fsf@xmission.com>
From: ebiederm@xmission.com (Eric W. Biederman)
Date: Tue, 19 Dec 2017 11:27:56 -0600
> (I can trivially verify that that idr_remove in cleanup_net happens
> after the network namespace count has dropped to zero --EWB)
>
> Function get_net_ns_by_id() does not check for net::count
> after it has found a peer in netns_ids idr.
>
> It may dereference a peer, after its count has already been
> finaly decremented. This leads to double free and memory
> corruption:
...
> Also, put_net() on the right cpu may reorder with left's cpu
> list_replace_init(&cleanup_list, ..), and then cleanup_list
> will be corrupted.
>
> Since cleanup_net() is executed in worker thread, while
> put_net(peer) can happen everywhere, there should be
> enough time for concurrent get_net_ns_by_id() to pick
> the peer up, and the race does not seem to be unlikely.
> The patch fixes the problem in standard way.
>
> (Also, there is possible problem in peernet2id_alloc(), which requires
> check for net::count under nsid_lock and maybe_get_net(peer), but
> in current stable kernel it's used under rtnl_lock() and it has to be
> safe. Openswitch begun to use peernet2id_alloc(), and possibly it should
> be fixed too. While this is not in stable kernel yet, so I'll send
> a separate message to netdev@ later).
>
> Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> Fixes: 0c7aecd4bde4 "netns: add rtnl cmd to add and get peer netns ids"
> Reviewed-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
> Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net v2] openvswitch: Fix pop_vlan action for double tagged frames
From: Jiri Benc @ 2017-12-20 17:41 UTC (permalink / raw)
To: Eric Garver; +Cc: netdev, ovs-dev
In-Reply-To: <20171220153932.1362-1-e@erig.me>
On Wed, 20 Dec 2017 10:39:32 -0500, Eric Garver wrote:
> + if (is_flow_key_valid(key) && key->eth.vlan.tci && key->eth.cvlan.tci)
Maybe (key->eth.vlan.tci & htons(VLAN_TAG_PRESENT)) for consistency
with the rest of the code? But it's just nitpicking.
The real problem here is when a double tagged packet leaves the ovs
bridge, it won't have the skb->protocol that the kernel expects: it
will be ethertype of the payload, while my understanding is it should
be the inner tpid, right?
This patch fixes that nicely for the pop vlan case. But what about
other cases? It seems to me that we need to add the logic to
key_extract.
Thanks!
Jiri
^ permalink raw reply
* Re: [PATCH net v2] openvswitch: Fix pop_vlan action for double tagged frames
From: Jiri Benc @ 2017-12-20 17:41 UTC (permalink / raw)
To: Eric Garver; +Cc: netdev, ovs-dev
In-Reply-To: <20171220153932.1362-1-e@erig.me>
On Wed, 20 Dec 2017 10:39:32 -0500, Eric Garver wrote:
> + if (is_flow_key_valid(key) && key->eth.vlan.tci && key->eth.cvlan.tci)
Maybe (key->eth.vlan.tci & htons(VLAN_TAG_PRESENT)) for consistency
with the rest of the code? But it's just nitpicking.
The real problem here is when a double tagged packet leaves the ovs
bridge, it won't have the skb->protocol that the kernel expects: it
will be ethertype of the payload, while my understanding is it should
be the inner tpid, right?
This patch fixes that nicely for the pop vlan case. But what about
other cases? It seems to me that we need to add the logic to
key_extract.
Thanks!
Jiri
^ permalink raw reply
* Re: [PATCH net v2] ipv4: Fix use-after-free when flushing FIB tables
From: Ido Schimmel @ 2017-12-20 17:41 UTC (permalink / raw)
To: Alexander Duyck
Cc: Ido Schimmel, Netdev, David Miller, Duyck, Alexander H,
David Ahern, Fengguang Wu, mlxsw
In-Reply-To: <CAKgT0UcJD=OYM5qEdGv-vvpv3EcAyRVTWJ34MWshrxABvFUWGw@mail.gmail.com>
On Wed, Dec 20, 2017 at 07:32:21AM -0800, Alexander Duyck wrote:
> I think we might want even more description here. Specifically why
> reversing the order allows local to be destroyed before main. I was
> thinking something along the lines of:
>
> Destroy the tables in reverse order to guarantee that the local table,
> ID 255, is destroyed before main table, ID 254. This is necessary as
> local may contain references to data contained in main.
Sent v3:
http://patchwork.ozlabs.org/patch/851564/
Thanks
^ permalink raw reply
* [PATCHv4 net-next 14/14] net: sch: sch_drr: add extack support
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the drr qdisc implementation by
adding NL_SET_ERR_MSG in validation of user input.
Also it serves to illustrate a use case of how the infrastructure ops
api changes are to be used by individual qdiscs.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
net/sched/sch_drr.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index bf638ce57c50..e0b0cf8a9939 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -74,17 +74,21 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
u32 quantum;
int err;
- if (!opt)
+ if (!opt) {
+ NL_SET_ERR_MSG(extack, "DRR options are required for this operation");
return -EINVAL;
+ }
- err = nla_parse_nested(tb, TCA_DRR_MAX, opt, drr_policy, NULL);
+ err = nla_parse_nested(tb, TCA_DRR_MAX, opt, drr_policy, extack);
if (err < 0)
return err;
if (tb[TCA_DRR_QUANTUM]) {
quantum = nla_get_u32(tb[TCA_DRR_QUANTUM]);
- if (quantum == 0)
+ if (quantum == 0) {
+ NL_SET_ERR_MSG(extack, "Specified DRR quantum cannot be zero");
return -EINVAL;
+ }
} else
quantum = psched_mtu(qdisc_dev(sch));
@@ -95,8 +99,10 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
NULL,
qdisc_root_sleeping_running(sch),
tca[TCA_RATE]);
- if (err)
+ if (err) {
+ NL_SET_ERR_MSG(extack, "Failed to replace estimator");
return err;
+ }
}
sch_tree_lock(sch);
@@ -127,6 +133,7 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
qdisc_root_sleeping_running(sch),
tca[TCA_RATE]);
if (err) {
+ NL_SET_ERR_MSG(extack, "Failed to replace estimator");
qdisc_destroy(cl->qdisc);
kfree(cl);
return err;
@@ -179,8 +186,10 @@ static struct tcf_block *drr_tcf_block(struct Qdisc *sch, unsigned long cl,
{
struct drr_sched *q = qdisc_priv(sch);
- if (cl)
+ if (cl) {
+ NL_SET_ERR_MSG(extack, "DRR classid must be zero");
return NULL;
+ }
return q->block;
}
--
2.11.0
^ permalink raw reply related
* [PATCHv4 net-next 13/14] net: sch: sch_cbs: add extack support
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the cbs qdisc implementation by
adding NL_SET_ERR_MSG in validation of user input.
Also it serves to illustrate a use case of how the infrastructure ops
api changes are to be used by individual qdiscs.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
net/sched/sch_cbs.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c
index 8bf6e163d29c..cdd96b9a27bc 100644
--- a/net/sched/sch_cbs.c
+++ b/net/sched/sch_cbs.c
@@ -219,14 +219,17 @@ static void cbs_disable_offload(struct net_device *dev,
}
static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
- const struct tc_cbs_qopt *opt)
+ const struct tc_cbs_qopt *opt,
+ struct netlink_ext_ack *extack)
{
const struct net_device_ops *ops = dev->netdev_ops;
struct tc_cbs_qopt_offload cbs = { };
int err;
- if (!ops->ndo_setup_tc)
+ if (!ops->ndo_setup_tc) {
+ NL_SET_ERR_MSG(extack, "Specified device does not support cbs offload");
return -EOPNOTSUPP;
+ }
cbs.queue = q->queue;
@@ -237,8 +240,10 @@ static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
cbs.sendslope = opt->sendslope;
err = ops->ndo_setup_tc(dev, TC_SETUP_QDISC_CBS, &cbs);
- if (err < 0)
+ if (err < 0) {
+ NL_SET_ERR_MSG(extack, "Specified device failed to setup cbs hardware offload");
return err;
+ }
q->enqueue = cbs_enqueue_offload;
q->dequeue = cbs_dequeue_offload;
@@ -255,12 +260,14 @@ static int cbs_change(struct Qdisc *sch, struct nlattr *opt,
struct tc_cbs_qopt *qopt;
int err;
- err = nla_parse_nested(tb, TCA_CBS_MAX, opt, cbs_policy, NULL);
+ err = nla_parse_nested(tb, TCA_CBS_MAX, opt, cbs_policy, extack);
if (err < 0)
return err;
- if (!tb[TCA_CBS_PARMS])
+ if (!tb[TCA_CBS_PARMS]) {
+ NL_SET_ERR_MSG(extack, "Missing CBS parameter which are mandatory");
return -EINVAL;
+ }
qopt = nla_data(tb[TCA_CBS_PARMS]);
@@ -277,7 +284,7 @@ static int cbs_change(struct Qdisc *sch, struct nlattr *opt,
cbs_disable_offload(dev, q);
} else {
- err = cbs_enable_offload(dev, q, qopt);
+ err = cbs_enable_offload(dev, q, qopt, extack);
if (err < 0)
return err;
}
@@ -298,8 +305,10 @@ static int cbs_init(struct Qdisc *sch, struct nlattr *opt,
struct cbs_sched_data *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
- if (!opt)
+ if (!opt) {
+ NL_SET_ERR_MSG(extack, "Missing CBS qdisc options which are mandatory");
return -EINVAL;
+ }
q->queue = sch->dev_queue - netdev_get_tx_queue(dev, 0);
--
2.11.0
^ permalink raw reply related
* [PATCHv4 net-next 11/14] net: sch: api: add extack support in qdisc_create_dflt
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the function qdisc_create_dflt which is
a common used function in the tc subsystem. Callers which are interested
in the receiving error can assign extack to get a more detailed
information why qdisc_create_dflt failed. The function qdisc_create_dflt
will also call an init callback which can fail by any per-qdisc specific
handling.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
include/net/pkt_sched.h | 3 ++-
include/net/sch_generic.h | 3 ++-
net/sched/sch_atm.c | 5 +++--
net/sched/sch_cbq.c | 9 +++++----
net/sched/sch_drr.c | 7 ++++---
net/sched/sch_dsmark.c | 5 +++--
net/sched/sch_fifo.c | 6 ++++--
net/sched/sch_generic.c | 15 +++++++++------
net/sched/sch_hfsc.c | 8 ++++----
net/sched/sch_htb.c | 9 +++++----
net/sched/sch_mq.c | 3 ++-
net/sched/sch_mqprio.c | 2 +-
net/sched/sch_multiq.c | 2 +-
net/sched/sch_prio.c | 3 ++-
net/sched/sch_qfq.c | 8 ++++----
net/sched/sch_red.c | 3 ++-
net/sched/sch_sfb.c | 2 +-
net/sched/sch_tbf.c | 3 ++-
18 files changed, 56 insertions(+), 40 deletions(-)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index a4f21c0b4a43..e2c75f52557b 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -89,7 +89,8 @@ extern struct Qdisc_ops pfifo_head_drop_qdisc_ops;
int fifo_set_limit(struct Qdisc *q, unsigned int limit);
struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
- unsigned int limit);
+ unsigned int limit,
+ struct netlink_ext_ack *extack);
int register_qdisc(struct Qdisc_ops *qops);
int unregister_qdisc(struct Qdisc_ops *qops);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index faf6b2dbc1b2..ac029d5d88e4 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -474,7 +474,8 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
const struct Qdisc_ops *ops,
struct netlink_ext_ack *extack);
struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
- const struct Qdisc_ops *ops, u32 parentid);
+ const struct Qdisc_ops *ops, u32 parentid,
+ struct netlink_ext_ack *extack);
void __qdisc_calculate_pkt_len(struct sk_buff *skb,
const struct qdisc_size_table *stab);
int skb_do_redirect(struct sk_buff *);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 493d5c25d83a..cd49afca9617 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -290,7 +290,8 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
goto err_out;
}
- flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
+ flow->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid,
+ extack);
if (!flow->q)
flow->q = &noop_qdisc;
pr_debug("atm_tc_change: qdisc %p\n", flow->q);
@@ -546,7 +547,7 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt,
INIT_LIST_HEAD(&p->link.list);
list_add(&p->link.list, &p->flows);
p->link.q = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, sch->handle);
+ &pfifo_qdisc_ops, sch->handle, extack);
if (!p->link.q)
p->link.q = &noop_qdisc;
pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 248ea26997b9..efe5bf15b031 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1172,7 +1172,7 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
q->link.common.classid = sch->handle;
q->link.qdisc = sch;
q->link.q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- sch->handle);
+ sch->handle, NULL);
if (!q->link.q)
q->link.q = &noop_qdisc;
else
@@ -1376,8 +1376,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
struct cbq_class *cl = (struct cbq_class *)arg;
if (new == NULL) {
- new = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, cl->common.classid);
+ new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+ cl->common.classid, extack);
if (new == NULL)
return -ENOBUFS;
}
@@ -1596,7 +1596,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
cl->R_tab = rtab;
rtab = NULL;
- cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid);
+ cl->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid,
+ NULL);
if (!cl->q)
cl->q = &noop_qdisc;
else
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 9dfff065e27d..bf638ce57c50 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -114,7 +114,8 @@ static int drr_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->common.classid = classid;
cl->quantum = quantum;
cl->qdisc = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, classid);
+ &pfifo_qdisc_ops, classid,
+ NULL);
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
else
@@ -209,8 +210,8 @@ static int drr_graft_class(struct Qdisc *sch, unsigned long arg,
struct drr_class *cl = (struct drr_class *)arg;
if (new == NULL) {
- new = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, cl->common.classid);
+ new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+ cl->common.classid, NULL);
if (new == NULL)
new = &noop_qdisc;
}
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 63f523b5e282..049714c57075 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -71,7 +71,7 @@ static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
if (new == NULL) {
new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- sch->handle);
+ sch->handle, NULL);
if (new == NULL)
new = &noop_qdisc;
}
@@ -381,7 +381,8 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt,
p->default_index = default_index;
p->set_tc_index = nla_get_flag(tb[TCA_DSMARK_SET_TC_INDEX]);
- p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle);
+ p->q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, sch->handle,
+ NULL);
if (p->q == NULL)
p->q = &noop_qdisc;
else
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index c65f23c70f40..24893d3b5d22 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -166,12 +166,14 @@ int fifo_set_limit(struct Qdisc *q, unsigned int limit)
EXPORT_SYMBOL(fifo_set_limit);
struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
- unsigned int limit)
+ unsigned int limit,
+ struct netlink_ext_ack *extack)
{
struct Qdisc *q;
int err = -ENOMEM;
- q = qdisc_create_dflt(sch->dev_queue, ops, TC_H_MAKE(sch->handle, 1));
+ q = qdisc_create_dflt(sch->dev_queue, ops, TC_H_MAKE(sch->handle, 1),
+ extack);
if (q) {
err = fifo_set_limit(q, limit);
if (err < 0) {
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 34ef4366f8e0..10aaa3b615ce 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -830,21 +830,24 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
const struct Qdisc_ops *ops,
- unsigned int parentid)
+ unsigned int parentid,
+ struct netlink_ext_ack *extack)
{
struct Qdisc *sch;
- if (!try_module_get(ops->owner))
+ if (!try_module_get(ops->owner)) {
+ NL_SET_ERR_MSG(extack, "Failed to increase module reference counter");
return NULL;
+ }
- sch = qdisc_alloc(dev_queue, ops, NULL);
+ sch = qdisc_alloc(dev_queue, ops, extack);
if (IS_ERR(sch)) {
module_put(ops->owner);
return NULL;
}
sch->parent = parentid;
- if (!ops->init || ops->init(sch, NULL, NULL) == 0)
+ if (!ops->init || ops->init(sch, NULL, extack) == 0)
return sch;
qdisc_destroy(sch);
@@ -956,7 +959,7 @@ static void attach_one_default_qdisc(struct net_device *dev,
if (dev->priv_flags & IFF_NO_QUEUE)
ops = &noqueue_qdisc_ops;
- qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT);
+ qdisc = qdisc_create_dflt(dev_queue, ops, TC_H_ROOT, NULL);
if (!qdisc) {
netdev_info(dev, "activation failed\n");
return;
@@ -979,7 +982,7 @@ static void attach_default_qdiscs(struct net_device *dev)
dev->qdisc = txq->qdisc_sleeping;
qdisc_refcount_inc(dev->qdisc);
} else {
- qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT);
+ qdisc = qdisc_create_dflt(txq, &mq_qdisc_ops, TC_H_ROOT, NULL);
if (qdisc) {
dev->qdisc = qdisc;
qdisc->ops->attach(qdisc);
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 9ae288fcbed8..3ae9877ea205 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1062,8 +1062,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->cl_common.classid = classid;
cl->sched = q;
cl->cl_parent = parent;
- cl->qdisc = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, classid);
+ cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+ classid, NULL);
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
else
@@ -1185,7 +1185,7 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
return -EINVAL;
if (new == NULL) {
new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- cl->cl_common.classid);
+ cl->cl_common.classid, NULL);
if (new == NULL)
new = &noop_qdisc;
}
@@ -1416,7 +1416,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
q->root.cl_common.classid = sch->handle;
q->root.sched = q;
q->root.qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- sch->handle);
+ sch->handle, NULL);
if (q->root.qdisc == NULL)
q->root.qdisc = &noop_qdisc;
else
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 54e1f860f1e5..1ea9846cc6ce 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1180,7 +1180,7 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
return -EINVAL;
if (new == NULL &&
(new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- cl->common.classid)) == NULL)
+ cl->common.classid, extack)) == NULL)
return -ENOBUFS;
*old = qdisc_replace(sch, new, &cl->un.leaf.q);
@@ -1290,7 +1290,8 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
if (!cl->level && htb_parent_last_child(cl)) {
new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- cl->parent->common.classid);
+ cl->parent->common.classid,
+ NULL);
last_child = 1;
}
@@ -1426,8 +1427,8 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
* so that can't be used inside of sch_tree_lock
* -- thanks to Karlis Peisenieks
*/
- new_q = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, classid);
+ new_q = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+ classid, NULL);
sch_tree_lock(sch);
if (parent && !parent->level) {
unsigned int qlen = parent->un.leaf.q->q.qlen;
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index 50292e470432..f062a18e9162 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -61,7 +61,8 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt,
dev_queue = netdev_get_tx_queue(dev, ntx);
qdisc = qdisc_create_dflt(dev_queue, get_default_qdisc_ops(dev, ntx),
TC_H_MAKE(TC_H_MAJ(sch->handle),
- TC_H_MIN(ntx + 1)));
+ TC_H_MIN(ntx + 1)),
+ extack);
if (!qdisc)
return -ENOMEM;
priv->qdiscs[ntx] = qdisc;
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index 29071cf329f3..0e9d761cdd80 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -230,7 +230,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt,
qdisc = qdisc_create_dflt(dev_queue,
get_default_qdisc_ops(dev, i),
TC_H_MAKE(TC_H_MAJ(sch->handle),
- TC_H_MIN(i + 1)));
+ TC_H_MIN(i + 1)), extack);
if (!qdisc)
return -ENOMEM;
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 35cbaf8bd96a..1da7ea8de0ad 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -216,7 +216,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt,
child = qdisc_create_dflt(sch->dev_queue,
&pfifo_qdisc_ops,
TC_H_MAKE(sch->handle,
- i + 1));
+ i + 1), extack);
if (child) {
sch_tree_lock(sch);
old = q->queues[i];
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 502352762f03..fe1510eb111f 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -176,7 +176,8 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
/* Before commit, make sure we can allocate all new qdiscs */
for (i = oldbands; i < qopt->bands; i++) {
queues[i] = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
- TC_H_MAKE(sch->handle, i + 1));
+ TC_H_MAKE(sch->handle, i + 1),
+ extack);
if (!queues[i]) {
while (i > oldbands)
qdisc_destroy(queues[--i]);
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 6ab58509cf49..bb1a9c11fc54 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -480,8 +480,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
cl->common.classid = classid;
cl->deficit = lmax;
- cl->qdisc = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, classid);
+ cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+ classid, NULL);
if (cl->qdisc == NULL)
cl->qdisc = &noop_qdisc;
@@ -601,8 +601,8 @@ static int qfq_graft_class(struct Qdisc *sch, unsigned long arg,
struct qfq_class *cl = (struct qfq_class *)arg;
if (new == NULL) {
- new = qdisc_create_dflt(sch->dev_queue,
- &pfifo_qdisc_ops, cl->common.classid);
+ new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+ cl->common.classid, NULL);
if (new == NULL)
new = &noop_qdisc;
}
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index ea7d400b9eb2..ec0bd36e09a9 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -225,7 +225,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt,
return -EINVAL;
if (ctl->limit > 0) {
- child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit);
+ child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit,
+ extack);
if (IS_ERR(child))
return PTR_ERR(child);
}
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index a1a11ded8e4f..7cbdad8419b7 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -513,7 +513,7 @@ static int sfb_change(struct Qdisc *sch, struct nlattr *opt,
if (limit == 0)
limit = qdisc_dev(sch)->tx_queue_len;
- child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit);
+ child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit, extack);
if (IS_ERR(child))
return PTR_ERR(child);
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 1ab53ff80f46..83e76d046993 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -386,7 +386,8 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
if (err)
goto done;
} else if (qopt->limit > 0) {
- child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit);
+ child = fifo_create_dflt(sch, &bfifo_qdisc_ops, qopt->limit,
+ extack);
if (IS_ERR(child)) {
err = PTR_ERR(child);
goto done;
--
2.11.0
^ permalink raw reply related
* [PATCHv4 net-next 12/14] net: sch: sch_cbq: add extack support
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the cbq qdisc implementation by
adding NL_SET_ERR_MSG in validation of user input.
Also it serves to illustrate a use case of how the infrastructure ops
api changes are to be used by individual qdiscs.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
net/sched/sch_cbq.c | 46 ++++++++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index efe5bf15b031..f42025d53cfe 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1144,15 +1144,19 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED);
q->delay_timer.function = cbq_undelay;
- if (!opt)
+ if (!opt) {
+ NL_SET_ERR_MSG(extack, "CBQ options are required for this operation");
return -EINVAL;
+ }
- err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, NULL);
+ err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, extack);
if (err < 0)
return err;
- if (!tb[TCA_CBQ_RTAB] || !tb[TCA_CBQ_RATE])
+ if (!tb[TCA_CBQ_RTAB] || !tb[TCA_CBQ_RATE]) {
+ NL_SET_ERR_MSG(extack, "Rate specification missing or incomplete");
return -EINVAL;
+ }
r = nla_data(tb[TCA_CBQ_RATE]);
@@ -1462,24 +1466,32 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
struct cbq_class *parent;
struct qdisc_rate_table *rtab = NULL;
- if (!opt)
+ if (!opt) {
+ NL_SET_ERR_MSG(extack, "Mandatory qdisc options missing");
return -EINVAL;
+ }
- err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, NULL);
+ err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy, extack);
if (err < 0)
return err;
- if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE])
+ if (tb[TCA_CBQ_OVL_STRATEGY] || tb[TCA_CBQ_POLICE]) {
+ NL_SET_ERR_MSG(extack, "Neither overlimit strategy nor policing attributes can be used for changing class params");
return -EOPNOTSUPP;
+ }
if (cl) {
/* Check parent */
if (parentid) {
if (cl->tparent &&
- cl->tparent->common.classid != parentid)
+ cl->tparent->common.classid != parentid) {
+ NL_SET_ERR_MSG(extack, "Invalid parent id");
return -EINVAL;
- if (!cl->tparent && parentid != TC_H_ROOT)
+ }
+ if (!cl->tparent && parentid != TC_H_ROOT) {
+ NL_SET_ERR_MSG(extack, "Parent must be root");
return -EINVAL;
+ }
}
if (tb[TCA_CBQ_RATE]) {
@@ -1496,6 +1508,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
qdisc_root_sleeping_running(sch),
tca[TCA_RATE]);
if (err) {
+ NL_SET_ERR_MSG(extack, "Failed to replace specified rate estimator");
qdisc_put_rtab(rtab);
return err;
}
@@ -1534,8 +1547,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (parentid == TC_H_ROOT)
return -EINVAL;
- if (!tb[TCA_CBQ_WRROPT] || !tb[TCA_CBQ_RATE] || !tb[TCA_CBQ_LSSOPT])
+ if (!tb[TCA_CBQ_WRROPT] || !tb[TCA_CBQ_RATE] || !tb[TCA_CBQ_LSSOPT]) {
+ NL_SET_ERR_MSG(extack, "One of the following attributes MUST be specified: WRR, rate or link sharing");
return -EINVAL;
+ }
rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB],
extack);
@@ -1545,8 +1560,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (classid) {
err = -EINVAL;
if (TC_H_MAJ(classid ^ sch->handle) ||
- cbq_class_lookup(q, classid))
+ cbq_class_lookup(q, classid)) {
+ NL_SET_ERR_MSG(extack, "Specified class not found");
goto failure;
+ }
} else {
int i;
classid = TC_H_MAKE(sch->handle, 0x8000);
@@ -1558,8 +1575,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
break;
}
err = -ENOSR;
- if (i >= 0x8000)
+ if (i >= 0x8000) {
+ NL_SET_ERR_MSG(extack, "Unable to generate classid");
goto failure;
+ }
classid = classid|q->hgenerator;
}
@@ -1567,8 +1586,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (parentid) {
parent = cbq_class_lookup(q, parentid);
err = -EINVAL;
- if (!parent)
+ if (!parent) {
+ NL_SET_ERR_MSG(extack, "Failed to find parentid");
goto failure;
+ }
}
err = -ENOBUFS;
@@ -1588,6 +1609,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
qdisc_root_sleeping_running(sch),
tca[TCA_RATE]);
if (err) {
+ NL_SET_ERR_MSG(extack, "Couldn't create new estimator");
tcf_block_put(cl->block);
kfree(cl);
goto failure;
--
2.11.0
^ permalink raw reply related
* [PATCHv4 net-next 09/14] net: sch: api: add extack support in tcf_block_get
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the function tcf_block_get which is
a common used function in the tc subsystem. Callers which are interested
in the receiving error can assign extack to get a more detailed
information why tcf_block_get failed.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
include/net/pkt_cls.h | 6 ++++--
net/sched/cls_api.c | 13 +++++++++----
net/sched/sch_atm.c | 6 ++++--
net/sched/sch_cbq.c | 4 ++--
net/sched/sch_drr.c | 2 +-
net/sched/sch_dsmark.c | 2 +-
net/sched/sch_fq_codel.c | 2 +-
net/sched/sch_hfsc.c | 4 ++--
net/sched/sch_htb.c | 4 ++--
net/sched/sch_ingress.c | 8 +++++---
net/sched/sch_multiq.c | 2 +-
net/sched/sch_prio.c | 2 +-
net/sched/sch_qfq.c | 2 +-
net/sched/sch_sfb.c | 2 +-
net/sched/sch_sfq.c | 2 +-
15 files changed, 36 insertions(+), 25 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 0105445cab83..58bba9c769ea 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -39,9 +39,11 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
bool create);
void tcf_chain_put(struct tcf_chain *chain);
int tcf_block_get(struct tcf_block **p_block,
- struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q);
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
+ struct netlink_ext_ack *extack);
int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
- struct tcf_block_ext_info *ei);
+ struct tcf_block_ext_info *ei,
+ struct netlink_ext_ack *extack);
void tcf_block_put(struct tcf_block *block);
void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
struct tcf_block_ext_info *ei);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 22b977d40e1d..4591b87eaab5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -281,20 +281,24 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
}
int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
- struct tcf_block_ext_info *ei)
+ struct tcf_block_ext_info *ei,
+ struct netlink_ext_ack *extack)
{
struct tcf_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
struct tcf_chain *chain;
int err;
- if (!block)
+ if (!block) {
+ NL_SET_ERR_MSG(extack, "Memory allocation for block failed");
return -ENOMEM;
+ }
INIT_LIST_HEAD(&block->chain_list);
INIT_LIST_HEAD(&block->cb_list);
/* Create chain 0 by default, it has to be always present. */
chain = tcf_chain_create(block, 0);
if (!chain) {
+ NL_SET_ERR_MSG(extack, "Failed to create new tcf chain");
err = -ENOMEM;
goto err_chain_create;
}
@@ -321,7 +325,8 @@ static void tcf_chain_head_change_dflt(struct tcf_proto *tp_head, void *priv)
}
int tcf_block_get(struct tcf_block **p_block,
- struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
+ struct netlink_ext_ack *extack)
{
struct tcf_block_ext_info ei = {
.chain_head_change = tcf_chain_head_change_dflt,
@@ -329,7 +334,7 @@ int tcf_block_get(struct tcf_block **p_block,
};
WARN_ON(!p_filter_chain);
- return tcf_block_get_ext(p_block, q, &ei);
+ return tcf_block_get_ext(p_block, q, &ei, extack);
}
EXPORT_SYMBOL(tcf_block_get);
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 8972ab72cda5..493d5c25d83a 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -283,7 +283,8 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
goto err_out;
}
- error = tcf_block_get(&flow->block, &flow->filter_list, sch);
+ error = tcf_block_get(&flow->block, &flow->filter_list, sch,
+ extack);
if (error) {
kfree(flow);
goto err_out;
@@ -550,7 +551,8 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt,
p->link.q = &noop_qdisc;
pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
- err = tcf_block_get(&p->link.block, &p->link.filter_list, sch);
+ err = tcf_block_get(&p->link.block, &p->link.filter_list, sch,
+ extack);
if (err)
return err;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 79f081eb6bb0..248ea26997b9 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1160,7 +1160,7 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
if (!q->link.R_tab)
return -EINVAL;
- err = tcf_block_get(&q->link.block, &q->link.filter_list, sch);
+ err = tcf_block_get(&q->link.block, &q->link.filter_list, sch, extack);
if (err)
goto put_rtab;
@@ -1576,7 +1576,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (cl == NULL)
goto failure;
- err = tcf_block_get(&cl->block, &cl->filter_list, sch);
+ err = tcf_block_get(&cl->block, &cl->filter_list, sch, extack);
if (err) {
kfree(cl);
return err;
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 30e9cba54ddb..9dfff065e27d 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -417,7 +417,7 @@ static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
struct drr_sched *q = qdisc_priv(sch);
int err;
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
err = qdisc_class_hash_init(&q->clhash);
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 92a36aa4c713..63f523b5e282 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -348,7 +348,7 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt,
if (!opt)
goto errout;
- err = tcf_block_get(&p->block, &p->filter_list, sch);
+ err = tcf_block_get(&p->block, &p->filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 06e5360c54d8..22fa13cf5d8b 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -484,7 +484,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
return err;
}
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 7f6a06ac4b9f..9ae288fcbed8 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1034,7 +1034,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (cl == NULL)
return -ENOBUFS;
- err = tcf_block_get(&cl->block, &cl->filter_list, sch);
+ err = tcf_block_get(&cl->block, &cl->filter_list, sch, extack);
if (err) {
kfree(cl);
return err;
@@ -1409,7 +1409,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
return err;
q->eligible = RB_ROOT;
- err = tcf_block_get(&q->root.block, &q->root.filter_list, sch);
+ err = tcf_block_get(&q->root.block, &q->root.filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 51be1b756e4e..54e1f860f1e5 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1032,7 +1032,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
if (!opt)
return -EINVAL;
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
@@ -1397,7 +1397,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!cl)
goto failure;
- err = tcf_block_get(&cl->block, &cl->filter_list, sch);
+ err = tcf_block_get(&cl->block, &cl->filter_list, sch, extack);
if (err) {
kfree(cl);
goto failure;
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index b9de7be531dd..7ca2be20dd6f 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -78,7 +78,7 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt,
q->block_info.chain_head_change = clsact_chain_head_change;
q->block_info.chain_head_change_priv = &q->miniqp;
- err = tcf_block_get_ext(&q->block, sch, &q->block_info);
+ err = tcf_block_get_ext(&q->block, sch, &q->block_info, extack);
if (err)
return err;
@@ -186,7 +186,8 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
q->ingress_block_info.chain_head_change = clsact_chain_head_change;
q->ingress_block_info.chain_head_change_priv = &q->miniqp_ingress;
- err = tcf_block_get_ext(&q->ingress_block, sch, &q->ingress_block_info);
+ err = tcf_block_get_ext(&q->ingress_block, sch, &q->ingress_block_info,
+ extack);
if (err)
return err;
@@ -196,7 +197,8 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt,
q->egress_block_info.chain_head_change = clsact_chain_head_change;
q->egress_block_info.chain_head_change_priv = &q->miniqp_egress;
- err = tcf_block_get_ext(&q->egress_block, sch, &q->egress_block_info);
+ err = tcf_block_get_ext(&q->egress_block, sch, &q->egress_block_info,
+ extack);
if (err)
return err;
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 177d86de4b32..35cbaf8bd96a 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -248,7 +248,7 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt,
if (!opt)
return -EINVAL;
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 8fbd65661d77..502352762f03 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -215,7 +215,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt,
if (!opt)
return -EINVAL;
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 7ec893f770d2..6ab58509cf49 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -1424,7 +1424,7 @@ static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt,
int i, j, err;
u32 max_cl_shift, maxbudg_shift, max_classes;
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 1a33d6c3ac42..a1a11ded8e4f 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -556,7 +556,7 @@ static int sfb_init(struct Qdisc *sch, struct nlattr *opt,
struct sfb_sched_data *q = qdisc_priv(sch);
int err;
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 7a217be39f2a..2f2678197760 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -731,7 +731,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt,
q->sch = sch;
timer_setup(&q->perturb_timer, sfq_perturbation, TIMER_DEFERRABLE);
- err = tcf_block_get(&q->block, &q->filter_list, sch);
+ err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
if (err)
return err;
--
2.11.0
^ permalink raw reply related
* [PATCHv4 net-next 10/14] net: sch: api: add extack support in qdisc_alloc
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the function qdisc_alloc which is
a common used function in the tc subsystem. Callers which are interested
in the receiving error can assign extack to get a more detailed
information why qdisc_alloc failed.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
include/net/sch_generic.h | 3 ++-
net/sched/sch_api.c | 2 +-
net/sched/sch_generic.c | 6 ++++--
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 3baadac9e7a5..faf6b2dbc1b2 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -471,7 +471,8 @@ void qdisc_destroy(struct Qdisc *qdisc);
void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
unsigned int len);
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
- const struct Qdisc_ops *ops);
+ const struct Qdisc_ops *ops,
+ struct netlink_ext_ack *extack);
struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
const struct Qdisc_ops *ops, u32 parentid);
void __qdisc_calculate_pkt_len(struct sk_buff *skb,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 79a9fdf9471d..3a3a1da6b071 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1052,7 +1052,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
goto err_out;
}
- sch = qdisc_alloc(dev_queue, ops);
+ sch = qdisc_alloc(dev_queue, ops, extack);
if (IS_ERR(sch)) {
err = PTR_ERR(sch);
goto err_out2;
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 30bc38c5d7ae..34ef4366f8e0 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -755,7 +755,8 @@ static struct lock_class_key qdisc_tx_busylock;
static struct lock_class_key qdisc_running_key;
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
- const struct Qdisc_ops *ops)
+ const struct Qdisc_ops *ops,
+ struct netlink_ext_ack *extack)
{
void *p;
struct Qdisc *sch;
@@ -764,6 +765,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
struct net_device *dev;
if (!dev_queue) {
+ NL_SET_ERR_MSG(extack, "No device queue given");
err = -EINVAL;
goto errout;
}
@@ -835,7 +837,7 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
if (!try_module_get(ops->owner))
return NULL;
- sch = qdisc_alloc(dev_queue, ops);
+ sch = qdisc_alloc(dev_queue, ops, NULL);
if (IS_ERR(sch)) {
module_put(ops->owner);
return NULL;
--
2.11.0
^ permalink raw reply related
* [PATCHv4 net-next 08/14] net: sch: api: add extack support in qdisc_get_rtab
From: Alexander Aring @ 2017-12-20 17:35 UTC (permalink / raw)
To: jhs
Cc: xiyou.wangcong, jiri, davem, netdev, kernel, Alexander Aring,
David Ahern
In-Reply-To: <20171220173524.25874-1-aring@mojatatu.com>
This patch adds extack support for the function qdisc_get_rtab which is
a common used function in the tc subsystem. Callers which are interested
in the receiving error can assign extack to get a more detailed
information why qdisc_get_rtab failed.
Cc: David Ahern <dsahern@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Alexander Aring <aring@mojatatu.com>
---
include/net/pkt_sched.h | 3 ++-
net/sched/act_police.c | 4 ++--
net/sched/sch_api.c | 9 +++++++--
net/sched/sch_cbq.c | 7 ++++---
net/sched/sch_htb.c | 6 ++++--
net/sched/sch_tbf.c | 6 ++++--
6 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 240469228851..a4f21c0b4a43 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -101,7 +101,8 @@ void qdisc_hash_del(struct Qdisc *q);
struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle);
struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
- struct nlattr *tab);
+ struct nlattr *tab,
+ struct netlink_ext_ack *extack);
void qdisc_put_rtab(struct qdisc_rate_table *tab);
void qdisc_put_stab(struct qdisc_size_table *tab);
void qdisc_warn_nonwc(const char *txt, struct Qdisc *qdisc);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index bf483db993a1..95d3c9097b25 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -118,13 +118,13 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
police = to_police(*a);
if (parm->rate.rate) {
err = -ENOMEM;
- R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
+ R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE], NULL);
if (R_tab == NULL)
goto failure;
if (parm->peakrate.rate) {
P_tab = qdisc_get_rtab(&parm->peakrate,
- tb[TCA_POLICE_PEAKRATE]);
+ tb[TCA_POLICE_PEAKRATE], NULL);
if (P_tab == NULL)
goto failure;
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 4b950d72d13b..79a9fdf9471d 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -393,13 +393,16 @@ static __u8 __detect_linklayer(struct tc_ratespec *r, __u32 *rtab)
static struct qdisc_rate_table *qdisc_rtab_list;
struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
- struct nlattr *tab)
+ struct nlattr *tab,
+ struct netlink_ext_ack *extack)
{
struct qdisc_rate_table *rtab;
if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
- nla_len(tab) != TC_RTAB_SIZE)
+ nla_len(tab) != TC_RTAB_SIZE) {
+ NL_SET_ERR_MSG(extack, "Invalid rate table parameters for searching");
return NULL;
+ }
for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) &&
@@ -418,6 +421,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
r->linklayer = __detect_linklayer(r, rtab->data);
rtab->next = qdisc_rtab_list;
qdisc_rtab_list = rtab;
+ } else {
+ NL_SET_ERR_MSG(extack, "Failed to allocate new qdisc rate table");
}
return rtab;
}
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index bb7e4ccd7caf..79f081eb6bb0 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1156,7 +1156,7 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt,
r = nla_data(tb[TCA_CBQ_RATE]);
- q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB]);
+ q->link.R_tab = qdisc_get_rtab(r, tb[TCA_CBQ_RTAB], extack);
if (!q->link.R_tab)
return -EINVAL;
@@ -1484,7 +1484,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (tb[TCA_CBQ_RATE]) {
rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]),
- tb[TCA_CBQ_RTAB]);
+ tb[TCA_CBQ_RTAB], extack);
if (rtab == NULL)
return -EINVAL;
}
@@ -1537,7 +1537,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (!tb[TCA_CBQ_WRROPT] || !tb[TCA_CBQ_RATE] || !tb[TCA_CBQ_LSSOPT])
return -EINVAL;
- rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]);
+ rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB],
+ extack);
if (rtab == NULL)
return -EINVAL;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 65762d57a70d..51be1b756e4e 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1357,10 +1357,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
/* Keeping backward compatible with rate_table based iproute2 tc */
if (hopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
- qdisc_put_rtab(qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]));
+ qdisc_put_rtab(qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB],
+ NULL));
if (hopt->ceil.linklayer == TC_LINKLAYER_UNAWARE)
- qdisc_put_rtab(qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]));
+ qdisc_put_rtab(qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB],
+ NULL));
if (!cl) { /* new class */
struct Qdisc *new_q;
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index db6bd23530d4..1ab53ff80f46 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -327,11 +327,13 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
qopt = nla_data(tb[TCA_TBF_PARMS]);
if (qopt->rate.linklayer == TC_LINKLAYER_UNAWARE)
qdisc_put_rtab(qdisc_get_rtab(&qopt->rate,
- tb[TCA_TBF_RTAB]));
+ tb[TCA_TBF_RTAB],
+ NULL));
if (qopt->peakrate.linklayer == TC_LINKLAYER_UNAWARE)
qdisc_put_rtab(qdisc_get_rtab(&qopt->peakrate,
- tb[TCA_TBF_PTAB]));
+ tb[TCA_TBF_PTAB],
+ NULL));
buffer = min_t(u64, PSCHED_TICKS2NS(qopt->buffer), ~0U);
mtu = min_t(u64, PSCHED_TICKS2NS(qopt->mtu), ~0U);
--
2.11.0
^ 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