Re: [PATCH] net: sched: split tc_ctl_tfilter into three handlers

2018-05-29 Thread David Miller
From: Vlad Buslov 
Date: Sun, 27 May 2018 22:55:03 +0300

> tc_ctl_tfilter handles three netlink message types: RTM_NEWTFILTER,
> RTM_DELTFILTER, RTM_GETTFILTER. However, implementation of this function
> involves a lot of branching on specific message type because most of the
> code is message-specific. This significantly complicates adding new
> functionality and doesn't provide much benefit of code reuse.
> 
> Split tc_ctl_tfilter to three standalone functions that handle filter new,
> delete and get requests.
> 
> The only truly protocol independent part of tc_ctl_tfilter is code that
> looks up queue, class, and block. Refactor this code to standalone
> tcf_block_find function that is used by all three new handlers.
> 
> Signed-off-by: Vlad Buslov 

This looks fine but doesn't apply cleanly to net-next.


Re: [PATCH] net: sched: split tc_ctl_tfilter into three handlers

2018-05-28 Thread Jamal Hadi Salim

On 28/05/18 12:02 PM, Jamal Hadi Salim wrote:

On 27/05/18 03:55 PM, Vlad Buslov wrote:

tc_ctl_tfilter handles three netlink message types: RTM_NEWTFILTER,
RTM_DELTFILTER, RTM_GETTFILTER. However, implementation of this function
involves a lot of branching on specific message type because most of the
code is message-specific. This significantly complicates adding new
functionality and doesn't provide much benefit of code reuse.

Split tc_ctl_tfilter to three standalone functions that handle filter 
new,

delete and get requests.

The only truly protocol independent part of tc_ctl_tfilter is code that
looks up queue, class, and block. Refactor this code to standalone
tcf_block_find function that is used by all three new handlers.

Signed-off-by: Vlad Buslov 


FWIW, I like this separation - makes things more maintainable and
readable (we should do it in act_api as well).


Sorry - meant to point out that this belongs to net-next not net.

cheers,
jamal


Re: [PATCH] net: sched: split tc_ctl_tfilter into three handlers

2018-05-28 Thread Jamal Hadi Salim

On 27/05/18 03:55 PM, Vlad Buslov wrote:

tc_ctl_tfilter handles three netlink message types: RTM_NEWTFILTER,
RTM_DELTFILTER, RTM_GETTFILTER. However, implementation of this function
involves a lot of branching on specific message type because most of the
code is message-specific. This significantly complicates adding new
functionality and doesn't provide much benefit of code reuse.

Split tc_ctl_tfilter to three standalone functions that handle filter new,
delete and get requests.

The only truly protocol independent part of tc_ctl_tfilter is code that
looks up queue, class, and block. Refactor this code to standalone
tcf_block_find function that is used by all three new handlers.

Signed-off-by: Vlad Buslov 


FWIW, I like this separation - makes things more maintainable and
readable (we should do it in act_api as well).


cheers,
jamal


[PATCH] net: sched: split tc_ctl_tfilter into three handlers

2018-05-27 Thread Vlad Buslov
tc_ctl_tfilter handles three netlink message types: RTM_NEWTFILTER,
RTM_DELTFILTER, RTM_GETTFILTER. However, implementation of this function
involves a lot of branching on specific message type because most of the
code is message-specific. This significantly complicates adding new
functionality and doesn't provide much benefit of code reuse.

Split tc_ctl_tfilter to three standalone functions that handle filter new,
delete and get requests.

The only truly protocol independent part of tc_ctl_tfilter is code that
looks up queue, class, and block. Refactor this code to standalone
tcf_block_find function that is used by all three new handlers.

Signed-off-by: Vlad Buslov 
---
 net/sched/cls_api.c | 438 +++-
 1 file changed, 293 insertions(+), 145 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 1ed673f501c2..8dfbad1bddf5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -436,6 +436,78 @@ static struct tcf_block *tcf_block_lookup(struct net *net, 
u32 block_index)
return idr_find(&tn->idr, block_index);
 }
 
+/* Find tcf block.
+ * Set q, parent, cl when appropriate.
+ */
+
+static struct tcf_block *tcf_block_find(struct net *net, struct Qdisc **q,
+   u32 *parent, unsigned long *cl,
+   int ifindex, u32 block_index,
+   struct netlink_ext_ack *extack)
+{
+   struct tcf_block *block;
+
+   if (ifindex == TCM_IFINDEX_MAGIC_BLOCK) {
+   block = tcf_block_lookup(net, block_index);
+   if (!block) {
+   NL_SET_ERR_MSG(extack, "Block of given index was not 
found");
+   return ERR_PTR(-EINVAL);
+   }
+   } else {
+   const struct Qdisc_class_ops *cops;
+   struct net_device *dev;
+
+   /* Find link */
+   dev = __dev_get_by_index(net, ifindex);
+   if (!dev)
+   return ERR_PTR(-ENODEV);
+
+   /* Find qdisc */
+   if (!*parent) {
+   *q = dev->qdisc;
+   *parent = (*q)->handle;
+   } else {
+   *q = qdisc_lookup(dev, TC_H_MAJ(*parent));
+   if (!*q) {
+   NL_SET_ERR_MSG(extack, "Parent Qdisc doesn't 
exists");
+   return ERR_PTR(-EINVAL);
+   }
+   }
+
+   /* Is it classful? */
+   cops = (*q)->ops->cl_ops;
+   if (!cops) {
+   NL_SET_ERR_MSG(extack, "Qdisc not classful");
+   return ERR_PTR(-EINVAL);
+   }
+
+   if (!cops->tcf_block) {
+   NL_SET_ERR_MSG(extack, "Class doesn't support blocks");
+   return ERR_PTR(-EOPNOTSUPP);
+   }
+
+   /* Do we search for filter, attached to class? */
+   if (TC_H_MIN(*parent)) {
+   *cl = cops->find(*q, *parent);
+   if (*cl == 0) {
+   NL_SET_ERR_MSG(extack, "Specified class doesn't 
exist");
+   return ERR_PTR(-ENOENT);
+   }
+   }
+
+   /* And the last stroke */
+   block = cops->tcf_block(*q, *cl, extack);
+   if (!block)
+   return ERR_PTR(-EINVAL);
+   if (tcf_block_shared(block)) {
+   NL_SET_ERR_MSG(extack, "This filter block is shared. 
Please use the block index to manipulate the filters");
+   return ERR_PTR(-EOPNOTSUPP);
+   }
+   }
+
+   return block;
+}
+
 static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block)
 {
return list_first_entry(&block->chain_list, struct tcf_chain, list);
@@ -1002,9 +1074,7 @@ static void tfilter_notify_chain(struct net *net, struct 
sk_buff *oskb,
   q, parent, 0, event, false);
 }
 
-/* Add/change/delete/get a filter node */
-
-static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
+static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
  struct netlink_ext_ack *extack)
 {
struct net *net = sock_net(skb->sk);
@@ -1025,8 +1095,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
int err;
int tp_created;
 
-   if ((n->nlmsg_type != RTM_GETTFILTER) &&
-   !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
+   if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
return -EPERM;
 
 replay:
@@ -1044,24 +1113,13 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct 
nlmsghdr *n,
cl = 0;
 
if (prio == 0) {
-   switch (n->nlmsg_type) {
-