Re: [patch net-next v2 2/4] net: sched: introduce per-egress action device callbacks

2017-11-19 Thread Jiri Pirko
Sun, Nov 19, 2017 at 08:37:49PM CET, manish.cho...@cavium.com wrote:
>> -Original Message-
>> From: netdev-ow...@vger.kernel.org [mailto:netdev-ow...@vger.kernel.org]
>> On Behalf Of Jiri Pirko
>> Sent: Wednesday, October 11, 2017 1:11 PM
>> To: netdev@vger.kernel.org
>> Cc: da...@davemloft.net; j...@mojatatu.com; xiyou.wangc...@gmail.com;
>> sae...@mellanox.com; mat...@mellanox.com; leo...@mellanox.com;
>> ml...@mellanox.com; david.lai...@aculab.com; gerlitz...@gmail.com
>> Subject: [patch net-next v2 2/4] net: sched: introduce per-egress action 
>> device
>> callbacks
>> 
>> From: Jiri Pirko <j...@mellanox.com>
>> 
>> Introduce infrastructure that allows drivers to register callbacks that are 
>> called
>> whenever tc would offload inserted rule and specified device acts as tc 
>> action
>> egress device.
>> 
>> Signed-off-by: Jiri Pirko <j...@mellanox.com>
>> ---
>> v1->v2:
>> - take rtnl for register/unregister
>> ---
>>  include/net/act_api.h |  34 
>>  include/net/pkt_cls.h |   2 +
>>  net/sched/act_api.c   | 220
>> ++
>>  net/sched/cls_api.c   |  30 +++
>>  4 files changed, 286 insertions(+)
>> 
>> diff --git a/include/net/act_api.h b/include/net/act_api.h index
>> 900168a..f5e8c90 100644
>> --- a/include/net/act_api.h
>> +++ b/include/net/act_api.h
>> @@ -174,4 +174,38 @@ static inline void tcf_action_stats_update(struct
>> tc_action *a, u64 bytes,  #endif  }
>> 
>> +typedef int tc_setup_cb_t(enum tc_setup_type type,
>> +  void *type_data, void *cb_priv);
>> +
>> +#ifdef CONFIG_NET_CLS_ACT
>> +int tc_setup_cb_egdev_register(const struct net_device *dev,
>> +   tc_setup_cb_t *cb, void *cb_priv); void
>> +tc_setup_cb_egdev_unregister(const struct net_device *dev,
>> +  tc_setup_cb_t *cb, void *cb_priv); int
>> +tc_setup_cb_egdev_call(const struct net_device *dev,
>> +   enum tc_setup_type type, void *type_data,
>> +   bool err_stop);
>> +#else
>> +static inline
>> +int tc_setup_cb_egdev_register(const struct net_device *dev,
>> +   tc_setup_cb_t *cb, void *cb_priv) {
>> +return 0;
>> +}
>> +
>> +static inline
>> +void tc_setup_cb_egdev_unregister(const struct net_device *dev,
>> +  tc_setup_cb_t *cb, void *cb_priv) { }
>> +
>> +static inline
>> +int tc_setup_cb_egdev_call(const struct net_device *dev,
>> +   enum tc_setup_type type, void *type_data,
>> +   bool err_stop)
>> +{
>> +return 0;
>> +}
>> +#endif
>> +
>>  #endif
>> diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index
>> e80edd8..6f8149c 100644
>> --- a/include/net/pkt_cls.h
>> +++ b/include/net/pkt_cls.h
>> @@ -206,6 +206,8 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts
>> *exts);  int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts 
>> *exts);  int
>> tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
>>   struct net_device **hw_dev);
>> +int tcf_exts_egdev_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
>> +   void *type_data, bool err_stop);
>> 
>>  /**
>>   * struct tcf_pkt_info - packet information diff --git a/net/sched/act_api.c
>> b/net/sched/act_api.c index da6fa82..ac97db9 100644
>> --- a/net/sched/act_api.c
>> +++ b/net/sched/act_api.c
>> @@ -21,6 +21,8 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>> +#include 
>>  #include 
>>  #include 
>>  #include 
>> @@ -1249,8 +1251,226 @@ static int tc_dump_action(struct sk_buff *skb,
>> struct netlink_callback *cb)
>>  return skb->len;
>>  }
>> 
>> +struct tcf_action_net {
>> +struct rhashtable egdev_ht;
>> +};
>> +
>> +static unsigned int tcf_action_net_id;
>> +
>> +struct tcf_action_egdev_cb {
>> +struct list_head list;
>> +tc_setup_cb_t *cb;
>> +void *cb_priv;
>> +};
>> +
>> +struct tcf_action_egdev {
>> +struct rhash_head ht_node;
>> +const struct net_device *dev;
>> +unsigned int refcnt;
>> +struct list_head cb_list;
>> +};
>> +
>> +static const struct rhashtable_params tcf_action_egdev_ht_params = {
>> +.key_offse

RE: [patch net-next v2 2/4] net: sched: introduce per-egress action device callbacks

2017-11-19 Thread Chopra, Manish
> -Original Message-
> From: netdev-ow...@vger.kernel.org [mailto:netdev-ow...@vger.kernel.org]
> On Behalf Of Jiri Pirko
> Sent: Wednesday, October 11, 2017 1:11 PM
> To: netdev@vger.kernel.org
> Cc: da...@davemloft.net; j...@mojatatu.com; xiyou.wangc...@gmail.com;
> sae...@mellanox.com; mat...@mellanox.com; leo...@mellanox.com;
> ml...@mellanox.com; david.lai...@aculab.com; gerlitz...@gmail.com
> Subject: [patch net-next v2 2/4] net: sched: introduce per-egress action 
> device
> callbacks
> 
> From: Jiri Pirko <j...@mellanox.com>
> 
> Introduce infrastructure that allows drivers to register callbacks that are 
> called
> whenever tc would offload inserted rule and specified device acts as tc action
> egress device.
> 
> Signed-off-by: Jiri Pirko <j...@mellanox.com>
> ---
> v1->v2:
> - take rtnl for register/unregister
> ---
>  include/net/act_api.h |  34 
>  include/net/pkt_cls.h |   2 +
>  net/sched/act_api.c   | 220
> ++
>  net/sched/cls_api.c   |  30 +++
>  4 files changed, 286 insertions(+)
> 
> diff --git a/include/net/act_api.h b/include/net/act_api.h index
> 900168a..f5e8c90 100644
> --- a/include/net/act_api.h
> +++ b/include/net/act_api.h
> @@ -174,4 +174,38 @@ static inline void tcf_action_stats_update(struct
> tc_action *a, u64 bytes,  #endif  }
> 
> +typedef int tc_setup_cb_t(enum tc_setup_type type,
> +   void *type_data, void *cb_priv);
> +
> +#ifdef CONFIG_NET_CLS_ACT
> +int tc_setup_cb_egdev_register(const struct net_device *dev,
> +tc_setup_cb_t *cb, void *cb_priv); void
> +tc_setup_cb_egdev_unregister(const struct net_device *dev,
> +   tc_setup_cb_t *cb, void *cb_priv); int
> +tc_setup_cb_egdev_call(const struct net_device *dev,
> +enum tc_setup_type type, void *type_data,
> +bool err_stop);
> +#else
> +static inline
> +int tc_setup_cb_egdev_register(const struct net_device *dev,
> +tc_setup_cb_t *cb, void *cb_priv) {
> + return 0;
> +}
> +
> +static inline
> +void tc_setup_cb_egdev_unregister(const struct net_device *dev,
> +   tc_setup_cb_t *cb, void *cb_priv) { }
> +
> +static inline
> +int tc_setup_cb_egdev_call(const struct net_device *dev,
> +enum tc_setup_type type, void *type_data,
> +bool err_stop)
> +{
> + return 0;
> +}
> +#endif
> +
>  #endif
> diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index
> e80edd8..6f8149c 100644
> --- a/include/net/pkt_cls.h
> +++ b/include/net/pkt_cls.h
> @@ -206,6 +206,8 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts
> *exts);  int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts); 
>  int
> tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
>struct net_device **hw_dev);
> +int tcf_exts_egdev_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
> +void *type_data, bool err_stop);
> 
>  /**
>   * struct tcf_pkt_info - packet information diff --git a/net/sched/act_api.c
> b/net/sched/act_api.c index da6fa82..ac97db9 100644
> --- a/net/sched/act_api.c
> +++ b/net/sched/act_api.c
> @@ -21,6 +21,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -1249,8 +1251,226 @@ static int tc_dump_action(struct sk_buff *skb,
> struct netlink_callback *cb)
>   return skb->len;
>  }
> 
> +struct tcf_action_net {
> + struct rhashtable egdev_ht;
> +};
> +
> +static unsigned int tcf_action_net_id;
> +
> +struct tcf_action_egdev_cb {
> + struct list_head list;
> + tc_setup_cb_t *cb;
> + void *cb_priv;
> +};
> +
> +struct tcf_action_egdev {
> + struct rhash_head ht_node;
> + const struct net_device *dev;
> + unsigned int refcnt;
> + struct list_head cb_list;
> +};
> +
> +static const struct rhashtable_params tcf_action_egdev_ht_params = {
> + .key_offset = offsetof(struct tcf_action_egdev, dev),
> + .head_offset = offsetof(struct tcf_action_egdev, ht_node),
> + .key_len = sizeof(const struct net_device *), };
> +
> +static struct tcf_action_egdev *
> +tcf_action_egdev_lookup(const struct net_device *dev) {
> + struct net *net = dev_net(dev);
> + struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
> +
> + return rhashtable_lookup_fast(>egdev_ht, ,
> +   tcf_action_egdev_ht_params);
> +}
&g

[patch net-next v2 2/4] net: sched: introduce per-egress action device callbacks

2017-10-11 Thread Jiri Pirko
From: Jiri Pirko 

Introduce infrastructure that allows drivers to register callbacks that
are called whenever tc would offload inserted rule and specified device
acts as tc action egress device.

Signed-off-by: Jiri Pirko 
---
v1->v2:
- take rtnl for register/unregister
---
 include/net/act_api.h |  34 
 include/net/pkt_cls.h |   2 +
 net/sched/act_api.c   | 220 ++
 net/sched/cls_api.c   |  30 +++
 4 files changed, 286 insertions(+)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 900168a..f5e8c90 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -174,4 +174,38 @@ static inline void tcf_action_stats_update(struct 
tc_action *a, u64 bytes,
 #endif
 }
 
+typedef int tc_setup_cb_t(enum tc_setup_type type,
+ void *type_data, void *cb_priv);
+
+#ifdef CONFIG_NET_CLS_ACT
+int tc_setup_cb_egdev_register(const struct net_device *dev,
+  tc_setup_cb_t *cb, void *cb_priv);
+void tc_setup_cb_egdev_unregister(const struct net_device *dev,
+ tc_setup_cb_t *cb, void *cb_priv);
+int tc_setup_cb_egdev_call(const struct net_device *dev,
+  enum tc_setup_type type, void *type_data,
+  bool err_stop);
+#else
+static inline
+int tc_setup_cb_egdev_register(const struct net_device *dev,
+  tc_setup_cb_t *cb, void *cb_priv)
+{
+   return 0;
+}
+
+static inline
+void tc_setup_cb_egdev_unregister(const struct net_device *dev,
+ tc_setup_cb_t *cb, void *cb_priv)
+{
+}
+
+static inline
+int tc_setup_cb_egdev_call(const struct net_device *dev,
+  enum tc_setup_type type, void *type_data,
+  bool err_stop)
+{
+   return 0;
+}
+#endif
+
 #endif
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index e80edd8..6f8149c 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -206,6 +206,8 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts 
*exts);
 int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
 int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
 struct net_device **hw_dev);
+int tcf_exts_egdev_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
+  void *type_data, bool err_stop);
 
 /**
  * struct tcf_pkt_info - packet information
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index da6fa82..ac97db9 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -1249,8 +1251,226 @@ static int tc_dump_action(struct sk_buff *skb, struct 
netlink_callback *cb)
return skb->len;
 }
 
+struct tcf_action_net {
+   struct rhashtable egdev_ht;
+};
+
+static unsigned int tcf_action_net_id;
+
+struct tcf_action_egdev_cb {
+   struct list_head list;
+   tc_setup_cb_t *cb;
+   void *cb_priv;
+};
+
+struct tcf_action_egdev {
+   struct rhash_head ht_node;
+   const struct net_device *dev;
+   unsigned int refcnt;
+   struct list_head cb_list;
+};
+
+static const struct rhashtable_params tcf_action_egdev_ht_params = {
+   .key_offset = offsetof(struct tcf_action_egdev, dev),
+   .head_offset = offsetof(struct tcf_action_egdev, ht_node),
+   .key_len = sizeof(const struct net_device *),
+};
+
+static struct tcf_action_egdev *
+tcf_action_egdev_lookup(const struct net_device *dev)
+{
+   struct net *net = dev_net(dev);
+   struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
+
+   return rhashtable_lookup_fast(>egdev_ht, ,
+ tcf_action_egdev_ht_params);
+}
+
+static struct tcf_action_egdev *
+tcf_action_egdev_get(const struct net_device *dev)
+{
+   struct tcf_action_egdev *egdev;
+   struct tcf_action_net *tan;
+
+   egdev = tcf_action_egdev_lookup(dev);
+   if (egdev)
+   goto inc_ref;
+
+   egdev = kzalloc(sizeof(*egdev), GFP_KERNEL);
+   if (!egdev)
+   return NULL;
+   INIT_LIST_HEAD(>cb_list);
+   tan = net_generic(dev_net(dev), tcf_action_net_id);
+   rhashtable_insert_fast(>egdev_ht, >ht_node,
+  tcf_action_egdev_ht_params);
+
+inc_ref:
+   egdev->refcnt++;
+   return egdev;
+}
+
+static void tcf_action_egdev_put(struct tcf_action_egdev *egdev)
+{
+   struct tcf_action_net *tan;
+
+   if (--egdev->refcnt)
+   return;
+   tan = net_generic(dev_net(egdev->dev), tcf_action_net_id);
+   rhashtable_remove_fast(>egdev_ht, >ht_node,
+  tcf_action_egdev_ht_params);
+   kfree(egdev);
+}
+
+static struct tcf_action_egdev_cb *
+tcf_action_egdev_cb_lookup(struct tcf_action_egdev *egdev,
+