[PATCH net-next] ieee802154: hwsim: using right kind of iteration

2018-08-12 Thread Alexander Aring
This patch fixes the error path to unsubscribe all other phy's from
current phy. The actually code using a wrong kind of list iteration may
copied from the case to unsubscribe the current phy from all other
phy's.

Cc: Stefan Schmidt 
Reported-by: Dan Carpenter 
Fixes: f25da51fdc38 ("ieee802154: hwsim: add replacement for fakelb")
Signed-off-by: Alexander Aring 
---
 drivers/net/ieee802154/mac802154_hwsim.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c 
b/drivers/net/ieee802154/mac802154_hwsim.c
index 07a493dea11e..bf70ab892e69 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -735,10 +735,12 @@ static int hwsim_subscribe_all_others(struct hwsim_phy 
*phy)
return 0;
 
 me_fail:
-   list_for_each_entry(phy, _phys, list) {
+   rcu_read_lock();
+   list_for_each_entry_rcu(e, >edges, list) {
list_del_rcu(>list);
hwsim_free_edge(e);
}
+   rcu_read_unlock();
 sub_fail:
hwsim_edge_unsubscribe_me(phy);
return -ENOMEM;
-- 
2.11.0



[PATCH net-next] ieee802154: hwsim: fix rcu handling

2018-08-07 Thread Alexander Aring
This patch adds missing rcu_assign_pointer()/rcu_dereference() to used rcu
pointers. There was already a previous commit c5d99d2b35da ("ieee802154:
hwsim: fix rcu address annotation"), but there was more which was
pointed out on my side by using newest sparse version.

Cc: Stefan Schmidt 
Fixes: f25da51fdc38 ("ieee802154: hwsim: add replacement for fakelb")
Signed-off-by: Alexander Aring 
---
After I installed finally the newest sparse version I found more what kbuild
was pointed out.

I hope I did it right, not sure if I really need rcu functionality in these
case because protection by mutex but I make sparse silent.
At some places the resource isn't a shared resource at this moment.

Anyway in my case I want to use this driver to create easily multi-hop
scenarios, if somebody report things (or I hit it) which smells like some
memory in this area - I will try and help to fix it.

Newest sparse version from git is happy now and I hope kbuild bot as well.

I tested this patch with RPOVE_RCU enabled and tried to update these settings
while heavy loading in rcu protected xmit hotpath is occured, without any
issues so far.

Sorry again.

 drivers/net/ieee802154/mac802154_hwsim.c | 24 +++-
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c 
b/drivers/net/ieee802154/mac802154_hwsim.c
index f4e92054f7df..53f39435321e 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -110,7 +111,7 @@ static int hwsim_hw_channel(struct ieee802154_hw *hw, u8 
page, u8 channel)
pib->page = page;
pib->channel = channel;
 
-   pib_old = phy->pib;
+   pib_old = rtnl_dereference(phy->pib);
rcu_assign_pointer(phy->pib, pib);
kfree_rcu(pib_old, rcu);
return 0;
@@ -406,7 +407,7 @@ static struct hwsim_edge *hwsim_alloc_edge(struct hwsim_phy 
*endpoint, u8 lqi)
}
 
einfo->lqi = 0xff;
-   e->info = einfo;
+   rcu_assign_pointer(e->info, einfo);
e->endpoint = endpoint;
 
return e;
@@ -414,7 +415,13 @@ static struct hwsim_edge *hwsim_alloc_edge(struct 
hwsim_phy *endpoint, u8 lqi)
 
 static void hwsim_free_edge(struct hwsim_edge *e)
 {
-   kfree_rcu(e->info, rcu);
+   struct hwsim_edge_info *einfo;
+
+   rcu_read_lock();
+   einfo = rcu_dereference(e->info);
+   rcu_read_unlock();
+
+   kfree_rcu(einfo, rcu);
kfree_rcu(e, rcu);
 }
 
@@ -796,7 +803,7 @@ static int hwsim_add_one(struct genl_info *info, struct 
device *dev,
goto err_pib;
}
 
-   phy->pib = pib;
+   rcu_assign_pointer(phy->pib, pib);
phy->idx = idx;
INIT_LIST_HEAD(>edges);
 
@@ -829,10 +836,17 @@ static int hwsim_add_one(struct genl_info *info, struct 
device *dev,
 
 static void hwsim_del(struct hwsim_phy *phy)
 {
+   struct hwsim_pib *pib;
+
hwsim_edge_unsubscribe_me(phy);
 
list_del(>list);
-   kfree_rcu(phy->pib, rcu);
+
+   rcu_read_lock();
+   pib = rcu_dereference(phy->pib);
+   rcu_read_unlock();
+
+   kfree_rcu(pib, rcu);
 
ieee802154_unregister_hw(phy->hw);
ieee802154_free_hw(phy->hw);
-- 
2.11.0



[PATCH net-next] ieee802154: hwsim: fix rcu address annotation

2018-08-07 Thread Alexander Aring
This patch fixes the following sparse warning about mismatch rcu
attribute for address space annotation:

...
error: incompatible types in comparison expression (different modifiers)
error: incompatible types in comparison expression (different address spaces)
...

Some __rcu annotation was at non-pointers list head structures and one was
missing in edge information which is used by rcu_assign_pointer() to
update edge setting information.

Cc: Stefan Schmidt 
Fixes: f25da51fdc38 ("ieee802154: hwsim: add replacement for fakelb")
Signed-off-by: Alexander Aring 
---
Hopefully I did it right now. Sorry again.

 drivers/net/ieee802154/mac802154_hwsim.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c 
b/drivers/net/ieee802154/mac802154_hwsim.c
index 1982308b9b1c..f4e92054f7df 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -36,7 +36,7 @@ MODULE_LICENSE("GPL");
 static LIST_HEAD(hwsim_phys);
 static DEFINE_MUTEX(hwsim_phys_lock);
 
-static __rcu LIST_HEAD(hwsim_ifup_phys);
+static LIST_HEAD(hwsim_ifup_phys);
 
 static struct platform_device *mac802154hwsim_dev;
 
@@ -68,7 +68,7 @@ struct hwsim_edge_info {
 
 struct hwsim_edge {
struct hwsim_phy *endpoint;
-   struct hwsim_edge_info *info;
+   struct hwsim_edge_info __rcu *info;
 
struct list_head list;
struct rcu_head rcu;
@@ -81,7 +81,7 @@ struct hwsim_phy {
struct hwsim_pib __rcu *pib;
 
bool suspended;
-   struct list_head __rcu edges;
+   struct list_head edges;
 
struct list_head list;
struct list_head list_ifup;
-- 
2.11.0



Re: [net-next:master 1745/1753] drivers/net/ieee802154/mac802154_hwsim.c:39:14: sparse: incorrect type in initializer (different address spaces)

2018-08-07 Thread Alexander Aring
Hi,

On Tue, Aug 07, 2018 at 07:07:20AM +0800, kbuild test robot wrote:
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 
> master
> head:   de7de576eca204de9a38e2f6dafe6b7c1ddc85c1
> commit: f25da51fdc381ca2863248c7060b3662632f0872 [1745/1753] ieee802154: 
> hwsim: add replacement for fakelb
> reproduce:
> # apt-get install sparse
> git checkout f25da51fdc381ca2863248c7060b3662632f0872
> make ARCH=x86_64 allmodconfig
> make C=1 CF=-D__CHECK_ENDIAN__
> 
> 
> sparse warnings: (new ones prefixed by >>)
> 

oops sorry, I will take care of those immediately.

- Alex


[PATCHv2 wpan] net: 6lowpan: fix reserved space for single frames

2018-07-14 Thread Alexander Aring
This patch fixes patch add handling to take care tail and headroom for
single 6lowpan frames. We need to be sure we have a skb with the right
head and tailroom for single frames. This patch do it by using
skb_copy_expand() if head and tailroom is not enough allocated by upper
layer.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195059
Reported-by: David Palma 
Reported-by: Rabi Narayan Sahoo 
Signed-off-by: Alexander Aring 
---
changes since v2:
 skb to nskb, pointed out by stefan

 net/ieee802154/6lowpan/tx.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index e6ff5128e61a..ca53efa17be1 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c
@@ -265,9 +265,24 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct 
net_device *ldev)
/* We must take a copy of the skb before we modify/replace the ipv6
 * header as the header could be used elsewhere
 */
-   skb = skb_unshare(skb, GFP_ATOMIC);
-   if (!skb)
-   return NET_XMIT_DROP;
+   if (unlikely(skb_headroom(skb) < ldev->needed_headroom ||
+skb_tailroom(skb) < ldev->needed_tailroom)) {
+   struct sk_buff *nskb;
+
+   nskb = skb_copy_expand(skb, ldev->needed_headroom,
+  ldev->needed_tailroom, GFP_ATOMIC);
+   if (likely(nskb)) {
+   consume_skb(skb);
+   skb = nskb;
+   } else {
+   kfree_skb(skb);
+   return NET_XMIT_DROP;
+   }
+   } else {
+   skb = skb_unshare(skb, GFP_ATOMIC);
+   if (!skb)
+   return NET_XMIT_DROP;
+   }
 
ret = lowpan_header(skb, ldev, _size, _offset);
if (ret < 0) {
-- 
2.11.0



[PATCH wpan 2/2] net: mac802154: tx: expand tailroom if necessary

2018-07-02 Thread Alexander Aring
This patch is necessary if case of AF_PACKET or other socket interface
which I am aware of it and didn't allocated the necessary room.

Reported-by: David Palma 
Reported-by: Rabi Narayan Sahoo 
Signed-off-by: Alexander Aring 
---
 net/mac802154/tx.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 7e253455f9dd..bcd1a5e6ebf4 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -63,8 +63,21 @@ ieee802154_tx(struct ieee802154_local *local, struct sk_buff 
*skb)
int ret;
 
if (!(local->hw.flags & IEEE802154_HW_TX_OMIT_CKSUM)) {
-   u16 crc = crc_ccitt(0, skb->data, skb->len);
+   struct sk_buff *nskb;
+   u16 crc;
+
+   if (unlikely(skb_tailroom(skb) < IEEE802154_FCS_LEN)) {
+   nskb = skb_copy_expand(skb, 0, IEEE802154_FCS_LEN,
+  GFP_ATOMIC);
+   if (likely(nskb)) {
+   consume_skb(skb);
+   skb = nskb;
+   } else {
+   goto err_tx;
+   }
+   }
 
+   crc = crc_ccitt(0, skb->data, skb->len);
put_unaligned_le16(crc, skb_put(skb, 2));
}
 
-- 
2.11.0



[PATCH wpan 1/2] net: 6lowpan: fix reserved space for single frames

2018-07-02 Thread Alexander Aring
This patch fixes patch add handling to take care tail and headroom for
single 6lowpan frames. We need to be sure we have a skb with the right
head and tailroom for single frames. This patch do it by using
skb_copy_expand() if head and tailroom is not enough allocated by upper
layer.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195059
Reported-by: David Palma 
Reported-by: Rabi Narayan Sahoo 
Signed-off-by: Alexander Aring 
---
 net/ieee802154/6lowpan/tx.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/net/ieee802154/6lowpan/tx.c b/net/ieee802154/6lowpan/tx.c
index e6ff5128e61a..d0c4d220de08 100644
--- a/net/ieee802154/6lowpan/tx.c
+++ b/net/ieee802154/6lowpan/tx.c
@@ -265,9 +265,24 @@ netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct 
net_device *ldev)
/* We must take a copy of the skb before we modify/replace the ipv6
 * header as the header could be used elsewhere
 */
-   skb = skb_unshare(skb, GFP_ATOMIC);
-   if (!skb)
-   return NET_XMIT_DROP;
+   if (unlikely(skb_headroom(skb) < ldev->needed_headroom ||
+skb_tailroom(skb) < ldev->needed_tailroom)) {
+   struct sk_buff *nskb;
+
+   nskb = skb_copy_expand(skb, ldev->needed_headroom,
+  ldev->needed_tailroom, GFP_ATOMIC);
+   if (likely(skb)) {
+   consume_skb(skb);
+   skb = nskb;
+   } else {
+   kfree_skb(skb);
+   return NET_XMIT_DROP;
+   }
+   } else {
+   skb = skb_unshare(skb, GFP_ATOMIC);
+   if (!skb)
+   return NET_XMIT_DROP;
+   }
 
ret = lowpan_header(skb, ldev, _size, _offset);
if (ret < 0) {
-- 
2.11.0



Re: netdevice notifier and device private data

2018-06-12 Thread Alexander Aring
Hi,

On Sun, Jun 10, 2018 at 10:09:39PM -0400, Michael Richardson wrote:
> 
> Alexander Aring  wrote:
> >> It totally seems like broken behaviour.  Maybe it's not even
> >> intentional.  Maybe they are just foobar.
> 
> > They simple don't know what they doing... somebody thought 6LoWPAN need
> > to be 6LoWPAN, but they actually don't use the 6LoWPAN handling inside
> > the kernel. _Except_ they doing out of tree stuff which I don't
> > believe.
> 
> So, it seems like this ioctl() should be disabled, or restricted to cases
> that actually work.  hate to break their code, but if it's broken anyway, at
> least the kernel won't crash under them.
> 

before we breaking their software I will gentle ask before why they
doing that and I get a good reason then. Then we look more how we deal
with an illegal read/dereference in dev->priv.

I will figure out how I can do that over github.

- Alex


Re: netdevice notifier and device private data

2018-06-10 Thread Alexander Aring
Hi,

On Sat, Jun 09, 2018 at 03:01:18PM -0400, Michael Richardson wrote:
> 
> Alexander Aring  wrote:
> > Futhermore user space programs e.g. radvd will do 6lowpan specific
> > handling on 6lowpan dev->type, it will not work either on tun
> > devices.
> 
> > I know that wpantund from NestLabs do this switch, I am very
> > curious about the reason but I think they do it because the name
> > is 6LoWPAN. But wpantund is just a SLIP like protocol with
> > additional radio/foo commands.
> 
> How do they change it then, and what does it do?

They change it with the ioctl() of tun characte device, see [0].

What it does, it just changing the interface type to something else,
also there is no check at all that Linux has this interface type.

User space software e.g. radvd [1] will evaluate this type and doing
specific handling. Obviously changing it to 6LoWPAN and using this code
will confuse everything, because the handling makes only sense for a
6LoWPAN Linux interface which actually also use the 6LoWPAN subsystem.

They just using tun as all other to feed a IPv6 stack on a remote
microcontroller e.g. openthread, contiki, riot. via slip. (wpantund also
allow some radio, foo configuration).

> It totally seems like broken behaviour.  Maybe it's not even intentional.
> Maybe they are just foobar.
> 

They simple don't know what they doing... somebody thought 6LoWPAN need
to be 6LoWPAN, but they actually don't use the 6LoWPAN handling inside
the kernel. _Except_ they doing out of tree stuff which I don't believe.

According to [0] it also works with tun default (I suppsoe raw IPv6),
because ifdef. And they should not change it because they don't use
in-kernel 6LoWPAN functionality.

I really think that this tun/tap feature makes a lot of trouble for some
type changes. I probably introduce lowpan_dev pointer to netdevice and
then check if it's really a 6LoPWAN interface, a dev->type will not
garantuee anymore you have a 6LoWPAN interface. At least in user space
it's not possible to have a check if you really have a 6LoWPAN interface.

- Alex

[0] https://github.com/openthread/wpantund/blob/master/src/util/tunnel.c#L180
[1] https://github.com/reubenhwk/radvd/blob/master/device-linux.c#L75


Re: netdevice notifier and device private data

2018-06-09 Thread Alexander Aring
Hi,

On Fri, Jun 08, 2018 at 03:37:44PM -0400, Michael Richardson wrote:
> 
> Alexander Aring  wrote:
> Alex> I already see code outside who changed tun netdevice to the
> Alex> ARPHRD_6LOWPAN type and I suppose they running into this
> Alex> issue.  (Btw: I don't know why somebody wants to changed that
> Alex> type to ARPHRD_6LOWPAN on tun).
> 
> so that they can have the kernel do 6lowpan processing, emitting 6lowPAN
> packets into userspace to be transfered into a radio via some proprietary
> interface (including, for instance SLIP over USB cable to Contiki or OpenWSN 
> stack, 
> set up to act as radio only)
> 

No, the datapath doesn't change. If the user space evaluate the
dev->type (there exists some ioctl() for it) it will assume it has a
6LoWPAN type interface.

A lot of user space software outside will doing interface specific
handling after detect the type. E.g. wireshark will select some dissector
handling.

On a tun interface and switch to 6LoWPAN it will not change much the
dissector view, because both raw IPv6 packets on datapath. For me as
6LoWPAN maintainer it makes no sense to switch to it. Currently
some netdevice notifier will crash (if you a lucky it will not).

Futhermore user space programs e.g. radvd will do 6lowpan specific
handling on 6lowpan dev->type, it will not work either on tun devices.

I know that wpantund from NestLabs do this switch, I am very curious
about the reason but I think they do it because the name is 6LoWPAN. But
wpantund is just a SLIP like protocol with additional radio/foo commands.

---

According to the people who say "I like to have a 6LoWPAN tun device,
that would be nice" - I don't know how this will ever work since 6LoWPAN
header highly depends on MAC header information. Tun devices works
because IP architecture allows a separation from MAC layer. I already
saw protocols at IETF where MAC header information are needed on top of
UDP payload in case of 6LoWPAN. (I talked about that at last netdev in
Montreal).

Bluetooth wanted to add a tun 6lowpan interface and I was curious how
this works. At the end it was a "Bluetooth mapping to ethernet header"
(not as tunnel, as propagated). I was not acking it, because if there
are protocols who needs more information than just what you can map to
ethernet... it will not work. At least it will also not work with IEEE
802.15.4 at all. They was just lucky that Bluetooth and ethernet use the
same mac address length (And I had some questions to the multicast bit
as well).

Tunnel might work to get mac information. But so far 6loWPAN works it is
that you have a L2 underlaying interface and on top (ip link set master)
a raw IPv6 interface which do the adaptation automatically as a protocol
translation (That's why I cannot understand Bluetooth 6LoWPAN use tx
queues on their 6LoWPAN interface, they need to fix the queue in the
underlaying L2 interface).

As an alternative solution I think it should be something done like TAP
like interface per subsystem. I mean NO ETHERTNET, but the ethernet in
TAP interfaces out and replace it with Bluetooth or IEEE 802.15.4.
I might can easily create a simple TAP IEEE 802.15.4 to show what I
mean.

With an IEEE 802.15.4 TAP device and a 6lowpan interface on top you can
realize your use case and pass 802.15.4 L2 frames to device node -> pops
up at 6LoPWAN interface and send IPv6 stuff and you can read on device
node.

I am still in the opinion the L2 TAP like interface is the way to go to
offer such feature.

- Alex


Re: netdevice notifier and device private data

2018-06-08 Thread Alexander Aring
Hi Stephen,

On Fri, Jun 08, 2018 at 11:14:57AM -0700, Stephen Hemminger wrote:
...
> 
> notifiers are always called with RTNL mutex held
> and dev->type should not change unless RTNL is held.

thanks for you answer. I am not talking about any race between notifiers
vs dev->type change.

I am talking that dev->type was already changed and a upcoming notifier ends
in undefined behaviour when it derefences dev->priv. I have some notifier
which maps a cast from dev->type to a specific structure at dev->priv. This
structure is not there in tap/tun devices if they changed to "my" dev->type
and the notifier occurs.

- Alex


netdevice notifier and device private data

2018-06-08 Thread Alexander Aring
Hey netdev community,

I am trying to solve some issue which Eric Dumazet points to me by
commit ca0edb131bdf ("ieee802154: 6lowpan: fix possible NULL deref in
lowpan_device_event()").

The issue is that dev->type can be changed during runtime. We don't have
any problems with the netdevice notifier which Eric Dumazet fixed. I am
bother with another netdevice notifier which is broken because the same
tun/tap feature and I don't have any dev->$SUBSYSTEM_DEV_POINTER to check
if this is my netdevice type.

This netdevice notifier will access the dev->priv area which is only
available for the dev->type which was allocated and initialized with the
right dev->priv room. If a tap/tun netdevice changed their dev->type I
might have an illegal read of netdev->priv and I can't confirm that it
has the data which I cast to it. The reason for that is that tap/tun
netdevices doesn't run my netdevice init.

I already see code outside who changed tun netdevice to the
ARPHRD_6LOWPAN type and I suppose they running into this issue.
(Btw: I don't know why somebody wants to changed that type to
ARPHRD_6LOWPAN on tun).

My question is:

How we deal with that? Is it forbidden to access dev->priv from a
global netdevice notifier which only checks for dev->type?

I could solve it like Eric Dumazet and introduce a special
dev->$SUBSYSTEM_DEV_POINTER and check on it if set. At least tun/tap
will not set these pointers, then I am sure the netdevice was running
through my init function. Seems for me the best solution right now and
I think I will go for it.

I assumed before the data of dev->priv is binded to dev->type.
This tun/tap feature will break at least my handling and I am not sure
if there are others users which using dev->priv in netdevice notifier
and don't check on dev->$SUBSYSTEM_DEV_POINTER if they have one.

Thanks for everybody in advance to solve this issue.

- Alex


Re: [PATCH net] net: ipv6: ip6_output: alloc skb with tailroom

2018-06-07 Thread Alexander Aring
Hi,

On Wed, Jun 06, 2018 at 04:26:19PM -0400, Willem de Bruijn wrote:
> On Wed, Jun 6, 2018 at 2:11 PM, David Miller  wrote:
> > From: Alexander Aring 
> > Date: Wed, 6 Jun 2018 14:09:20 -0400
> >
> >> okay, then you want to have this patch for net-next? As an optimization?
> >>
> >> Of course, when it's open again.
> >
> > Like you, I have questions about where this adjustment is applied and
> > why.  So I'm not sure yet.
> >
> > For example, only IPV6 really takes it into consideration and as you
> > saw only really for the fragmentation path and not the normal output
> > path.
> >
> > This needs more consideration and investigation.
> 
> This is the unconditional skb_put in ieee802154_tx. In many cases
> there is some tailroom due to SKB_DATA_ALIGN in __alloc_skb,
> so it may take a specific case to not have even 2 bytes of tailroom
> available.

Yes it's in ieee802154_tx, but we need tailroom not just for checksum.
The bugreport is related to the two bytes of tailroom, because virtual
hardware doing checksum by software. The most real transceivers offload
this feature, so zero tailroom is needed.

I will of course add checks before adding L2 header for headroom and
tailroom in related subsystem code.

In IEEE 802.15.4 and secured enabled frames we need a MIC field at the
end of the frame. In worst case this can be 16 bytes.

I looked ethernet macsec feature and it seems they need to have a similar
reseved tailroom which is 16 bytes by default (max 32 bytes).

Maybe it's worth to take care for the tailroom in this path since it's
not just 2 bytes in some cases.

---

Meanwhile I think I found a bug in macsec, I cc Sabrina here:

diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 7de88b33d5b9..687323c0caf5 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -522,7 +522,7 @@ static bool macsec_validate_skb(struct sk_buff *skb, u16 
icv_len)
 }
 
 #define MACSEC_NEEDED_HEADROOM (macsec_extra_len(true))
-#define MACSEC_NEEDED_TAILROOM MACSEC_STD_ICV_LEN
+#define MACSEC_NEEDED_TAILROOM MACSEC_MAX_ICV_LEN
 
 static void macsec_fill_iv(unsigned char *iv, sci_t sci, u32 pn)
 {

---

MACSEC_NEEDED_TAILROOM is the define to check and run skb_copy_expand()
and should use the ?worst case? or the the value (icv_len + ?extra_foo?)
is set as runtime generation on newlink.

I see that in macsec_newlink() following code:

if (data && data[IFLA_MACSEC_ICV_LEN])
icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]);

so the user can change it to (even a value above 32?, there is no check
for that). Anyway everything higher than MACSEC_STD_ICV_LEN could run
into a skb_over_panic().

- Alex


Re: [PATCH net] net: ipv6: ip6_output: alloc skb with tailroom

2018-06-06 Thread Alexander Aring
Hi,

On Wed, Jun 06, 2018 at 01:53:39PM -0400, David Miller wrote:
> From: Alexander Aring 
> Date: Tue,  5 Jun 2018 18:04:04 -0400
> 
> > This patch adds care about tailroom length for allocate a skb from ipv6
> > level stack. In case of 6lowpan we had the problem the skb runs into a
> > skb_over_panic() in some special length cases. The root was there was no
> > tailroom allocated for the IEEE 802.15.4 checksum, although we had
> > the necessary tailroom specified inside the netdev structure.
> > 
> > Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195059
> > Reported-by: David Palma 
> > Reported-by: Rabi Narayan Sahoo 
> > Signed-off-by: Alexander Aring 
> 
> needed_tailroom is an optimization to avoid SKB reallocations
> and adjustments, it is not a guarantee.
> 

okay, then you want to have this patch for net-next? As an optimization?

Of course, when it's open again.

> If you are seeing crashes, it means code is assuming something which
> is not to be assumed.
> 
> Whatever code is involved, it needs to check that the necessary
> tailroom is there and reallocate if necessary, rather than
> blindly pushing past the end of the SKB data.
> 

I see, I will add checks and reallocs (if necessary) in the underlaying
subsystem level.

Thanks for clarifying this.

- Alex


[PATCH net] net: ipv6: ip6_output: alloc skb with tailroom

2018-06-05 Thread Alexander Aring
This patch adds care about tailroom length for allocate a skb from ipv6
level stack. In case of 6lowpan we had the problem the skb runs into a
skb_over_panic() in some special length cases. The root was there was no
tailroom allocated for the IEEE 802.15.4 checksum, although we had
the necessary tailroom specified inside the netdev structure.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195059
Reported-by: David Palma 
Reported-by: Rabi Narayan Sahoo 
Signed-off-by: Alexander Aring 
---
Hi,

nasty bug, I suppose this is the correct fix to my last question for
what dev->needed_tailroom is designed for.

I added two Reported-by here, David Palma reported this bug one year ago
and I didn't had time to investigate. Interesting is that he told this
bug doesn't occur (in case of 6lowpan 802.15.4) on 32 bit systems.
Maybe alignment is related to the question why it works on 32 bit.

Anyway, a week ago "Rabi Narayan Sahoo" reported the bug again and I
needed to investigate something "why", since I also use a 64 bit vm.

David Palma did a nice job for reproduce this bug and he (I think) lives
at least one year with it, so I put him at first.

Anyway, Rabi Narayan Sahoo was very very close to fix it and found the
right code part which I also found. I read his mail afterwards because
it was received messed on the linux-wpan mailinglist. So it's correct
to give him credits too. :-)

I hope there are no other cases where tailroom is missing.
The second one is not needed to fix my bug but I think we need it there.
Also hh_len is also used inside a skb_resever() in this function,
but this is for headroom only.

- Alex

 net/ipv6/ip6_output.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 7b6d1689087b..b4e521cfe3cf 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1262,6 +1262,7 @@ static int __ip6_append_data(struct sock *sk,
int exthdrlen = 0;
int dst_exthdrlen = 0;
int hh_len;
+   int t_len;
int copy;
int err;
int offset = 0;
@@ -1283,6 +1284,7 @@ static int __ip6_append_data(struct sock *sk,
orig_mtu = mtu;
 
hh_len = LL_RESERVED_SPACE(rt->dst.dev);
+   t_len = rt->dst.dev->needed_tailroom;
 
fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
(opt ? opt->opt_nflen : 0);
@@ -1425,13 +1427,13 @@ static int __ip6_append_data(struct sock *sk,
}
if (transhdrlen) {
skb = sock_alloc_send_skb(sk,
-   alloclen + hh_len,
+   alloclen + hh_len + t_len,
(flags & MSG_DONTWAIT), );
} else {
skb = NULL;
if (refcount_read(>sk_wmem_alloc) + 
wmem_alloc_delta <=
2 * sk->sk_sndbuf)
-   skb = alloc_skb(alloclen + hh_len,
+   skb = alloc_skb(alloclen + hh_len + 
t_len,
sk->sk_allocation);
if (unlikely(!skb))
err = -ENOBUFS;
-- 
2.11.0



ndo_star_xmit() - resevered head and tailroom

2018-06-01 Thread Alexander Aring
Hi netdev community,

I am again on bug fixing in 6lowpan branch and thought that my
needed_headroom and needed_tailroom of net_device are available inside
my ndo_start_xmit() callback.

In case of a UDP socket, it was not the case. I send a fix now to use
skb_expand_copy() to make sure this space is available. (I need to
unshare the buffer anyway).

I am just curious is this suppose to work like that? I cannot believe
that I need to run a realloc() inside my ndo_start_xmit(). If possible,
when the net_device is known at socket layer it should allocate the
necessary space and I thought this is the designed transmit flow.

- Alex


Re: [PATCH v4 net-next 00/19] inet: frags: bring rhashtables to IP defrag

2018-05-28 Thread Alexander Aring
Hi,

On Mon, May 28, 2018 at 12:12:42PM +0300, Tariq Toukan wrote:
> 
> 
> On 01/04/2018 6:25 AM, David Miller wrote:
> > From: Eric Dumazet 
> > Date: Sat, 31 Mar 2018 12:58:41 -0700
> > 
> > > IP defrag processing is one of the remaining problematic layer in linux.
> > > 
> > > It uses static hash tables of 1024 buckets, and up to 128 items per 
> > > bucket.
> > > 
> > > A work queue is supposed to garbage collect items when host is under 
> > > memory
> > > pressure, and doing a hash rebuild, changing seed used in hash 
> > > computations.
> > > 
> > > This work queue blocks softirqs for up to 25 ms when doing a hash rebuild,
> > > occurring every 5 seconds if host is under fire.
> > > 
> > > Then there is the problem of sharing this hash table for all netns.
> > > 
> > > It is time to switch to rhashtables, and allocate one of them per netns
> > > to speedup netns dismantle, since this is a critical metric these days.
> > > 
> > > Lookup is now using RCU, and 64bit hosts can now provision whatever amount
> > > of memory needed to handle the expected workloads.
> >   ...
> > 
> > Series applied, thanks Eric.
> > 
> 
> Hi Eric,
> 
> Recently my colleague (Moshe Shemesh) got a failure in upstream regression,
> which is related to this patchset. We don’t see the failure before it was
> merged.
> We checked again on net-next (from May 24th), it still reproduces.
> 
> The test case runs netperf with ipv6 udp single stream (64K message size).
> After the change we see huge packet loss:
> 145,134 messages failed out of 145,419 (only 285 fully received)
> 

as somebody who had similar issues with this patch series I can tell you
about what happened for the 6LoWPAN fragmentation.

The issue sounds similar, but there is too much missing information here
to say something about if you have exactly the issue which we had.

Our problem:

The patch series uses memcmp() to compare hash keys, we had some padding
bytes in our hash key and it occurs that we had sometimes random bytes
in this structure when it's put on stack. We solved it by a struct
foo_key bar = {}, which in case of gcc it _seems_ it makes a whole
memset(bar, 0, ..) on the structure.

I asked on the netdev mailinglist how to deal with this problem in
general, because = {} works in case of gcc, others compilers may have a
different handling or even gcc will changes this behaviour in future.
I got no reply so I did what it works for me. :-)

At least maybe a memcmp() on structures should never be used, it should
be compared by field. I would recommend this way when the compiler is
always clever enough to optimize it in some cases, but I am not so a
compiler expert to say anything about that.

I checked the hash key structures for x86_64 and pahole, so far I didn't
find any padding bytes there, but it might be different on
architectures or ?compiler?.

Additional useful information to check if you running into the same problem
would be:

 - Which architecture do you use?

 - Do you have similar problems with a veth setup?

You could also try this:

diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index b939b94e7e91..40ece9ab8b12 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -142,19 +142,19 @@ static void ip6_frag_expire(struct timer_list *t)
 static struct frag_queue *
 fq_find(struct net *net, __be32 id, const struct ipv6hdr *hdr, int iif)
 {
-   struct frag_v6_compare_key key = {
-   .id = id,
-   .saddr = hdr->saddr,
-   .daddr = hdr->daddr,
-   .user = IP6_DEFRAG_LOCAL_DELIVER,
-   .iif = iif,
-   };
+   struct frag_v6_compare_key key = {};
struct inet_frag_queue *q;
 
if (!(ipv6_addr_type(>daddr) & (IPV6_ADDR_MULTICAST |
IPV6_ADDR_LINKLOCAL)))
key.iif = 0;
 
+   key.id = id;
+   key.saddr = hdr->saddr;
+   key.daddr = hdr->daddr;
+   key.user = IP6_DEFRAG_LOCAL_DELIVER;
+   key.iif = iif;
+
q = inet_frag_find(>ipv6.frags, );
if (!q)
return NULL;

- Alex


Re: Kernel panic on kernel-3.10.0-693.21.1.el7 in ndisc.h

2018-05-14 Thread Alexander Aring
Hi,

On Mon, May 14, 2018 at 11:40:02AM -0400, Alexander Aring wrote:
...
> I cannot help you with such a dinosaurs kernel. Please try it with the
> latest one and check if the problem still exists.
> 

and please don't write me private e-mails, always use the mailingst.

Thanks.

- Alex


Re: Kernel panic on kernel-3.10.0-693.21.1.el7 in ndisc.h

2018-05-14 Thread Alexander Aring
Hi,

On Sun, May 13, 2018 at 02:35:07PM +0300, Roman Makhov wrote:
> Hello,
> 
> We have a problem with Kernel panic after upgrade from CentOS 7.3
> (kernel-3.10.0-514.el7) to CentOS 7.4 (kernel-3.10.0-693.21.1.el7).
> It occurs when we have the incoming traffic from other nodes and we
> are performing the re-configuration of IPv6 interfaces.
> 
> It is high-availability system without 802.15.4 support.
> 
> The log of crash:
> =
> #10 [88043fc03cf0] async_page_fault at 816b7798
> [exception RIP: ndisc_send_rs+238]
> RIP: 8166575e  RSP: 88043fc03da8  RFLAGS: 00010202
> RAX: 0002  RBX: 88042caa9000  RCX: 0001
> RDX:   RSI: 0200  RDI: 816534f7
> RBP: 88043fc03dd0   R8:    R9: 81e9f1c0
> R10: 0002  R11: 88043fc03da8  R12: 0008
> R13: 0006  R14: 88043fc03de0  R15: 81772410
> ORIG_RAX:   CS: 0010  SS: 0018
> #11 [88043fc03da0] ndisc_send_rs at 81665704
> =
> 
> I see that crash points on ndisc.h, it is ndisc_ops_opt_addr_space()
> in function:
> =
> crash> kmem 8166575e
> 8166575e (T) ndisc_send_rs+238
> /usr/src/debug/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/include/net/ndisc.h:
> 251
> 
>   PAGEPHYSICAL  MAPPING   INDEX CNT FLAGS
> ea059940   166500000  1 1f0400 
> reserved
> crash>
> =
> 
> I checked the difference between 514 and 693 kernels is in the patch
> https://patchwork.kernel.org/patch/9179229/ .
> 
> Any suggesions about what I am doing wrong are welcome.
> 

Me as original author of this patch,

I cannot help you with such a dinosaurs kernel. Please try it with the
latest one and check if the problem still exists.

- Alex


struct stack initialization and padding bits

2018-04-27 Thread Alexander Aring
Hi,

I currently struggle with an issue with latest changes in inet_frag api.
I struggle at two points [0] which do a struct stack initialization and
[1] who do a memcmp() on this structure.

The struct "frag_lowpan_compare_key" has padding bits which are in my
case of system and compiler random initialized.

I wrote a small userspace testcase to confirm that (see below of this
mail). It compares with memcmp() a struct init by memset and per field
assign to a struct init like [0]. Of course I have 3 bytes hole after the
foo field.

My output is:

...
23:85:00:00:42:00:00:00
23:85:00:00:42:00:00:00
23:85:00:00:42:00:00:00
bingos 100
23:00:00:00:42:00:00:00

So all of my 100 tries are different between by field compare and memcmp().

My question is how kernel code handles this now when there is padding bytes?
According my simple test (if it's correct) we cannot use the style according
to [0].

I searched and found [3] which said the style of [0] should make
padding bits to zero. Also it was pointed out [4] that the compiler may
change this behavior.

- Alex

#include 
#include 
#include 
#include 

struct foo {
uint8_t foo;
uint32_t bar;
};

static int decdump(const void *src, size_t size)
{
const unsigned char *buf = src;
int i;

for (i = 0; i < size; i++) {
if (i != size - 1)
printf("%02d:", buf[i]);
else
printf("%02d", buf[i]);
}

printf("\n");
}

int main(int argc, const char *argv[])
{
struct foo test2;
uint32_t bingo = 0;
int i, rc;

memset(, 0, sizeof(test2));
test2.foo = 23;
test2.bar = 42;

for (i = 0; i < 100; i++) {
struct foo test = {
.foo = 23,
.bar = 42,
};

rc = !!memcmp(, , sizeof(test));

if ((test2.foo == test.foo) &&
(test2.bar == test.bar)) {
if (rc) {
bingo++;
decdump(, sizeof(test));
}
}
}

printf("bingos %" PRIu32 "\n", bingo);
decdump(, sizeof(test2));
  
return 0;
}

[0] 
https://elixir.bootlin.com/linux/v4.17-rc2/source/net/ieee802154/6lowpan/reassembly.c#L78
[1] 
https://elixir.bootlin.com/linux/v4.17-rc2/source/net/ieee802154/6lowpan/reassembly.c#L594
[3] https://lwn.net/Articles/417994/
[4] https://lwn.net/Articles/417996/


[PATCHv4 net 3/3] net: sched: ife: check on metadata length

2018-04-20 Thread Alexander Aring
This patch checks if sk buffer is available to dererence ife header. If
not then NULL will returned to signal an malformed ife packet. This
avoids to crashing the kernel from outside.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 net/ife/ife.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7fbe70a0af4b..13bbf8cb6a39 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -69,6 +69,9 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
int total_pull;
u16 ifehdrln;
 
+   if (!pskb_may_pull(skb, skb->dev->hard_header_len + IFE_METAHDRLEN))
+   return NULL;
+
ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
ifehdrln = ntohs(ifehdr->metalen);
total_pull = skb->dev->hard_header_len + ifehdrln;
-- 
2.11.0



[PATCHv4 net 1/3] net: sched: ife: signal not finding metaid

2018-04-20 Thread Alexander Aring
We need to record stats for received metadata that we dont know how
to process. Have find_decode_metaid() return -ENOENT to capture this.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 net/sched/act_ife.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index a5994cf0512b..49b8ab551fbe 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -652,7 +652,7 @@ static int find_decode_metaid(struct sk_buff *skb, struct 
tcf_ife_info *ife,
}
}
 
-   return 0;
+   return -ENOENT;
 }
 
 static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
-- 
2.11.0



[PATCHv4 net 2/3] net: sched: ife: handle malformed tlv length

2018-04-20 Thread Alexander Aring
There is currently no handling to check on a invalid tlv length. This
patch adds such handling to avoid killing the kernel with a malformed
ife packet.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 35 +--
 net/sched/act_ife.c |  7 ++-
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/net/ife.h b/include/net/ife.h
index 44b9c00f7223..e117617e3c34 100644
--- a/include/net/ife.h
+++ b/include/net/ife.h
@@ -12,7 +12,8 @@
 void *ife_encode(struct sk_buff *skb, u16 metalen);
 void *ife_decode(struct sk_buff *skb, u16 *metalen);
 
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 
*totlen);
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen);
 int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval);
 
diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7d1ec76e7f43..7fbe70a0af4b 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -92,12 +92,43 @@ struct meta_tlvhdr {
__be16 len;
 };
 
+static bool __ife_tlv_meta_valid(const unsigned char *skbdata,
+const unsigned char *ifehdr_end)
+{
+   const struct meta_tlvhdr *tlv;
+   u16 tlvlen;
+
+   if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end))
+   return false;
+
+   tlv = (const struct meta_tlvhdr *)skbdata;
+   tlvlen = ntohs(tlv->len);
+
+   /* tlv length field is inc header, check on minimum */
+   if (tlvlen < NLA_HDRLEN)
+   return false;
+
+   /* overflow by NLA_ALIGN check */
+   if (NLA_ALIGN(tlvlen) < tlvlen)
+   return false;
+
+   if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end))
+   return false;
+
+   return true;
+}
+
 /* Caller takes care of presenting data in network order
  */
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen)
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen)
 {
-   struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata;
+   struct meta_tlvhdr *tlv;
+
+   if (!__ife_tlv_meta_valid(skbdata, ifehdr_end))
+   return NULL;
 
+   tlv = (struct meta_tlvhdr *)skbdata;
*dlen = ntohs(tlv->len) - NLA_HDRLEN;
*attrtype = ntohs(tlv->type);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 49b8ab551fbe..8527cfdc446d 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -682,7 +682,12 @@ static int tcf_ife_decode(struct sk_buff *skb, const 
struct tc_action *a,
u16 mtype;
u16 dlen;
 
-   curr_data = ife_tlv_meta_decode(tlv_data, , , NULL);
+   curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, ,
+   , NULL);
+   if (!curr_data) {
+   qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
+   return TC_ACT_SHOT;
+   }
 
if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
/* abuse overlimits to count when we receive metadata
-- 
2.11.0



[PATCHv4 net 0/3] net: sched: ife: malformed ife packet fixes

2018-04-20 Thread Alexander Aring
As promised at netdev 2.2 tc workshop I am working on adding scapy support for
tdc testing. It is still work in progress. I will submit the patches to tdc
later (they are not in good shape yet). The good news is I have been able to
find bugs which normal packet testing would not be able to find.
With fuzzy testing I was able to craft certain malformed packets that IFE
action was not able to deal with. This patch set fixes those bugs.

changes since v4:
 - use pskb_may_pull before pointer assign

changes since v3:
 - use pskb_may_pull

changes since v2:
 - remove inline from __ife_tlv_meta_valid
 - add const to cast to meta_tlvhdr
 - add acked and reviewed tags

Alexander Aring (3):
  net: sched: ife: signal not finding metaid
  net: sched: ife: handle malformed tlv length
  net: sched: ife: check on metadata length

 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 38 --
 net/sched/act_ife.c |  9 +++--
 3 files changed, 45 insertions(+), 5 deletions(-)

-- 
2.11.0



[PATCHv3 net 2/3] net: sched: ife: handle malformed tlv length

2018-04-19 Thread Alexander Aring
There is currently no handling to check on a invalid tlv length. This
patch adds such handling to avoid killing the kernel with a malformed
ife packet.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 35 +--
 net/sched/act_ife.c |  7 ++-
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/net/ife.h b/include/net/ife.h
index 44b9c00f7223..e117617e3c34 100644
--- a/include/net/ife.h
+++ b/include/net/ife.h
@@ -12,7 +12,8 @@
 void *ife_encode(struct sk_buff *skb, u16 metalen);
 void *ife_decode(struct sk_buff *skb, u16 *metalen);
 
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 
*totlen);
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen);
 int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval);
 
diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7d1ec76e7f43..7fbe70a0af4b 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -92,12 +92,43 @@ struct meta_tlvhdr {
__be16 len;
 };
 
+static bool __ife_tlv_meta_valid(const unsigned char *skbdata,
+const unsigned char *ifehdr_end)
+{
+   const struct meta_tlvhdr *tlv;
+   u16 tlvlen;
+
+   if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end))
+   return false;
+
+   tlv = (const struct meta_tlvhdr *)skbdata;
+   tlvlen = ntohs(tlv->len);
+
+   /* tlv length field is inc header, check on minimum */
+   if (tlvlen < NLA_HDRLEN)
+   return false;
+
+   /* overflow by NLA_ALIGN check */
+   if (NLA_ALIGN(tlvlen) < tlvlen)
+   return false;
+
+   if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end))
+   return false;
+
+   return true;
+}
+
 /* Caller takes care of presenting data in network order
  */
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen)
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen)
 {
-   struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata;
+   struct meta_tlvhdr *tlv;
+
+   if (!__ife_tlv_meta_valid(skbdata, ifehdr_end))
+   return NULL;
 
+   tlv = (struct meta_tlvhdr *)skbdata;
*dlen = ntohs(tlv->len) - NLA_HDRLEN;
*attrtype = ntohs(tlv->type);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 49b8ab551fbe..8527cfdc446d 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -682,7 +682,12 @@ static int tcf_ife_decode(struct sk_buff *skb, const 
struct tc_action *a,
u16 mtype;
u16 dlen;
 
-   curr_data = ife_tlv_meta_decode(tlv_data, , , NULL);
+   curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, ,
+   , NULL);
+   if (!curr_data) {
+   qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
+   return TC_ACT_SHOT;
+   }
 
if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
/* abuse overlimits to count when we receive metadata
-- 
2.11.0



[PATCHv3 net 3/3] net: sched: ife: check on metadata length

2018-04-19 Thread Alexander Aring
This patch checks if sk buffer is available to dererence ife header. If
not then NULL will returned to signal an malformed ife packet. This
avoids to crashing the kernel from outside.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 net/ife/ife.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7fbe70a0af4b..570a18d4ca32 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -70,6 +70,9 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
u16 ifehdrln;
 
ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
+   if (!pskb_may_pull(skb, skb->dev->hard_header_len + IFE_METAHDRLEN))
+   return NULL;
+
ifehdrln = ntohs(ifehdr->metalen);
total_pull = skb->dev->hard_header_len + ifehdrln;
 
-- 
2.11.0



[PATCHv3 net 1/3] net: sched: ife: signal not finding metaid

2018-04-19 Thread Alexander Aring
We need to record stats for received metadata that we dont know how
to process. Have find_decode_metaid() return -ENOENT to capture this.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 net/sched/act_ife.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index a5994cf0512b..49b8ab551fbe 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -652,7 +652,7 @@ static int find_decode_metaid(struct sk_buff *skb, struct 
tcf_ife_info *ife,
}
}
 
-   return 0;
+   return -ENOENT;
 }
 
 static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
-- 
2.11.0



[PATCHv3 net 0/3] net: sched: ife: malformed ife packet fixes

2018-04-19 Thread Alexander Aring
As promised at netdev 2.2 tc workshop I am working on adding scapy support for
tdc testing. It is still work in progress. I will submit the patches to tdc
later (they are not in good shape yet). The good news is I have been able to
find bugs which normal packet testing would not be able to find.
With fuzzy testing I was able to craft certain malformed packets that IFE
action was not able to deal with. This patch set fixes those bugs.

changes since v3:
 - use pskb_may_pull

changes since v2:
 - remove inline from __ife_tlv_meta_valid
 - add const to cast to meta_tlvhdr
 - add acked and reviewed tags

Alexander Aring (3):
  net: sched: ife: signal not finding metaid
  net: sched: ife: handle malformed tlv length
  net: sched: ife: check on metadata length

 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 38 --
 net/sched/act_ife.c |  9 +++--
 3 files changed, 45 insertions(+), 5 deletions(-)

-- 
2.11.0



[PATCHv2 net 1/3] net: sched: ife: signal not finding metaid

2018-04-19 Thread Alexander Aring
We need to record stats for received metadata that we dont know how
to process. Have find_decode_metaid() return -ENOENT to capture this.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 net/sched/act_ife.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index a5994cf0512b..49b8ab551fbe 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -652,7 +652,7 @@ static int find_decode_metaid(struct sk_buff *skb, struct 
tcf_ife_info *ife,
}
}
 
-   return 0;
+   return -ENOENT;
 }
 
 static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
-- 
2.11.0



[PATCHv2 net 3/3] net: sched: ife: check on metadata length

2018-04-19 Thread Alexander Aring
This patch checks if sk buffer is available to dererence ife header. If
not then NULL will returned to signal an malformed ife packet. This
avoids to crashing the kernel from outside.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 net/ife/ife.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7fbe70a0af4b..93e8c36ce6ec 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -70,6 +70,9 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
u16 ifehdrln;
 
ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
+   if (skb->len < skb->dev->hard_header_len + IFE_METAHDRLEN)
+   return NULL;
+
ifehdrln = ntohs(ifehdr->metalen);
total_pull = skb->dev->hard_header_len + ifehdrln;
 
-- 
2.11.0



[PATCHv2 net 0/3] net: sched: ife: malformed ife packet fixes

2018-04-19 Thread Alexander Aring
As promised at netdev 2.2 tc workshop I am working on adding scapy support for
tdc testing. It is still work in progress. I will submit the patches to tdc
later (they are not in good shape yet). The good news is I have been able to
find bugs which normal packet testing would not be able to find.
With fuzzy testing I was able to craft certain malformed packets that IFE
action was not able to deal with. This patch set fixes those bugs.

changes since v2:
 - remove inline from __ife_tlv_meta_valid
 - add const to cast to meta_tlvhdr
 - add acked and reviewed tags

Alexander Aring (3):
  net: sched: ife: signal not finding metaid
  net: sched: ife: handle malformed tlv length
  net: sched: ife: check on metadata length

 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 38 --
 net/sched/act_ife.c |  9 +++--
 3 files changed, 45 insertions(+), 5 deletions(-)

-- 
2.11.0



[PATCHv2 net 2/3] net: sched: ife: handle malformed tlv length

2018-04-19 Thread Alexander Aring
There is currently no handling to check on a invalid tlv length. This
patch adds such handling to avoid killing the kernel with a malformed
ife packet.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
Reviewed-by: Yotam Gigi <yotam...@gmail.com>
Acked-by: Jamal Hadi Salim <j...@mojatatu.com>
---
 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 35 +--
 net/sched/act_ife.c |  7 ++-
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/net/ife.h b/include/net/ife.h
index 44b9c00f7223..e117617e3c34 100644
--- a/include/net/ife.h
+++ b/include/net/ife.h
@@ -12,7 +12,8 @@
 void *ife_encode(struct sk_buff *skb, u16 metalen);
 void *ife_decode(struct sk_buff *skb, u16 *metalen);
 
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 
*totlen);
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen);
 int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval);
 
diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7d1ec76e7f43..7fbe70a0af4b 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -92,12 +92,43 @@ struct meta_tlvhdr {
__be16 len;
 };
 
+static bool __ife_tlv_meta_valid(const unsigned char *skbdata,
+const unsigned char *ifehdr_end)
+{
+   const struct meta_tlvhdr *tlv;
+   u16 tlvlen;
+
+   if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end))
+   return false;
+
+   tlv = (const struct meta_tlvhdr *)skbdata;
+   tlvlen = ntohs(tlv->len);
+
+   /* tlv length field is inc header, check on minimum */
+   if (tlvlen < NLA_HDRLEN)
+   return false;
+
+   /* overflow by NLA_ALIGN check */
+   if (NLA_ALIGN(tlvlen) < tlvlen)
+   return false;
+
+   if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end))
+   return false;
+
+   return true;
+}
+
 /* Caller takes care of presenting data in network order
  */
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen)
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen)
 {
-   struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata;
+   struct meta_tlvhdr *tlv;
+
+   if (!__ife_tlv_meta_valid(skbdata, ifehdr_end))
+   return NULL;
 
+   tlv = (struct meta_tlvhdr *)skbdata;
*dlen = ntohs(tlv->len) - NLA_HDRLEN;
*attrtype = ntohs(tlv->type);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 49b8ab551fbe..8527cfdc446d 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -682,7 +682,12 @@ static int tcf_ife_decode(struct sk_buff *skb, const 
struct tc_action *a,
u16 mtype;
u16 dlen;
 
-   curr_data = ife_tlv_meta_decode(tlv_data, , , NULL);
+   curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, ,
+   , NULL);
+   if (!curr_data) {
+   qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
+   return TC_ACT_SHOT;
+   }
 
if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
/* abuse overlimits to count when we receive metadata
-- 
2.11.0



Re: [bisected] Stack overflow after fs: "switch the IO-triggering parts of umount to fs_pin" (was net namespaces kernel stack overflow)

2018-04-19 Thread Alexander Aring
Hi,

On Thu, Apr 19, 2018 at 12:56 PM, Kirill Tkhai <ktk...@virtuozzo.com> wrote:
> On 19.04.2018 19:44, Al Viro wrote:
>> On Thu, Apr 19, 2018 at 04:34:48PM +0100, Al Viro wrote:
>>
>>> IOW, we only get there if our vfsmount was an MNT_INTERNAL one.
>>> So we have mnt->mnt_umount of some MNT_INTERNAL mount found in
>>> ->mnt_pins of some other mount.  Which, AFAICS, means that
>>> it used to be mounted on that other mount.  How the hell can
>>> that happen?
>>>
>>> It looks like you somehow get a long chain of MNT_INTERNAL mounts
>>> stacked on top of each other, which ought to be prevented by
>>> mnt_flags &= ~MNT_INTERNAL_FLAGS;
>>> in do_add_mount().  Nuts...
>>
>> Argh...  Nuts is right - clone_mnt() preserves the sodding
>> MNT_INTERNAL, with obvious results.
>>
>> netns is related to the problem, by exposing MNT_INTERNAL mounts
>> (in /proc/*/ns/*) for mount --bind to copy and attach to the
>> tree.  AFAICS, the minimal reproducer is
>>
>> touch /tmp/a
>> unshare -m sh -c 'for i in `seq 1`; do mount --bind /proc/1/ns/net 
>> /tmp/a; done'
>>
>> (and it can be anything in /proc/*/ns/*, really)
>>
>> I think the fix should be along the lines of the following:
>>
>> Don't leak MNT_INTERNAL away from internal mounts
>>
>> We want it only for the stuff created by SB_KERNMOUNT mounts, *not* for
>> their copies.
>>
>> Cc: sta...@kernel.org
>> Signed-off-by: Al Viro <v...@zeniv.linux.org.uk>
>
> Flawless victory! Thanks.
>

Thanks to all.

Also thanks to Kirill for helping me here and doing the main part by
bisecting this issue.

Finally, my testing stuff which produced this bug also works well now.

Tested-by: Alexander Aring <ar...@mojatatu.com>

- Alex


[PATCH net 1/3] net: sched: ife: signal not finding metaid

2018-04-18 Thread Alexander Aring
We need to record stats for received metadata that we dont know how
to process. Have find_decode_metaid() return -ENOENT to capture this.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_ife.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index a5994cf0512b..49b8ab551fbe 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -652,7 +652,7 @@ static int find_decode_metaid(struct sk_buff *skb, struct 
tcf_ife_info *ife,
}
}
 
-   return 0;
+   return -ENOENT;
 }
 
 static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
-- 
2.11.0



[PATCH net 3/3] net: sched: ife: check on metadata length

2018-04-18 Thread Alexander Aring
This patch checks if sk buffer is available to dererence ife header. If
not then NULL will returned to signal an malformed ife packet. This
avoids to crashing the kernel from outside.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/ife/ife.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ife/ife.c b/net/ife/ife.c
index 8632d2685efb..7c100034fbee 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -70,6 +70,9 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
u16 ifehdrln;
 
ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
+   if (skb->len < skb->dev->hard_header_len + IFE_METAHDRLEN)
+   return NULL;
+
ifehdrln = ntohs(ifehdr->metalen);
total_pull = skb->dev->hard_header_len + ifehdrln;
 
-- 
2.11.0



[PATCH net 0/3] net: sched: ife: malformed ife packet fixes

2018-04-18 Thread Alexander Aring
As promised at netdev 2.2 tc workshop I am working on adding scapy support for
tdc testing. It is still work in progress. I will submit the patches to tdc
later (they are not in good shape yet). The good news is I have been able to
find bugs which normal packet testing would not be able to find.
With fuzzy testing I was able to craft certain malformed packets that IFE
action was not able to deal with. This patch set fixes those bugs.

Alexander Aring (3):
  net: sched: ife: signal not finding metaid
  net: sched: ife: handle malformed tlv length
  net: sched: ife: check on metadata length

 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 38 --
 net/sched/act_ife.c |  9 +++--
 3 files changed, 45 insertions(+), 5 deletions(-)

-- 
2.11.0



[PATCH net 2/3] net: sched: ife: handle malformed tlv length

2018-04-18 Thread Alexander Aring
There is currently no handling to check on a invalid tlv length. This
patch adds such handling to avoid killing the kernel with a malformed
ife packet.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/ife.h   |  3 ++-
 net/ife/ife.c   | 35 +--
 net/sched/act_ife.c |  7 ++-
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/include/net/ife.h b/include/net/ife.h
index 44b9c00f7223..e117617e3c34 100644
--- a/include/net/ife.h
+++ b/include/net/ife.h
@@ -12,7 +12,8 @@
 void *ife_encode(struct sk_buff *skb, u16 metalen);
 void *ife_decode(struct sk_buff *skb, u16 *metalen);
 
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 
*totlen);
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen);
 int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval);
 
diff --git a/net/ife/ife.c b/net/ife/ife.c
index 7d1ec76e7f43..8632d2685efb 100644
--- a/net/ife/ife.c
+++ b/net/ife/ife.c
@@ -92,12 +92,43 @@ struct meta_tlvhdr {
__be16 len;
 };
 
+static inline bool __ife_tlv_meta_valid(const unsigned char *skbdata,
+   const unsigned char *ifehdr_end)
+{
+   const struct meta_tlvhdr *tlv;
+   u16 tlvlen;
+
+   if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end))
+   return false;
+
+   tlv = (struct meta_tlvhdr *)skbdata;
+   tlvlen = ntohs(tlv->len);
+
+   /* tlv length field is inc header, check on minimum */
+   if (tlvlen < NLA_HDRLEN)
+   return false;
+
+   /* overflow by NLA_ALIGN check */
+   if (NLA_ALIGN(tlvlen) < tlvlen)
+   return false;
+
+   if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end))
+   return false;
+
+   return true;
+}
+
 /* Caller takes care of presenting data in network order
  */
-void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen)
+void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
+ u16 *dlen, u16 *totlen)
 {
-   struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata;
+   struct meta_tlvhdr *tlv;
+
+   if (!__ife_tlv_meta_valid(skbdata, ifehdr_end))
+   return NULL;
 
+   tlv = (struct meta_tlvhdr *)skbdata;
*dlen = ntohs(tlv->len) - NLA_HDRLEN;
*attrtype = ntohs(tlv->type);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 49b8ab551fbe..8527cfdc446d 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -682,7 +682,12 @@ static int tcf_ife_decode(struct sk_buff *skb, const 
struct tc_action *a,
u16 mtype;
u16 dlen;
 
-   curr_data = ife_tlv_meta_decode(tlv_data, , , NULL);
+   curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, ,
+   , NULL);
+   if (!curr_data) {
+   qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
+   return TC_ACT_SHOT;
+   }
 
if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
/* abuse overlimits to count when we receive metadata
-- 
2.11.0



net namespaces kernel stack overflow

2018-04-18 Thread Alexander Aring
Hi,

I currently can crash my net/master kernel by execute the following script:

--- snip

modprobe dummy

#mkdir /var/run/netns
#touch /var/run/netns/init_net
#mount --bind /proc/1/ns/net /var/run/netns/init_net

while true
do
mkdir /var/run/netns
touch /var/run/netns/init_net
mount --bind /proc/1/ns/net /var/run/netns/init_net

ip netns add foo
ip netns exec foo ip link add dummy0 type dummy
ip netns delete foo
done

--- snap

After max ~1 minute the kernel will crash.
Doing my hack of saving init_net outside the loop it will run fine...
So the mount bind is necessary.

The last message which I see is:

BUG: stack guard page was hit at f0751759 (stack is
69363195..73ddc474)
kernel stack overflow (double-fault):  [#1] SMP PTI
Modules linked in:
CPU: 0 PID: 13917 Comm: ip Not tainted 4.16.0-11878-gef9d066f6808 #32
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
RIP: 0010:validate_chain.isra.23+0x44/0xc40
RSP: 0018:c92cbff8 EFLAGS: 00010002
RAX: 0004 RBX: 0e58b88e1d4d15da RCX: 0e58b88e1d4d15da
RDX:  RSI: 8802b25ee2a0 RDI: 8802b25edb00
RBP: 0e58b88e1d4d15da R08:  R09: 0004
R10: c92cc050 R11: 8802b1054be8 R12: 0001
R13: 8802b25ee268 R14: 8802b25edb00 R15: 
FS:  () GS:8802bfc0() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: c92cbfe8 CR3: 02024000 CR4: 06f0
Call Trace:
 ? get_max_files+0x10/0x10
 __lock_acquire+0x332/0x710
 lock_acquire+0x67/0xb0
 ? lockref_put_or_lock+0x9/0x30
 ? dput.part.7+0x17/0x2d0
 _raw_spin_lock+0x2b/0x60
 ? lockref_put_or_lock+0x9/0x30
 lockref_put_or_lock+0x9/0x30
 dput.part.7+0x1ec/0x2d0
 drop_mountpoint+0x10/0x40
 pin_kill+0x9b/0x3a0
 ? wait_woken+0x90/0x90
 ? mnt_pin_kill+0x2d/0x100
 mnt_pin_kill+0x2d/0x100
 cleanup_mnt+0x66/0x70
 pin_kill+0x9b/0x3a0
 ? wait_woken+0x90/0x90
 ? mnt_pin_kill+0x2d/0x100
 mnt_pin_kill+0x2d/0x100
 cleanup_mnt+0x66/0x70
...

I guess maybe it has something to do with recently switching to
migrate per-net ops to async.

- Alex


Re: [patch net-next 09/10] net: sch: prio: Add offload ability for grafting a child

2018-03-02 Thread Alexander Aring
Hi,

On Fri, Mar 2, 2018 at 3:37 AM, Jiri Pirko <j...@resnulli.us> wrote:
> Fri, Mar 02, 2018 at 04:48:40AM CET, kubak...@wp.pl wrote:
>>On Thu, 1 Mar 2018 22:38:50 -0500, Alexander Aring wrote:
>>> I guess to make extack working, you need to return an errno if failed.
>>
>>AFAIK extack is printed as a warning if operation did not fail.
>
> Yes, I checked this and it is printed as warning.

ouch, so far I know extack it allows only one messages delivered back
to the user space.

If we introduce a warning in the successful path here, it could be
that in the callpath (after "successful" part of this callback), that
somebody else want to add a warning and overwrites actually your
warning (even, he is not aware that this warning was set - okay I
suppose you can do another check on NULL and set a warning, that
somebody overwrites a warning :-D).

If extack messages get's append and is some kind of for_each_nested
string in netlink -> we have no problem, but I guess this not how it's
working. :-/

- Alex


Re: [patch net-next 09/10] net: sch: prio: Add offload ability for grafting a child

2018-03-01 Thread Alexander Aring
Hi,

On Wed, Feb 28, 2018 at 4:45 AM, Jiri Pirko  wrote:
> From: Nogah Frankel 
>
> Offload sch_prio graft command for capable drivers.
> Warn in case of a failure, unless the graft was done as part of a destroy
> operation (the new qdisc is a noop) or if all the qdiscs (the parent, the
> old child, and the new one) are not offloaded.
>
> Signed-off-by: Nogah Frankel 
> Reviewed-by: Yuval Mintz 
> Signed-off-by: Jiri Pirko 
> ---
>  include/net/pkt_cls.h |  8 
>  net/sched/sch_prio.c  | 32 
...
> +   if (*old)
> +   any_qdisc_is_offloaded |= (*old)->flags &
> +  TCQ_F_OFFLOADED;
> +
> +   if (any_qdisc_is_offloaded)
> +   NL_SET_ERR_MSG(extack, "Offloading graft operation 
> failed.");
> +   }
> +
> return 0;
>  }
>

I guess to make extack working, you need to return an errno if failed.

- Alex


Re: [PATCHv2 net-next 3/8] net: sched: act: handle generic action errors

2018-02-15 Thread Alexander Aring
Hi,

On Thu, Feb 15, 2018 at 6:14 AM, Davide Caratti <dcara...@redhat.com> wrote:
> On Wed, 2018-02-14 at 17:13 -0500, Alexander Aring wrote:
>> This patch adds extack support for generic act handling. The extack
>> will be set deeper to each called function which is not part of netdev
>> core api.
>>
>> Based on work by David Ahern <dsah...@gmail.com>
>
> hello Alexander,
>
> after looking at the code more closely, I think there is margin for some
> more improvement here (i.e make the message contents easier to grep from a
> log). Please let me know if the comments below make sense for you.
>

I will send v3 with your changes. But not with one error handling in
label, the most whole point is to get some messages when somebody
throw a -EINVAL to the userspace and TC subsystem has a lot of places
with that.

- Alex


[PATCHv3 net-next 5/8] net: sched: act: add extack for lookup callback

2018-02-15 Thread Alexander Aring
This patch adds extack support for act lookup callback api. This
prepares to handle extack support inside each specific act
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 2 +-
 net/sched/act_bpf.c| 3 ++-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 3 ++-
 net/sched/act_gact.c   | 3 ++-
 net/sched/act_ife.c| 3 ++-
 net/sched/act_ipt.c| 6 --
 net/sched/act_mirred.c | 3 ++-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 3 ++-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 3 ++-
 net/sched/act_simple.c | 3 ++-
 net/sched/act_skbedit.c| 3 ++-
 net/sched/act_skbmod.c | 3 ++-
 net/sched/act_tunnel_key.c | 3 ++-
 net/sched/act_vlan.c   | 3 ++-
 18 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 3717e0f2bb1b..0bd65db506ba 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -87,7 +87,8 @@ struct tc_action_ops {
   struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void(*cleanup)(struct tc_action *);
-   int (*lookup)(struct net *net, struct tc_action **a, u32 index);
+   int (*lookup)(struct net *net, struct tc_action **a, u32 index,
+ struct netlink_ext_ack *extack);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind, struct netlink_ext_ack *extack);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 1f39f7800d7c..02b3c99da786 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -901,7 +901,7 @@ static struct tc_action *tcf_action_get_1(struct net *net, 
struct nlattr *nla,
goto err_out;
}
err = -ENOENT;
-   if (ops->lookup(net, , index) == 0)
+   if (ops->lookup(net, , index, extack) == 0)
goto err_mod;
 
module_put(ops->owner);
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index b3ebfa9598e2..d9654b863347 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -374,7 +374,8 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
+ struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 20e0215360b5..0504b7600fb6 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -184,7 +184,8 @@ static int tcf_connmark_walker(struct net *net, struct 
sk_buff *skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index)
+static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 3b8c48bb2683..bdd17b9ef034 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -638,7 +638,8 @@ static int tcf_csum_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 912f3398f1c1..e1e69e38f4b0 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -208,7 +208,8 @@ static int tcf_gact_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index e5127d400737..0b70fb0cc609 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -831,7 +831,8 @@ static int tcf_ife_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_ife_search(struct net *

[PATCHv3 net-next 1/8] net: sched: act: fix code style

2018-02-15 Thread Alexander Aring
This patch is used by subsequent patches. It fixes code style issues
caught by checkpatch.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  |  5 +++--
 net/sched/act_api.c| 12 ++--
 net/sched/act_mirred.c |  6 +++---
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 6ed9692f20bd..32ef544f4ddc 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -87,12 +87,13 @@ struct tc_action_ops {
   struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void(*cleanup)(struct tc_action *);
-   int (*lookup)(struct net *, struct tc_action **, u32);
+   int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind);
int (*walk)(struct net *, struct sk_buff *,
-   struct netlink_callback *, int, const struct 
tc_action_ops *);
+   struct netlink_callback *, int,
+   const struct tc_action_ops *);
void(*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a);
 };
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 4886ea4a7d6e..becc63689fae 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -621,7 +621,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
goto err_out;
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
-   if (kind == NULL)
+   if (!kind)
goto err_out;
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
@@ -822,7 +822,7 @@ static int tca_get_fill(struct sk_buff *skb, struct 
list_head *actions,
t->tca__pad2 = 0;
 
nest = nla_nest_start(skb, TCA_ACT_TAB);
-   if (nest == NULL)
+   if (!nest)
goto out_nlmsg_trim;
 
if (tcf_action_dump(skb, actions, bind, ref) < 0)
@@ -934,7 +934,7 @@ static int tca_action_flush(struct net *net, struct nlattr 
*nla,
t->tca__pad2 = 0;
 
nest = nla_nest_start(skb, TCA_ACT_TAB);
-   if (nest == NULL)
+   if (!nest)
goto out_module_put;
 
err = ops->walk(net, skb, , RTM_DELACTION, ops);
@@ -1005,10 +1005,10 @@ tca_action_gd(struct net *net, struct nlattr *nla, 
struct nlmsghdr *n,
return ret;
 
if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
-   if (tb[1] != NULL)
+   if (tb[1])
return tca_action_flush(net, tb[1], n, portid);
-   else
-   return -EINVAL;
+
+   return -EINVAL;
}
 
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index e6ff88f72900..abcd5f12b913 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,12 +80,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
bool exists = false;
int ret;
 
-   if (nla == NULL)
+   if (!nla)
return -EINVAL;
ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL);
if (ret < 0)
return ret;
-   if (tb[TCA_MIRRED_PARMS] == NULL)
+   if (!tb[TCA_MIRRED_PARMS])
return -EINVAL;
parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
@@ -117,7 +117,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
}
 
if (!exists) {
-   if (dev == NULL)
+   if (!dev)
return -EINVAL;
ret = tcf_idr_create(tn, parm->index, est, a,
 _mirred_ops, bind, true);
-- 
2.11.0



[PATCHv3 net-next 3/8] net: sched: act: handle generic action errors

2018-02-15 Thread Alexander Aring
This patch adds extack support for generic act handling. The extack
will be set deeper to each called function which is not part of netdev
core api.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_api.c | 93 +++--
 1 file changed, 61 insertions(+), 32 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 8d89b026414f..5d62f1d123ee 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -617,31 +617,40 @@ struct tc_action *tcf_action_init_1(struct net *net, 
struct tcf_proto *tp,
int err;
 
if (name == NULL) {
-   err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
+   err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
if (err < 0)
goto err_out;
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
-   if (!kind)
+   if (!kind) {
+   NL_SET_ERR_MSG(extack, "TC action kind must be 
specified");
goto err_out;
-   if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
+   }
+   if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "TC action name too long");
goto err_out;
+   }
if (tb[TCA_ACT_COOKIE]) {
int cklen = nla_len(tb[TCA_ACT_COOKIE]);
 
-   if (cklen > TC_COOKIE_MAX_SIZE)
+   if (cklen > TC_COOKIE_MAX_SIZE) {
+   NL_SET_ERR_MSG(extack, "TC cookie size above 
the maximum");
goto err_out;
+   }
 
cookie = nla_memdup_cookie(tb);
if (!cookie) {
+   NL_SET_ERR_MSG(extack, "No memory to generate 
TC cookie");
err = -ENOMEM;
goto err_out;
}
}
} else {
-   err = -EINVAL;
-   if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
+   if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "TC action name too long");
+   err = -EINVAL;
goto err_out;
+   }
}
 
a_o = tc_lookup_action_n(act_name);
@@ -664,6 +673,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
goto err_mod;
}
 #endif
+   NL_SET_ERR_MSG(extack, "Failed to load TC action module");
err = -ENOENT;
goto err_out;
}
@@ -698,6 +708,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
 
list_add_tail(>list, );
tcf_action_destroy(, bind);
+   NL_SET_ERR_MSG(extack, "Failed to init TC action 
chain");
return ERR_PTR(err);
}
}
@@ -734,7 +745,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, 
struct nlattr *nla,
int err;
int i;
 
-   err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
+   err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
if (err < 0)
return err;
 
@@ -842,7 +853,8 @@ static int tca_get_fill(struct sk_buff *skb, struct 
list_head *actions,
 
 static int
 tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
-  struct list_head *actions, int event)
+  struct list_head *actions, int event,
+  struct netlink_ext_ack *extack)
 {
struct sk_buff *skb;
 
@@ -851,6 +863,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr 
*n,
return -ENOBUFS;
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
 0, 0) <= 0) {
+   NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while 
adding TC action");
kfree_skb(skb);
return -EINVAL;
}
@@ -859,7 +872,8 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr 
*n,
 }
 
 static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
- struct nlmsghdr *n, u32 portid)
+ struct nlmsghdr *n, u32 portid,
+ struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_ACT_MAX + 1];
const struct tc_action_ops *ops;
@@ -867,20 +881,24 @

[PATCHv3 net-next 4/8] net: sched: act: add extack to init callback

2018-02-15 Thread Alexander Aring
This patch adds extack support for act init callback api. This
prepares to handle extack support inside each specific act
implementation.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 2 +-
 net/sched/act_api.c| 5 +++--
 net/sched/act_bpf.c| 2 +-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 2 +-
 net/sched/act_gact.c   | 2 +-
 net/sched/act_ife.c| 2 +-
 net/sched/act_ipt.c| 4 ++--
 net/sched/act_mirred.c | 2 +-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 2 +-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 2 +-
 net/sched/act_simple.c | 2 +-
 net/sched/act_skbedit.c| 2 +-
 net/sched/act_skbmod.c | 2 +-
 net/sched/act_tunnel_key.c | 2 +-
 net/sched/act_vlan.c   | 2 +-
 18 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 41d95930ffbc..3717e0f2bb1b 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -90,7 +90,7 @@ struct tc_action_ops {
int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
-   int bind);
+   int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
const struct tc_action_ops *);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 5d62f1d123ee..1f39f7800d7c 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -680,9 +680,10 @@ struct tc_action *tcf_action_init_1(struct net *net, 
struct tcf_proto *tp,
 
/* backward compatibility for policer */
if (name == NULL)
-   err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, , ovr, bind);
+   err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, , ovr, bind,
+   extack);
else
-   err = a_o->init(net, nla, est, , ovr, bind);
+   err = a_o->init(net, nla, est, , ovr, bind, extack);
if (err < 0)
goto err_mod;
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index b3f2c15affa7..b3ebfa9598e2 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -272,7 +272,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf 
*prog,
 
 static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act,
-   int replace, int bind)
+   int replace, int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 2b15ba84e0c8..20e0215360b5 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -96,7 +96,8 @@ static const struct nla_policy 
connmark_policy[TCA_CONNMARK_MAX + 1] = {
 
 static int tcf_connmark_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a,
-int ovr, int bind)
+int ovr, int bind,
+struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
struct nlattr *tb[TCA_CONNMARK_MAX + 1];
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index b7ba9b06b147..3b8c48bb2683 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -46,7 +46,7 @@ static struct tc_action_ops act_csum_ops;
 
 static int tcf_csum_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a, int ovr,
-int bind)
+int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
struct tcf_csum_params *params_old, *params_new;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index b56986d41c87..912f3398f1c1 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -56,7 +56,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] 
= {
 
 static int tcf_gact_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a,
-int ovr, int bind)
+int ovr, int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
struct nlattr *tb[TCA_GACT_MAX + 1];
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 5954e992685a..e5127d400737 100644
--- a/net/sched/act_ife.c
+++ b/net

[PATCHv3 net-next 7/8] net: sched: act: handle extack in tcf_generic_walker

2018-02-15 Thread Alexander Aring
This patch adds extack handling for a common used TC act function
"tcf_generic_walker()" to add an extack message on failures.
The tcf_generic_walker() function can fail if get a invalid command
different than DEL and GET. The naming "action" here is wrong, the
correct naming would be command.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 6 --
 net/sched/act_bpf.c| 2 +-
 net/sched/act_connmark.c   | 2 +-
 net/sched/act_csum.c   | 2 +-
 net/sched/act_gact.c   | 2 +-
 net/sched/act_ife.c| 2 +-
 net/sched/act_ipt.c| 4 ++--
 net/sched/act_mirred.c | 2 +-
 net/sched/act_nat.c| 2 +-
 net/sched/act_pedit.c  | 2 +-
 net/sched/act_police.c | 2 +-
 net/sched/act_sample.c | 2 +-
 net/sched/act_simple.c | 2 +-
 net/sched/act_skbedit.c| 2 +-
 net/sched/act_skbmod.c | 2 +-
 net/sched/act_tunnel_key.c | 2 +-
 net/sched/act_vlan.c   | 2 +-
 18 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index ab3529255377..9c2f22695025 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -140,7 +140,8 @@ static inline void tc_action_net_exit(struct list_head 
*net_list,
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops);
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack);
 int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
 bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 18df1e956e6a..ce18cd9c2860 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -202,7 +202,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, 
struct sk_buff *skb,
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tcf_idrinfo *idrinfo = tn->idrinfo;
 
@@ -211,7 +212,8 @@ int tcf_generic_walker(struct tc_action_net *tn, struct 
sk_buff *skb,
} else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb);
} else {
-   WARN(1, "tcf_generic_walker: unknown action %d\n", type);
+   WARN(1, "tcf_generic_walker: unknown command %d\n", type);
+   NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
return -EINVAL;
}
 }
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 7e01e2c710c4..cb3c5d403c88 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -372,7 +372,7 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index cb722da0bb15..e4b880fa51fe 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -182,7 +182,7 @@ static int tcf_connmark_walker(struct net *net, struct 
sk_buff *skb,
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index,
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 3e8efadb750f..d5c2e528d150 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -636,7 +636,7 @@ static int tcf_csum_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index d96ebe4bb65a..f072bcf33760 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -206,7 +206,7 @@ static int tcf_gact_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_g

[PATCHv3 net-next 8/8] net: sched: act: mirred: add extack support

2018-02-15 Thread Alexander Aring
This patch adds extack support for TC mirred action.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_mirred.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 05c2ebe92eca..fd34015331ab 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,13 +80,17 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
bool exists = false;
int ret;
 
-   if (!nla)
+   if (!nla) {
+   NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be 
passed");
return -EINVAL;
-   ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL);
+   }
+   ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, extack);
if (ret < 0)
return ret;
-   if (!tb[TCA_MIRRED_PARMS])
+   if (!tb[TCA_MIRRED_PARMS]) {
+   NL_SET_ERR_MSG_MOD(extack, "Missing required mirred 
parameters");
return -EINVAL;
+   }
parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -102,6 +106,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
default:
if (exists)
tcf_idr_release(*a, bind);
+   NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
return -EINVAL;
}
if (parm->ifindex) {
@@ -117,8 +122,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
}
 
if (!exists) {
-   if (!dev)
+   if (!dev) {
+   NL_SET_ERR_MSG_MOD(extack, "Specified device does not 
exist");
return -EINVAL;
+   }
ret = tcf_idr_create(tn, parm->index, est, a,
 _mirred_ops, bind, true);
if (ret)
-- 
2.11.0



[PATCHv3 net-next 6/8] net: sched: act: add extack for walk callback

2018-02-15 Thread Alexander Aring
This patch adds extack support for act walker callback api. This
prepares to handle extack support inside each specific act
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 4 ++--
 net/sched/act_bpf.c| 3 ++-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 3 ++-
 net/sched/act_gact.c   | 3 ++-
 net/sched/act_ife.c| 3 ++-
 net/sched/act_ipt.c| 6 --
 net/sched/act_mirred.c | 3 ++-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 3 ++-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 3 ++-
 net/sched/act_simple.c | 3 ++-
 net/sched/act_skbedit.c| 3 ++-
 net/sched/act_skbmod.c | 3 ++-
 net/sched/act_tunnel_key.c | 3 ++-
 net/sched/act_vlan.c   | 3 ++-
 18 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 0bd65db506ba..ab3529255377 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -94,7 +94,8 @@ struct tc_action_ops {
int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
-   const struct tc_action_ops *);
+   const struct tc_action_ops *,
+   struct netlink_ext_ack *);
void(*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a);
 };
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 02b3c99da786..18df1e956e6a 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -963,7 +963,7 @@ static int tca_action_flush(struct net *net, struct nlattr 
*nla,
goto out_module_put;
}
 
-   err = ops->walk(net, skb, , RTM_DELACTION, ops);
+   err = ops->walk(net, skb, , RTM_DELACTION, ops, extack);
if (err <= 0)
goto out_module_put;
 
@@ -1253,7 +1253,7 @@ static int tc_dump_action(struct sk_buff *skb, struct 
netlink_callback *cb)
if (nest == NULL)
goto out_module_put;
 
-   ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o);
+   ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
if (ret < 0)
goto out_module_put;
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index d9654b863347..7e01e2c710c4 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -367,7 +367,8 @@ static void tcf_bpf_cleanup(struct tc_action *act)
 
 static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
  struct netlink_callback *cb, int type,
- const struct tc_action_ops *ops)
+ const struct tc_action_ops *ops,
+ struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 0504b7600fb6..cb722da0bb15 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -177,7 +177,8 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, 
struct tc_action *a,
 
 static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index bdd17b9ef034..3e8efadb750f 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -631,7 +631,8 @@ static void tcf_csum_cleanup(struct tc_action *a)
 
 static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e1e69e38f4b0..d96ebe4bb65a 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -201,7 +201,8 @@ static int tcf_gact_dump(struct sk_buff *skb, struct 
tc_action *a,
 
 static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
diff --git a/net/sched/act_ife.c b/net/sche

[PATCHv3 net-next 2/8] net: sched: act: add extack to init

2018-02-15 Thread Alexander Aring
This patch adds extack to tcf_action_init and tcf_action_init_1
functions. These are necessary to make individual extack handling in
each act implementation.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h |  5 +++--
 net/sched/act_api.c   | 17 +++--
 net/sched/cls_api.c   |  4 ++--
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 32ef544f4ddc..41d95930ffbc 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -163,10 +163,11 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action 
**actions,
int nr_actions, struct tcf_result *res);
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
-   struct list_head *actions);
+   struct list_head *actions, struct netlink_ext_ack *extack);
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
-   char *name, int ovr, int bind);
+   char *name, int ovr, int bind,
+   struct netlink_ext_ack *extack);
 int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
 int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index becc63689fae..8d89b026414f 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -605,7 +605,8 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr 
**tb)
 
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
-   char *name, int ovr, int bind)
+   char *name, int ovr, int bind,
+   struct netlink_ext_ack *extack)
 {
struct tc_action *a;
struct tc_action_ops *a_o;
@@ -726,7 +727,7 @@ static void cleanup_a(struct list_head *actions, int ovr)
 
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
-   struct list_head *actions)
+   struct list_head *actions, struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
struct tc_action *act;
@@ -738,7 +739,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, 
struct nlattr *nla,
return err;
 
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
-   act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind);
+   act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
+   extack);
if (IS_ERR(act)) {
err = PTR_ERR(act);
goto err;
@@ -1060,12 +1062,14 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, 
struct list_head *actions,
 }
 
 static int tcf_action_add(struct net *net, struct nlattr *nla,
- struct nlmsghdr *n, u32 portid, int ovr)
+ struct nlmsghdr *n, u32 portid, int ovr,
+ struct netlink_ext_ack *extack)
 {
int ret = 0;
LIST_HEAD(actions);
 
-   ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, );
+   ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, ,
+ extack);
if (ret)
return ret;
 
@@ -1113,7 +1117,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct 
nlmsghdr *n,
if (n->nlmsg_flags & NLM_F_REPLACE)
ovr = 1;
 replay:
-   ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr);
+   ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
+extack);
if (ret == -EAGAIN)
goto replay;
break;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 2bc1bc23d42e..f21610c5da1a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1434,7 +1434,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto 
*tp, struct nlattr **tb,
if (exts->police && tb[exts->police]) {
act = tcf_action_init_1(net, tp, tb[exts->police],
rate_tlv, "police", ovr,
-   TCA_ACT_BIND);
+ 

[PATCHv3 net-next 0/8] net: sched: act: add extack support

2018-02-15 Thread Alexander Aring
Hi,

this patch series adds extack support for the TC action subsystem.
As example I for the extack support in a TC action I choosed mirred
action.

- Alex

Cc: David Ahern <dsah...@gmail.com>

changes since v3:
- adapt recommended changes from Davide Caratti, please check if
  I catch everything. Thanks.

changes since v2:

- remove newline in extack of generic walker handling
  Thanks to Davide Caratti
- add ker...@mojatatu.com in cc

Alexander Aring (8):
  net: sched: act: fix code style
  net: sched: act: add extack to init
  net: sched: act: handle generic action errors
  net: sched: act: add extack to init callback
  net: sched: act: add extack for lookup callback
  net: sched: act: add extack for walk callback
  net: sched: act: handle extack in tcf_generic_walker
  net: sched: act: mirred: add extack support

 include/net/act_api.h  |  17 --
 net/sched/act_api.c| 135 +
 net/sched/act_bpf.c|  10 ++--
 net/sched/act_connmark.c   |  11 ++--
 net/sched/act_csum.c   |  10 ++--
 net/sched/act_gact.c   |  10 ++--
 net/sched/act_ife.c|  10 ++--
 net/sched/act_ipt.c|  20 ---
 net/sched/act_mirred.c |  25 ++---
 net/sched/act_nat.c|  11 ++--
 net/sched/act_pedit.c  |  10 ++--
 net/sched/act_police.c |  11 ++--
 net/sched/act_sample.c |  10 ++--
 net/sched/act_simple.c |  10 ++--
 net/sched/act_skbedit.c|  10 ++--
 net/sched/act_skbmod.c |  10 ++--
 net/sched/act_tunnel_key.c |  10 ++--
 net/sched/act_vlan.c   |  10 ++--
 net/sched/cls_api.c|   4 +-
 19 files changed, 215 insertions(+), 129 deletions(-)

-- 
2.11.0



[PATCHv2 net-next 1/8] net: sched: act: fix code style

2018-02-14 Thread Alexander Aring
This patch is used by subsequent patches. It fixes code style issues
caught by checkpatch.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  |  5 +++--
 net/sched/act_api.c| 12 ++--
 net/sched/act_mirred.c |  6 +++---
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 6ed9692f20bd..32ef544f4ddc 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -87,12 +87,13 @@ struct tc_action_ops {
   struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void(*cleanup)(struct tc_action *);
-   int (*lookup)(struct net *, struct tc_action **, u32);
+   int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind);
int (*walk)(struct net *, struct sk_buff *,
-   struct netlink_callback *, int, const struct 
tc_action_ops *);
+   struct netlink_callback *, int,
+   const struct tc_action_ops *);
void(*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a);
 };
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 4886ea4a7d6e..becc63689fae 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -621,7 +621,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
goto err_out;
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
-   if (kind == NULL)
+   if (!kind)
goto err_out;
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
@@ -822,7 +822,7 @@ static int tca_get_fill(struct sk_buff *skb, struct 
list_head *actions,
t->tca__pad2 = 0;
 
nest = nla_nest_start(skb, TCA_ACT_TAB);
-   if (nest == NULL)
+   if (!nest)
goto out_nlmsg_trim;
 
if (tcf_action_dump(skb, actions, bind, ref) < 0)
@@ -934,7 +934,7 @@ static int tca_action_flush(struct net *net, struct nlattr 
*nla,
t->tca__pad2 = 0;
 
nest = nla_nest_start(skb, TCA_ACT_TAB);
-   if (nest == NULL)
+   if (!nest)
goto out_module_put;
 
err = ops->walk(net, skb, , RTM_DELACTION, ops);
@@ -1005,10 +1005,10 @@ tca_action_gd(struct net *net, struct nlattr *nla, 
struct nlmsghdr *n,
return ret;
 
if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
-   if (tb[1] != NULL)
+   if (tb[1])
return tca_action_flush(net, tb[1], n, portid);
-   else
-   return -EINVAL;
+
+   return -EINVAL;
}
 
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index e6ff88f72900..abcd5f12b913 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,12 +80,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
bool exists = false;
int ret;
 
-   if (nla == NULL)
+   if (!nla)
return -EINVAL;
ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL);
if (ret < 0)
return ret;
-   if (tb[TCA_MIRRED_PARMS] == NULL)
+   if (!tb[TCA_MIRRED_PARMS])
return -EINVAL;
parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
@@ -117,7 +117,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
}
 
if (!exists) {
-   if (dev == NULL)
+   if (!dev)
return -EINVAL;
ret = tcf_idr_create(tn, parm->index, est, a,
 _mirred_ops, bind, true);
-- 
2.11.0



[PATCHv2 net-next 2/8] net: sched: act: add extack to init

2018-02-14 Thread Alexander Aring
This patch adds extack to tcf_action_init and tcf_action_init_1
functions. These are necessary to make individual extack handling in
each act implementation.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h |  5 +++--
 net/sched/act_api.c   | 17 +++--
 net/sched/cls_api.c   |  4 ++--
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 32ef544f4ddc..41d95930ffbc 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -163,10 +163,11 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action 
**actions,
int nr_actions, struct tcf_result *res);
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
-   struct list_head *actions);
+   struct list_head *actions, struct netlink_ext_ack *extack);
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
-   char *name, int ovr, int bind);
+   char *name, int ovr, int bind,
+   struct netlink_ext_ack *extack);
 int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
 int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index becc63689fae..8d89b026414f 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -605,7 +605,8 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr 
**tb)
 
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
-   char *name, int ovr, int bind)
+   char *name, int ovr, int bind,
+   struct netlink_ext_ack *extack)
 {
struct tc_action *a;
struct tc_action_ops *a_o;
@@ -726,7 +727,7 @@ static void cleanup_a(struct list_head *actions, int ovr)
 
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
-   struct list_head *actions)
+   struct list_head *actions, struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
struct tc_action *act;
@@ -738,7 +739,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, 
struct nlattr *nla,
return err;
 
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
-   act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind);
+   act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
+   extack);
if (IS_ERR(act)) {
err = PTR_ERR(act);
goto err;
@@ -1060,12 +1062,14 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, 
struct list_head *actions,
 }
 
 static int tcf_action_add(struct net *net, struct nlattr *nla,
- struct nlmsghdr *n, u32 portid, int ovr)
+ struct nlmsghdr *n, u32 portid, int ovr,
+ struct netlink_ext_ack *extack)
 {
int ret = 0;
LIST_HEAD(actions);
 
-   ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, );
+   ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, ,
+ extack);
if (ret)
return ret;
 
@@ -1113,7 +1117,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct 
nlmsghdr *n,
if (n->nlmsg_flags & NLM_F_REPLACE)
ovr = 1;
 replay:
-   ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr);
+   ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
+extack);
if (ret == -EAGAIN)
goto replay;
break;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 2bc1bc23d42e..f21610c5da1a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1434,7 +1434,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto 
*tp, struct nlattr **tb,
if (exts->police && tb[exts->police]) {
act = tcf_action_init_1(net, tp, tb[exts->police],
rate_tlv, "police", ovr,
-   TCA_ACT_BIND);
+ 

[PATCHv2 net-next 0/8] net: sched: act: add extack support

2018-02-14 Thread Alexander Aring
Hi,

this patch series adds extack support for the TC action subsystem.
As example I for the extack support in a TC action I choosed mirred
action.

- Alex

Cc: David Ahern <dsah...@gmail.com>

changes since v2:

- remove newline in extack of generic walker handling
  Thanks to Davide Caratti
- add ker...@mojatatu.com in cc

Alexander Aring (8):
  net: sched: act: fix code style
  net: sched: act: add extack to init
  net: sched: act: handle generic action errors
  net: sched: act: add extack to init callback
  net: sched: act: add extack for lookup callback
  net: sched: act: add extack for walk callback
  net: sched: act: handle extack in tcf_generic_walker
  net: sched: act: mirred: add extack support

 include/net/act_api.h  |  17 --
 net/sched/act_api.c| 135 +
 net/sched/act_bpf.c|  10 ++--
 net/sched/act_connmark.c   |  11 ++--
 net/sched/act_csum.c   |  10 ++--
 net/sched/act_gact.c   |  10 ++--
 net/sched/act_ife.c|  10 ++--
 net/sched/act_ipt.c|  20 ---
 net/sched/act_mirred.c |  25 ++---
 net/sched/act_nat.c|  11 ++--
 net/sched/act_pedit.c  |  10 ++--
 net/sched/act_police.c |  11 ++--
 net/sched/act_sample.c |  10 ++--
 net/sched/act_simple.c |  10 ++--
 net/sched/act_skbedit.c|  10 ++--
 net/sched/act_skbmod.c |  10 ++--
 net/sched/act_tunnel_key.c |  10 ++--
 net/sched/act_vlan.c   |  10 ++--
 net/sched/cls_api.c|   4 +-
 19 files changed, 215 insertions(+), 129 deletions(-)

-- 
2.11.0



[PATCHv2 net-next 4/8] net: sched: act: add extack to init callback

2018-02-14 Thread Alexander Aring
This patch adds extack support for act init callback api. This
prepares to handle extack support inside each specific act
implementation.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 2 +-
 net/sched/act_api.c| 5 +++--
 net/sched/act_bpf.c| 2 +-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 2 +-
 net/sched/act_gact.c   | 2 +-
 net/sched/act_ife.c| 2 +-
 net/sched/act_ipt.c| 4 ++--
 net/sched/act_mirred.c | 2 +-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 2 +-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 2 +-
 net/sched/act_simple.c | 2 +-
 net/sched/act_skbedit.c| 2 +-
 net/sched/act_skbmod.c | 2 +-
 net/sched/act_tunnel_key.c | 2 +-
 net/sched/act_vlan.c   | 2 +-
 18 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 41d95930ffbc..3717e0f2bb1b 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -90,7 +90,7 @@ struct tc_action_ops {
int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
-   int bind);
+   int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
const struct tc_action_ops *);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index a5138ae026a1..00c5a1d9a21e 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -680,9 +680,10 @@ struct tc_action *tcf_action_init_1(struct net *net, 
struct tcf_proto *tp,
 
/* backward compatibility for policer */
if (name == NULL)
-   err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, , ovr, bind);
+   err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, , ovr, bind,
+   extack);
else
-   err = a_o->init(net, nla, est, , ovr, bind);
+   err = a_o->init(net, nla, est, , ovr, bind, extack);
if (err < 0)
goto err_mod;
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index b3f2c15affa7..b3ebfa9598e2 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -272,7 +272,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf 
*prog,
 
 static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act,
-   int replace, int bind)
+   int replace, int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 2b15ba84e0c8..20e0215360b5 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -96,7 +96,8 @@ static const struct nla_policy 
connmark_policy[TCA_CONNMARK_MAX + 1] = {
 
 static int tcf_connmark_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a,
-int ovr, int bind)
+int ovr, int bind,
+struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
struct nlattr *tb[TCA_CONNMARK_MAX + 1];
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index b7ba9b06b147..3b8c48bb2683 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -46,7 +46,7 @@ static struct tc_action_ops act_csum_ops;
 
 static int tcf_csum_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a, int ovr,
-int bind)
+int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
struct tcf_csum_params *params_old, *params_new;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index b56986d41c87..912f3398f1c1 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -56,7 +56,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] 
= {
 
 static int tcf_gact_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a,
-int ovr, int bind)
+int ovr, int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
struct nlattr *tb[TCA_GACT_MAX + 1];
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 5954e992685a..e5127d400737 100644
--- a/net/sched/act_ife.c
+++ b/net

[PATCHv2 net-next 3/8] net: sched: act: handle generic action errors

2018-02-14 Thread Alexander Aring
This patch adds extack support for generic act handling. The extack
will be set deeper to each called function which is not part of netdev
core api.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_api.c | 93 +++--
 1 file changed, 61 insertions(+), 32 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 8d89b026414f..a5138ae026a1 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -617,31 +617,40 @@ struct tc_action *tcf_action_init_1(struct net *net, 
struct tcf_proto *tp,
int err;
 
if (name == NULL) {
-   err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
+   err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
if (err < 0)
goto err_out;
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
-   if (!kind)
+   if (!kind) {
+   NL_SET_ERR_MSG(extack, "TC action kind must be 
specified");
goto err_out;
-   if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
+   }
+   if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "TC action name too long");
goto err_out;
+   }
if (tb[TCA_ACT_COOKIE]) {
int cklen = nla_len(tb[TCA_ACT_COOKIE]);
 
-   if (cklen > TC_COOKIE_MAX_SIZE)
+   if (cklen > TC_COOKIE_MAX_SIZE) {
+   NL_SET_ERR_MSG(extack, "TC cookie size above 
the maximum");
goto err_out;
+   }
 
cookie = nla_memdup_cookie(tb);
if (!cookie) {
+   NL_SET_ERR_MSG(extack, "No memory to generate 
TC cookie");
err = -ENOMEM;
goto err_out;
}
}
} else {
-   err = -EINVAL;
-   if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
+   if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "TC action name too long");
+   err = -EINVAL;
goto err_out;
+   }
}
 
a_o = tc_lookup_action_n(act_name);
@@ -664,6 +673,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
goto err_mod;
}
 #endif
+   NL_SET_ERR_MSG(extack, "Failed to load TC action module");
err = -ENOENT;
goto err_out;
}
@@ -698,6 +708,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
 
list_add_tail(>list, );
tcf_action_destroy(, bind);
+   NL_SET_ERR_MSG(extack, "Failed to init action chain");
return ERR_PTR(err);
}
}
@@ -734,7 +745,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, 
struct nlattr *nla,
int err;
int i;
 
-   err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
+   err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
if (err < 0)
return err;
 
@@ -842,7 +853,8 @@ static int tca_get_fill(struct sk_buff *skb, struct 
list_head *actions,
 
 static int
 tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
-  struct list_head *actions, int event)
+  struct list_head *actions, int event,
+  struct netlink_ext_ack *extack)
 {
struct sk_buff *skb;
 
@@ -851,6 +863,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr 
*n,
return -ENOBUFS;
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
 0, 0) <= 0) {
+   NL_SET_ERR_MSG(extack, "Failed to fill netlink tc action 
attributes");
kfree_skb(skb);
return -EINVAL;
}
@@ -859,7 +872,8 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr 
*n,
 }
 
 static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
- struct nlmsghdr *n, u32 portid)
+ struct nlmsghdr *n, u32 portid,
+ struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_ACT_MAX + 1];
const struct tc_action_ops *ops;
@@ -867,20 +881,24 @@ static struct tc_act

[PATCHv2 net-next 8/8] net: sched: act: mirred: add extack support

2018-02-14 Thread Alexander Aring
This patch adds extack support for TC mirred action.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_mirred.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 05c2ebe92eca..fd34015331ab 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,13 +80,17 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
bool exists = false;
int ret;
 
-   if (!nla)
+   if (!nla) {
+   NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be 
passed");
return -EINVAL;
-   ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL);
+   }
+   ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, extack);
if (ret < 0)
return ret;
-   if (!tb[TCA_MIRRED_PARMS])
+   if (!tb[TCA_MIRRED_PARMS]) {
+   NL_SET_ERR_MSG_MOD(extack, "Missing required mirred 
parameters");
return -EINVAL;
+   }
parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -102,6 +106,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
default:
if (exists)
tcf_idr_release(*a, bind);
+   NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
return -EINVAL;
}
if (parm->ifindex) {
@@ -117,8 +122,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
}
 
if (!exists) {
-   if (!dev)
+   if (!dev) {
+   NL_SET_ERR_MSG_MOD(extack, "Specified device does not 
exist");
return -EINVAL;
+   }
ret = tcf_idr_create(tn, parm->index, est, a,
 _mirred_ops, bind, true);
if (ret)
-- 
2.11.0



[PATCHv2 net-next 6/8] net: sched: act: add extack for walk callback

2018-02-14 Thread Alexander Aring
This patch adds extack support for act walker callback api. This
prepares to handle extack support inside each specific act
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 4 ++--
 net/sched/act_bpf.c| 3 ++-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 3 ++-
 net/sched/act_gact.c   | 3 ++-
 net/sched/act_ife.c| 3 ++-
 net/sched/act_ipt.c| 6 --
 net/sched/act_mirred.c | 3 ++-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 3 ++-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 3 ++-
 net/sched/act_simple.c | 3 ++-
 net/sched/act_skbedit.c| 3 ++-
 net/sched/act_skbmod.c | 3 ++-
 net/sched/act_tunnel_key.c | 3 ++-
 net/sched/act_vlan.c   | 3 ++-
 18 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 0bd65db506ba..ab3529255377 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -94,7 +94,8 @@ struct tc_action_ops {
int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
-   const struct tc_action_ops *);
+   const struct tc_action_ops *,
+   struct netlink_ext_ack *);
void(*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a);
 };
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 6d2a035f1177..cb284a0437eb 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -963,7 +963,7 @@ static int tca_action_flush(struct net *net, struct nlattr 
*nla,
goto out_module_put;
}
 
-   err = ops->walk(net, skb, , RTM_DELACTION, ops);
+   err = ops->walk(net, skb, , RTM_DELACTION, ops, extack);
if (err <= 0)
goto out_module_put;
 
@@ -1253,7 +1253,7 @@ static int tc_dump_action(struct sk_buff *skb, struct 
netlink_callback *cb)
if (nest == NULL)
goto out_module_put;
 
-   ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o);
+   ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
if (ret < 0)
goto out_module_put;
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index d9654b863347..7e01e2c710c4 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -367,7 +367,8 @@ static void tcf_bpf_cleanup(struct tc_action *act)
 
 static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
  struct netlink_callback *cb, int type,
- const struct tc_action_ops *ops)
+ const struct tc_action_ops *ops,
+ struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 0504b7600fb6..cb722da0bb15 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -177,7 +177,8 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, 
struct tc_action *a,
 
 static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index bdd17b9ef034..3e8efadb750f 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -631,7 +631,8 @@ static void tcf_csum_cleanup(struct tc_action *a)
 
 static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e1e69e38f4b0..d96ebe4bb65a 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -201,7 +201,8 @@ static int tcf_gact_dump(struct sk_buff *skb, struct 
tc_action *a,
 
 static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
diff --git a/net/sched/act_ife.c b/net/sche

[PATCHv2 net-next 7/8] net: sched: act: handle extack in tcf_generic_walker

2018-02-14 Thread Alexander Aring
This patch adds extack handling for a common used TC act function
"tcf_generic_walker()" to add an extack message on failures.
The tcf_generic_walker() function can fail if get a invalid command
different than DEL and GET. The naming "action" here is wrong, the
correct naming would be command.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 6 --
 net/sched/act_bpf.c| 2 +-
 net/sched/act_connmark.c   | 2 +-
 net/sched/act_csum.c   | 2 +-
 net/sched/act_gact.c   | 2 +-
 net/sched/act_ife.c| 2 +-
 net/sched/act_ipt.c| 4 ++--
 net/sched/act_mirred.c | 2 +-
 net/sched/act_nat.c| 2 +-
 net/sched/act_pedit.c  | 2 +-
 net/sched/act_police.c | 2 +-
 net/sched/act_sample.c | 2 +-
 net/sched/act_simple.c | 2 +-
 net/sched/act_skbedit.c| 2 +-
 net/sched/act_skbmod.c | 2 +-
 net/sched/act_tunnel_key.c | 2 +-
 net/sched/act_vlan.c   | 2 +-
 18 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index ab3529255377..9c2f22695025 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -140,7 +140,8 @@ static inline void tc_action_net_exit(struct list_head 
*net_list,
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops);
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack);
 int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
 bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index cb284a0437eb..08f326560d5e 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -202,7 +202,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, 
struct sk_buff *skb,
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tcf_idrinfo *idrinfo = tn->idrinfo;
 
@@ -211,7 +212,8 @@ int tcf_generic_walker(struct tc_action_net *tn, struct 
sk_buff *skb,
} else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb);
} else {
-   WARN(1, "tcf_generic_walker: unknown action %d\n", type);
+   WARN(1, "tcf_generic_walker: unknown command %d\n", type);
+   NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command");
return -EINVAL;
}
 }
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 7e01e2c710c4..cb3c5d403c88 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -372,7 +372,7 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index cb722da0bb15..e4b880fa51fe 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -182,7 +182,7 @@ static int tcf_connmark_walker(struct net *net, struct 
sk_buff *skb,
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index,
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 3e8efadb750f..d5c2e528d150 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -636,7 +636,7 @@ static int tcf_csum_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index d96ebe4bb65a..f072bcf33760 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -206,7 +206,7 @@ static int tcf_gact_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_g

[PATCHv2 net-next 5/8] net: sched: act: add extack for lookup callback

2018-02-14 Thread Alexander Aring
This patch adds extack support for act lookup callback api. This
prepares to handle extack support inside each specific act
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 2 +-
 net/sched/act_bpf.c| 3 ++-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 3 ++-
 net/sched/act_gact.c   | 3 ++-
 net/sched/act_ife.c| 3 ++-
 net/sched/act_ipt.c| 6 --
 net/sched/act_mirred.c | 3 ++-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 3 ++-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 3 ++-
 net/sched/act_simple.c | 3 ++-
 net/sched/act_skbedit.c| 3 ++-
 net/sched/act_skbmod.c | 3 ++-
 net/sched/act_tunnel_key.c | 3 ++-
 net/sched/act_vlan.c   | 3 ++-
 18 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 3717e0f2bb1b..0bd65db506ba 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -87,7 +87,8 @@ struct tc_action_ops {
   struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void(*cleanup)(struct tc_action *);
-   int (*lookup)(struct net *net, struct tc_action **a, u32 index);
+   int (*lookup)(struct net *net, struct tc_action **a, u32 index,
+ struct netlink_ext_ack *extack);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind, struct netlink_ext_ack *extack);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 00c5a1d9a21e..6d2a035f1177 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -901,7 +901,7 @@ static struct tc_action *tcf_action_get_1(struct net *net, 
struct nlattr *nla,
goto err_out;
}
err = -ENOENT;
-   if (ops->lookup(net, , index) == 0)
+   if (ops->lookup(net, , index, extack) == 0)
goto err_mod;
 
module_put(ops->owner);
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index b3ebfa9598e2..d9654b863347 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -374,7 +374,8 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
+ struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 20e0215360b5..0504b7600fb6 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -184,7 +184,8 @@ static int tcf_connmark_walker(struct net *net, struct 
sk_buff *skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index)
+static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 3b8c48bb2683..bdd17b9ef034 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -638,7 +638,8 @@ static int tcf_csum_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 912f3398f1c1..e1e69e38f4b0 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -208,7 +208,8 @@ static int tcf_gact_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index e5127d400737..0b70fb0cc609 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -831,7 +831,8 @@ static int tcf_ife_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_ife_search(struct net *

Re: [PATCH net-next 7/8] net: sched: act: handle extack in tcf_generic_walker

2018-02-13 Thread Alexander Aring
Hi,

2018-02-13 11:18 GMT-05:00 David Miller <da...@davemloft.net>:
> From: Davide Caratti <dcara...@redhat.com>
> Date: Tue, 13 Feb 2018 10:58:01 +0100
>
>> On Mon, 2018-02-12 at 15:19 -0500, Alexander Aring wrote:
>>>
>>> @@ -211,7 +212,8 @@ int tcf_generic_walker(struct tc_action_net *tn, struct 
>>> sk_buff *skb,
>>>  } else if (type == RTM_GETACTION) {
>>>  return tcf_dump_walker(idrinfo, skb, cb);
>>>  } else {
>>> -WARN(1, "tcf_generic_walker: unknown action %d\n", type);
>>> +WARN(1, "tcf_generic_walker: unknown command %d\n", type);
>>> +NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown 
>>> command\n");
>>
>> minor nit: maybe we don't need the '\n' in the above message?
>

Yep, I will send v2.

Thanks.

- Alex


[PATCH net-next 5/8] net: sched: act: add extack for lookup callback

2018-02-12 Thread Alexander Aring
This patch adds extack support for act lookup callback api. This
prepares to handle extack support inside each specific act
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 2 +-
 net/sched/act_bpf.c| 3 ++-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 3 ++-
 net/sched/act_gact.c   | 3 ++-
 net/sched/act_ife.c| 3 ++-
 net/sched/act_ipt.c| 6 --
 net/sched/act_mirred.c | 3 ++-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 3 ++-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 3 ++-
 net/sched/act_simple.c | 3 ++-
 net/sched/act_skbedit.c| 3 ++-
 net/sched/act_skbmod.c | 3 ++-
 net/sched/act_tunnel_key.c | 3 ++-
 net/sched/act_vlan.c   | 3 ++-
 18 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 3717e0f2bb1b..0bd65db506ba 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -87,7 +87,8 @@ struct tc_action_ops {
   struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void(*cleanup)(struct tc_action *);
-   int (*lookup)(struct net *net, struct tc_action **a, u32 index);
+   int (*lookup)(struct net *net, struct tc_action **a, u32 index,
+ struct netlink_ext_ack *extack);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind, struct netlink_ext_ack *extack);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 60dec7b762dd..77093432ddc3 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -901,7 +901,7 @@ static struct tc_action *tcf_action_get_1(struct net *net, 
struct nlattr *nla,
goto err_out;
}
err = -ENOENT;
-   if (ops->lookup(net, , index) == 0)
+   if (ops->lookup(net, , index, extack) == 0)
goto err_mod;
 
module_put(ops->owner);
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index b3ebfa9598e2..d9654b863347 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -374,7 +374,8 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
+ struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 20e0215360b5..0504b7600fb6 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -184,7 +184,8 @@ static int tcf_connmark_walker(struct net *net, struct 
sk_buff *skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index)
+static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 3b8c48bb2683..bdd17b9ef034 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -638,7 +638,8 @@ static int tcf_csum_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 912f3398f1c1..e1e69e38f4b0 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -208,7 +208,8 @@ static int tcf_gact_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index e5127d400737..0b70fb0cc609 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -831,7 +831,8 @@ static int tcf_ife_walker(struct net *net, struct sk_buff 
*skb,
return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
+static int tcf_ife_search(struct net *

[PATCH net-next 2/8] net: sched: act: add extack to init

2018-02-12 Thread Alexander Aring
This patch adds extack to tcf_action_init and tcf_action_init_1
functions. These are necessary to make individual extack handling in
each act implementation.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h |  5 +++--
 net/sched/act_api.c   | 17 +++--
 net/sched/cls_api.c   |  4 ++--
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 32ef544f4ddc..41d95930ffbc 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -163,10 +163,11 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action 
**actions,
int nr_actions, struct tcf_result *res);
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
-   struct list_head *actions);
+   struct list_head *actions, struct netlink_ext_ack *extack);
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
-   char *name, int ovr, int bind);
+   char *name, int ovr, int bind,
+   struct netlink_ext_ack *extack);
 int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
 int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
 int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index d885b3127e53..db7500d613fc 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -605,7 +605,8 @@ static struct tc_cookie *nla_memdup_cookie(struct nlattr 
**tb)
 
 struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
struct nlattr *nla, struct nlattr *est,
-   char *name, int ovr, int bind)
+   char *name, int ovr, int bind,
+   struct netlink_ext_ack *extack)
 {
struct tc_action *a;
struct tc_action_ops *a_o;
@@ -726,7 +727,7 @@ static void cleanup_a(struct list_head *actions, int ovr)
 
 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
struct nlattr *est, char *name, int ovr, int bind,
-   struct list_head *actions)
+   struct list_head *actions, struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
struct tc_action *act;
@@ -738,7 +739,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, 
struct nlattr *nla,
return err;
 
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
-   act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind);
+   act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
+   extack);
if (IS_ERR(act)) {
err = PTR_ERR(act);
goto err;
@@ -1060,12 +1062,14 @@ tcf_add_notify(struct net *net, struct nlmsghdr *n, 
struct list_head *actions,
 }
 
 static int tcf_action_add(struct net *net, struct nlattr *nla,
- struct nlmsghdr *n, u32 portid, int ovr)
+ struct nlmsghdr *n, u32 portid, int ovr,
+ struct netlink_ext_ack *extack)
 {
int ret = 0;
LIST_HEAD(actions);
 
-   ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, );
+   ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, ,
+ extack);
if (ret)
return ret;
 
@@ -1113,7 +1117,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct 
nlmsghdr *n,
if (n->nlmsg_flags & NLM_F_REPLACE)
ovr = 1;
 replay:
-   ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr);
+   ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, portid, ovr,
+extack);
if (ret == -EAGAIN)
goto replay;
break;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 2bc1bc23d42e..f21610c5da1a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1434,7 +1434,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto 
*tp, struct nlattr **tb,
if (exts->police && tb[exts->police]) {
act = tcf_action_init_1(net, tp, tb[exts->police],
rate_tlv, "police", ovr,
-   TCA_ACT_BIND);
+ 

[PATCH net-next 4/8] net: sched: act: add extack to init callback

2018-02-12 Thread Alexander Aring
This patch adds extack support for act init callback api. This
prepares to handle extack support inside each specific act
implementation.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 2 +-
 net/sched/act_api.c| 5 +++--
 net/sched/act_bpf.c| 2 +-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 2 +-
 net/sched/act_gact.c   | 2 +-
 net/sched/act_ife.c| 2 +-
 net/sched/act_ipt.c| 4 ++--
 net/sched/act_mirred.c | 2 +-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 2 +-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 2 +-
 net/sched/act_simple.c | 2 +-
 net/sched/act_skbedit.c| 2 +-
 net/sched/act_skbmod.c | 2 +-
 net/sched/act_tunnel_key.c | 2 +-
 net/sched/act_vlan.c   | 2 +-
 18 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 41d95930ffbc..3717e0f2bb1b 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -90,7 +90,7 @@ struct tc_action_ops {
int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
-   int bind);
+   int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
const struct tc_action_ops *);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 90ae3593ca2b..60dec7b762dd 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -680,9 +680,10 @@ struct tc_action *tcf_action_init_1(struct net *net, 
struct tcf_proto *tp,
 
/* backward compatibility for policer */
if (name == NULL)
-   err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, , ovr, bind);
+   err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, , ovr, bind,
+   extack);
else
-   err = a_o->init(net, nla, est, , ovr, bind);
+   err = a_o->init(net, nla, est, , ovr, bind, extack);
if (err < 0)
goto err_mod;
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index b3f2c15affa7..b3ebfa9598e2 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -272,7 +272,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf 
*prog,
 
 static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act,
-   int replace, int bind)
+   int replace, int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 2b15ba84e0c8..20e0215360b5 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -96,7 +96,8 @@ static const struct nla_policy 
connmark_policy[TCA_CONNMARK_MAX + 1] = {
 
 static int tcf_connmark_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a,
-int ovr, int bind)
+int ovr, int bind,
+struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
struct nlattr *tb[TCA_CONNMARK_MAX + 1];
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index b7ba9b06b147..3b8c48bb2683 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -46,7 +46,7 @@ static struct tc_action_ops act_csum_ops;
 
 static int tcf_csum_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a, int ovr,
-int bind)
+int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
struct tcf_csum_params *params_old, *params_new;
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index b56986d41c87..912f3398f1c1 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -56,7 +56,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] 
= {
 
 static int tcf_gact_init(struct net *net, struct nlattr *nla,
 struct nlattr *est, struct tc_action **a,
-int ovr, int bind)
+int ovr, int bind, struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
struct nlattr *tb[TCA_GACT_MAX + 1];
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 5954e992685a..e5127d400737 100644
--- a/net/sched/act_ife.c
+++ b/net

[PATCH net-next 6/8] net: sched: act: add extack for walk callback

2018-02-12 Thread Alexander Aring
This patch adds extack support for act walker callback api. This
prepares to handle extack support inside each specific act
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 4 ++--
 net/sched/act_bpf.c| 3 ++-
 net/sched/act_connmark.c   | 3 ++-
 net/sched/act_csum.c   | 3 ++-
 net/sched/act_gact.c   | 3 ++-
 net/sched/act_ife.c| 3 ++-
 net/sched/act_ipt.c| 6 --
 net/sched/act_mirred.c | 3 ++-
 net/sched/act_nat.c| 3 ++-
 net/sched/act_pedit.c  | 3 ++-
 net/sched/act_police.c | 3 ++-
 net/sched/act_sample.c | 3 ++-
 net/sched/act_simple.c | 3 ++-
 net/sched/act_skbedit.c| 3 ++-
 net/sched/act_skbmod.c | 3 ++-
 net/sched/act_tunnel_key.c | 3 ++-
 net/sched/act_vlan.c   | 3 ++-
 18 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 0bd65db506ba..ab3529255377 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -94,7 +94,8 @@ struct tc_action_ops {
int bind, struct netlink_ext_ack *extack);
int (*walk)(struct net *, struct sk_buff *,
struct netlink_callback *, int,
-   const struct tc_action_ops *);
+   const struct tc_action_ops *,
+   struct netlink_ext_ack *);
void(*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a);
 };
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 77093432ddc3..1b30a29a2d9d 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -963,7 +963,7 @@ static int tca_action_flush(struct net *net, struct nlattr 
*nla,
goto out_module_put;
}
 
-   err = ops->walk(net, skb, , RTM_DELACTION, ops);
+   err = ops->walk(net, skb, , RTM_DELACTION, ops, extack);
if (err <= 0)
goto out_module_put;
 
@@ -1253,7 +1253,7 @@ static int tc_dump_action(struct sk_buff *skb, struct 
netlink_callback *cb)
if (nest == NULL)
goto out_module_put;
 
-   ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o);
+   ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
if (ret < 0)
goto out_module_put;
 
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index d9654b863347..7e01e2c710c4 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -367,7 +367,8 @@ static void tcf_bpf_cleanup(struct tc_action *act)
 
 static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
  struct netlink_callback *cb, int type,
- const struct tc_action_ops *ops)
+ const struct tc_action_ops *ops,
+ struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 0504b7600fb6..cb722da0bb15 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -177,7 +177,8 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, 
struct tc_action *a,
 
 static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index bdd17b9ef034..3e8efadb750f 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -631,7 +631,8 @@ static void tcf_csum_cleanup(struct tc_action *a)
 
 static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index e1e69e38f4b0..d96ebe4bb65a 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -201,7 +201,8 @@ static int tcf_gact_dump(struct sk_buff *skb, struct 
tc_action *a,
 
 static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
diff --git a/net/sched/act_ife.c b/net/sche

[PATCH net-next 7/8] net: sched: act: handle extack in tcf_generic_walker

2018-02-12 Thread Alexander Aring
This patch adds extack handling for a common used TC act function
"tcf_generic_walker()" to add an extack message on failures.
The tcf_generic_walker() function can fail if get a invalid command
different than DEL and GET. The naming "action" here is wrong, the
correct naming would be command.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  | 3 ++-
 net/sched/act_api.c| 6 --
 net/sched/act_bpf.c| 2 +-
 net/sched/act_connmark.c   | 2 +-
 net/sched/act_csum.c   | 2 +-
 net/sched/act_gact.c   | 2 +-
 net/sched/act_ife.c| 2 +-
 net/sched/act_ipt.c| 4 ++--
 net/sched/act_mirred.c | 2 +-
 net/sched/act_nat.c| 2 +-
 net/sched/act_pedit.c  | 2 +-
 net/sched/act_police.c | 2 +-
 net/sched/act_sample.c | 2 +-
 net/sched/act_simple.c | 2 +-
 net/sched/act_skbedit.c| 2 +-
 net/sched/act_skbmod.c | 2 +-
 net/sched/act_tunnel_key.c | 2 +-
 net/sched/act_vlan.c   | 2 +-
 18 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index ab3529255377..9c2f22695025 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -140,7 +140,8 @@ static inline void tc_action_net_exit(struct list_head 
*net_list,
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops);
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack);
 int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
 bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 1b30a29a2d9d..ab8431031d79 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -202,7 +202,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, 
struct sk_buff *skb,
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
   struct netlink_callback *cb, int type,
-  const struct tc_action_ops *ops)
+  const struct tc_action_ops *ops,
+  struct netlink_ext_ack *extack)
 {
struct tcf_idrinfo *idrinfo = tn->idrinfo;
 
@@ -211,7 +212,8 @@ int tcf_generic_walker(struct tc_action_net *tn, struct 
sk_buff *skb,
} else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb);
} else {
-   WARN(1, "tcf_generic_walker: unknown action %d\n", type);
+   WARN(1, "tcf_generic_walker: unknown command %d\n", type);
+   NL_SET_ERR_MSG(extack, "tcf_generic_walker: unknown command\n");
return -EINVAL;
}
 }
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 7e01e2c710c4..cb3c5d403c88 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -372,7 +372,7 @@ static int tcf_bpf_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index cb722da0bb15..e4b880fa51fe 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -182,7 +182,7 @@ static int tcf_connmark_walker(struct net *net, struct 
sk_buff *skb,
 {
struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 
index,
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 3e8efadb750f..d5c2e528d150 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -636,7 +636,7 @@ static int tcf_csum_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, csum_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index,
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index d96ebe4bb65a..f072bcf33760 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -206,7 +206,7 @@ static int tcf_gact_walker(struct net *net, struct sk_buff 
*skb,
 {
struct tc_action_net *tn = net_generic(net, gact_net_id);
 
-   return tcf_generic_walker(tn, skb, cb, type, ops);
+   return tcf_generic_walker(tn, skb, cb, type, ops, extack);
 }
 
 static int tcf_g

[PATCH net-next 0/8] net: sched: act: add extack support

2018-02-12 Thread Alexander Aring
Hi,

this patch series adds extack support for the TC action subsystem.
As example I for the extack support in a TC action I choosed mirred
action.

- Alex

Cc: David Ahern <dsah...@gmail.com>

Alexander Aring (8):
  net: sched: act: fix code style
  net: sched: act: add extack to init
  net: sched: act: handle generic action errors
  net: sched: act: add extack to init callback
  net: sched: act: add extack for lookup callback
  net: sched: act: add extack for walk callback
  net: sched: act: handle extack in tcf_generic_walker
  net: sched: act: mirred: add extack support

 include/net/act_api.h  |  17 --
 net/sched/act_api.c| 135 +
 net/sched/act_bpf.c|  10 ++--
 net/sched/act_connmark.c   |  11 ++--
 net/sched/act_csum.c   |  10 ++--
 net/sched/act_gact.c   |  10 ++--
 net/sched/act_ife.c|  10 ++--
 net/sched/act_ipt.c|  20 ---
 net/sched/act_mirred.c |  25 ++---
 net/sched/act_nat.c|  11 ++--
 net/sched/act_pedit.c  |  10 ++--
 net/sched/act_police.c |  11 ++--
 net/sched/act_sample.c |  10 ++--
 net/sched/act_simple.c |  10 ++--
 net/sched/act_skbedit.c|  10 ++--
 net/sched/act_skbmod.c |  10 ++--
 net/sched/act_tunnel_key.c |  10 ++--
 net/sched/act_vlan.c   |  10 ++--
 net/sched/cls_api.c|   4 +-
 19 files changed, 215 insertions(+), 129 deletions(-)

-- 
2.11.0



[PATCH net-next 8/8] net: sched: act: mirred: add extack support

2018-02-12 Thread Alexander Aring
This patch adds extack support for TC mirred action.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_mirred.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 05c2ebe92eca..fd34015331ab 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,13 +80,17 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
bool exists = false;
int ret;
 
-   if (!nla)
+   if (!nla) {
+   NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be 
passed");
return -EINVAL;
-   ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL);
+   }
+   ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, extack);
if (ret < 0)
return ret;
-   if (!tb[TCA_MIRRED_PARMS])
+   if (!tb[TCA_MIRRED_PARMS]) {
+   NL_SET_ERR_MSG_MOD(extack, "Missing required mirred 
parameters");
return -EINVAL;
+   }
parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
exists = tcf_idr_check(tn, parm->index, a, bind);
@@ -102,6 +106,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
default:
if (exists)
tcf_idr_release(*a, bind);
+   NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option");
return -EINVAL;
}
if (parm->ifindex) {
@@ -117,8 +122,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
}
 
if (!exists) {
-   if (!dev)
+   if (!dev) {
+   NL_SET_ERR_MSG_MOD(extack, "Specified device does not 
exist");
return -EINVAL;
+   }
ret = tcf_idr_create(tn, parm->index, est, a,
 _mirred_ops, bind, true);
if (ret)
-- 
2.11.0



[PATCH net-next 1/8] net: sched: act: fix code style

2018-02-12 Thread Alexander Aring
This patch is used by subsequent patches. It fixes code style issues
caught by checkpatch.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/act_api.h  |  5 +++--
 net/sched/act_api.c| 12 ++--
 net/sched/act_mirred.c |  6 +++---
 3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 6ed9692f20bd..32ef544f4ddc 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -87,12 +87,13 @@ struct tc_action_ops {
   struct tcf_result *);
int (*dump)(struct sk_buff *, struct tc_action *, int, int);
void(*cleanup)(struct tc_action *);
-   int (*lookup)(struct net *, struct tc_action **, u32);
+   int (*lookup)(struct net *net, struct tc_action **a, u32 index);
int (*init)(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action **act, int ovr,
int bind);
int (*walk)(struct net *, struct sk_buff *,
-   struct netlink_callback *, int, const struct 
tc_action_ops *);
+   struct netlink_callback *, int,
+   const struct tc_action_ops *);
void(*stats_update)(struct tc_action *, u64, u32, u64);
struct net_device *(*get_dev)(const struct tc_action *a);
 };
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index eba6682727dd..d885b3127e53 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -621,7 +621,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
goto err_out;
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
-   if (kind == NULL)
+   if (!kind)
goto err_out;
if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
goto err_out;
@@ -822,7 +822,7 @@ static int tca_get_fill(struct sk_buff *skb, struct 
list_head *actions,
t->tca__pad2 = 0;
 
nest = nla_nest_start(skb, TCA_ACT_TAB);
-   if (nest == NULL)
+   if (!nest)
goto out_nlmsg_trim;
 
if (tcf_action_dump(skb, actions, bind, ref) < 0)
@@ -934,7 +934,7 @@ static int tca_action_flush(struct net *net, struct nlattr 
*nla,
t->tca__pad2 = 0;
 
nest = nla_nest_start(skb, TCA_ACT_TAB);
-   if (nest == NULL)
+   if (!nest)
goto out_module_put;
 
err = ops->walk(net, skb, , RTM_DELACTION, ops);
@@ -1005,10 +1005,10 @@ tca_action_gd(struct net *net, struct nlattr *nla, 
struct nlmsghdr *n,
return ret;
 
if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
-   if (tb[1] != NULL)
+   if (tb[1])
return tca_action_flush(net, tb[1], n, portid);
-   else
-   return -EINVAL;
+
+   return -EINVAL;
}
 
for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index e6ff88f72900..abcd5f12b913 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -80,12 +80,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
bool exists = false;
int ret;
 
-   if (nla == NULL)
+   if (!nla)
return -EINVAL;
ret = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy, NULL);
if (ret < 0)
return ret;
-   if (tb[TCA_MIRRED_PARMS] == NULL)
+   if (!tb[TCA_MIRRED_PARMS])
return -EINVAL;
parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
@@ -117,7 +117,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr 
*nla,
}
 
if (!exists) {
-   if (dev == NULL)
+   if (!dev)
return -EINVAL;
ret = tcf_idr_create(tn, parm->index, est, a,
 _mirred_ops, bind, true);
-- 
2.11.0



[PATCH net-next 3/8] net: sched: act: handle generic action errors

2018-02-12 Thread Alexander Aring
This patch adds extack support for generic act handling. The extack
will be set deeper to each called function which is not part of netdev
core api.

Based on work by David Ahern <dsah...@gmail.com>

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/act_api.c | 93 +++--
 1 file changed, 61 insertions(+), 32 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index db7500d613fc..90ae3593ca2b 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -617,31 +617,40 @@ struct tc_action *tcf_action_init_1(struct net *net, 
struct tcf_proto *tp,
int err;
 
if (name == NULL) {
-   err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
+   err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
if (err < 0)
goto err_out;
err = -EINVAL;
kind = tb[TCA_ACT_KIND];
-   if (!kind)
+   if (!kind) {
+   NL_SET_ERR_MSG(extack, "TC action kind must be 
specified");
goto err_out;
-   if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
+   }
+   if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "TC action name too long");
goto err_out;
+   }
if (tb[TCA_ACT_COOKIE]) {
int cklen = nla_len(tb[TCA_ACT_COOKIE]);
 
-   if (cklen > TC_COOKIE_MAX_SIZE)
+   if (cklen > TC_COOKIE_MAX_SIZE) {
+   NL_SET_ERR_MSG(extack, "TC cookie size above 
the maximum");
goto err_out;
+   }
 
cookie = nla_memdup_cookie(tb);
if (!cookie) {
+   NL_SET_ERR_MSG(extack, "No memory to generate 
TC cookie");
err = -ENOMEM;
goto err_out;
}
}
} else {
-   err = -EINVAL;
-   if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
+   if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "TC action name too long");
+   err = -EINVAL;
goto err_out;
+   }
}
 
a_o = tc_lookup_action_n(act_name);
@@ -664,6 +673,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
goto err_mod;
}
 #endif
+   NL_SET_ERR_MSG(extack, "Failed to load TC action module");
err = -ENOENT;
goto err_out;
}
@@ -698,6 +708,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct 
tcf_proto *tp,
 
list_add_tail(>list, );
tcf_action_destroy(, bind);
+   NL_SET_ERR_MSG(extack, "Failed to init action chain");
return ERR_PTR(err);
}
}
@@ -734,7 +745,7 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, 
struct nlattr *nla,
int err;
int i;
 
-   err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
+   err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
if (err < 0)
return err;
 
@@ -842,7 +853,8 @@ static int tca_get_fill(struct sk_buff *skb, struct 
list_head *actions,
 
 static int
 tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
-  struct list_head *actions, int event)
+  struct list_head *actions, int event,
+  struct netlink_ext_ack *extack)
 {
struct sk_buff *skb;
 
@@ -851,6 +863,7 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr 
*n,
return -ENOBUFS;
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
 0, 0) <= 0) {
+   NL_SET_ERR_MSG(extack, "Failed to fill netlink tc action 
attributes");
kfree_skb(skb);
return -EINVAL;
}
@@ -859,7 +872,8 @@ tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr 
*n,
 }
 
 static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
- struct nlmsghdr *n, u32 portid)
+ struct nlmsghdr *n, u32 portid,
+ struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_ACT_MAX + 1];
const struct tc_action_ops *ops;
@@ -867,20 +881,24 @@ static struct tc_act

Re: [PATCH] Bluetooth: 6lowpan: Fix disconnect bug in 6lowpan

2018-01-22 Thread Alexander Aring
Hi,

2018-01-22 8:00 GMT-05:00 Luiz Augusto von Dentz :
> Hi Alex,
>
...
>>
>> or is there a special bluetooth API call needed, like the current case
>> with debugfs.
>> I know hcis are not netdevs, but it bothers me that we running into
>> two different worlds on how to deal with that and it just requires
>> "more" special bluetooth specific handling in user space applications.
>> Later more "netdev" capable link layers will maybe support 6LoWPAN and
>> then bluetooth might the only subsystem where different handling is
>> needed to do such job like that.
>
> Keep in mind that the transport on Bluetooth happens to be in a
> different layer, so you are basically suggesting that the kernel
> maintain a L2CAP connection, similar to TCP, which has several
> security implications.
>

no, I didn't said to change something in protocol handling etc.
I just wanted to say that I am aware that hci is not netdev and it's
hard to use net core api on these "interface types", because net core
knows netdevs only.

>> We maybe need to support a special handling in "ip link add" to map to
>> bluetooth instead moving that to people in user space?
>
> Afaik ip tool cannot support any tunnel interface since the kernel
> cleanup any socket opened when the tool exit. Btw, with the patches
> above bluetoothd would take care of adding/removing the links
> automatically so at least this step will not be necessary. Other ip
> commands should work though.
>

not tunneling, etc. I just want to know how you create a netdev
capable 6LoWPAN interface, it is not done by net core API so far I see
and it will never be done?
You say bluetoothd will care about it, but then bluetoothd will call
the right bluetooth API (not net core API, e.g. netlink (what iproute
uses))
Example:

ip link add link hci0 name 6lo0 type 6lowpan

This cannot work because the net core API will not work on HCI
"devices", I see..., but it highly bothers me that we cannot use
similar API to add or delete such interfaces with netlink API and
iproute2 -> you are forced to use bluetooth API with everything behind
it. At least a delete should work... (I am currently not sure if "ip
link del" would work with bluetooth 6LoWPAN).

According to adding a 6LoWPAN interface, so far I see it will never be
handled by net core API and creating a mapping from net core API to
bluetooth sounds fragile...

At least there is some command "create an 6LoWPAN interface for my
link layer hci device" or it's still magically created/removed by if
there exists a connection or not (I highly don't recommend it, because
user space applications cannot simple deal with dynamically creation
and removal of netdevs (and at the end it should be act like the
removed one again)), ifup/ifdown -> that's okay...
We already had this discussion once if I remember correctly.

- Alex


Re: [PATCHv3 net-next 7/7] net: sched: cls_u32: add extack support

2018-01-18 Thread Alexander Aring
Hi,

On Thu, Jan 18, 2018 at 11:51 AM, Jiri Pirko <j...@resnulli.us> wrote:
> Thu, Jan 18, 2018 at 05:20:55PM CET, ar...@mojatatu.com wrote:
>>This patch adds extack support for the u32 classifier as example for
>>delete and init callback.
>>
>>Cc: David Ahern <dsah...@gmail.com>
>>Signed-off-by: Alexander Aring <ar...@mojatatu.com>
>
> Acked-by: Jiri Pirko <j...@mellanox.com>
>
> Any plan to continue with other classifiers? Like cls_flower? :)
>

Not yet, the next step is extack support in tc actions. If you want to
do cls_flower extack support go ahead and make it.
As you are the author of it, you know better than everybody else how
the extack messages should look like.

- Alex


[PATCHv3 net-next 4/7] net: sched: cls: add extack support for tcf_exts_validate

2018-01-18 Thread Alexander Aring
The tcf_exts_validate function calls the act api change callback. For
preparing extack support for act api, this patch adds the extack as
parameter for this function which is common used in cls implementations.

Furthermore the tcf_exts_validate will call action init callback which
prepares the TC action subsystem for extack support.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h|  3 ++-
 net/sched/cls_api.c  |  7 +--
 net/sched/cls_basic.c|  8 +---
 net/sched/cls_bpf.c  |  8 +---
 net/sched/cls_cgroup.c   |  3 ++-
 net/sched/cls_flow.c |  3 ++-
 net/sched/cls_flower.c   |  8 +---
 net/sched/cls_fw.c   | 10 ++
 net/sched/cls_matchall.c |  8 +---
 net/sched/cls_route.c|  6 +++---
 net/sched/cls_rsvp.h |  2 +-
 net/sched/cls_tcindex.c  |  6 +++---
 net/sched/cls_u32.c  | 10 ++
 13 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 789d818c4a61..6dd009e10e5d 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -376,7 +376,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
  struct nlattr **tb, struct nlattr *rate_tlv,
- struct tcf_exts *exts, bool ovr);
+ struct tcf_exts *exts, bool ovr,
+ struct netlink_ext_ack *extack);
 void tcf_exts_destroy(struct tcf_exts *exts);
 void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 077740c8e906..f71192a5987c 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1416,7 +1416,8 @@ void tcf_exts_destroy(struct tcf_exts *exts)
 EXPORT_SYMBOL(tcf_exts_destroy);
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr 
**tb,
- struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
+ struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr,
+ struct netlink_ext_ack *extack)
 {
 #ifdef CONFIG_NET_CLS_ACT
{
@@ -1449,8 +1450,10 @@ int tcf_exts_validate(struct net *net, struct tcf_proto 
*tp, struct nlattr **tb,
}
 #else
if ((exts->action && tb[exts->action]) ||
-   (exts->police && tb[exts->police]))
+   (exts->police && tb[exts->police])) {
+   NL_SET_ERR_MSG(extack, "Classifier actions are not supported 
per compile options (CONFIG_NET_CLS_ACT)");
return -EOPNOTSUPP;
+   }
 #endif
 
return 0;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 2cc38cd71938..b7bcf67641bf 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -152,11 +152,12 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX 
+ 1] = {
 static int basic_set_parms(struct net *net, struct tcf_proto *tp,
   struct basic_filter *f, unsigned long base,
   struct nlattr **tb,
-  struct nlattr *est, bool ovr)
+  struct nlattr *est, bool ovr,
+  struct netlink_ext_ack *extack)
 {
int err;
 
-   err = tcf_exts_validate(net, tp, tb, est, >exts, ovr);
+   err = tcf_exts_validate(net, tp, tb, est, >exts, ovr, extack);
if (err < 0)
return err;
 
@@ -222,7 +223,8 @@ static int basic_change(struct net *net, struct sk_buff 
*in_skb,
fnew->handle = idr_index;
}
 
-   err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr);
+   err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr,
+ extack);
if (err < 0) {
if (!fold)
idr_remove_ext(>handle_idr, fnew->handle);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index e51eb503a23a..c86072779b0a 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -403,7 +403,8 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct 
cls_bpf_prog *prog,
 
 static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
 struct cls_bpf_prog *prog, unsigned long base,
-struct nlattr **tb, struct nlattr *est, bool ovr)
+struct nlattr **tb, struct nlattr *est, bool ovr,
+struct netlink_ext_ack *extack)
 {
bool is_bpf, is_ebpf, have_exts = false;
u32 gen_flags = 0;
@@ -414,7 +415,7 @@ static int cls_bpf_set_parms(struct net *net, struct 
tcf_proto *tp,
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
return -EINVAL;
 
-   ret = tcf_exts

[PATCHv3 net-next 3/7] net: sched: cls: add extack support for change callback

2018-01-18 Thread Alexander Aring
This patch adds extack support for classifier change callback api. This
prepares to handle extack support inside each specific classifier
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 3 ++-
 net/sched/cls_basic.c | 3 ++-
 net/sched/cls_bpf.c   | 2 +-
 net/sched/cls_cgroup.c| 3 ++-
 net/sched/cls_flow.c  | 2 +-
 net/sched/cls_flower.c| 2 +-
 net/sched/cls_fw.c| 2 +-
 net/sched/cls_matchall.c  | 2 +-
 net/sched/cls_route.c | 3 ++-
 net/sched/cls_rsvp.h  | 2 +-
 net/sched/cls_tcindex.c   | 3 ++-
 net/sched/cls_u32.c   | 3 ++-
 13 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c90f5fe6bed9..ee398bcd46e7 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -239,7 +239,8 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
-   void **, bool);
+   void **, bool,
+   struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
  bool *last);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 76f40b3d89d3..077740c8e906 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1231,7 +1231,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
}
 
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, ,
- n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE 
: TCA_ACT_REPLACE);
+ n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE 
: TCA_ACT_REPLACE,
+ extack);
if (err == 0) {
if (tp_created)
tcf_chain_tp_insert(chain, _info, tp);
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 5f169ded347e..2cc38cd71938 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -175,7 +175,8 @@ static int basic_set_parms(struct net *net, struct 
tcf_proto *tp,
 
 static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle,
-   struct nlattr **tca, void **arg, bool ovr)
+   struct nlattr **tca, void **arg, bool ovr,
+   struct netlink_ext_ack *extack)
 {
int err;
struct basic_head *head = rtnl_dereference(tp->root);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index cf72aefcf98d..e51eb503a23a 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -452,7 +452,7 @@ static int cls_bpf_set_parms(struct net *net, struct 
tcf_proto *tp,
 static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
  struct tcf_proto *tp, unsigned long base,
  u32 handle, struct nlattr **tca,
- void **arg, bool ovr)
+ void **arg, bool ovr, struct netlink_ext_ack *extack)
 {
struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *oldprog = *arg;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 309d5899265f..b74af0b55820 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -91,7 +91,8 @@ static void cls_cgroup_destroy_rcu(struct rcu_head *root)
 static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
 struct tcf_proto *tp, unsigned long base,
 u32 handle, struct nlattr **tca,
-void **arg, bool ovr)
+void **arg, bool ovr,
+struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_CGROUP_MAX + 1];
struct cls_cgroup_head *head = rtnl_dereference(tp->root);
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 28cd6fb52c16..faa0b6793a17 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -401,7 +401,7 @@ static void flow_destroy_filter(struct rcu_head *head)
 static int flow_change(struct net *net, struct sk_buff *in_skb,
   struct tcf_proto *tp, unsigned long base,
   u32 handle, struct nlattr **tca,
-  void **arg, bool ovr)
+  void **arg, bool ovr, struct netlink_ext_ack *extack)
 {
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *fold, *fnew;

[PATCHv3 net-next 1/7] net: sched: cls: fix code style issues

2018-01-18 Thread Alexander Aring
This patch changes some code style issues pointed out by checkpatch
inside the TC cls subsystem.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_matchall.c  | 2 +-
 net/sched/cls_u32.c   | 8 
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index cfc19d0ba2ad..c90f5fe6bed9 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -240,7 +240,8 @@ struct tcf_proto_ops {
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
void **, bool);
-   int (*delete)(struct tcf_proto*, void *, bool*);
+   int (*delete)(struct tcf_proto *tp, void *arg,
+ bool *last);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
void(*bind_class)(void *, u32, unsigned long);
 
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index d0e57c86636f..aeae89eeed0d 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -203,7 +203,7 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
goto err_set_parms;
 
if (!tc_skip_hw(new->flags)) {
-   err = mall_replace_hw_filter(tp, new, (unsigned long) new);
+   err = mall_replace_hw_filter(tp, new, (unsigned long)new);
if (err)
goto err_replace_hw_filter;
}
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 020d328d0afd..84129b3c14e5 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -783,7 +783,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
 
-   if (ht_down == NULL)
+   if (!ht_down)
return -EINVAL;
ht_down->refcnt++;
}
@@ -907,7 +907,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
size_t size;
 #endif
 
-   if (opt == NULL)
+   if (!opt)
return handle ? -EINVAL : 0;
 
err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
@@ -1011,7 +1011,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
htid = ht->handle;
} else {
ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
-   if (ht == NULL)
+   if (!ht)
return -EINVAL;
}
} else {
@@ -1023,7 +1023,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
return -EINVAL;
 
if (handle) {
-   if (TC_U32_HTID(handle) && TC_U32_HTID(handle^htid))
+   if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid))
return -EINVAL;
handle = htid | TC_U32_NODE(handle);
err = idr_alloc_ext(>handle_idr, NULL, NULL,
-- 
2.11.0



[PATCHv3 net-next 5/7] net: sched: cls: add extack support for delete callback

2018-01-18 Thread Alexander Aring
This patch adds extack support for classifier delete callback api. This
prepares to handle extack support inside each specific classifier
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 2 +-
 net/sched/cls_basic.c | 3 ++-
 net/sched/cls_bpf.c   | 3 ++-
 net/sched/cls_cgroup.c| 3 ++-
 net/sched/cls_flow.c  | 3 ++-
 net/sched/cls_flower.c| 3 ++-
 net/sched/cls_fw.c| 3 ++-
 net/sched/cls_matchall.c  | 3 ++-
 net/sched/cls_route.c | 3 ++-
 net/sched/cls_rsvp.h  | 3 ++-
 net/sched/cls_tcindex.c   | 5 +++--
 net/sched/cls_u32.c   | 3 ++-
 13 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index ee398bcd46e7..cd1be1f25c36 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -242,7 +242,8 @@ struct tcf_proto_ops {
void **, bool,
struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
- bool *last);
+ bool *last,
+ struct netlink_ext_ack *);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
void(*bind_class)(void *, u32, unsigned long);
 
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index f71192a5987c..9f88107c29c5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -955,7 +955,7 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
return -EINVAL;
}
 
-   err = tp->ops->delete(tp, fh, last);
+   err = tp->ops->delete(tp, fh, last, extack);
if (err) {
kfree_skb(skb);
return err;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index b7bcf67641bf..6088be65d167 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -130,7 +130,8 @@ static void basic_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
 }
 
-static int basic_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
+   struct netlink_ext_ack *extack)
 {
struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f = arg;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index c86072779b0a..fc024fc3ec2f 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -295,7 +295,8 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct 
cls_bpf_prog *prog)
__cls_bpf_delete_prog(prog);
 }
 
-static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
+ struct netlink_ext_ack *extack)
 {
struct cls_bpf_head *head = rtnl_dereference(tp->root);
 
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index aaafcf6965f7..1b54fbfca414 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -156,7 +156,8 @@ static void cls_cgroup_destroy(struct tcf_proto *tp)
}
 }
 
-static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last,
+struct netlink_ext_ack *extack)
 {
return -EOPNOTSUPP;
 }
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 07816133cbb9..64c24b488058 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -575,7 +575,8 @@ static int flow_change(struct net *net, struct sk_buff 
*in_skb,
return err;
 }
 
-static int flow_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int flow_delete(struct tcf_proto *tp, void *arg, bool *last,
+  struct netlink_ext_ack *extack)
 {
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f = arg;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 8235ed9143c4..50145b873ff1 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -985,7 +985,8 @@ static int fl_change(struct net *net, struct sk_buff 
*in_skb,
return err;
 }
 
-static int fl_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
+struct netlink_ext_ack *extack)
 {
struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f = arg;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 72a924a38753..bd21ed83eb07 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -172,7 +172,8 @@ static void fw_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
 }
 
-static int fw_delete(s

[PATCHv3 net-next 7/7] net: sched: cls_u32: add extack support

2018-01-18 Thread Alexander Aring
This patch adds extack support for the u32 classifier as example for
delete and init callback.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/cls_u32.c | 58 -
 1 file changed, 44 insertions(+), 14 deletions(-)

diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index e8963ed35899..57113e936155 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -689,13 +689,16 @@ static int u32_delete(struct tcf_proto *tp, void *arg, 
bool *last,
goto out;
}
 
-   if (root_ht == ht)
+   if (root_ht == ht) {
+   NL_SET_ERR_MSG_MOD(extack, "Not allowed to delete root node");
return -EINVAL;
+   }
 
if (ht->refcnt == 1) {
ht->refcnt--;
u32_destroy_hnode(tp, ht);
} else {
+   NL_SET_ERR_MSG_MOD(extack, "Can not delete in-use filter");
return -EBUSY;
}
 
@@ -779,14 +782,18 @@ static int u32_set_parms(struct net *net, struct 
tcf_proto *tp,
u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
struct tc_u_hnode *ht_down = NULL, *ht_old;
 
-   if (TC_U32_KEY(handle))
+   if (TC_U32_KEY(handle)) {
+   NL_SET_ERR_MSG_MOD(extack, "u32 Link handle must be a 
hash table");
return -EINVAL;
+   }
 
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
 
-   if (!ht_down)
+   if (!ht_down) {
+   NL_SET_ERR_MSG_MOD(extack, "Link hash table not 
found");
return -EINVAL;
+   }
ht_down->refcnt++;
}
 
@@ -910,28 +917,40 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
size_t size;
 #endif
 
-   if (!opt)
-   return handle ? -EINVAL : 0;
+   if (!opt) {
+   if (handle) {
+   NL_SET_ERR_MSG_MOD(extack, "Filter handle requires 
options");
+   return -EINVAL;
+   } else {
+   return 0;
+   }
+   }
 
-   err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
+   err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, extack);
if (err < 0)
return err;
 
if (tb[TCA_U32_FLAGS]) {
flags = nla_get_u32(tb[TCA_U32_FLAGS]);
-   if (!tc_flags_valid(flags))
+   if (!tc_flags_valid(flags)) {
+   NL_SET_ERR_MSG_MOD(extack, "Invalid filter flags");
return -EINVAL;
+   }
}
 
n = *arg;
if (n) {
struct tc_u_knode *new;
 
-   if (TC_U32_KEY(n->handle) == 0)
+   if (TC_U32_KEY(n->handle) == 0) {
+   NL_SET_ERR_MSG_MOD(extack, "Key node id cannot be 
zero");
return -EINVAL;
+   }
 
-   if (n->flags != flags)
+   if (n->flags != flags) {
+   NL_SET_ERR_MSG_MOD(extack, "Key node flags do not match 
passed flags");
return -EINVAL;
+   }
 
new = u32_init_knode(tp, n);
if (!new)
@@ -965,10 +984,14 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
if (tb[TCA_U32_DIVISOR]) {
unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
 
-   if (--divisor > 0x100)
+   if (--divisor > 0x100) {
+   NL_SET_ERR_MSG_MOD(extack, "Exceeded maximum 256 hash 
buckets");
return -EINVAL;
-   if (TC_U32_KEY(handle))
+   }
+   if (TC_U32_KEY(handle)) {
+   NL_SET_ERR_MSG_MOD(extack, "Divisor can only be used on 
a hash table");
return -EINVAL;
+   }
ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);
if (ht == NULL)
return -ENOBUFS;
@@ -1014,20 +1037,26 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
htid = ht->handle;
} else {
ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
-   if (!ht)
+   if (!ht) {
+   NL_SET_ERR_MSG_MOD(extack, "Specified hash 
table not found");
return -EINVAL;
+   }
}
} else {
ht = rtnl_dereference(tp->root);
 

[PATCHv3 net-next 6/7] net: sched: cls: add extack support for tcf_change_indev

2018-01-18 Thread Alexander Aring
This patch adds extack handling for the tcf_change_indev function which
is common used by TC classifier implementations.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h  | 7 +--
 net/sched/cls_flower.c | 7 ---
 net/sched/cls_fw.c | 2 +-
 net/sched/cls_u32.c| 2 +-
 4 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 6dd009e10e5d..2e4b8e436d25 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -557,13 +557,16 @@ static inline int tcf_valid_offset(const struct sk_buff 
*skb,
 #include 
 
 static inline int
-tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
+tcf_change_indev(struct net *net, struct nlattr *indev_tlv,
+struct netlink_ext_ack *extack)
 {
char indev[IFNAMSIZ];
struct net_device *dev;
 
-   if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
+   if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "Interface name too long");
return -EINVAL;
+   }
dev = __dev_get_by_name(net, indev);
if (!dev)
return -ENODEV;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 50145b873ff1..c6ac4a612c4a 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -526,13 +526,14 @@ static void fl_set_key_ip(struct nlattr **tb,
 }
 
 static int fl_set_key(struct net *net, struct nlattr **tb,
- struct fl_flow_key *key, struct fl_flow_key *mask)
+ struct fl_flow_key *key, struct fl_flow_key *mask,
+ struct netlink_ext_ack *extack)
 {
__be16 ethertype;
int ret = 0;
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FLOWER_INDEV]) {
-   int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV]);
+   int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV], extack);
if (err < 0)
return err;
key->indev_ifindex = err;
@@ -841,7 +842,7 @@ static int fl_set_parms(struct net *net, struct tcf_proto 
*tp,
tcf_bind_filter(tp, >res, base);
}
 
-   err = fl_set_key(net, tb, >key, >key);
+   err = fl_set_key(net, tb, >key, >key, extack);
if (err)
return err;
 
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index bd21ed83eb07..94d159a8869a 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -239,7 +239,7 @@ static int fw_set_parms(struct net *net, struct tcf_proto 
*tp,
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FW_INDEV]) {
int ret;
-   ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
+   ret = tcf_change_indev(net, tb[TCA_FW_INDEV], extack);
if (ret < 0)
return ret;
f->ifindex = ret;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 7f772da8e627..e8963ed35899 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -804,7 +804,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_U32_INDEV]) {
int ret;
-   ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
+   ret = tcf_change_indev(net, tb[TCA_U32_INDEV], extack);
if (ret < 0)
return -EINVAL;
n->ifindex = ret;
-- 
2.11.0



[PATCHv3 net-next 2/7] net: sched: cls_api: handle generic cls errors

2018-01-18 Thread Alexander Aring
This patch adds extack support for generic cls handling. The extack
will be set deeper to each called function which is not part of netdev
core api.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/cls_api.c | 52 +---
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index e500d11da9cd..76f40b3d89d3 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -122,7 +122,8 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 }
 
 static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
- u32 prio, struct tcf_chain *chain)
+ u32 prio, struct tcf_chain *chain,
+ struct netlink_ext_ack *extack)
 {
struct tcf_proto *tp;
int err;
@@ -148,6 +149,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, 
u32 protocol,
module_put(tp->ops->owner);
err = -EAGAIN;
} else {
+   NL_SET_ERR_MSG(extack, "TC classifier not found");
err = -ENOENT;
}
goto errout;
@@ -935,7 +937,8 @@ static int tfilter_notify(struct net *net, struct sk_buff 
*oskb,
 static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
  struct nlmsghdr *n, struct tcf_proto *tp,
  struct tcf_block *block, struct Qdisc *q,
- u32 parent, void *fh, bool unicast, bool *last)
+ u32 parent, void *fh, bool unicast, bool *last,
+ struct netlink_ext_ack *extack)
 {
struct sk_buff *skb;
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
@@ -947,6 +950,7 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
 
if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid,
  n->nlmsg_seq, n->nlmsg_flags, RTM_DELTFILTER) <= 0) {
+   NL_SET_ERR_MSG(extack, "Failed to build del event 
notification");
kfree_skb(skb);
return -EINVAL;
}
@@ -960,8 +964,11 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
if (unicast)
return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);
 
-   return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
- n->nlmsg_flags & NLM_F_ECHO);
+   err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
+n->nlmsg_flags & NLM_F_ECHO);
+   if (err < 0)
+   NL_SET_ERR_MSG(extack, "Failed to send filter delete 
notification");
+   return err;
 }
 
 static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
@@ -1021,8 +1028,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
if (prio == 0) {
switch (n->nlmsg_type) {
case RTM_DELTFILTER:
-   if (protocol || t->tcm_handle || tca[TCA_KIND])
+   if (protocol || t->tcm_handle || tca[TCA_KIND]) {
+   NL_SET_ERR_MSG(extack, "Cannot flush filters 
with protocol, handle or kind set");
return -ENOENT;
+   }
break;
case RTM_NEWTFILTER:
/* If no priority is provided by the user,
@@ -1035,6 +1044,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
}
/* fall-through */
default:
+   NL_SET_ERR_MSG(extack, "Invalid filter command with 
priority of zero");
return -ENOENT;
}
}
@@ -1063,23 +1073,31 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
parent = q->handle;
} else {
q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
-   if (!q)
+   if (!q) {
+   NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't 
exists");
return -EINVAL;
+   }
}
 
/* Is it classful? */
cops = q->ops->cl_ops;
-   if (!cops)
+   if (!cops) {
+   NL_SET_ERR_MSG(extack, "Qdisc not classful");
return -EINVAL;
+   }
 
-   if (!cops->tcf_block)
+   if (!cops->tcf_block) {
+   NL_SET_ERR_MSG(extack, "

[PATCHv3 net-next 0/7] net: sched: cls: add extack support

2018-01-18 Thread Alexander Aring
Hi,

this patch adds extack support for TC classifier subsystem. The first
patch fixes some code style issues for this patch series pointed out
by checkpatch. The other patches until the last one prepares extack
handling for the TC classifier subsystem and handle generic extack
errors.

The last patch is an example for u32 classifier to add extack support
inside the callbacks delete and change. There exists a init callback as
well, but most classifier implementation run a kalloc() once to allocate
something. Not necessary _yet_ to add extack support now.

- Alex

Cc: David Ahern <dsah...@gmail.com>

changes since v3:
 - fix accidentally move of config option mismatch message in PATCH 2/8
   correct one is 4/8, detected by kbuildbot (Thank you)
 - Removed patch "net: sched: cls: add extack support for tc_setup_cb_call"
   PATCH 7/8 in version v2 as suggested by Jakub Kicinski (Thank you)
 - changed NL_SET_ERR_MSG to NL_SET_ERR_MSG_MOD as suggested by Jakub Kicinski
   in u32 cls (Thank You)
 - Removed text from cover letter that I was waiting for Jiri's Patches as
   detected by Jamal Hadi Salim (Thank you).

changes since v2:
 - rebased on Jiri's patches (Thank you)
 - several spelling fixes pointed out by Cong Wang (Thank you)
 - several spelling fixes pointed out by David Ahern (Thank you)
 - use David Ahern recommendation if config option is mismatch, but
   combine it with Cong Wang recommendation to put config name into it
   (Thank you)

Alexander Aring (7):
  net: sched: cls: fix code style issues
  net: sched: cls_api: handle generic cls errors
  net: sched: cls: add extack support for change callback
  net: sched: cls: add extack support for tcf_exts_validate
  net: sched: cls: add extack support for delete callback
  net: sched: cls: add extack support for tcf_change_indev
  net: sched: cls_u32: add extack support

 include/net/pkt_cls.h | 10 +--
 include/net/sch_generic.h |  7 +++--
 net/sched/cls_api.c   | 64 +--
 net/sched/cls_basic.c | 14 +
 net/sched/cls_bpf.c   | 13 
 net/sched/cls_cgroup.c|  9 --
 net/sched/cls_flow.c  |  8 +++--
 net/sched/cls_flower.c| 20 -
 net/sched/cls_fw.c| 17 ++-
 net/sched/cls_matchall.c  | 15 ++
 net/sched/cls_route.c | 12 
 net/sched/cls_rsvp.h  |  7 +++--
 net/sched/cls_tcindex.c   | 14 +
 net/sched/cls_u32.c   | 76 ++-
 14 files changed, 194 insertions(+), 92 deletions(-)

-- 
2.11.0



Re: [PATCHv2 net-next 8/8] net: sched: cls_u32: add extack support

2018-01-18 Thread Alexander Aring
Hi,

On Wed, Jan 17, 2018 at 8:27 PM, Jakub Kicinski <kubak...@wp.pl> wrote:
> On Wed, 17 Jan 2018 17:40:27 -0500, Alexander Aring wrote:
>> diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
>> index 8840baa1b9b4..daeac7282387 100644
>> --- a/net/sched/cls_u32.c
>> +++ b/net/sched/cls_u32.c
>> @@ -524,8 +524,10 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, 
>> struct tc_u_hnode *h,
>>   offloaded = true;
>>   }
>>
>> - if (skip_sw && !offloaded)
>> + if (skip_sw && !offloaded) {
>> + NL_SET_ERR_MSG(extack, "Failed to offload filter requested 
>> with skip sw");
>>   return -EINVAL;
>> + }
>>
>>   return 0;
>>  }
>
> Why did you ignore my comment about using NL_SET_ERR_MSG_MOD?  Do you
> disagree with it?

Sorry, I missed it I will add this. Thanks.

- Alex


Re: [PATCHv2 net-next 7/8] net: sched: cls: add extack support for tc_setup_cb_call

2018-01-18 Thread Alexander Aring
Hi,

On Wed, Jan 17, 2018 at 8:25 PM, Jakub Kicinski <kubak...@wp.pl> wrote:
> On Wed, 17 Jan 2018 17:40:26 -0500, Alexander Aring wrote:
>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
>> index 9f88107c29c5..e864ad523800 100644
>> --- a/net/sched/cls_api.c
>> +++ b/net/sched/cls_api.c
>> @@ -1566,21 +1566,26 @@ static int tc_exts_setup_cb_egdev_call(struct 
>> tcf_exts *exts,
>>  }
>>
>>  int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
>> -  enum tc_setup_type type, void *type_data, bool err_stop)
>> +  enum tc_setup_type type, void *type_data, bool err_stop,
>> +  struct netlink_ext_ack *extack)
>>  {
>>   int ok_count;
>>   int ret;
>>
>>   ret = tcf_block_cb_call(block, type, type_data, err_stop);
>> - if (ret < 0)
>> + if (ret < 0) {
>> + NL_SET_ERR_MSG(extack, "Failed to initialize tcf block");
>
> This has nothing to do with block init.
>
>>   return ret;
>> + }
>>   ok_count = ret;
>>
>>   if (!exts)
>>   return ok_count;
>>   ret = tc_exts_setup_cb_egdev_call(exts, type, type_data, err_stop);
>> - if (ret < 0)
>> + if (ret < 0) {
>> + NL_SET_ERR_MSG(extack, "Failed to initialize tcf block 
>> extensions");
>
> Ditto, plus this is about redirections to other devices (hence
> eg[ress ]dev).  exts part is an internal detail.
>

Ok, I am going to remove this patch.

- Alex


[PATCHv2 net-next 8/8] net: sched: cls_u32: add extack support

2018-01-17 Thread Alexander Aring
This patch adds extack support for the u32 classifier as example for
delete and init callback.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/cls_u32.c | 66 -
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 8840baa1b9b4..daeac7282387 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -524,8 +524,10 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, 
struct tc_u_hnode *h,
offloaded = true;
}
 
-   if (skip_sw && !offloaded)
+   if (skip_sw && !offloaded) {
+   NL_SET_ERR_MSG(extack, "Failed to offload filter requested with 
skip sw");
return -EINVAL;
+   }
 
return 0;
 }
@@ -576,8 +578,10 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, 
struct tc_u_knode *n,
tcf_block_offload_inc(block, >flags);
}
 
-   if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW))
+   if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW)) {
+   NL_SET_ERR_MSG(extack, "Failed to offload filter requested with 
skip sw");
return -EINVAL;
+   }
 
return 0;
 }
@@ -691,13 +695,16 @@ static int u32_delete(struct tcf_proto *tp, void *arg, 
bool *last,
goto out;
}
 
-   if (root_ht == ht)
+   if (root_ht == ht) {
+   NL_SET_ERR_MSG(extack, "Not allowed to delete root node");
return -EINVAL;
+   }
 
if (ht->refcnt == 1) {
ht->refcnt--;
u32_destroy_hnode(tp, ht);
} else {
+   NL_SET_ERR_MSG(extack, "Can not delete in-use filter");
return -EBUSY;
}
 
@@ -781,14 +788,18 @@ static int u32_set_parms(struct net *net, struct 
tcf_proto *tp,
u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
struct tc_u_hnode *ht_down = NULL, *ht_old;
 
-   if (TC_U32_KEY(handle))
+   if (TC_U32_KEY(handle)) {
+   NL_SET_ERR_MSG(extack, "u32 Link handle must be a hash 
table");
return -EINVAL;
+   }
 
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
 
-   if (!ht_down)
+   if (!ht_down) {
+   NL_SET_ERR_MSG(extack, "Link hash table not 
found");
return -EINVAL;
+   }
ht_down->refcnt++;
}
 
@@ -912,28 +923,40 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
size_t size;
 #endif
 
-   if (!opt)
-   return handle ? -EINVAL : 0;
+   if (!opt) {
+   if (handle) {
+   NL_SET_ERR_MSG(extack, "Filter handle requires 
options");
+   return -EINVAL;
+   } else {
+   return 0;
+   }
+   }
 
-   err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
+   err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, extack);
if (err < 0)
return err;
 
if (tb[TCA_U32_FLAGS]) {
flags = nla_get_u32(tb[TCA_U32_FLAGS]);
-   if (!tc_flags_valid(flags))
+   if (!tc_flags_valid(flags)) {
+   NL_SET_ERR_MSG(extack, "Invalid filter flags");
return -EINVAL;
+   }
}
 
n = *arg;
if (n) {
struct tc_u_knode *new;
 
-   if (TC_U32_KEY(n->handle) == 0)
+   if (TC_U32_KEY(n->handle) == 0) {
+   NL_SET_ERR_MSG(extack, "Key node id cannot be zero");
return -EINVAL;
+   }
 
-   if (n->flags != flags)
+   if (n->flags != flags) {
+   NL_SET_ERR_MSG(extack, "Key node flags do not match 
passed flags");
return -EINVAL;
+   }
 
new = u32_init_knode(tp, n);
if (!new)
@@ -967,10 +990,14 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
if (tb[TCA_U32_DIVISOR]) {
unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
 
-   if (--divisor > 0x100)
+   if (--divisor > 0x100) {
+   NL_SET_ERR_MSG(extack, "Exceeded maximum 256 hash 
buckets");
return -EINVAL;
-   if (TC_U32_KEY(handle))
+   }
+   if (TC_U32_KEY(handle)) {
+   NL_SET_ERR_MSG(extack, "Divi

[PATCHv2 net-next 4/8] net: sched: cls: add extack support for tcf_exts_validate

2018-01-17 Thread Alexander Aring
The tcf_exts_validate function calls the act api change callback. For
preparing extack support for act api, this patch adds the extack as
parameter for this function which is common used in cls implementations.

Furthermore the tcf_exts_validate will call action init callback which
prepares the TC action subsystem for extack support.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h|  3 ++-
 net/sched/cls_api.c  |  3 ++-
 net/sched/cls_basic.c|  8 +---
 net/sched/cls_bpf.c  |  8 +---
 net/sched/cls_cgroup.c   |  3 ++-
 net/sched/cls_flow.c |  3 ++-
 net/sched/cls_flower.c   |  8 +---
 net/sched/cls_fw.c   | 10 ++
 net/sched/cls_matchall.c |  8 +---
 net/sched/cls_route.c|  6 +++---
 net/sched/cls_rsvp.h |  2 +-
 net/sched/cls_tcindex.c  |  6 +++---
 net/sched/cls_u32.c  | 10 ++
 13 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 789d818c4a61..6dd009e10e5d 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -376,7 +376,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
  struct nlattr **tb, struct nlattr *rate_tlv,
- struct tcf_exts *exts, bool ovr);
+ struct tcf_exts *exts, bool ovr,
+ struct netlink_ext_ack *extack);
 void tcf_exts_destroy(struct tcf_exts *exts);
 void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index c700b82eafa2..f71192a5987c 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1416,7 +1416,8 @@ void tcf_exts_destroy(struct tcf_exts *exts)
 EXPORT_SYMBOL(tcf_exts_destroy);
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr 
**tb,
- struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
+ struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr,
+ struct netlink_ext_ack *extack)
 {
 #ifdef CONFIG_NET_CLS_ACT
{
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 2cc38cd71938..b7bcf67641bf 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -152,11 +152,12 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX 
+ 1] = {
 static int basic_set_parms(struct net *net, struct tcf_proto *tp,
   struct basic_filter *f, unsigned long base,
   struct nlattr **tb,
-  struct nlattr *est, bool ovr)
+  struct nlattr *est, bool ovr,
+  struct netlink_ext_ack *extack)
 {
int err;
 
-   err = tcf_exts_validate(net, tp, tb, est, >exts, ovr);
+   err = tcf_exts_validate(net, tp, tb, est, >exts, ovr, extack);
if (err < 0)
return err;
 
@@ -222,7 +223,8 @@ static int basic_change(struct net *net, struct sk_buff 
*in_skb,
fnew->handle = idr_index;
}
 
-   err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr);
+   err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr,
+ extack);
if (err < 0) {
if (!fold)
idr_remove_ext(>handle_idr, fnew->handle);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index e51eb503a23a..c86072779b0a 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -403,7 +403,8 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct 
cls_bpf_prog *prog,
 
 static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
 struct cls_bpf_prog *prog, unsigned long base,
-struct nlattr **tb, struct nlattr *est, bool ovr)
+struct nlattr **tb, struct nlattr *est, bool ovr,
+struct netlink_ext_ack *extack)
 {
bool is_bpf, is_ebpf, have_exts = false;
u32 gen_flags = 0;
@@ -414,7 +415,7 @@ static int cls_bpf_set_parms(struct net *net, struct 
tcf_proto *tp,
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
return -EINVAL;
 
-   ret = tcf_exts_validate(net, tp, tb, est, >exts, ovr);
+   ret = tcf_exts_validate(net, tp, tb, est, >exts, ovr, extack);
if (ret < 0)
return ret;
 
@@ -500,7 +501,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff 
*in_skb,
prog->handle = handle;
}
 
-   ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr);
+   ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr,
+   extack);
if 

[PATCHv2 net-next 7/8] net: sched: cls: add extack support for tc_setup_cb_call

2018-01-17 Thread Alexander Aring
This patch adds extack handling for the tc_setup_cb_call function which
is common used by TC classifier implementations.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h|  3 ++-
 net/sched/cls_api.c  | 11 ---
 net/sched/cls_bpf.c  | 19 +++
 net/sched/cls_flower.c   | 11 ++-
 net/sched/cls_matchall.c | 11 +++
 net/sched/cls_u32.c  | 20 +++-
 6 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 2e4b8e436d25..7457232ae59f 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -585,7 +585,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
 #endif /* CONFIG_NET_CLS_IND */
 
 int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
-enum tc_setup_type type, void *type_data, bool err_stop);
+enum tc_setup_type type, void *type_data, bool err_stop,
+struct netlink_ext_ack *extack);
 
 enum tc_block_command {
TC_BLOCK_BIND,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 9f88107c29c5..e864ad523800 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1566,21 +1566,26 @@ static int tc_exts_setup_cb_egdev_call(struct tcf_exts 
*exts,
 }
 
 int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
-enum tc_setup_type type, void *type_data, bool err_stop)
+enum tc_setup_type type, void *type_data, bool err_stop,
+struct netlink_ext_ack *extack)
 {
int ok_count;
int ret;
 
ret = tcf_block_cb_call(block, type, type_data, err_stop);
-   if (ret < 0)
+   if (ret < 0) {
+   NL_SET_ERR_MSG(extack, "Failed to initialize tcf block");
return ret;
+   }
ok_count = ret;
 
if (!exts)
return ok_count;
ret = tc_exts_setup_cb_egdev_call(exts, type, type_data, err_stop);
-   if (ret < 0)
+   if (ret < 0) {
+   NL_SET_ERR_MSG(extack, "Failed to initialize tcf block 
extensions");
return ret;
+   }
ok_count += ret;
 
return ok_count;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index fc024fc3ec2f..566befb6ac71 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -147,7 +147,8 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
 }
 
 static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
-  struct cls_bpf_prog *oldprog)
+  struct cls_bpf_prog *oldprog,
+  struct netlink_ext_ack *extack)
 {
struct tcf_block *block = tp->chain->block;
struct tc_cls_bpf_offload cls_bpf = {};
@@ -170,10 +171,11 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, 
struct cls_bpf_prog *prog,
if (oldprog)
tcf_block_offload_dec(block, >gen_flags);
 
-   err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, _bpf, skip_sw);
+   err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, _bpf, skip_sw,
+  extack);
if (prog) {
if (err < 0) {
-   cls_bpf_offload_cmd(tp, oldprog, prog);
+   cls_bpf_offload_cmd(tp, oldprog, prog, NULL);
return err;
} else if (err > 0) {
tcf_block_offload_inc(block, >gen_flags);
@@ -187,7 +189,8 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct 
cls_bpf_prog *prog,
 }
 
 static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
-  struct cls_bpf_prog *oldprog)
+  struct cls_bpf_prog *oldprog,
+  struct netlink_ext_ack *extack)
 {
if (prog && oldprog && prog->gen_flags != oldprog->gen_flags)
return -EINVAL;
@@ -199,7 +202,7 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct 
cls_bpf_prog *prog,
if (!prog && !oldprog)
return 0;
 
-   return cls_bpf_offload_cmd(tp, prog, oldprog);
+   return cls_bpf_offload_cmd(tp, prog, oldprog, extack);
 }
 
 static void cls_bpf_stop_offload(struct tcf_proto *tp,
@@ -207,7 +210,7 @@ static void cls_bpf_stop_offload(struct tcf_proto *tp,
 {
int err;
 
-   err = cls_bpf_offload_cmd(tp, NULL, prog);
+   err = cls_bpf_offload_cmd(tp, NULL, prog, NULL);
if (err)
pr_err("Stopping hardware offload failed: %d\n", err);
 }
@@ -226,7 +229,7 @@ static void cls_bpf_offload_update_stats(struct tcf_proto 
*tp,
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_flags;
 
-   tc_setup_cb_

[PATCHv2 net-next 1/8] net: sched: cls: fix code style issues

2018-01-17 Thread Alexander Aring
This patch changes some code style issues pointed out by checkpatch
inside the TC cls subsystem.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_matchall.c  | 2 +-
 net/sched/cls_u32.c   | 8 
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index cfc19d0ba2ad..c90f5fe6bed9 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -240,7 +240,8 @@ struct tcf_proto_ops {
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
void **, bool);
-   int (*delete)(struct tcf_proto*, void *, bool*);
+   int (*delete)(struct tcf_proto *tp, void *arg,
+ bool *last);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
void(*bind_class)(void *, u32, unsigned long);
 
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index d0e57c86636f..aeae89eeed0d 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -203,7 +203,7 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
goto err_set_parms;
 
if (!tc_skip_hw(new->flags)) {
-   err = mall_replace_hw_filter(tp, new, (unsigned long) new);
+   err = mall_replace_hw_filter(tp, new, (unsigned long)new);
if (err)
goto err_replace_hw_filter;
}
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 020d328d0afd..84129b3c14e5 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -783,7 +783,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
 
-   if (ht_down == NULL)
+   if (!ht_down)
return -EINVAL;
ht_down->refcnt++;
}
@@ -907,7 +907,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
size_t size;
 #endif
 
-   if (opt == NULL)
+   if (!opt)
return handle ? -EINVAL : 0;
 
err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
@@ -1011,7 +1011,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
htid = ht->handle;
} else {
ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
-   if (ht == NULL)
+   if (!ht)
return -EINVAL;
}
} else {
@@ -1023,7 +1023,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
return -EINVAL;
 
if (handle) {
-   if (TC_U32_HTID(handle) && TC_U32_HTID(handle^htid))
+   if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid))
return -EINVAL;
handle = htid | TC_U32_NODE(handle);
err = idr_alloc_ext(>handle_idr, NULL, NULL,
-- 
2.11.0



[PATCHv2 net-next 6/8] net: sched: cls: add extack support for tcf_change_indev

2018-01-17 Thread Alexander Aring
This patch adds extack handling for the tcf_change_indev function which
is common used by TC classifier implementations.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h  | 7 +--
 net/sched/cls_flower.c | 7 ---
 net/sched/cls_fw.c | 2 +-
 net/sched/cls_u32.c| 2 +-
 4 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 6dd009e10e5d..2e4b8e436d25 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -557,13 +557,16 @@ static inline int tcf_valid_offset(const struct sk_buff 
*skb,
 #include 
 
 static inline int
-tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
+tcf_change_indev(struct net *net, struct nlattr *indev_tlv,
+struct netlink_ext_ack *extack)
 {
char indev[IFNAMSIZ];
struct net_device *dev;
 
-   if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
+   if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "Interface name too long");
return -EINVAL;
+   }
dev = __dev_get_by_name(net, indev);
if (!dev)
return -ENODEV;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 50145b873ff1..c6ac4a612c4a 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -526,13 +526,14 @@ static void fl_set_key_ip(struct nlattr **tb,
 }
 
 static int fl_set_key(struct net *net, struct nlattr **tb,
- struct fl_flow_key *key, struct fl_flow_key *mask)
+ struct fl_flow_key *key, struct fl_flow_key *mask,
+ struct netlink_ext_ack *extack)
 {
__be16 ethertype;
int ret = 0;
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FLOWER_INDEV]) {
-   int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV]);
+   int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV], extack);
if (err < 0)
return err;
key->indev_ifindex = err;
@@ -841,7 +842,7 @@ static int fl_set_parms(struct net *net, struct tcf_proto 
*tp,
tcf_bind_filter(tp, >res, base);
}
 
-   err = fl_set_key(net, tb, >key, >key);
+   err = fl_set_key(net, tb, >key, >key, extack);
if (err)
return err;
 
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index bd21ed83eb07..94d159a8869a 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -239,7 +239,7 @@ static int fw_set_parms(struct net *net, struct tcf_proto 
*tp,
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FW_INDEV]) {
int ret;
-   ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
+   ret = tcf_change_indev(net, tb[TCA_FW_INDEV], extack);
if (ret < 0)
return ret;
f->ifindex = ret;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 7f772da8e627..e8963ed35899 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -804,7 +804,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_U32_INDEV]) {
int ret;
-   ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
+   ret = tcf_change_indev(net, tb[TCA_U32_INDEV], extack);
if (ret < 0)
return -EINVAL;
n->ifindex = ret;
-- 
2.11.0



[PATCHv2 net-next 3/8] net: sched: cls: add extack support for change callback

2018-01-17 Thread Alexander Aring
This patch adds extack support for classifier change callback api. This
prepares to handle extack support inside each specific classifier
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 3 ++-
 net/sched/cls_basic.c | 3 ++-
 net/sched/cls_bpf.c   | 2 +-
 net/sched/cls_cgroup.c| 3 ++-
 net/sched/cls_flow.c  | 2 +-
 net/sched/cls_flower.c| 2 +-
 net/sched/cls_fw.c| 2 +-
 net/sched/cls_matchall.c  | 2 +-
 net/sched/cls_route.c | 3 ++-
 net/sched/cls_rsvp.h  | 2 +-
 net/sched/cls_tcindex.c   | 3 ++-
 net/sched/cls_u32.c   | 3 ++-
 13 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c90f5fe6bed9..ee398bcd46e7 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -239,7 +239,8 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
-   void **, bool);
+   void **, bool,
+   struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
  bool *last);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 0a3e2a2f8917..c700b82eafa2 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1231,7 +1231,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
}
 
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, ,
- n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE 
: TCA_ACT_REPLACE);
+ n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE 
: TCA_ACT_REPLACE,
+ extack);
if (err == 0) {
if (tp_created)
tcf_chain_tp_insert(chain, _info, tp);
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 5f169ded347e..2cc38cd71938 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -175,7 +175,8 @@ static int basic_set_parms(struct net *net, struct 
tcf_proto *tp,
 
 static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle,
-   struct nlattr **tca, void **arg, bool ovr)
+   struct nlattr **tca, void **arg, bool ovr,
+   struct netlink_ext_ack *extack)
 {
int err;
struct basic_head *head = rtnl_dereference(tp->root);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index cf72aefcf98d..e51eb503a23a 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -452,7 +452,7 @@ static int cls_bpf_set_parms(struct net *net, struct 
tcf_proto *tp,
 static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
  struct tcf_proto *tp, unsigned long base,
  u32 handle, struct nlattr **tca,
- void **arg, bool ovr)
+ void **arg, bool ovr, struct netlink_ext_ack *extack)
 {
struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *oldprog = *arg;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 309d5899265f..b74af0b55820 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -91,7 +91,8 @@ static void cls_cgroup_destroy_rcu(struct rcu_head *root)
 static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
 struct tcf_proto *tp, unsigned long base,
 u32 handle, struct nlattr **tca,
-void **arg, bool ovr)
+void **arg, bool ovr,
+struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_CGROUP_MAX + 1];
struct cls_cgroup_head *head = rtnl_dereference(tp->root);
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 28cd6fb52c16..faa0b6793a17 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -401,7 +401,7 @@ static void flow_destroy_filter(struct rcu_head *head)
 static int flow_change(struct net *net, struct sk_buff *in_skb,
   struct tcf_proto *tp, unsigned long base,
   u32 handle, struct nlattr **tca,
-  void **arg, bool ovr)
+  void **arg, bool ovr, struct netlink_ext_ack *extack)
 {
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *fold, *fnew;

[PATCHv2 net-next 2/8] net: sched: cls_api: handle generic cls errors

2018-01-17 Thread Alexander Aring
This patch adds extack support for generic cls handling. The extack
will be set deeper to each called function which is not part of netdev
core api.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/cls_api.c | 56 +
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index e500d11da9cd..0a3e2a2f8917 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -122,7 +122,8 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 }
 
 static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
- u32 prio, struct tcf_chain *chain)
+ u32 prio, struct tcf_chain *chain,
+ struct netlink_ext_ack *extack)
 {
struct tcf_proto *tp;
int err;
@@ -148,6 +149,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, 
u32 protocol,
module_put(tp->ops->owner);
err = -EAGAIN;
} else {
+   NL_SET_ERR_MSG(extack, "TC classifier not found");
err = -ENOENT;
}
goto errout;
@@ -935,7 +937,8 @@ static int tfilter_notify(struct net *net, struct sk_buff 
*oskb,
 static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
  struct nlmsghdr *n, struct tcf_proto *tp,
  struct tcf_block *block, struct Qdisc *q,
- u32 parent, void *fh, bool unicast, bool *last)
+ u32 parent, void *fh, bool unicast, bool *last,
+ struct netlink_ext_ack *extack)
 {
struct sk_buff *skb;
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
@@ -947,6 +950,7 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
 
if (tcf_fill_node(net, skb, tp, block, q, parent, fh, portid,
  n->nlmsg_seq, n->nlmsg_flags, RTM_DELTFILTER) <= 0) {
+   NL_SET_ERR_MSG(extack, "Failed to build del event 
notification");
kfree_skb(skb);
return -EINVAL;
}
@@ -960,8 +964,11 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
if (unicast)
return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);
 
-   return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
- n->nlmsg_flags & NLM_F_ECHO);
+   err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
+n->nlmsg_flags & NLM_F_ECHO);
+   if (err < 0)
+   NL_SET_ERR_MSG(extack, "Failed to send filter delete 
notification");
+   return err;
 }
 
 static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
@@ -1021,8 +1028,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
if (prio == 0) {
switch (n->nlmsg_type) {
case RTM_DELTFILTER:
-   if (protocol || t->tcm_handle || tca[TCA_KIND])
+   if (protocol || t->tcm_handle || tca[TCA_KIND]) {
+   NL_SET_ERR_MSG(extack, "Cannot flush filters 
with protocol, handle or kind set");
return -ENOENT;
+   }
break;
case RTM_NEWTFILTER:
/* If no priority is provided by the user,
@@ -1035,6 +1044,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
}
/* fall-through */
default:
+   NL_SET_ERR_MSG(extack, "Invalid filter command with 
priority of zero");
return -ENOENT;
}
}
@@ -1063,23 +1073,31 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
parent = q->handle;
} else {
q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
-   if (!q)
+   if (!q) {
+   NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't 
exists");
return -EINVAL;
+   }
}
 
/* Is it classful? */
cops = q->ops->cl_ops;
-   if (!cops)
+   if (!cops) {
+   NL_SET_ERR_MSG(extack, "Qdisc not classful");
return -EINVAL;
+   }
 
-   if (!cops->tcf_block)
+   if (!cops->tcf_block) {
+   NL_SET_ERR_MSG(extack, "

[PATCHv2 net-next 0/8] net: sched: cls: add extack support

2018-01-17 Thread Alexander Aring
Hi,

this patch adds extack support for TC classifier subsystem. The first
patch fixes some code style issues for this patch series pointed out
by checkpatch. The other patches until the last one prepares extack
handling for the TC classifier subsystem and handle generic extack
errors.

The last patch is an example for u32 classifier to add extack support
inside the callbacks delete and change. There exists a init callback as
well, but most classifier implementation run a kalloc() once to allocate
something. Not necessary _yet_ to add extack support now.

I know there are patches around which makes changes to these files.
I will rebase my stuff on Jiri's patches if they get in before mine.

- Alex

Cc: David Ahern <dsah...@gmail.com>

changes since v2:
 - rebased on Jiri's patches (Thank you)
 - several spelling fixes pointed out by Cong Wang (Thank you)
 - several spelling fixes pointed out by David Ahern (Thank you)
 - use David Ahern recommendation if config option is mismatch, but
   combine it with Cong Wang recommendation to put config name into it
   (Thank you)

Alexander Aring (8):
  net: sched: cls: fix code style issues
  net: sched: cls_api: handle generic cls errors
  net: sched: cls: add extack support for change callback
  net: sched: cls: add extack support for tcf_exts_validate
  net: sched: cls: add extack support for delete callback
  net: sched: cls: add extack support for tcf_change_indev
  net: sched: cls: add extack support for tc_setup_cb_call
  net: sched: cls_u32: add extack support

 include/net/pkt_cls.h |  13 --
 include/net/sch_generic.h |   7 +++-
 net/sched/cls_api.c   |  75 +
 net/sched/cls_basic.c |  14 ---
 net/sched/cls_bpf.c   |  32 --
 net/sched/cls_cgroup.c|   9 ++--
 net/sched/cls_flow.c  |   8 ++--
 net/sched/cls_flower.c|  31 --
 net/sched/cls_fw.c|  17 
 net/sched/cls_matchall.c  |  24 +++
 net/sched/cls_route.c |  12 +++---
 net/sched/cls_rsvp.h  |   7 ++--
 net/sched/cls_tcindex.c   |  14 ---
 net/sched/cls_u32.c   | 104 --
 14 files changed, 244 insertions(+), 123 deletions(-)

-- 
2.11.0



[PATCHv2 net-next 5/8] net: sched: cls: add extack support for delete callback

2018-01-17 Thread Alexander Aring
This patch adds extack support for classifier delete callback api. This
prepares to handle extack support inside each specific classifier
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 2 +-
 net/sched/cls_basic.c | 3 ++-
 net/sched/cls_bpf.c   | 3 ++-
 net/sched/cls_cgroup.c| 3 ++-
 net/sched/cls_flow.c  | 3 ++-
 net/sched/cls_flower.c| 3 ++-
 net/sched/cls_fw.c| 3 ++-
 net/sched/cls_matchall.c  | 3 ++-
 net/sched/cls_route.c | 3 ++-
 net/sched/cls_rsvp.h  | 3 ++-
 net/sched/cls_tcindex.c   | 5 +++--
 net/sched/cls_u32.c   | 3 ++-
 13 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index ee398bcd46e7..cd1be1f25c36 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -242,7 +242,8 @@ struct tcf_proto_ops {
void **, bool,
struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
- bool *last);
+ bool *last,
+ struct netlink_ext_ack *);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
void(*bind_class)(void *, u32, unsigned long);
 
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index f71192a5987c..9f88107c29c5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -955,7 +955,7 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
return -EINVAL;
}
 
-   err = tp->ops->delete(tp, fh, last);
+   err = tp->ops->delete(tp, fh, last, extack);
if (err) {
kfree_skb(skb);
return err;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index b7bcf67641bf..6088be65d167 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -130,7 +130,8 @@ static void basic_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
 }
 
-static int basic_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
+   struct netlink_ext_ack *extack)
 {
struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f = arg;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index c86072779b0a..fc024fc3ec2f 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -295,7 +295,8 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct 
cls_bpf_prog *prog)
__cls_bpf_delete_prog(prog);
 }
 
-static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
+ struct netlink_ext_ack *extack)
 {
struct cls_bpf_head *head = rtnl_dereference(tp->root);
 
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index aaafcf6965f7..1b54fbfca414 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -156,7 +156,8 @@ static void cls_cgroup_destroy(struct tcf_proto *tp)
}
 }
 
-static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last,
+struct netlink_ext_ack *extack)
 {
return -EOPNOTSUPP;
 }
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 07816133cbb9..64c24b488058 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -575,7 +575,8 @@ static int flow_change(struct net *net, struct sk_buff 
*in_skb,
return err;
 }
 
-static int flow_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int flow_delete(struct tcf_proto *tp, void *arg, bool *last,
+  struct netlink_ext_ack *extack)
 {
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f = arg;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 8235ed9143c4..50145b873ff1 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -985,7 +985,8 @@ static int fl_change(struct net *net, struct sk_buff 
*in_skb,
return err;
 }
 
-static int fl_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
+struct netlink_ext_ack *extack)
 {
struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f = arg;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 72a924a38753..bd21ed83eb07 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -172,7 +172,8 @@ static void fw_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
 }
 
-static int fw_delete(s

Re: [PATCH] Bluetooth: 6lowpan: Fix disconnect bug in 6lowpan

2018-01-17 Thread Alexander Aring
Hi,

2018-01-17 7:15 GMT-05:00 Luiz Augusto von Dentz :
> Hi,
>
> On Wed, Jan 17, 2018 at 1:47 AM, Guo Yi  wrote:
>> This patch fix the bluetooth 6lowpan disconnect fail bug.
>>
>> The type of the same address type have different define value in HCI layer
>> and L2CAP layer.That makes disconnect fail due to wrong network type.User
>> will not be able to disconnect from console with the network type that used
>> in connect.
>>
>> This patch add a var lookup_type, and covert the channel address type to
>> HCI address type. By these means, user can disconnect successfuly.
>>
>> Signed-off-by: Guo Yi 
>
> While this fix seems alright the debugfs interface was never meant for
> production, in fact we are working on a replacement:
>

Is the new API fixing the issue that the 6LoWPAN device creation is
done by iproute e.g.:

ip link add link wpan0 name lowpan0 type lowpan

or is there a special bluetooth API call needed, like the current case
with debugfs.
I know hcis are not netdevs, but it bothers me that we running into
two different worlds on how to deal with that and it just requires
"more" special bluetooth specific handling in user space applications.
Later more "netdev" capable link layers will maybe support 6LoWPAN and
then bluetooth might the only subsystem where different handling is
needed to do such job like that.

We maybe need to support a special handling in "ip link add" to map to
bluetooth instead moving that to people in user space?

- Alex


[PATCH net-next 4/8] net: sched: cls: add extack support for tcf_exts_validate

2018-01-16 Thread Alexander Aring
The tcf_exts_validate function calls the act api change callback. For
preparing extack support for act api, this patch adds the extack as
parameter for this function which is common used in cls implementations.

Furthermore the tcf_exts_validate will call action init callback which
prepares the TC action subsystem for extack support.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h|  3 ++-
 net/sched/cls_api.c  |  3 ++-
 net/sched/cls_basic.c|  8 +---
 net/sched/cls_bpf.c  |  8 +---
 net/sched/cls_cgroup.c   |  3 ++-
 net/sched/cls_flow.c |  3 ++-
 net/sched/cls_flower.c   |  8 +---
 net/sched/cls_fw.c   | 10 ++
 net/sched/cls_matchall.c |  8 +---
 net/sched/cls_route.c|  6 +++---
 net/sched/cls_rsvp.h |  2 +-
 net/sched/cls_tcindex.c  |  6 +++---
 net/sched/cls_u32.c  | 10 ++
 13 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 9c341f003091..0286d42d08ef 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -368,7 +368,8 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
  struct nlattr **tb, struct nlattr *rate_tlv,
- struct tcf_exts *exts, bool ovr);
+ struct tcf_exts *exts, bool ovr,
+ struct netlink_ext_ack *extack);
 void tcf_exts_destroy(struct tcf_exts *exts);
 void tcf_exts_change(struct tcf_exts *dst, struct tcf_exts *src);
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 520b5deec7af..011fe66c82b5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1114,7 +1114,8 @@ void tcf_exts_destroy(struct tcf_exts *exts)
 EXPORT_SYMBOL(tcf_exts_destroy);
 
 int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr 
**tb,
- struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr)
+ struct nlattr *rate_tlv, struct tcf_exts *exts, bool ovr,
+ struct netlink_ext_ack *extack)
 {
 #ifdef CONFIG_NET_CLS_ACT
{
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 2cc38cd71938..b7bcf67641bf 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -152,11 +152,12 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX 
+ 1] = {
 static int basic_set_parms(struct net *net, struct tcf_proto *tp,
   struct basic_filter *f, unsigned long base,
   struct nlattr **tb,
-  struct nlattr *est, bool ovr)
+  struct nlattr *est, bool ovr,
+  struct netlink_ext_ack *extack)
 {
int err;
 
-   err = tcf_exts_validate(net, tp, tb, est, >exts, ovr);
+   err = tcf_exts_validate(net, tp, tb, est, >exts, ovr, extack);
if (err < 0)
return err;
 
@@ -222,7 +223,8 @@ static int basic_change(struct net *net, struct sk_buff 
*in_skb,
fnew->handle = idr_index;
}
 
-   err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr);
+   err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr,
+ extack);
if (err < 0) {
if (!fold)
idr_remove_ext(>handle_idr, fnew->handle);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index fcb831b3917e..50abd71f99ed 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -400,7 +400,8 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct 
cls_bpf_prog *prog,
 
 static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
 struct cls_bpf_prog *prog, unsigned long base,
-struct nlattr **tb, struct nlattr *est, bool ovr)
+struct nlattr **tb, struct nlattr *est, bool ovr,
+struct netlink_ext_ack *extack)
 {
bool is_bpf, is_ebpf, have_exts = false;
u32 gen_flags = 0;
@@ -411,7 +412,7 @@ static int cls_bpf_set_parms(struct net *net, struct 
tcf_proto *tp,
if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
return -EINVAL;
 
-   ret = tcf_exts_validate(net, tp, tb, est, >exts, ovr);
+   ret = tcf_exts_validate(net, tp, tb, est, >exts, ovr, extack);
if (ret < 0)
return ret;
 
@@ -497,7 +498,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff 
*in_skb,
prog->handle = handle;
}
 
-   ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr);
+   ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr,
+   extack);
if 

[PATCH net-next 2/8] net: sched: cls_api: handle generic cls errors

2018-01-16 Thread Alexander Aring
This patch adds extack support for generic cls handling. The extack
will be set deeper to each called function which is not part of netdev
core api.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/cls_api.c | 55 +
 1 file changed, 43 insertions(+), 12 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 01d09055707d..c25a9b4bcb4b 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -122,7 +122,8 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 
 static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
  u32 prio, u32 parent, struct Qdisc *q,
- struct tcf_chain *chain)
+ struct tcf_chain *chain,
+ struct netlink_ext_ack *extack)
 {
struct tcf_proto *tp;
int err;
@@ -148,6 +149,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, 
u32 protocol,
module_put(tp->ops->owner);
err = -EAGAIN;
} else {
+   NL_SET_ERR_MSG(extack, "TC classifier not found");
err = -ENOENT;
}
goto errout;
@@ -662,7 +664,8 @@ static int tfilter_notify(struct net *net, struct sk_buff 
*oskb,
 static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
  struct nlmsghdr *n, struct tcf_proto *tp,
  struct Qdisc *q, u32 parent,
- void *fh, bool unicast, bool *last)
+ void *fh, bool unicast, bool *last,
+ struct netlink_ext_ack *extack)
 {
struct sk_buff *skb;
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
@@ -674,6 +677,7 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
 
if (tcf_fill_node(net, skb, tp, q, parent, fh, portid, n->nlmsg_seq,
  n->nlmsg_flags, RTM_DELTFILTER) <= 0) {
+   NL_SET_ERR_MSG(extack, "Failed to build del event 
notification");
kfree_skb(skb);
return -EINVAL;
}
@@ -687,8 +691,11 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
if (unicast)
return netlink_unicast(net->rtnl, skb, portid, MSG_DONTWAIT);
 
-   return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
- n->nlmsg_flags & NLM_F_ECHO);
+   err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
+n->nlmsg_flags & NLM_F_ECHO);
+   if (err < 0)
+   NL_SET_ERR_MSG(extack, "Failed to send filter delete 
notification");
+   return err;
 }
 
 static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
@@ -749,8 +756,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
if (prio == 0) {
switch (n->nlmsg_type) {
case RTM_DELTFILTER:
-   if (protocol || t->tcm_handle || tca[TCA_KIND])
+   if (protocol || t->tcm_handle || tca[TCA_KIND]) {
+   NL_SET_ERR_MSG(extack, "Cannot flush filters 
with protocol, handle or kind set");
return -ENOENT;
+   }
break;
case RTM_NEWTFILTER:
/* If no priority is provided by the user,
@@ -763,6 +772,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
}
/* fall-through */
default:
+   NL_SET_ERR_MSG(extack, "Invalid filter command with 
priority of zero");
return -ENOENT;
}
}
@@ -780,23 +790,31 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
parent = q->handle;
} else {
q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
-   if (!q)
+   if (!q) {
+   NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't exists");
return -EINVAL;
+   }
}
 
/* Is it classful? */
cops = q->ops->cl_ops;
-   if (!cops)
+   if (!cops) {
+   NL_SET_ERR_MSG(extack, "Qdisc not classful");
return -EINVAL;
+   }
 
-   if (!cops->tcf_block)
+   if (!cops->tcf_block) {
+   NL_SET_ERR_MSG(extack, "Class doesn't support blocks");
return -EOPNOTSUPP;
+   }
 
/* Do we search for filter, 

[PATCH net-next 7/8] net: sched: cls: add extack support for tc_setup_cb_call

2018-01-16 Thread Alexander Aring
This patch adds extack handling for the tc_setup_cb_call function which
is common used by TC classifier implementations.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h|  3 ++-
 net/sched/cls_api.c  | 11 ---
 net/sched/cls_bpf.c  | 19 +++
 net/sched/cls_flower.c   | 11 ++-
 net/sched/cls_matchall.c | 11 +++
 net/sched/cls_u32.c  | 20 +++-
 6 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 03f62be4e57e..991f5011510b 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -577,7 +577,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
 #endif /* CONFIG_NET_CLS_IND */
 
 int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
-enum tc_setup_type type, void *type_data, bool err_stop);
+enum tc_setup_type type, void *type_data, bool err_stop,
+struct netlink_ext_ack *extack);
 
 enum tc_block_command {
TC_BLOCK_BIND,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 6f9fe99ebe2b..c4484a8341cd 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1264,21 +1264,26 @@ static int tc_exts_setup_cb_egdev_call(struct tcf_exts 
*exts,
 }
 
 int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
-enum tc_setup_type type, void *type_data, bool err_stop)
+enum tc_setup_type type, void *type_data, bool err_stop,
+struct netlink_ext_ack *extack)
 {
int ok_count;
int ret;
 
ret = tcf_block_cb_call(block, type, type_data, err_stop);
-   if (ret < 0)
+   if (ret < 0) {
+   NL_SET_ERR_MSG(extack, "Failed to inialize tcf block");
return ret;
+   }
ok_count = ret;
 
if (!exts)
return ok_count;
ret = tc_exts_setup_cb_egdev_call(exts, type, type_data, err_stop);
-   if (ret < 0)
+   if (ret < 0) {
+   NL_SET_ERR_MSG(extack, "Failed to inialize tcf block 
extensions");
return ret;
+   }
ok_count += ret;
 
return ok_count;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 4e30863723d9..79a07ae405f7 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -147,7 +147,8 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
 }
 
 static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
-  struct cls_bpf_prog *oldprog)
+  struct cls_bpf_prog *oldprog,
+  struct netlink_ext_ack *extack)
 {
struct tcf_block *block = tp->chain->block;
struct tc_cls_bpf_offload cls_bpf = {};
@@ -167,10 +168,11 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, 
struct cls_bpf_prog *prog,
cls_bpf.exts_integrated = obj->exts_integrated;
cls_bpf.gen_flags = obj->gen_flags;
 
-   err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, _bpf, skip_sw);
+   err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, _bpf, skip_sw,
+  extack);
if (prog) {
if (err < 0) {
-   cls_bpf_offload_cmd(tp, oldprog, prog);
+   cls_bpf_offload_cmd(tp, oldprog, prog, NULL);
return err;
} else if (err > 0) {
prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
@@ -184,7 +186,8 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct 
cls_bpf_prog *prog,
 }
 
 static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
-  struct cls_bpf_prog *oldprog)
+  struct cls_bpf_prog *oldprog,
+  struct netlink_ext_ack *extack)
 {
if (prog && oldprog && prog->gen_flags != oldprog->gen_flags)
return -EINVAL;
@@ -196,7 +199,7 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct 
cls_bpf_prog *prog,
if (!prog && !oldprog)
return 0;
 
-   return cls_bpf_offload_cmd(tp, prog, oldprog);
+   return cls_bpf_offload_cmd(tp, prog, oldprog, extack);
 }
 
 static void cls_bpf_stop_offload(struct tcf_proto *tp,
@@ -204,7 +207,7 @@ static void cls_bpf_stop_offload(struct tcf_proto *tp,
 {
int err;
 
-   err = cls_bpf_offload_cmd(tp, NULL, prog);
+   err = cls_bpf_offload_cmd(tp, NULL, prog, NULL);
if (err)
pr_err("Stopping hardware offload failed: %d\n", err);
 }
@@ -223,7 +226,7 @@ static void cls_bpf_offload_update_stats(struct tcf_proto 
*tp,
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_fla

[PATCH net-next 6/8] net: sched: cls: add extack support for tcf_change_indev

2018-01-16 Thread Alexander Aring
This patch adds extack handling for the tcf_change_indev function which
is common used by TC classifier implementations.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/pkt_cls.h  | 7 +--
 net/sched/cls_flower.c | 7 ---
 net/sched/cls_fw.c | 2 +-
 net/sched/cls_u32.c| 2 +-
 4 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 0286d42d08ef..03f62be4e57e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -549,13 +549,16 @@ static inline int tcf_valid_offset(const struct sk_buff 
*skb,
 #include 
 
 static inline int
-tcf_change_indev(struct net *net, struct nlattr *indev_tlv)
+tcf_change_indev(struct net *net, struct nlattr *indev_tlv,
+struct netlink_ext_ack *extack)
 {
char indev[IFNAMSIZ];
struct net_device *dev;
 
-   if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ)
+   if (nla_strlcpy(indev, indev_tlv, IFNAMSIZ) >= IFNAMSIZ) {
+   NL_SET_ERR_MSG(extack, "Interface name too long");
return -EINVAL;
+   }
dev = __dev_get_by_name(net, indev);
if (!dev)
return -ENODEV;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index a3ad5d24b0b9..9eb552257890 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -525,13 +525,14 @@ static void fl_set_key_ip(struct nlattr **tb,
 }
 
 static int fl_set_key(struct net *net, struct nlattr **tb,
- struct fl_flow_key *key, struct fl_flow_key *mask)
+ struct fl_flow_key *key, struct fl_flow_key *mask,
+ struct netlink_ext_ack *extack)
 {
__be16 ethertype;
int ret = 0;
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FLOWER_INDEV]) {
-   int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV]);
+   int err = tcf_change_indev(net, tb[TCA_FLOWER_INDEV], extack);
if (err < 0)
return err;
key->indev_ifindex = err;
@@ -840,7 +841,7 @@ static int fl_set_parms(struct net *net, struct tcf_proto 
*tp,
tcf_bind_filter(tp, >res, base);
}
 
-   err = fl_set_key(net, tb, >key, >key);
+   err = fl_set_key(net, tb, >key, >key, extack);
if (err)
return err;
 
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index bd21ed83eb07..94d159a8869a 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -239,7 +239,7 @@ static int fw_set_parms(struct net *net, struct tcf_proto 
*tp,
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_FW_INDEV]) {
int ret;
-   ret = tcf_change_indev(net, tb[TCA_FW_INDEV]);
+   ret = tcf_change_indev(net, tb[TCA_FW_INDEV], extack);
if (ret < 0)
return ret;
f->ifindex = ret;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index b2c83490cc73..78d0a320e7fa 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -803,7 +803,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
 #ifdef CONFIG_NET_CLS_IND
if (tb[TCA_U32_INDEV]) {
int ret;
-   ret = tcf_change_indev(net, tb[TCA_U32_INDEV]);
+   ret = tcf_change_indev(net, tb[TCA_U32_INDEV], extack);
if (ret < 0)
return -EINVAL;
n->ifindex = ret;
-- 
2.11.0



[PATCH net-next 5/8] net: sched: cls: add extack support for delete callback

2018-01-16 Thread Alexander Aring
This patch adds extack support for classifier delete callback api. This
prepares to handle extack support inside each specific classifier
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 2 +-
 net/sched/cls_basic.c | 3 ++-
 net/sched/cls_bpf.c   | 3 ++-
 net/sched/cls_cgroup.c| 3 ++-
 net/sched/cls_flow.c  | 3 ++-
 net/sched/cls_flower.c| 3 ++-
 net/sched/cls_fw.c| 3 ++-
 net/sched/cls_matchall.c  | 3 ++-
 net/sched/cls_route.c | 3 ++-
 net/sched/cls_rsvp.h  | 3 ++-
 net/sched/cls_tcindex.c   | 5 +++--
 net/sched/cls_u32.c   | 3 ++-
 13 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index f999ee6bac2e..01227fcaa09a 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -235,7 +235,8 @@ struct tcf_proto_ops {
void **, bool,
struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
- bool *last);
+ bool *last,
+ struct netlink_ext_ack *);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
void(*bind_class)(void *, u32, unsigned long);
 
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 011fe66c82b5..6f9fe99ebe2b 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -682,7 +682,7 @@ static int tfilter_del_notify(struct net *net, struct 
sk_buff *oskb,
return -EINVAL;
}
 
-   err = tp->ops->delete(tp, fh, last);
+   err = tp->ops->delete(tp, fh, last, extack);
if (err) {
kfree_skb(skb);
return err;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index b7bcf67641bf..6088be65d167 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -130,7 +130,8 @@ static void basic_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
 }
 
-static int basic_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
+   struct netlink_ext_ack *extack)
 {
struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f = arg;
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 50abd71f99ed..4e30863723d9 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -292,7 +292,8 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct 
cls_bpf_prog *prog)
__cls_bpf_delete_prog(prog);
 }
 
-static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last,
+ struct netlink_ext_ack *extack)
 {
struct cls_bpf_head *head = rtnl_dereference(tp->root);
 
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index aaafcf6965f7..1b54fbfca414 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -156,7 +156,8 @@ static void cls_cgroup_destroy(struct tcf_proto *tp)
}
 }
 
-static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last,
+struct netlink_ext_ack *extack)
 {
return -EOPNOTSUPP;
 }
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 5bc702f66bb5..c37c0415c40c 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -575,7 +575,8 @@ static int flow_change(struct net *net, struct sk_buff 
*in_skb,
return err;
 }
 
-static int flow_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int flow_delete(struct tcf_proto *tp, void *arg, bool *last,
+  struct netlink_ext_ack *extack)
 {
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *f = arg;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index b9664e1df8f0..a3ad5d24b0b9 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -984,7 +984,8 @@ static int fl_change(struct net *net, struct sk_buff 
*in_skb,
return err;
 }
 
-static int fl_delete(struct tcf_proto *tp, void *arg, bool *last)
+static int fl_delete(struct tcf_proto *tp, void *arg, bool *last,
+struct netlink_ext_ack *extack)
 {
struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f = arg;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 72a924a38753..bd21ed83eb07 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -172,7 +172,8 @@ static void fw_destroy(struct tcf_proto *tp)
kfree_rcu(head, rcu);
 }
 
-static int fw_delete(s

[PATCH net-next 8/8] net: sched: cls_u32: add extack support

2018-01-16 Thread Alexander Aring
This patch adds extack support for the u32 classifier as example for
delete and init callback.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 net/sched/cls_u32.c | 66 -
 1 file changed, 50 insertions(+), 16 deletions(-)

diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 03dc08ab3cf1..69c2fbafd0a3 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -524,8 +524,10 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, 
struct tc_u_hnode *h,
offloaded = true;
}
 
-   if (skip_sw && !offloaded)
+   if (skip_sw && !offloaded) {
+   NL_SET_ERR_MSG(extack, "Failed to offload filter requested with 
skip sw");
return -EINVAL;
+   }
 
return 0;
 }
@@ -575,8 +577,10 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, 
struct tc_u_knode *n,
n->flags |= TCA_CLS_FLAGS_IN_HW;
}
 
-   if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW))
+   if (skip_sw && !(n->flags & TCA_CLS_FLAGS_IN_HW)) {
+   NL_SET_ERR_MSG(extack, "Failed to offload filter requested with 
skip sw");
return -EINVAL;
+   }
 
return 0;
 }
@@ -690,13 +694,16 @@ static int u32_delete(struct tcf_proto *tp, void *arg, 
bool *last,
goto out;
}
 
-   if (root_ht == ht)
+   if (root_ht == ht) {
+   NL_SET_ERR_MSG(extack, "Not allowd to delete root node");
return -EINVAL;
+   }
 
if (ht->refcnt == 1) {
ht->refcnt--;
u32_destroy_hnode(tp, ht);
} else {
+   NL_SET_ERR_MSG(extack, "Can not delete in-use filter");
return -EBUSY;
}
 
@@ -780,14 +787,18 @@ static int u32_set_parms(struct net *net, struct 
tcf_proto *tp,
u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
struct tc_u_hnode *ht_down = NULL, *ht_old;
 
-   if (TC_U32_KEY(handle))
+   if (TC_U32_KEY(handle)) {
+   NL_SET_ERR_MSG(extack, "u32 Link handle must be a hash 
table");
return -EINVAL;
+   }
 
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
 
-   if (!ht_down)
+   if (!ht_down) {
+   NL_SET_ERR_MSG(extack, "Link hash table not 
found");
return -EINVAL;
+   }
ht_down->refcnt++;
}
 
@@ -911,28 +922,40 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
size_t size;
 #endif
 
-   if (!opt)
-   return handle ? -EINVAL : 0;
+   if (!opt) {
+   if (handle) {
+   NL_SET_ERR_MSG(extack, "Filter handle requires 
options");
+   return -EINVAL;
+   } else {
+   return 0;
+   }
+   }
 
-   err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
+   err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, extack);
if (err < 0)
return err;
 
if (tb[TCA_U32_FLAGS]) {
flags = nla_get_u32(tb[TCA_U32_FLAGS]);
-   if (!tc_flags_valid(flags))
+   if (!tc_flags_valid(flags)) {
+   NL_SET_ERR_MSG(extack, "Invalid filter flags");
return -EINVAL;
+   }
}
 
n = *arg;
if (n) {
struct tc_u_knode *new;
 
-   if (TC_U32_KEY(n->handle) == 0)
+   if (TC_U32_KEY(n->handle) == 0) {
+   NL_SET_ERR_MSG(extack, "Key node id cannot be zero");
return -EINVAL;
+   }
 
-   if (n->flags != flags)
+   if (n->flags != flags) {
+   NL_SET_ERR_MSG(extack, "Key node flags do not match 
passed flags");
return -EINVAL;
+   }
 
new = u32_init_knode(tp, n);
if (!new)
@@ -966,10 +989,14 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
if (tb[TCA_U32_DIVISOR]) {
unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
 
-   if (--divisor > 0x100)
+   if (--divisor > 0x100) {
+   NL_SET_ERR_MSG(extack, "Exceeded maximum 256 hash 
buckets");
return -EINVAL;
-   if (TC_U32_KEY(handle))
+   }
+   if (TC_U32_KEY(handle)) {
+   NL_SET_ERR_MSG(extack, "Divi

[PATCH net-next 3/8] net: sched: cls: add extack support for change callback

2018-01-16 Thread Alexander Aring
This patch adds extack support for classifier change callback api. This
prepares to handle extack support inside each specific classifier
implementation.

Cc: David Ahern <dsah...@gmail.com>
Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 3 ++-
 net/sched/cls_basic.c | 3 ++-
 net/sched/cls_bpf.c   | 2 +-
 net/sched/cls_cgroup.c| 3 ++-
 net/sched/cls_flow.c  | 2 +-
 net/sched/cls_flower.c| 2 +-
 net/sched/cls_fw.c| 2 +-
 net/sched/cls_matchall.c  | 2 +-
 net/sched/cls_route.c | 3 ++-
 net/sched/cls_rsvp.h  | 2 +-
 net/sched/cls_tcindex.c   | 3 ++-
 net/sched/cls_u32.c   | 3 ++-
 13 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b6ca86a8caeb..f999ee6bac2e 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -232,7 +232,8 @@ struct tcf_proto_ops {
int (*change)(struct net *net, struct sk_buff *,
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
-   void **, bool);
+   void **, bool,
+   struct netlink_ext_ack *);
int (*delete)(struct tcf_proto *tp, void *arg,
  bool *last);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index c25a9b4bcb4b..520b5deec7af 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -941,7 +941,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
}
 
err = tp->ops->change(net, skb, tp, cl, t->tcm_handle, tca, ,
- n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE 
: TCA_ACT_REPLACE);
+ n->nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE 
: TCA_ACT_REPLACE,
+ extack);
if (err == 0) {
if (tp_created)
tcf_chain_tp_insert(chain, _info, tp);
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 5f169ded347e..2cc38cd71938 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -175,7 +175,8 @@ static int basic_set_parms(struct net *net, struct 
tcf_proto *tp,
 
 static int basic_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base, u32 handle,
-   struct nlattr **tca, void **arg, bool ovr)
+   struct nlattr **tca, void **arg, bool ovr,
+   struct netlink_ext_ack *extack)
 {
int err;
struct basic_head *head = rtnl_dereference(tp->root);
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 8d78e7f4ecc3..fcb831b3917e 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -449,7 +449,7 @@ static int cls_bpf_set_parms(struct net *net, struct 
tcf_proto *tp,
 static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
  struct tcf_proto *tp, unsigned long base,
  u32 handle, struct nlattr **tca,
- void **arg, bool ovr)
+ void **arg, bool ovr, struct netlink_ext_ack *extack)
 {
struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *oldprog = *arg;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 309d5899265f..b74af0b55820 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -91,7 +91,8 @@ static void cls_cgroup_destroy_rcu(struct rcu_head *root)
 static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
 struct tcf_proto *tp, unsigned long base,
 u32 handle, struct nlattr **tca,
-void **arg, bool ovr)
+void **arg, bool ovr,
+struct netlink_ext_ack *extack)
 {
struct nlattr *tb[TCA_CGROUP_MAX + 1];
struct cls_cgroup_head *head = rtnl_dereference(tp->root);
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 25c2a888e1f0..e944f01d5394 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -401,7 +401,7 @@ static void flow_destroy_filter(struct rcu_head *head)
 static int flow_change(struct net *net, struct sk_buff *in_skb,
   struct tcf_proto *tp, unsigned long base,
   u32 handle, struct nlattr **tca,
-  void **arg, bool ovr)
+  void **arg, bool ovr, struct netlink_ext_ack *extack)
 {
struct flow_head *head = rtnl_dereference(tp->root);
struct flow_filter *fold, *fnew;

[PATCH net-next 1/8] net: sched: cls: fix code style issues

2018-01-16 Thread Alexander Aring
This patch changes some code style issues pointed out by checkpatch
inside the TC cls subsystem.

Signed-off-by: Alexander Aring <ar...@mojatatu.com>
---
 include/net/sch_generic.h | 3 ++-
 net/sched/cls_api.c   | 2 +-
 net/sched/cls_matchall.c  | 2 +-
 net/sched/cls_u32.c   | 8 
 4 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index ac029d5d88e4..b6ca86a8caeb 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -233,7 +233,8 @@ struct tcf_proto_ops {
struct tcf_proto*, unsigned long,
u32 handle, struct nlattr **,
void **, bool);
-   int (*delete)(struct tcf_proto*, void *, bool*);
+   int (*delete)(struct tcf_proto *tp, void *arg,
+ bool *last);
void(*walk)(struct tcf_proto*, struct tcf_walker 
*arg);
void(*bind_class)(void *, u32, unsigned long);
 
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 6708b6953bfa..01d09055707d 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -780,7 +780,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
parent = q->handle;
} else {
q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent));
-   if (q == NULL)
+   if (!q)
return -EINVAL;
}
 
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 66d4e0099158..634114111adf 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -202,7 +202,7 @@ static int mall_change(struct net *net, struct sk_buff 
*in_skb,
goto err_set_parms;
 
if (!tc_skip_hw(new->flags)) {
-   err = mall_replace_hw_filter(tp, new, (unsigned long) new);
+   err = mall_replace_hw_filter(tp, new, (unsigned long)new);
if (err)
goto err_replace_hw_filter;
}
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 507859cdd1cb..2e1b4580f798 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -782,7 +782,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto 
*tp,
if (handle) {
ht_down = u32_lookup_ht(ht->tp_c, handle);
 
-   if (ht_down == NULL)
+   if (!ht_down)
return -EINVAL;
ht_down->refcnt++;
}
@@ -906,7 +906,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
size_t size;
 #endif
 
-   if (opt == NULL)
+   if (!opt)
return handle ? -EINVAL : 0;
 
err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy, NULL);
@@ -1010,7 +1010,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
htid = ht->handle;
} else {
ht = u32_lookup_ht(tp->data, TC_U32_HTID(htid));
-   if (ht == NULL)
+   if (!ht)
return -EINVAL;
}
} else {
@@ -1022,7 +1022,7 @@ static int u32_change(struct net *net, struct sk_buff 
*in_skb,
return -EINVAL;
 
if (handle) {
-   if (TC_U32_HTID(handle) && TC_U32_HTID(handle^htid))
+   if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid))
return -EINVAL;
handle = htid | TC_U32_NODE(handle);
err = idr_alloc_ext(>handle_idr, NULL, NULL,
-- 
2.11.0



[PATCH net-next 0/8] net: sched: cls: add extack support

2018-01-16 Thread Alexander Aring
Hi,

this patch adds extack support for TC classifier subsystem. The first
patch fixes some code style issues for this patch series pointed out
by checkpatch. The other patches until the last one prepares extack
handling for the TC classifier subsystem and handle generic extack
errors.

The last patch is an example for u32 classifier to add extack support
inside the callbacks delete and change. There exists a init callback as
well, but most classifier implementation run a kalloc() once to allocate
something. Not necessary _yet_ to add extack support now.

I know there are patches around which makes changes to these files.
I will rebase my stuff on Jiri's patches if they get in before mine.

- Alex

Cc: David Ahern <dsah...@gmail.com>

Alexander Aring (8):
  net: sched: cls: fix code style issues
  net: sched: cls_api: handle generic cls errors
  net: sched: cls: add extack support for change callback
  net: sched: cls: add extack support for tcf_exts_validate
  net: sched: cls: add extack support for delete callback
  net: sched: cls: add extack support for tcf_change_indev
  net: sched: cls: add extack support for tc_setup_cb_call
  net: sched: cls_u32: add extack support

 include/net/pkt_cls.h |  13 --
 include/net/sch_generic.h |   7 +++-
 net/sched/cls_api.c   |  74 +
 net/sched/cls_basic.c |  14 ---
 net/sched/cls_bpf.c   |  32 --
 net/sched/cls_cgroup.c|   9 ++--
 net/sched/cls_flow.c  |   8 ++--
 net/sched/cls_flower.c|  31 --
 net/sched/cls_fw.c|  17 
 net/sched/cls_matchall.c  |  24 +++
 net/sched/cls_route.c |  12 +++---
 net/sched/cls_rsvp.h  |   7 ++--
 net/sched/cls_tcindex.c   |  14 ---
 net/sched/cls_u32.c   | 104 --
 14 files changed, 243 insertions(+), 123 deletions(-)

-- 
2.11.0



  1   2   3   4   >