Netdev List
 help / color / mirror / Atom feed
* Re: [Patch net-next v3 3/5] net_sched: act: move tcf_hashinfo_init() into tcf_register_action()
From: Jamal Hadi Salim @ 2014-02-12 12:44 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1392167255-21744-4-git-send-email-xiyou.wangcong@gmail.com>

On 02/11/14 20:07, Cong Wang wrote:
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>

> ---
>   include/net/act_api.h   |  2 +-
>   net/sched/act_api.c     | 16 +++++++++++++++-
>   net/sched/act_csum.c    |  8 +-------
>   net/sched/act_gact.c    |  8 +-------
>   net/sched/act_ipt.c     | 14 +++-----------
>   net/sched/act_mirred.c  | 10 +---------
>   net/sched/act_nat.c     |  9 +--------
>   net/sched/act_pedit.c   |  9 +--------
>   net/sched/act_police.c  | 13 ++-----------
>   net/sched/act_simple.c  | 14 ++------------
>   net/sched/act_skbedit.c |  8 +-------
>   11 files changed, 29 insertions(+), 82 deletions(-)
>
> diff --git a/include/net/act_api.h b/include/net/act_api.h
> index 3d22f42..969cac6 100644
> --- a/include/net/act_api.h
> +++ b/include/net/act_api.h
> @@ -107,7 +107,7 @@ int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
>   void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
>   void tcf_hash_insert(struct tc_action *a);
>
> -int tcf_register_action(struct tc_action_ops *a);
> +int tcf_register_action(struct tc_action_ops *a, unsigned int mask);
>   int tcf_unregister_action(struct tc_action_ops *a);
>   void tcf_action_destroy(struct list_head *actions, int bind);
>   int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
> diff --git a/net/sched/act_api.c b/net/sched/act_api.c
> index a5bf935..c88d382 100644
> --- a/net/sched/act_api.c
> +++ b/net/sched/act_api.c
> @@ -275,9 +275,10 @@ EXPORT_SYMBOL(tcf_hash_insert);
>   static LIST_HEAD(act_base);
>   static DEFINE_RWLOCK(act_mod_lock);
>
> -int tcf_register_action(struct tc_action_ops *act)
> +int tcf_register_action(struct tc_action_ops *act, unsigned int mask)
>   {
>   	struct tc_action_ops *a;
> +	int err;
>
>   	/* Must supply act, dump and init */
>   	if (!act->act || !act->dump || !act->init)
> @@ -289,10 +290,21 @@ int tcf_register_action(struct tc_action_ops *act)
>   	if (!act->walk)
>   		act->walk = tcf_generic_walker;
>
> +	act->hinfo = kmalloc(sizeof(struct tcf_hashinfo), GFP_KERNEL);
> +	if (!act->hinfo)
> +		return -ENOMEM;
> +	err = tcf_hashinfo_init(act->hinfo, mask);
> +	if (err) {
> +		kfree(act->hinfo);
> +		return err;
> +	}
> +
>   	write_lock(&act_mod_lock);
>   	list_for_each_entry(a, &act_base, head) {
>   		if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
>   			write_unlock(&act_mod_lock);
> +			tcf_hashinfo_destroy(act->hinfo);
> +			kfree(act->hinfo);
>   			return -EEXIST;
>   		}
>   	}
> @@ -311,6 +323,8 @@ int tcf_unregister_action(struct tc_action_ops *act)
>   	list_for_each_entry(a, &act_base, head) {
>   		if (a == act) {
>   			list_del(&act->head);
> +			tcf_hashinfo_destroy(act->hinfo);
> +			kfree(act->hinfo);
>   			err = 0;
>   			break;
>   		}
> diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
> index 8df3060..edbf40d 100644
> --- a/net/sched/act_csum.c
> +++ b/net/sched/act_csum.c
> @@ -37,7 +37,6 @@
>   #include <net/tc_act/tc_csum.h>
>
>   #define CSUM_TAB_MASK 15
> -static struct tcf_hashinfo csum_hash_info;
>
>   static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
>   	[TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), },
> @@ -561,7 +560,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_csum_ops = {
>   	.kind		= "csum",
> -	.hinfo		= &csum_hash_info,
>   	.type		= TCA_ACT_CSUM,
>   	.owner		= THIS_MODULE,
>   	.act		= tcf_csum,
> @@ -574,11 +572,7 @@ MODULE_LICENSE("GPL");
>
>   static int __init csum_init_module(void)
>   {
> -	int err = tcf_hashinfo_init(&csum_hash_info, CSUM_TAB_MASK);
> -	if (err)
> -		return err;
> -
> -	return tcf_register_action(&act_csum_ops);
> +	return tcf_register_action(&act_csum_ops, CSUM_TAB_MASK);
>   }
>
>   static void __exit csum_cleanup_module(void)
> diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
> index 094a1b5..d6bcbd9 100644
> --- a/net/sched/act_gact.c
> +++ b/net/sched/act_gact.c
> @@ -24,7 +24,6 @@
>   #include <net/tc_act/tc_gact.h>
>
>   #define GACT_TAB_MASK	15
> -static struct tcf_hashinfo gact_hash_info;
>
>   #ifdef CONFIG_GACT_PROB
>   static int gact_net_rand(struct tcf_gact *gact)
> @@ -180,7 +179,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_gact_ops = {
>   	.kind		=	"gact",
> -	.hinfo		=	&gact_hash_info,
>   	.type		=	TCA_ACT_GACT,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_gact,
> @@ -194,21 +192,17 @@ MODULE_LICENSE("GPL");
>
>   static int __init gact_init_module(void)
>   {
> -	int err = tcf_hashinfo_init(&gact_hash_info, GACT_TAB_MASK);
> -	if (err)
> -		return err;
>   #ifdef CONFIG_GACT_PROB
>   	pr_info("GACT probability on\n");
>   #else
>   	pr_info("GACT probability NOT on\n");
>   #endif
> -	return tcf_register_action(&act_gact_ops);
> +	return tcf_register_action(&act_gact_ops, GACT_TAB_MASK);
>   }
>
>   static void __exit gact_cleanup_module(void)
>   {
>   	tcf_unregister_action(&act_gact_ops);
> -	tcf_hashinfo_destroy(&gact_hash_info);
>   }
>
>   module_init(gact_init_module);
> diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
> index 71f29f1..8a64a07 100644
> --- a/net/sched/act_ipt.c
> +++ b/net/sched/act_ipt.c
> @@ -29,7 +29,6 @@
>
>
>   #define IPT_TAB_MASK     15
> -static struct tcf_hashinfo ipt_hash_info;
>
>   static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook)
>   {
> @@ -262,7 +261,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_ipt_ops = {
>   	.kind		=	"ipt",
> -	.hinfo		=	&ipt_hash_info,
>   	.type		=	TCA_ACT_IPT,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_ipt,
> @@ -273,7 +271,6 @@ static struct tc_action_ops act_ipt_ops = {
>
>   static struct tc_action_ops act_xt_ops = {
>   	.kind		=	"xt",
> -	.hinfo		=	&ipt_hash_info,
>   	.type		=	TCA_ACT_XT,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_ipt,
> @@ -289,20 +286,16 @@ MODULE_ALIAS("act_xt");
>
>   static int __init ipt_init_module(void)
>   {
> -	int ret1, ret2, err;
> -	err = tcf_hashinfo_init(&ipt_hash_info, IPT_TAB_MASK);
> -	if (err)
> -		return err;
> +	int ret1, ret2;
>
> -	ret1 = tcf_register_action(&act_xt_ops);
> +	ret1 = tcf_register_action(&act_xt_ops, IPT_TAB_MASK);
>   	if (ret1 < 0)
>   		printk("Failed to load xt action\n");
> -	ret2 = tcf_register_action(&act_ipt_ops);
> +	ret2 = tcf_register_action(&act_ipt_ops, IPT_TAB_MASK);
>   	if (ret2 < 0)
>   		printk("Failed to load ipt action\n");
>
>   	if (ret1 < 0 && ret2 < 0) {
> -		tcf_hashinfo_destroy(&ipt_hash_info);
>   		return ret1;
>   	} else
>   		return 0;
> @@ -312,7 +305,6 @@ static void __exit ipt_cleanup_module(void)
>   {
>   	tcf_unregister_action(&act_xt_ops);
>   	tcf_unregister_action(&act_ipt_ops);
> -	tcf_hashinfo_destroy(&ipt_hash_info);
>   }
>
>   module_init(ipt_init_module);
> diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
> index 0f00eb9..4f912c0 100644
> --- a/net/sched/act_mirred.c
> +++ b/net/sched/act_mirred.c
> @@ -31,7 +31,6 @@
>
>   #define MIRRED_TAB_MASK     7
>   static LIST_HEAD(mirred_list);
> -static struct tcf_hashinfo mirred_hash_info;
>
>   static void tcf_mirred_release(struct tc_action *a, int bind)
>   {
> @@ -234,7 +233,6 @@ static struct notifier_block mirred_device_notifier = {
>
>   static struct tc_action_ops act_mirred_ops = {
>   	.kind		=	"mirred",
> -	.hinfo		=	&mirred_hash_info,
>   	.type		=	TCA_ACT_MIRRED,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_mirred,
> @@ -253,19 +251,13 @@ static int __init mirred_init_module(void)
>   	if (err)
>   		return err;
>
> -	err = tcf_hashinfo_init(&mirred_hash_info, MIRRED_TAB_MASK);
> -	if (err) {
> -		unregister_netdevice_notifier(&mirred_device_notifier);
> -		return err;
> -	}
>   	pr_info("Mirror/redirect action on\n");
> -	return tcf_register_action(&act_mirred_ops);
> +	return tcf_register_action(&act_mirred_ops, MIRRED_TAB_MASK);
>   }
>
>   static void __exit mirred_cleanup_module(void)
>   {
>   	tcf_unregister_action(&act_mirred_ops);
> -	tcf_hashinfo_destroy(&mirred_hash_info);
>   	unregister_netdevice_notifier(&mirred_device_notifier);
>   }
>
> diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
> index 9a3cb1d..270a030 100644
> --- a/net/sched/act_nat.c
> +++ b/net/sched/act_nat.c
> @@ -31,8 +31,6 @@
>
>   #define NAT_TAB_MASK	15
>
> -static struct tcf_hashinfo nat_hash_info;
> -
>   static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
>   	[TCA_NAT_PARMS]	= { .len = sizeof(struct tc_nat) },
>   };
> @@ -284,7 +282,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_nat_ops = {
>   	.kind		=	"nat",
> -	.hinfo		=	&nat_hash_info,
>   	.type		=	TCA_ACT_NAT,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_nat,
> @@ -297,16 +294,12 @@ MODULE_LICENSE("GPL");
>
>   static int __init nat_init_module(void)
>   {
> -	int err = tcf_hashinfo_init(&nat_hash_info, NAT_TAB_MASK);
> -	if (err)
> -		return err;
> -	return tcf_register_action(&act_nat_ops);
> +	return tcf_register_action(&act_nat_ops, NAT_TAB_MASK);
>   }
>
>   static void __exit nat_cleanup_module(void)
>   {
>   	tcf_unregister_action(&act_nat_ops);
> -	tcf_hashinfo_destroy(&nat_hash_info);
>   }
>
>   module_init(nat_init_module);
> diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
> index 8aa795b..5f9bcb2 100644
> --- a/net/sched/act_pedit.c
> +++ b/net/sched/act_pedit.c
> @@ -25,8 +25,6 @@
>
>   #define PEDIT_TAB_MASK	15
>
> -static struct tcf_hashinfo pedit_hash_info;
> -
>   static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
>   	[TCA_PEDIT_PARMS]	= { .len = sizeof(struct tc_pedit) },
>   };
> @@ -218,7 +216,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_pedit_ops = {
>   	.kind		=	"pedit",
> -	.hinfo		=	&pedit_hash_info,
>   	.type		=	TCA_ACT_PEDIT,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_pedit,
> @@ -233,15 +230,11 @@ MODULE_LICENSE("GPL");
>
>   static int __init pedit_init_module(void)
>   {
> -	int err = tcf_hashinfo_init(&pedit_hash_info, PEDIT_TAB_MASK);
> -	if (err)
> -		return err;
> -	return tcf_register_action(&act_pedit_ops);
> +	return tcf_register_action(&act_pedit_ops, PEDIT_TAB_MASK);
>   }
>
>   static void __exit pedit_cleanup_module(void)
>   {
> -	tcf_hashinfo_destroy(&pedit_hash_info);
>   	tcf_unregister_action(&act_pedit_ops);
>   }
>
> diff --git a/net/sched/act_police.c b/net/sched/act_police.c
> index 7ff7bef..0566e46 100644
> --- a/net/sched/act_police.c
> +++ b/net/sched/act_police.c
> @@ -41,7 +41,6 @@ struct tcf_police {
>   	container_of(pc, struct tcf_police, common)
>
>   #define POL_TAB_MASK     15
> -static struct tcf_hashinfo police_hash_info;
>
>   /* old policer structure from before tc actions */
>   struct tc_police_compat {
> @@ -234,7 +233,7 @@ override:
>
>   	police->tcfp_t_c = ktime_to_ns(ktime_get());
>   	police->tcf_index = parm->index ? parm->index :
> -		tcf_hash_new_index(a->ops->hinfo);
> +		tcf_hash_new_index(hinfo);
>   	h = tcf_hash(police->tcf_index, POL_TAB_MASK);
>   	spin_lock_bh(&hinfo->lock);
>   	hlist_add_head(&police->tcf_head, &hinfo->htab[h]);
> @@ -349,7 +348,6 @@ MODULE_LICENSE("GPL");
>
>   static struct tc_action_ops act_police_ops = {
>   	.kind		=	"police",
> -	.hinfo		=	&police_hash_info,
>   	.type		=	TCA_ID_POLICE,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_act_police,
> @@ -361,19 +359,12 @@ static struct tc_action_ops act_police_ops = {
>   static int __init
>   police_init_module(void)
>   {
> -	int err = tcf_hashinfo_init(&police_hash_info, POL_TAB_MASK);
> -	if (err)
> -		return err;
> -	err = tcf_register_action(&act_police_ops);
> -	if (err)
> -		tcf_hashinfo_destroy(&police_hash_info);
> -	return err;
> +	return tcf_register_action(&act_police_ops, POL_TAB_MASK);
>   }
>
>   static void __exit
>   police_cleanup_module(void)
>   {
> -	tcf_hashinfo_destroy(&police_hash_info);
>   	tcf_unregister_action(&act_police_ops);
>   }
>
> diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
> index 14b5e36..992c231 100644
> --- a/net/sched/act_simple.c
> +++ b/net/sched/act_simple.c
> @@ -25,7 +25,6 @@
>   #include <net/tc_act/tc_defact.h>
>
>   #define SIMP_TAB_MASK     7
> -static struct tcf_hashinfo simp_hash_info;
>
>   #define SIMP_MAX_DATA	32
>   static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
> @@ -163,7 +162,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_simp_ops = {
>   	.kind		=	"simple",
> -	.hinfo		=	&simp_hash_info,
>   	.type		=	TCA_ACT_SIMP,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_simp,
> @@ -178,23 +176,15 @@ MODULE_LICENSE("GPL");
>
>   static int __init simp_init_module(void)
>   {
> -	int err, ret;
> -	err = tcf_hashinfo_init(&simp_hash_info, SIMP_TAB_MASK);
> -	if (err)
> -		return err;
> -
> -	ret = tcf_register_action(&act_simp_ops);
> +	int ret;
> +	ret = tcf_register_action(&act_simp_ops, SIMP_TAB_MASK);
>   	if (!ret)
>   		pr_info("Simple TC action Loaded\n");
> -	else
> -		tcf_hashinfo_destroy(&simp_hash_info);
> -
>   	return ret;
>   }
>
>   static void __exit simp_cleanup_module(void)
>   {
> -	tcf_hashinfo_destroy(&simp_hash_info);
>   	tcf_unregister_action(&act_simp_ops);
>   }
>
> diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
> index 9f91928..fcfeeaf 100644
> --- a/net/sched/act_skbedit.c
> +++ b/net/sched/act_skbedit.c
> @@ -28,7 +28,6 @@
>   #include <net/tc_act/tc_skbedit.h>
>
>   #define SKBEDIT_TAB_MASK     15
> -static struct tcf_hashinfo skbedit_hash_info;
>
>   static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
>   		       struct tcf_result *res)
> @@ -175,7 +174,6 @@ nla_put_failure:
>
>   static struct tc_action_ops act_skbedit_ops = {
>   	.kind		=	"skbedit",
> -	.hinfo		=	&skbedit_hash_info,
>   	.type		=	TCA_ACT_SKBEDIT,
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_skbedit,
> @@ -189,15 +187,11 @@ MODULE_LICENSE("GPL");
>
>   static int __init skbedit_init_module(void)
>   {
> -	int err = tcf_hashinfo_init(&skbedit_hash_info, SKBEDIT_TAB_MASK);
> -	if (err)
> -		return err;
> -	return tcf_register_action(&act_skbedit_ops);
> +	return tcf_register_action(&act_skbedit_ops, SKBEDIT_TAB_MASK);
>   }
>
>   static void __exit skbedit_cleanup_module(void)
>   {
> -	tcf_hashinfo_destroy(&skbedit_hash_info);
>   	tcf_unregister_action(&act_skbedit_ops);
>   }
>
>

^ permalink raw reply

* Re: [Patch net-next v3 2/5] net_sched: act: refactor cleanup ops
From: Jamal Hadi Salim @ 2014-02-12 12:43 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1392167255-21744-3-git-send-email-xiyou.wangcong@gmail.com>

On 02/11/14 20:07, Cong Wang wrote:
> For bindcnt and refcnt etc., they are common for all actions,
> not need to repeat such operations for their own, they can be unified
> now. Actions just need to do its specific cleanup if needed.
>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>


> ---
>   include/net/act_api.h   |  2 +-
>   net/sched/act_api.c     |  8 +++++---
>   net/sched/act_csum.c    |  1 -
>   net/sched/act_gact.c    |  1 -
>   net/sched/act_ipt.c     | 21 +++++----------------
>   net/sched/act_mirred.c  | 20 +++++---------------
>   net/sched/act_nat.c     |  1 -
>   net/sched/act_pedit.c   | 13 +++----------
>   net/sched/act_police.c  |  1 -
>   net/sched/act_simple.c  | 17 +++--------------
>   net/sched/act_skbedit.c |  1 -
>   11 files changed, 22 insertions(+), 64 deletions(-)
>
> diff --git a/include/net/act_api.h b/include/net/act_api.h
> index 24ae910..3d22f42 100644
> --- a/include/net/act_api.h
> +++ b/include/net/act_api.h
> @@ -89,7 +89,7 @@ struct tc_action_ops {
>   	struct module		*owner;
>   	int     (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *);
>   	int     (*dump)(struct sk_buff *, struct tc_action *, int, int);
> -	int     (*cleanup)(struct tc_action *, int bind);
> +	void	(*cleanup)(struct tc_action *, int bind);
>   	int     (*lookup)(struct tc_action *, u32);
>   	int     (*init)(struct net *net, struct nlattr *nla,
>   			struct nlattr *est, struct tc_action *act, int ovr,
> diff --git a/net/sched/act_api.c b/net/sched/act_api.c
> index 4f2b807..a5bf935 100644
> --- a/net/sched/act_api.c
> +++ b/net/sched/act_api.c
> @@ -56,6 +56,8 @@ int tcf_hash_release(struct tc_action *a, int bind)
>
>   		p->tcfc_refcnt--;
>   		if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
> +			if (a->ops->cleanup)
> +				a->ops->cleanup(a, bind);
>   			tcf_hash_destroy(a);
>   			ret = 1;
>   		}
> @@ -277,8 +279,8 @@ int tcf_register_action(struct tc_action_ops *act)
>   {
>   	struct tc_action_ops *a;
>
> -	/* Must supply act, dump, cleanup and init */
> -	if (!act->act || !act->dump || !act->cleanup || !act->init)
> +	/* Must supply act, dump and init */
> +	if (!act->act || !act->dump || !act->init)
>   		return -EINVAL;
>
>   	/* Supply defaults */
> @@ -390,7 +392,7 @@ void tcf_action_destroy(struct list_head *actions, int bind)
>   	struct tc_action *a, *tmp;
>
>   	list_for_each_entry_safe(a, tmp, actions, list) {
> -		if (a->ops->cleanup(a, bind) == ACT_P_DELETED)
> +		if (tcf_hash_release(a, bind) == ACT_P_DELETED)
>   			module_put(a->ops->owner);
>   		list_del(&a->list);
>   		kfree(a);
> diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
> index f0f6e7a..8df3060 100644
> --- a/net/sched/act_csum.c
> +++ b/net/sched/act_csum.c
> @@ -566,7 +566,6 @@ static struct tc_action_ops act_csum_ops = {
>   	.owner		= THIS_MODULE,
>   	.act		= tcf_csum,
>   	.dump		= tcf_csum_dump,
> -	.cleanup	= tcf_hash_release,
>   	.init		= tcf_csum_init,
>   };
>
> diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
> index af6c0ac..094a1b5 100644
> --- a/net/sched/act_gact.c
> +++ b/net/sched/act_gact.c
> @@ -185,7 +185,6 @@ static struct tc_action_ops act_gact_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_gact,
>   	.dump		=	tcf_gact_dump,
> -	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_gact_init,
>   };
>
> diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
> index f5e6978..71f29f1 100644
> --- a/net/sched/act_ipt.c
> +++ b/net/sched/act_ipt.c
> @@ -69,23 +69,12 @@ static void ipt_destroy_target(struct xt_entry_target *t)
>   	module_put(par.target->me);
>   }
>
> -static int tcf_ipt_release(struct tc_action *a, int bind)
> +static void tcf_ipt_release(struct tc_action *a, int bind)
>   {
>   	struct tcf_ipt *ipt = to_ipt(a);
> -	int ret = 0;
> -	if (ipt) {
> -		if (bind)
> -			ipt->tcf_bindcnt--;
> -		ipt->tcf_refcnt--;
> -		if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) {
> -			ipt_destroy_target(ipt->tcfi_t);
> -			kfree(ipt->tcfi_tname);
> -			kfree(ipt->tcfi_t);
> -			tcf_hash_destroy(a);
> -			ret = ACT_P_DELETED;
> -		}
> -	}
> -	return ret;
> +	ipt_destroy_target(ipt->tcfi_t);
> +	kfree(ipt->tcfi_tname);
> +	kfree(ipt->tcfi_t);
>   }
>
>   static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
> @@ -133,7 +122,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   	} else {
>   		if (bind)/* dont override defaults */
>   			return 0;
> -		tcf_ipt_release(a, bind);
> +		tcf_hash_release(a, bind);
>
>   		if (!ovr)
>   			return -EEXIST;
> diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
> index 3edeeca..0f00eb9 100644
> --- a/net/sched/act_mirred.c
> +++ b/net/sched/act_mirred.c
> @@ -33,22 +33,12 @@
>   static LIST_HEAD(mirred_list);
>   static struct tcf_hashinfo mirred_hash_info;
>
> -static int tcf_mirred_release(struct tc_action *a, int bind)
> +static void tcf_mirred_release(struct tc_action *a, int bind)
>   {
>   	struct tcf_mirred *m = to_mirred(a);
> -	if (m) {
> -		if (bind)
> -			m->tcf_bindcnt--;
> -		m->tcf_refcnt--;
> -		if (!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
> -			list_del(&m->tcfm_list);
> -			if (m->tcfm_dev)
> -				dev_put(m->tcfm_dev);
> -			tcf_hash_destroy(a);
> -			return 1;
> -		}
> -	}
> -	return 0;
> +	list_del(&m->tcfm_list);
> +	if (m->tcfm_dev)
> +		dev_put(m->tcfm_dev);
>   }
>
>   static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
> @@ -110,7 +100,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
>   		ret = ACT_P_CREATED;
>   	} else {
>   		if (!ovr) {
> -			tcf_mirred_release(a, bind);
> +			tcf_hash_release(a, bind);
>   			return -EEXIST;
>   		}
>   	}
> diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
> index ce9a391..9a3cb1d 100644
> --- a/net/sched/act_nat.c
> +++ b/net/sched/act_nat.c
> @@ -289,7 +289,6 @@ static struct tc_action_ops act_nat_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_nat,
>   	.dump		=	tcf_nat_dump,
> -	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_nat_init,
>   };
>
> diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
> index 091ced3..8aa795b 100644
> --- a/net/sched/act_pedit.c
> +++ b/net/sched/act_pedit.c
> @@ -99,18 +99,11 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
>   	return ret;
>   }
>
> -static int tcf_pedit_cleanup(struct tc_action *a, int bind)
> +static void tcf_pedit_cleanup(struct tc_action *a, int bind)
>   {
>   	struct tcf_pedit *p = a->priv;
> -
> -	if (p) {
> -		struct tc_pedit_key *keys = p->tcfp_keys;
> -		if (tcf_hash_release(a, bind)) {
> -			kfree(keys);
> -			return 1;
> -		}
> -	}
> -	return 0;
> +	struct tc_pedit_key *keys = p->tcfp_keys;
> +	kfree(keys);
>   }
>
>   static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
> diff --git a/net/sched/act_police.c b/net/sched/act_police.c
> index 4695d02..7ff7bef 100644
> --- a/net/sched/act_police.c
> +++ b/net/sched/act_police.c
> @@ -354,7 +354,6 @@ static struct tc_action_ops act_police_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_act_police,
>   	.dump		=	tcf_act_police_dump,
> -	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_act_police_locate,
>   	.walk		=	tcf_act_police_walker
>   };
> diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
> index 11c2922..14b5e36 100644
> --- a/net/sched/act_simple.c
> +++ b/net/sched/act_simple.c
> @@ -47,21 +47,10 @@ static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
>   	return d->tcf_action;
>   }
>
> -static int tcf_simp_release(struct tc_action *a, int bind)
> +static void tcf_simp_release(struct tc_action *a, int bind)
>   {
>   	struct tcf_defact *d = to_defact(a);
> -	int ret = 0;
> -	if (d) {
> -		if (bind)
> -			d->tcf_bindcnt--;
> -		d->tcf_refcnt--;
> -		if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) {
> -			kfree(d->tcfd_defdata);
> -			tcf_hash_destroy(a);
> -			ret = 1;
> -		}
> -	}
> -	return ret;
> +	kfree(d->tcfd_defdata);
>   }
>
>   static int alloc_defdata(struct tcf_defact *d, char *defdata)
> @@ -132,7 +121,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
>
>   		if (bind)
>   			return 0;
> -		tcf_simp_release(a, bind);
> +		tcf_hash_release(a, bind);
>   		if (!ovr)
>   			return -EEXIST;
>
> diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
> index 71fd2d4..9f91928 100644
> --- a/net/sched/act_skbedit.c
> +++ b/net/sched/act_skbedit.c
> @@ -180,7 +180,6 @@ static struct tc_action_ops act_skbedit_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_skbedit,
>   	.dump		=	tcf_skbedit_dump,
> -	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_skbedit_init,
>   };
>
>

^ permalink raw reply

* Re: [Patch net-next v3 1/5] net_sched: act: hide struct tcf_common from API
From: Jamal Hadi Salim @ 2014-02-12 12:43 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: David S. Miller
In-Reply-To: <1392167255-21744-2-git-send-email-xiyou.wangcong@gmail.com>

On 02/11/14 20:07, Cong Wang wrote:
> Now we can totally hide it from modules. tcf_hash_*() API's
> will operate on struct tc_action, modules don't need to care about
> the details.
>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>


> ---
>   include/net/act_api.h           | 16 +++++++--------
>   include/net/tc_act/tc_csum.h    |  4 ++--
>   include/net/tc_act/tc_defact.h  |  4 ++--
>   include/net/tc_act/tc_gact.h    |  4 ++--
>   include/net/tc_act/tc_ipt.h     |  4 ++--
>   include/net/tc_act/tc_mirred.h  |  4 ++--
>   include/net/tc_act/tc_nat.h     |  4 ++--
>   include/net/tc_act/tc_pedit.h   |  4 ++--
>   include/net/tc_act/tc_skbedit.h |  4 ++--
>   net/sched/act_api.c             | 43 ++++++++++++++++++++++++++++-------------
>   net/sched/act_csum.c            | 24 ++++++++---------------
>   net/sched/act_gact.c            | 27 ++++++++------------------
>   net/sched/act_ipt.c             | 39 ++++++++++++++-----------------------
>   net/sched/act_mirred.c          | 32 +++++++++++-------------------
>   net/sched/act_nat.c             | 25 ++++++++----------------
>   net/sched/act_pedit.c           | 25 ++++++++++--------------
>   net/sched/act_police.c          | 10 +---------
>   net/sched/act_simple.c          | 39 +++++++++++++------------------------
>   net/sched/act_skbedit.c         | 29 +++++++++------------------
>   19 files changed, 135 insertions(+), 206 deletions(-)
>
> diff --git a/include/net/act_api.h b/include/net/act_api.h
> index 788d837..24ae910 100644
> --- a/include/net/act_api.h
> +++ b/include/net/act_api.h
> @@ -98,16 +98,14 @@ struct tc_action_ops {
>   };
>
>   int tcf_hash_search(struct tc_action *a, u32 index);
> -void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo);
> -int tcf_hash_release(struct tcf_common *p, int bind,
> -		     struct tcf_hashinfo *hinfo);
> +void tcf_hash_destroy(struct tc_action *a);
> +int tcf_hash_release(struct tc_action *a, int bind);
>   u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo);
> -struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a,
> -				  int bind);
> -struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
> -				   struct tc_action *a, int size,
> -				   int bind);
> -void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo);
> +int tcf_hash_check(u32 index, struct tc_action *a, int bind);
> +int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
> +		    int size, int bind);
> +void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
> +void tcf_hash_insert(struct tc_action *a);
>
>   int tcf_register_action(struct tc_action_ops *a);
>   int tcf_unregister_action(struct tc_action_ops *a);
> diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h
> index 9e8710b..fa8f5fa 100644
> --- a/include/net/tc_act/tc_csum.h
> +++ b/include/net/tc_act/tc_csum.h
> @@ -9,7 +9,7 @@ struct tcf_csum {
>
>   	u32 update_flags;
>   };
> -#define to_tcf_csum(pc) \
> -	container_of(pc,struct tcf_csum,common)
> +#define to_tcf_csum(a) \
> +	container_of(a->priv,struct tcf_csum,common)
>
>   #endif /* __NET_TC_CSUM_H */
> diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
> index 65f024b..9763dcb 100644
> --- a/include/net/tc_act/tc_defact.h
> +++ b/include/net/tc_act/tc_defact.h
> @@ -8,7 +8,7 @@ struct tcf_defact {
>   	u32     		tcfd_datalen;
>   	void    		*tcfd_defdata;
>   };
> -#define to_defact(pc) \
> -	container_of(pc, struct tcf_defact, common)
> +#define to_defact(a) \
> +	container_of(a->priv, struct tcf_defact, common)
>
>   #endif /* __NET_TC_DEF_H */
> diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
> index 9e3f676..9fc9b57 100644
> --- a/include/net/tc_act/tc_gact.h
> +++ b/include/net/tc_act/tc_gact.h
> @@ -11,7 +11,7 @@ struct tcf_gact {
>           int			tcfg_paction;
>   #endif
>   };
> -#define to_gact(pc) \
> -	container_of(pc, struct tcf_gact, common)
> +#define to_gact(a) \
> +	container_of(a->priv, struct tcf_gact, common)
>
>   #endif /* __NET_TC_GACT_H */
> diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h
> index f7d25df..c0f4193 100644
> --- a/include/net/tc_act/tc_ipt.h
> +++ b/include/net/tc_act/tc_ipt.h
> @@ -11,7 +11,7 @@ struct tcf_ipt {
>   	char			*tcfi_tname;
>   	struct xt_entry_target	*tcfi_t;
>   };
> -#define to_ipt(pc) \
> -	container_of(pc, struct tcf_ipt, common)
> +#define to_ipt(a) \
> +	container_of(a->priv, struct tcf_ipt, common)
>
>   #endif /* __NET_TC_IPT_H */
> diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
> index cfe2943..4dd77a1 100644
> --- a/include/net/tc_act/tc_mirred.h
> +++ b/include/net/tc_act/tc_mirred.h
> @@ -11,7 +11,7 @@ struct tcf_mirred {
>   	struct net_device	*tcfm_dev;
>   	struct list_head	tcfm_list;
>   };
> -#define to_mirred(pc) \
> -	container_of(pc, struct tcf_mirred, common)
> +#define to_mirred(a) \
> +	container_of(a->priv, struct tcf_mirred, common)
>
>   #endif /* __NET_TC_MIR_H */
> diff --git a/include/net/tc_act/tc_nat.h b/include/net/tc_act/tc_nat.h
> index 4a691f3..63d8e9c 100644
> --- a/include/net/tc_act/tc_nat.h
> +++ b/include/net/tc_act/tc_nat.h
> @@ -13,9 +13,9 @@ struct tcf_nat {
>   	u32 flags;
>   };
>
> -static inline struct tcf_nat *to_tcf_nat(struct tcf_common *pc)
> +static inline struct tcf_nat *to_tcf_nat(struct tc_action *a)
>   {
> -	return container_of(pc, struct tcf_nat, common);
> +	return container_of(a->priv, struct tcf_nat, common);
>   }
>
>   #endif /* __NET_TC_NAT_H */
> diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
> index e6f6e15..5b80998 100644
> --- a/include/net/tc_act/tc_pedit.h
> +++ b/include/net/tc_act/tc_pedit.h
> @@ -9,7 +9,7 @@ struct tcf_pedit {
>   	unsigned char		tcfp_flags;
>   	struct tc_pedit_key	*tcfp_keys;
>   };
> -#define to_pedit(pc) \
> -	container_of(pc, struct tcf_pedit, common)
> +#define to_pedit(a) \
> +	container_of(a->priv, struct tcf_pedit, common)
>
>   #endif /* __NET_TC_PED_H */
> diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
> index dd5d86f..0df9a0d 100644
> --- a/include/net/tc_act/tc_skbedit.h
> +++ b/include/net/tc_act/tc_skbedit.h
> @@ -29,7 +29,7 @@ struct tcf_skbedit {
>   	u16			queue_mapping;
>   	/* XXX: 16-bit pad here? */
>   };
> -#define to_skbedit(pc) \
> -	container_of(pc, struct tcf_skbedit, common)
> +#define to_skbedit(a) \
> +	container_of(a->priv, struct tcf_skbedit, common)
>
>   #endif /* __NET_TC_SKBEDIT_H */
> diff --git a/net/sched/act_api.c b/net/sched/act_api.c
> index 72bdc71..4f2b807 100644
> --- a/net/sched/act_api.c
> +++ b/net/sched/act_api.c
> @@ -27,8 +27,11 @@
>   #include <net/act_api.h>
>   #include <net/netlink.h>
>
> -void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
> +void tcf_hash_destroy(struct tc_action *a)
>   {
> +	struct tcf_common *p = a->priv;
> +	struct tcf_hashinfo *hinfo = a->ops->hinfo;
> +
>   	spin_lock_bh(&hinfo->lock);
>   	hlist_del(&p->tcfc_head);
>   	spin_unlock_bh(&hinfo->lock);
> @@ -42,9 +45,9 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
>   }
>   EXPORT_SYMBOL(tcf_hash_destroy);
>
> -int tcf_hash_release(struct tcf_common *p, int bind,
> -		     struct tcf_hashinfo *hinfo)
> +int tcf_hash_release(struct tc_action *a, int bind)
>   {
> +	struct tcf_common *p = a->priv;
>   	int ret = 0;
>
>   	if (p) {
> @@ -53,7 +56,7 @@ int tcf_hash_release(struct tcf_common *p, int bind,
>
>   		p->tcfc_refcnt--;
>   		if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
> -			tcf_hash_destroy(p, hinfo);
> +			tcf_hash_destroy(a);
>   			ret = 1;
>   		}
>   	}
> @@ -127,7 +130,8 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
>   	for (i = 0; i < (hinfo->hmask + 1); i++) {
>   		head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
>   		hlist_for_each_entry_safe(p, n, head, tcfc_head) {
> -			if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) {
> +			a->priv = p;
> +			if (ACT_P_DELETED == tcf_hash_release(a, 0)) {
>   				module_put(a->ops->owner);
>   				n_i++;
>   			}
> @@ -198,7 +202,7 @@ int tcf_hash_search(struct tc_action *a, u32 index)
>   }
>   EXPORT_SYMBOL(tcf_hash_search);
>
> -struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind)
> +int tcf_hash_check(u32 index, struct tc_action *a, int bind)
>   {
>   	struct tcf_hashinfo *hinfo = a->ops->hinfo;
>   	struct tcf_common *p = NULL;
> @@ -207,19 +211,30 @@ struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind)
>   			p->tcfc_bindcnt++;
>   		p->tcfc_refcnt++;
>   		a->priv = p;
> +		return 1;
>   	}
> -	return p;
> +	return 0;
>   }
>   EXPORT_SYMBOL(tcf_hash_check);
>
> -struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
> -				   struct tc_action *a, int size, int bind)
> +void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
> +{
> +	struct tcf_common *pc = a->priv;
> +	if (est)
> +		gen_kill_estimator(&pc->tcfc_bstats,
> +				   &pc->tcfc_rate_est);
> +	kfree_rcu(pc, tcfc_rcu);
> +}
> +EXPORT_SYMBOL(tcf_hash_cleanup);
> +
> +int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
> +		    int size, int bind)
>   {
>   	struct tcf_hashinfo *hinfo = a->ops->hinfo;
>   	struct tcf_common *p = kzalloc(size, GFP_KERNEL);
>
>   	if (unlikely(!p))
> -		return ERR_PTR(-ENOMEM);
> +		return -ENOMEM;
>   	p->tcfc_refcnt = 1;
>   	if (bind)
>   		p->tcfc_bindcnt = 1;
> @@ -234,17 +249,19 @@ struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
>   					    &p->tcfc_lock, est);
>   		if (err) {
>   			kfree(p);
> -			return ERR_PTR(err);
> +			return err;
>   		}
>   	}
>
>   	a->priv = (void *) p;
> -	return p;
> +	return 0;
>   }
>   EXPORT_SYMBOL(tcf_hash_create);
>
> -void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo)
> +void tcf_hash_insert(struct tc_action *a)
>   {
> +	struct tcf_common *p = a->priv;
> +	struct tcf_hashinfo *hinfo = a->ops->hinfo;
>   	unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
>
>   	spin_lock_bh(&hinfo->lock);
> diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
> index 2210187..f0f6e7a 100644
> --- a/net/sched/act_csum.c
> +++ b/net/sched/act_csum.c
> @@ -48,7 +48,6 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
>   {
>   	struct nlattr *tb[TCA_CSUM_MAX + 1];
>   	struct tc_csum *parm;
> -	struct tcf_common *pc;
>   	struct tcf_csum *p;
>   	int ret = 0, err;
>
> @@ -63,38 +62,31 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
>   		return -EINVAL;
>   	parm = nla_data(tb[TCA_CSUM_PARMS]);
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +	if (!tcf_hash_check(parm->index, a, bind)) {
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
> +		if (ret)
> +			return ret;
>   		ret = ACT_P_CREATED;
>   	} else {
>   		if (bind)/* dont override defaults */
>   			return 0;
> -		tcf_hash_release(pc, bind, a->ops->hinfo);
> +		tcf_hash_release(a, bind);
>   		if (!ovr)
>   			return -EEXIST;
>   	}
>
> -	p = to_tcf_csum(pc);
> +	p = to_tcf_csum(a);
>   	spin_lock_bh(&p->tcf_lock);
>   	p->tcf_action = parm->action;
>   	p->update_flags = parm->update_flags;
>   	spin_unlock_bh(&p->tcf_lock);
>
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>
>   	return ret;
>   }
>
> -static int tcf_csum_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_csum *p = a->priv;
> -	return tcf_hash_release(&p->common, bind, &csum_hash_info);
> -}
> -
>   /**
>    * tcf_csum_skb_nextlayer - Get next layer pointer
>    * @skb: sk_buff to use
> @@ -574,7 +566,7 @@ static struct tc_action_ops act_csum_ops = {
>   	.owner		= THIS_MODULE,
>   	.act		= tcf_csum,
>   	.dump		= tcf_csum_dump,
> -	.cleanup	= tcf_csum_cleanup,
> +	.cleanup	= tcf_hash_release,
>   	.init		= tcf_csum_init,
>   };
>
> diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
> index a0eed30..af6c0ac 100644
> --- a/net/sched/act_gact.c
> +++ b/net/sched/act_gact.c
> @@ -57,7 +57,6 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
>   	struct nlattr *tb[TCA_GACT_MAX + 1];
>   	struct tc_gact *parm;
>   	struct tcf_gact *gact;
> -	struct tcf_common *pc;
>   	int ret = 0;
>   	int err;
>   #ifdef CONFIG_GACT_PROB
> @@ -86,21 +85,20 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
>   	}
>   #endif
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +	if (!tcf_hash_check(parm->index, a, bind)) {
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind);
> +		if (ret)
> +			return ret;
>   		ret = ACT_P_CREATED;
>   	} else {
>   		if (bind)/* dont override defaults */
>   			return 0;
> -		tcf_hash_release(pc, bind, a->ops->hinfo);
> +		tcf_hash_release(a, bind);
>   		if (!ovr)
>   			return -EEXIST;
>   	}
>
> -	gact = to_gact(pc);
> +	gact = to_gact(a);
>
>   	spin_lock_bh(&gact->tcf_lock);
>   	gact->tcf_action = parm->action;
> @@ -113,19 +111,10 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
>   #endif
>   	spin_unlock_bh(&gact->tcf_lock);
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>   	return ret;
>   }
>
> -static int tcf_gact_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_gact *gact = a->priv;
> -
> -	if (gact)
> -		return tcf_hash_release(&gact->common, bind, a->ops->hinfo);
> -	return 0;
> -}
> -
>   static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
>   		    struct tcf_result *res)
>   {
> @@ -196,7 +185,7 @@ static struct tc_action_ops act_gact_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_gact,
>   	.dump		=	tcf_gact_dump,
> -	.cleanup	=	tcf_gact_cleanup,
> +	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_gact_init,
>   };
>
> diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
> index 0a6d621..f5e6978 100644
> --- a/net/sched/act_ipt.c
> +++ b/net/sched/act_ipt.c
> @@ -69,8 +69,9 @@ static void ipt_destroy_target(struct xt_entry_target *t)
>   	module_put(par.target->me);
>   }
>
> -static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
> +static int tcf_ipt_release(struct tc_action *a, int bind)
>   {
> +	struct tcf_ipt *ipt = to_ipt(a);
>   	int ret = 0;
>   	if (ipt) {
>   		if (bind)
> @@ -80,7 +81,7 @@ static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
>   			ipt_destroy_target(ipt->tcfi_t);
>   			kfree(ipt->tcfi_tname);
>   			kfree(ipt->tcfi_t);
> -			tcf_hash_destroy(&ipt->common, &ipt_hash_info);
> +			tcf_hash_destroy(a);
>   			ret = ACT_P_DELETED;
>   		}
>   	}
> @@ -99,7 +100,6 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   {
>   	struct nlattr *tb[TCA_IPT_MAX + 1];
>   	struct tcf_ipt *ipt;
> -	struct tcf_common *pc;
>   	struct xt_entry_target *td, *t;
>   	char *tname;
>   	int ret = 0, err;
> @@ -125,21 +125,20 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   	if (tb[TCA_IPT_INDEX] != NULL)
>   		index = nla_get_u32(tb[TCA_IPT_INDEX]);
>
> -	pc = tcf_hash_check(index, a, bind);
> -	if (!pc) {
> -		pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +	if (!tcf_hash_check(index, a, bind) ) {
> +		ret = tcf_hash_create(index, est, a, sizeof(*ipt), bind);
> +		if (ret)
> +			return ret;
>   		ret = ACT_P_CREATED;
>   	} else {
>   		if (bind)/* dont override defaults */
>   			return 0;
> -		tcf_ipt_release(to_ipt(pc), bind);
> +		tcf_ipt_release(a, bind);
>
>   		if (!ovr)
>   			return -EEXIST;
>   	}
> -	ipt = to_ipt(pc);
> +	ipt = to_ipt(a);
>
>   	hook = nla_get_u32(tb[TCA_IPT_HOOK]);
>
> @@ -170,7 +169,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   	ipt->tcfi_hook  = hook;
>   	spin_unlock_bh(&ipt->tcf_lock);
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>   	return ret;
>
>   err3:
> @@ -178,21 +177,11 @@ err3:
>   err2:
>   	kfree(tname);
>   err1:
> -	if (ret == ACT_P_CREATED) {
> -		if (est)
> -			gen_kill_estimator(&pc->tcfc_bstats,
> -					   &pc->tcfc_rate_est);
> -		kfree_rcu(pc, tcfc_rcu);
> -	}
> +	if (ret == ACT_P_CREATED)
> +		tcf_hash_cleanup(a, est);
>   	return err;
>   }
>
> -static int tcf_ipt_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_ipt *ipt = a->priv;
> -	return tcf_ipt_release(ipt, bind);
> -}
> -
>   static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
>   		   struct tcf_result *res)
>   {
> @@ -289,7 +278,7 @@ static struct tc_action_ops act_ipt_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_ipt,
>   	.dump		=	tcf_ipt_dump,
> -	.cleanup	=	tcf_ipt_cleanup,
> +	.cleanup	=	tcf_ipt_release,
>   	.init		=	tcf_ipt_init,
>   };
>
> @@ -300,7 +289,7 @@ static struct tc_action_ops act_xt_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_ipt,
>   	.dump		=	tcf_ipt_dump,
> -	.cleanup	=	tcf_ipt_cleanup,
> +	.cleanup	=	tcf_ipt_release,
>   	.init		=	tcf_ipt_init,
>   };
>
> diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
> index 0b2c6d3..3edeeca 100644
> --- a/net/sched/act_mirred.c
> +++ b/net/sched/act_mirred.c
> @@ -33,8 +33,9 @@
>   static LIST_HEAD(mirred_list);
>   static struct tcf_hashinfo mirred_hash_info;
>
> -static int tcf_mirred_release(struct tcf_mirred *m, int bind)
> +static int tcf_mirred_release(struct tc_action *a, int bind)
>   {
> +	struct tcf_mirred *m = to_mirred(a);
>   	if (m) {
>   		if (bind)
>   			m->tcf_bindcnt--;
> @@ -43,7 +44,7 @@ static int tcf_mirred_release(struct tcf_mirred *m, int bind)
>   			list_del(&m->tcfm_list);
>   			if (m->tcfm_dev)
>   				dev_put(m->tcfm_dev);
> -			tcf_hash_destroy(&m->common, &mirred_hash_info);
> +			tcf_hash_destroy(a);
>   			return 1;
>   		}
>   	}
> @@ -61,7 +62,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
>   	struct nlattr *tb[TCA_MIRRED_MAX + 1];
>   	struct tc_mirred *parm;
>   	struct tcf_mirred *m;
> -	struct tcf_common *pc;
>   	struct net_device *dev;
>   	int ret, ok_push = 0;
>
> @@ -101,21 +101,20 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
>   		dev = NULL;
>   	}
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> +	if (!tcf_hash_check(parm->index, a, bind)) {
>   		if (dev == NULL)
>   			return -EINVAL;
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*m), bind);
> +		if (ret)
> +			return ret;
>   		ret = ACT_P_CREATED;
>   	} else {
>   		if (!ovr) {
> -			tcf_mirred_release(to_mirred(pc), bind);
> +			tcf_mirred_release(a, bind);
>   			return -EEXIST;
>   		}
>   	}
> -	m = to_mirred(pc);
> +	m = to_mirred(a);
>
>   	spin_lock_bh(&m->tcf_lock);
>   	m->tcf_action = parm->action;
> @@ -131,21 +130,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
>   	spin_unlock_bh(&m->tcf_lock);
>   	if (ret == ACT_P_CREATED) {
>   		list_add(&m->tcfm_list, &mirred_list);
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>   	}
>
>   	return ret;
>   }
>
> -static int tcf_mirred_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_mirred *m = a->priv;
> -
> -	if (m)
> -		return tcf_mirred_release(m, bind);
> -	return 0;
> -}
> -
>   static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
>   		      struct tcf_result *res)
>   {
> @@ -259,7 +249,7 @@ static struct tc_action_ops act_mirred_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_mirred,
>   	.dump		=	tcf_mirred_dump,
> -	.cleanup	=	tcf_mirred_cleanup,
> +	.cleanup	=	tcf_mirred_release,
>   	.init		=	tcf_mirred_init,
>   };
>
> diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
> index 81f0404..ce9a391 100644
> --- a/net/sched/act_nat.c
> +++ b/net/sched/act_nat.c
> @@ -44,7 +44,6 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   	struct tc_nat *parm;
>   	int ret = 0, err;
>   	struct tcf_nat *p;
> -	struct tcf_common *pc;
>
>   	if (nla == NULL)
>   		return -EINVAL;
> @@ -57,20 +56,19 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   		return -EINVAL;
>   	parm = nla_data(tb[TCA_NAT_PARMS]);
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +	if (!tcf_hash_check(parm->index, a, bind)) {
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
> +		if (ret)
> +			return ret;
>   		ret = ACT_P_CREATED;
>   	} else {
>   		if (bind)
>   			return 0;
> -		tcf_hash_release(pc, bind, a->ops->hinfo);
> +		tcf_hash_release(a, bind);
>   		if (!ovr)
>   			return -EEXIST;
>   	}
> -	p = to_tcf_nat(pc);
> +	p = to_tcf_nat(a);
>
>   	spin_lock_bh(&p->tcf_lock);
>   	p->old_addr = parm->old_addr;
> @@ -82,18 +80,11 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
>   	spin_unlock_bh(&p->tcf_lock);
>
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>
>   	return ret;
>   }
>
> -static int tcf_nat_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_nat *p = a->priv;
> -
> -	return tcf_hash_release(&p->common, bind, &nat_hash_info);
> -}
> -
>   static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
>   		   struct tcf_result *res)
>   {
> @@ -298,7 +289,7 @@ static struct tc_action_ops act_nat_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_nat,
>   	.dump		=	tcf_nat_dump,
> -	.cleanup	=	tcf_nat_cleanup,
> +	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_nat_init,
>   };
>
> diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
> index be3f0f6..091ced3 100644
> --- a/net/sched/act_pedit.c
> +++ b/net/sched/act_pedit.c
> @@ -39,7 +39,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
>   	struct tc_pedit *parm;
>   	int ret = 0, err;
>   	struct tcf_pedit *p;
> -	struct tcf_common *pc;
>   	struct tc_pedit_key *keys = NULL;
>   	int ksize;
>
> @@ -57,26 +56,22 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
>   	if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize)
>   		return -EINVAL;
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> +	if (!tcf_hash_check(parm->index, a, bind)) {
>   		if (!parm->nkeys)
>   			return -EINVAL;
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> -		p = to_pedit(pc);
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
> +		if (ret)
> +			return ret;
> +		p = to_pedit(a);
>   		keys = kmalloc(ksize, GFP_KERNEL);
>   		if (keys == NULL) {
> -			if (est)
> -				gen_kill_estimator(&pc->tcfc_bstats,
> -						   &pc->tcfc_rate_est);
> -			kfree_rcu(pc, tcfc_rcu);
> +			tcf_hash_cleanup(a, est);
>   			return -ENOMEM;
>   		}
>   		ret = ACT_P_CREATED;
>   	} else {
> -		p = to_pedit(pc);
> -		tcf_hash_release(pc, bind, a->ops->hinfo);
> +		p = to_pedit(a);
> +		tcf_hash_release(a, bind);
>   		if (bind)
>   			return 0;
>   		if (!ovr)
> @@ -100,7 +95,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
>   	memcpy(p->tcfp_keys, parm->keys, ksize);
>   	spin_unlock_bh(&p->tcf_lock);
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>   	return ret;
>   }
>
> @@ -110,7 +105,7 @@ static int tcf_pedit_cleanup(struct tc_action *a, int bind)
>
>   	if (p) {
>   		struct tc_pedit_key *keys = p->tcfp_keys;
> -		if (tcf_hash_release(&p->common, bind, &pedit_hash_info)) {
> +		if (tcf_hash_release(a, bind)) {
>   			kfree(keys);
>   			return 1;
>   		}
> diff --git a/net/sched/act_police.c b/net/sched/act_police.c
> index 1778209..4695d02 100644
> --- a/net/sched/act_police.c
> +++ b/net/sched/act_police.c
> @@ -253,14 +253,6 @@ failure:
>   	return err;
>   }
>
> -static int tcf_act_police_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_police *p = a->priv;
> -	if (p)
> -		return tcf_hash_release(&p->common, bind, &police_hash_info);
> -	return 0;
> -}
> -
>   static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
>   			  struct tcf_result *res)
>   {
> @@ -362,7 +354,7 @@ static struct tc_action_ops act_police_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_act_police,
>   	.dump		=	tcf_act_police_dump,
> -	.cleanup	=	tcf_act_police_cleanup,
> +	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_act_police_locate,
>   	.walk		=	tcf_act_police_walker
>   };
> diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
> index 8ef2f1f..11c2922 100644
> --- a/net/sched/act_simple.c
> +++ b/net/sched/act_simple.c
> @@ -47,8 +47,9 @@ static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
>   	return d->tcf_action;
>   }
>
> -static int tcf_simp_release(struct tcf_defact *d, int bind)
> +static int tcf_simp_release(struct tc_action *a, int bind)
>   {
> +	struct tcf_defact *d = to_defact(a);
>   	int ret = 0;
>   	if (d) {
>   		if (bind)
> @@ -56,7 +57,7 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
>   		d->tcf_refcnt--;
>   		if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) {
>   			kfree(d->tcfd_defdata);
> -			tcf_hash_destroy(&d->common, &simp_hash_info);
> +			tcf_hash_destroy(a);
>   			ret = 1;
>   		}
>   	}
> @@ -94,7 +95,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
>   	struct nlattr *tb[TCA_DEF_MAX + 1];
>   	struct tc_defact *parm;
>   	struct tcf_defact *d;
> -	struct tcf_common *pc;
>   	char *defdata;
>   	int ret = 0, err;
>
> @@ -114,29 +114,25 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
>   	parm = nla_data(tb[TCA_DEF_PARMS]);
>   	defdata = nla_data(tb[TCA_DEF_DATA]);
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +	if (!tcf_hash_check(parm->index, a, bind)) {
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind);
> +		if (ret)
> +			return ret;
>
> -		d = to_defact(pc);
> +		d = to_defact(a);
>   		ret = alloc_defdata(d, defdata);
>   		if (ret < 0) {
> -			if (est)
> -				gen_kill_estimator(&pc->tcfc_bstats,
> -						   &pc->tcfc_rate_est);
> -			kfree_rcu(pc, tcfc_rcu);
> +			tcf_hash_cleanup(a, est);
>   			return ret;
>   		}
>   		d->tcf_action = parm->action;
>   		ret = ACT_P_CREATED;
>   	} else {
> -		d = to_defact(pc);
> +		d = to_defact(a);
>
>   		if (bind)
>   			return 0;
> -		tcf_simp_release(d, bind);
> +		tcf_simp_release(a, bind);
>   		if (!ovr)
>   			return -EEXIST;
>
> @@ -144,19 +140,10 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
>   	}
>
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>   	return ret;
>   }
>
> -static int tcf_simp_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_defact *d = a->priv;
> -
> -	if (d)
> -		return tcf_simp_release(d, bind);
> -	return 0;
> -}
> -
>   static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
>   			 int bind, int ref)
>   {
> @@ -192,7 +179,7 @@ static struct tc_action_ops act_simp_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_simp,
>   	.dump		=	tcf_simp_dump,
> -	.cleanup	=	tcf_simp_cleanup,
> +	.cleanup	=	tcf_simp_release,
>   	.init		=	tcf_simp_init,
>   };
>
> diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
> index 9872508..71fd2d4 100644
> --- a/net/sched/act_skbedit.c
> +++ b/net/sched/act_skbedit.c
> @@ -65,7 +65,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
>   	struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
>   	struct tc_skbedit *parm;
>   	struct tcf_skbedit *d;
> -	struct tcf_common *pc;
>   	u32 flags = 0, *priority = NULL, *mark = NULL;
>   	u16 *queue_mapping = NULL;
>   	int ret = 0, err;
> @@ -100,19 +99,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
>
>   	parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
>
> -	pc = tcf_hash_check(parm->index, a, bind);
> -	if (!pc) {
> -		pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind);
> -		if (IS_ERR(pc))
> -			return PTR_ERR(pc);
> +	if (!tcf_hash_check(parm->index, a, bind)) {
> +		ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind);
> +		if (ret)
> +			return ret;
>
> -		d = to_skbedit(pc);
> +		d = to_skbedit(a);
>   		ret = ACT_P_CREATED;
>   	} else {
> -		d = to_skbedit(pc);
> +		d = to_skbedit(a);
>   		if (bind)
>   			return 0;
> -		tcf_hash_release(pc, bind, a->ops->hinfo);
> +		tcf_hash_release(a, bind);
>   		if (!ovr)
>   			return -EEXIST;
>   	}
> @@ -132,19 +130,10 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
>   	spin_unlock_bh(&d->tcf_lock);
>
>   	if (ret == ACT_P_CREATED)
> -		tcf_hash_insert(pc, a->ops->hinfo);
> +		tcf_hash_insert(a);
>   	return ret;
>   }
>
> -static int tcf_skbedit_cleanup(struct tc_action *a, int bind)
> -{
> -	struct tcf_skbedit *d = a->priv;
> -
> -	if (d)
> -		return tcf_hash_release(&d->common, bind, &skbedit_hash_info);
> -	return 0;
> -}
> -
>   static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
>   			    int bind, int ref)
>   {
> @@ -191,7 +180,7 @@ static struct tc_action_ops act_skbedit_ops = {
>   	.owner		=	THIS_MODULE,
>   	.act		=	tcf_skbedit,
>   	.dump		=	tcf_skbedit_dump,
> -	.cleanup	=	tcf_skbedit_cleanup,
> +	.cleanup	=	tcf_hash_release,
>   	.init		=	tcf_skbedit_init,
>   };
>
>

^ permalink raw reply

* Re: [RFC 2/2] xen-netback: disable multicast and use a random hw MAC address
From: Wei Liu @ 2014-02-12 12:19 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Ian Campbell, netdev@vger.kernel.org, xen-devel, Paul Durrant,
	Wei Liu, kvm, linux-kernel@vger.kernel.org
In-Reply-To: <CAB=NE6Vu=khpj_3J7r-u8DFkhyC-RgLikNFtOU-WO7te_4HMCw@mail.gmail.com>

On Tue, Feb 11, 2014 at 01:53:26PM -0800, Luis R. Rodriguez wrote:
> Cc'ing kvm folks as they may have a shared interest on the shared
> physical case with the bridge (non NAT).
> 
> On Tue, Feb 11, 2014 at 12:43 AM, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Mon, 2014-02-10 at 14:29 -0800, Luis R. Rodriguez wrote:
> >> From: "Luis R. Rodriguez" <mcgrof@suse.com>
> >>
> >> Although the xen-netback interfaces do not participate in the
> >> link as a typical Ethernet device interfaces for them are
> >> still required under the current archtitecture. IPv6 addresses
> >> do not need to be created or assigned on the xen-netback interfaces
> >> however, even if the frontend devices do need them, so clear the
> >> multicast flag to ensure the net core does not initiate IPv6
> >> Stateless Address Autoconfiguration.
> >
> > How does disabling SAA flow from the absence of multicast?
> 
> See patch 1 in this series [0], but I explain the issue I see with
> this on the cover letter [1]. In summary the RFCs on IPv6 make it
> clear you need multicast for Stateless address autoconfiguration
> (SLAAC is the preferred acronym) and DAD, however the net core has not
> made this a requirement, and hence the patch. The caveat which I
> address on the cover letter needs to be seriously considered though.
> 
> [0] http://marc.info/?l=linux-netdev&m=139207142110535&w=2
> [1] http://marc.info/?l=linux-netdev&m=139207142110536&w=2
> 
> > Surely these should be controlled logically independently even if there is some
> > notional linkage.
> 
> When a node hops on a network it will query its network by sending a
> router solicitation multicast request for its configuration
> parameters, the router can respond with router advertisements to
> disable SLAAC.
> 
> Apart from that we have no other means to disable SLAAC neatly, and as
> I gather that would be counter to the IPv6 RFCs anyway, and that makes
> sense.
> 
> > Can SAA not be disabled directly?
> 
> Nope. The ipv6 core assumes all device want ipv6 and this is done upon
> netdev registration, and as I noted on my patch 1 description --
> although ipv6 supports a module parameter to disable autoconfiguration
> RFC4682 Section 5.4 makes it clear that DAD *MUST* be performed on all

FWIW: RFC4862 :-)

You had the same typo in patch 1.

Wei.

^ permalink raw reply

* Re: [PATCH] xfrm: avoid creating temporary SA when there are no listeners
From: Steffen Klassert @ 2014-02-12 12:09 UTC (permalink / raw)
  To: Horia Geanta; +Cc: David S. Miller, netdev
In-Reply-To: <1390986731-12861-1-git-send-email-horia.geanta@freescale.com>

On Wed, Jan 29, 2014 at 11:12:11AM +0200, Horia Geanta wrote:
> In the case when KMs have no listeners, km_query() will fail and
> temporary SAs are garbage collected immediately after their allocation.
> This causes strain on memory allocation, leading even to OOM since
> temporary SA alloc/free cycle is performed for every packet
> and garbage collection does not keep up the pace.
> 
> The sane thing to do is to make sure we have audience before
> temporary SA allocation.
> 
> Signed-off-by: Horia Geanta <horia.geanta@freescale.com>

After merging net-next into ipsec-next, I get a build failure
when I apply your patch. Please rebase onto ipsec-next current.

Thanks!

^ permalink raw reply

* Re: [PATCHv5 net-next 0/6] xfrm: Add ESN support for AH
From: Steffen Klassert @ 2014-02-12 12:06 UTC (permalink / raw)
  To: Fan Du; +Cc: davem, netdev
In-Reply-To: <1390010068-15715-1-git-send-email-fan.du@windriver.com>

On Sat, Jan 18, 2014 at 09:54:22AM +0800, Fan Du wrote:
> Hi,
> 
> This is initial Extended Sequence Number support for AH based on IPv4/6.
> The rationale is totally by the RFC 4302, which states:
> 
> 3.3.3.2.2.  Implicit Packet Padding and ESN
> 
>    If the ESN option is elected for an SA, then the high-order 32 bits
>    of the ESN must be included in the ICV computation.  For purposes of
>    ICV computation, these bits are appended (implicitly) immediately
>    after the end of the payload, and before any implicit packet padding.
> 
> So we attach the high-order 32bits as a scatterlist right after the packet
> payload to compute ICV value. 
> 
> Test:
> I add a knob in iproute2/ip/xfrm_state.c to enable esn when setting SA,
> which make it possible to test with-esn and without-esn scenarios, both
> cases works ok with ping using packetsize(-s) from default to 32768. 
> 
> v2:
>   - Patch3/5 and Patch4/5 add IPv6 part as requested by Steffen.
>   - Patch5/5 restrict ESN feature only to ESP and AH.
> v3:
>   - Fix double parens spotted by Sergei, and thanks for reporting.
> v4:
>   - Incorperate feedbacks from Steffen by simplify the code flow.
>   - Add Patch1/6 to introduce skb_to_sgvec_nomark
>   - Patch2/6 remove rebundant inclusion crypto/scatterwalk.h
> v5:
>   - Before calling type 'input' method, XFRM_SKB_CB(skb)->seq.input.hi
>     has already been set in network byte order in xfrm_input, so no
>     need to change the byte once in type 'input' method. So fix
>     Patch3/6 and Patch5/6.
> 
> 
> Fan Du (6):
>   skbuff: Introduce skb_to_sgvec_nomark to map skb without mark new end
>   {IPv4,xfrm} Add ESN support for AH egress part
>   {IPv4,xfrm} Add ESN support for AH ingress part
>   {IPv6,xfrm} Add ESN support for AH egress part
>   {IPv6,xfrm} Add ESN support for AH ingress part
>   xfrm: Don't prohibit AH from using ESN feature
> 

All applied to ipsec-next, thanks a lot for your work Fan!

^ permalink raw reply

* Re: [BUG] at include/linux/page-flags.h:415 (PageTransHuge)
From: Daniel Borkmann @ 2014-02-12 12:02 UTC (permalink / raw)
  To: Vlastimil Babka, Andrew Morton, linux-kernel, Michel Lespinasse,
	linux-mm, Jared Hulbert, netdev, Thomas Hellstrom,
	John David Anglin, HATAYAMA Daisuke, Konstantin Khlebnikov,
	Carsten Otte, Peter Zijlstra
In-Reply-To: <20140207185816.GA7764@order.stressinduktion.org>

Hi Vlastimil,

On 02/07/2014 07:58 PM, Hannes Frederic Sowa wrote:
> On Fri, Jan 31, 2014 at 03:40:38PM +0100, Vlastimil Babka wrote:
>> From: Vlastimil Babka <vbabka@suse.cz>
>> Date: Fri, 31 Jan 2014 11:50:21 +0100
>> Subject: [PATCH] mm: include VM_MIXEDMAP flag in the VM_SPECIAL list to avoid
>>   m(un)locking
>>
>> Daniel Borkmann reported a bug with VM_BUG_ON assertions failing where
>> munlock_vma_pages_range() thinks it's unexpectedly in the middle of a THP page.
>> This can be reproduced in tools/testing/selftests/net/ by running make and
>> then ./psock_tpacket.
>>
>> The problem is that an order=2 compound page (allocated by
>> alloc_one_pg_vec_page() is part of the munlocked VM_MIXEDMAP vma (mapped by
>> packet_mmap()) and mistaken for a THP page and assumed to be order=9.
>>
>> The checks for THP in munlock came with commit ff6a6da60b89 ("mm: accelerate
>> munlock() treatment of THP pages"), i.e. since 3.9, but did not trigger a bug.
>> It just makes munlock_vma_pages_range() skip such compound pages until the next
>> 512-pages-aligned page, when it encounters a head page. This is however not a
>> problem for vma's where mlocking has no effect anyway, but it can distort the
>> accounting.
>> Since commit 7225522bb ("mm: munlock: batch non-THP page isolation and
>> munlock+putback using pagevec") this can trigger a VM_BUG_ON in PageTransHuge()
>> check.
>>
>> This patch fixes the issue by adding VM_MIXEDMAP flag to VM_SPECIAL - a list of
>> flags that make vma's non-mlockable and non-mergeable. The reasoning is that
>> VM_MIXEDMAP vma's are similar to VM_PFNMAP, which is already on the VM_SPECIAL
>> list, and both are intended for non-LRU pages where mlocking makes no sense
>> anyway.

Thanks a lot for your efforts.

Is your patch queued up somewhere for mainline and stable?

> I also ran into this problem and wanted to ask what the status of this
> patch is? Does it need further testing? I can surely help with that. ;)
>
> Thanks,
>
>    Hannes
>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH net] virtio-net: alloc big buffers also when guest can receive UFO
From: Michael S. Tsirkin @ 2014-02-12 11:59 UTC (permalink / raw)
  To: Jason Wang
  Cc: virtio-dev, netdev, linux-kernel, virtualization,
	Sridhar Samudrala
In-Reply-To: <1392183808-16789-1-git-send-email-jasowang@redhat.com>

On Wed, Feb 12, 2014 at 01:43:28PM +0800, Jason Wang wrote:
> We should alloc big buffers also when guest can receive UFO
> pakcets. Otherwise the big packets will be truncated when mergeable rx
> buffer is disabled.

Not truncated, they will be dropped.

> Fixes 5c5167515d80f78f6bb538492c423adcae31ad65
> (virtio-net: Allow UFO feature to be set and advertised.)
>
> Cc: Rusty Russell <rusty@rustcorp.com.au>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Sridhar Samudrala <sri@us.ibm.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>

Acked-by: Michael S. Tsirkin <mst@redhat.com>

for patch but please fix commit message.


> ---
>  drivers/net/virtio_net.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index d75f8ed..5632a99 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -1711,7 +1711,8 @@ static int virtnet_probe(struct virtio_device *vdev)
>  	/* If we can receive ANY GSO packets, we must allocate large ones. */
>  	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
>  	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
> -	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
> +	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
> +	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
>  		vi->big_packets = true;
>  
>  	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
> -- 
> 1.8.3.2

^ permalink raw reply

* Re: [PATCH v3 2/2] sctp: optimize the sctp_sysctl_net_register
From: Neil Horman @ 2014-02-12 11:53 UTC (permalink / raw)
  To: Wang Weidong; +Cc: davem, vyasevich, dborkman, sergei.shtylyov, netdev
In-Reply-To: <1392169484-8256-3-git-send-email-wangweidong1@huawei.com>

On Wed, Feb 12, 2014 at 09:44:44AM +0800, Wang Weidong wrote:
> Here, when the net is init_net, we needn't to kmemdup the ctl_table
> again. So add a check for net. Also we can save some memory.
> 
> Signed-off-by: Wang Weidong <wangweidong1@huawei.com>
> ---
>  net/sctp/sysctl.c | 17 ++++++++++-------
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
> index d354de5..35c8923 100644
> --- a/net/sctp/sysctl.c
> +++ b/net/sctp/sysctl.c
> @@ -402,15 +402,18 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
>  
>  int sctp_sysctl_net_register(struct net *net)
>  {
> -	struct ctl_table *table;
> -	int i;
> +	struct ctl_table *table = sctp_net_table;
> +
> +	if (!net_eq(net, &init_net)) {
> +		int i;
>  
> -	table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
> -	if (!table)
> -		return -ENOMEM;
> +		table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL);
> +		if (!table)
> +			return -ENOMEM;
>  
> -	for (i = 0; table[i].data; i++)
> -		table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
> +		for (i = 0; table[i].data; i++)
> +			table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp;
> +	}
>  
In the first version of this patch you complained about a lockdep issue.  Did
you figure out what that was, and if it related to these changes?

Neil

^ permalink raw reply

* Re: [PATCH net] vhost_net: do not report a used len larger than receive buffer size
From: Michael S. Tsirkin @ 2014-02-12 11:52 UTC (permalink / raw)
  To: Jason Wang; +Cc: virtio-dev, netdev, linux-kernel, kvm, virtualization
In-Reply-To: <1392184666-17616-1-git-send-email-jasowang@redhat.com>

On Wed, Feb 12, 2014 at 01:57:46PM +0800, Jason Wang wrote:
> Currently, even if the packet were truncated by lower socket, we still
> report the packet size as the used len which may confuse guest
> driver. Fixes this by returning the size of guest receive buffer instead.
> 
> Fixes 3a4d5c94e959359ece6d6b55045c3f046677f55c
> (vhost_net: a kernel-level virtio server)
> 
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>

As discussed off-line:

NAK

and a fixed version will be sent.

> ---
>  drivers/vhost/net.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 9a68409..06268a0 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -525,7 +525,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
>  		++headcount;
>  		seg += in;
>  	}
> -	heads[headcount - 1].len += datalen;
> +	if (likely(datalen < 0))
> +		heads[headcount - 1].len += datalen;
>  	*iovcount = seg;
>  	if (unlikely(log))
>  		*log_num = nlogs;
> -- 
> 1.8.3.2

^ permalink raw reply

* Re: [Patch net-next v2] net: allow setting mac address of loopback device
From: Neil Horman @ 2014-02-12 11:50 UTC (permalink / raw)
  To: Cong Wang
  Cc: netdev, Hannes Frederic Sowa, Stephen Hemminger, Eric Dumazet,
	David S. Miller
In-Reply-To: <1392168086-25607-1-git-send-email-xiyou.wangcong@gmail.com>

On Tue, Feb 11, 2014 at 05:21:26PM -0800, Cong Wang wrote:
> We are trying to mirror the local traffic from lo to eth0,
> allowing setting mac address of lo to eth0 would make
> the ether addresses in these packets correct, so that
> we don't have to modify the ether header again.
> 
> Since usually no one cares about its mac address (all-zero),
> it is safe to allow those who care to set its mac address.
> 
> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org>
> Cc: Neil Horman <nhorman@tuxdriver.com>
> Cc: Stephen Hemminger <stephen@networkplumber.org>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> 
Acked-by: Neil Horman <nhorman@tuxdriver.com>

> ---
> diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
> index c5011e0..e7c1d5f 100644
> --- a/drivers/net/loopback.c
> +++ b/drivers/net/loopback.c
> @@ -160,6 +160,7 @@ static const struct net_device_ops loopback_ops = {
>  	.ndo_init      = loopback_dev_init,
>  	.ndo_start_xmit= loopback_xmit,
>  	.ndo_get_stats64 = loopback_get_stats64,
> +	.ndo_set_mac_address = eth_mac_addr,
>  };
>  
>  /*
> @@ -174,6 +175,7 @@ static void loopback_setup(struct net_device *dev)
>  	dev->tx_queue_len	= 0;
>  	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
>  	dev->flags		= IFF_LOOPBACK;
> +	dev->priv_flags		|= IFF_LIVE_ADDR_CHANGE;
>  	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
>  	dev->hw_features	= NETIF_F_ALL_TSO | NETIF_F_UFO;
>  	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
> 

^ permalink raw reply

* Re: [net-next 3/3] cfg80211: add MPLS and 802.21 classification
From: Joe Perches @ 2014-02-12 11:49 UTC (permalink / raw)
  To: Simon Wunderlich; +Cc: netdev, davem, linux-wireless, mathias.kretschmer
In-Reply-To: <1392202386-8826-4-git-send-email-sw@simonwunderlich.de>

On Wed, 2014-02-12 at 11:53 +0100, Simon Wunderlich wrote:
> MPLS labels may contain traffic control information, which should be
> evaluated and used by the wireless subsystem if present.

trivial notes:

> diff --git a/net/wireless/util.c b/net/wireless/util.c
[]
> @@ -11,6 +11,7 @@
>  #include <net/ip.h>
>  #include <net/dsfield.h>
>  #include <linux/if_vlan.h>
> +#include <uapi/linux/mpls.h>

Please try not to #include uapi files.

> @@ -710,6 +711,29 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
>  			return vlan_priority;
>  	}
>  
> +	if (skb_headlen(skb) >= sizeof(struct ethhdr)) {
> +		struct ethhdr *eh = (struct ethhdr *) skb->data;
> +		struct mpls_label_stack mpls_tmp, *mpls;
> +
> +		switch (eh->h_proto) {
> +		case __constant_htons(ETH_P_MPLS_UC):
> +		case __constant_htons(ETH_P_MPLS_MC):

__constant_ isn't necessary for these labels.

>  	switch (skb->protocol) {
>  	case htons(ETH_P_IP):
>  		dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;

like this, just case htons(ETH_<FOO>) is enough.

^ permalink raw reply

* Re: Experimental Privacy Functions and TCP SYN Payloads
From: Daniel Borkmann @ 2014-02-12 11:35 UTC (permalink / raw)
  To: Quinn Wood; +Cc: linux-kernel, netdev
In-Reply-To: <CAM83q7AiCBc5qSH18KhBHYknYf67Pnjkd3JUbC_WrBwefxHJMg@mail.gmail.com>

(please cc netdev)

On 02/12/2014 11:25 AM, Quinn Wood wrote:
> If program on host A spoofs the source address of an outgoing IPv4 packet then
> places that address in the first 32 bits of a UDP payload, a program on host B
> that is aware of these behaviors can still reply to the program on host A. [1]
>
> Continuing with this approach the program on host A could encrypt the UDP pay-
> load in a way that the program on host B can decrypt, and effectively reduce
> the ability of others in the wide network to passively determine who host A is
> sending transmissions to while simultaneously ensuring the program on host B
> can respond to the program on host A. [2]
>
> I'm uncertain how to proceed if I want to use TCP for stateful connections.
> The requirement of a handshake before data is handed off to the program means
> this approach won't work out of the box. I'm looking for any insight folks may
> have regarding this.
>
> My original approach to the handshake included setting one of the reserved
> bits in the TCP header to indicate the first 32 bits of the payload were the
> real source address. However this would be reliant on SYN packets containing
> a payload. Does the Linux kernel allow this?
>
> -
>
> [1] Barring any non store-and-forward network behavior like dropping packets
>      with questionable source addresses. Considering recent NTP-related  news
>      this seems to be a not-entirely common activity :)
> [2] This is of course reliant on both programs knowing the proper key for the
>      other.

^ permalink raw reply

* Re: [RFC 2/2] xen-netback: disable multicast and use a random hw MAC address
From: Ian Campbell @ 2014-02-12 11:15 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: netdev@vger.kernel.org, xen-devel, Paul Durrant, Wei Liu, kvm,
	linux-kernel@vger.kernel.org
In-Reply-To: <CAB=NE6Vu=khpj_3J7r-u8DFkhyC-RgLikNFtOU-WO7te_4HMCw@mail.gmail.com>

On Tue, 2014-02-11 at 13:53 -0800, Luis R. Rodriguez wrote:
> Cc'ing kvm folks as they may have a shared interest on the shared
> physical case with the bridge (non NAT).
> 
> On Tue, Feb 11, 2014 at 12:43 AM, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> > On Mon, 2014-02-10 at 14:29 -0800, Luis R. Rodriguez wrote:
> >> From: "Luis R. Rodriguez" <mcgrof@suse.com>
> >>
> >> Although the xen-netback interfaces do not participate in the
> >> link as a typical Ethernet device interfaces for them are
> >> still required under the current archtitecture. IPv6 addresses
> >> do not need to be created or assigned on the xen-netback interfaces
> >> however, even if the frontend devices do need them, so clear the
> >> multicast flag to ensure the net core does not initiate IPv6
> >> Stateless Address Autoconfiguration.
> >
> > How does disabling SAA flow from the absence of multicast?
> 
> See patch 1 in this series [0], but I explain the issue I see with
> this on the cover letter [1].

Oop, I felt like I'd missed some context. Thanks for pointing out that
it was right under my nose.

> In summary the RFCs on IPv6 make it
> clear you need multicast for Stateless address autoconfiguration
> (SLAAC is the preferred acronym) and DAD,

That seems reasonable, but I think is the opposite to what I was trying
to get at.

Why is it not possible to disable SLAAC and/or DAD even if multicast is
present?

IOW -- enabling/disabling multicast seems to me to be an odd proxy for
disabling SLAAC or DAD and AIUI your patch fixes the opposite case,
which is to avoid SLAAC and DAD on interfaces which don't do multicast
(which makes sense since those protocols involve multicast).

>  however the net core has not
> made this a requirement, and hence the patch. The caveat which I
> address on the cover letter needs to be seriously considered though.
> 
> [0] http://marc.info/?l=linux-netdev&m=139207142110535&w=2
> [1] http://marc.info/?l=linux-netdev&m=139207142110536&w=2
> 
> > Surely these should be controlled logically independently even if there is some
> > notional linkage.
> 
> When a node hops on a network it will query its network by sending a
> router solicitation multicast request for its configuration
> parameters, the router can respond with router advertisements to
> disable SLAAC.

Surely it should be possible for an interface to be explicitly not ipv6
enabled, in which case it doesn't want to do any solicitation at all.

> Apart from that we have no other means to disable SLAAC neatly, and as
> I gather that would be counter to the IPv6 RFCs anyway, and that makes
> sense.

In your[0] post you say:
        it should be noted that RFC4682 Section 5.4
        makes it clear that DAD *MUST* be performed on all unicast
        addresses prior to assigning them to an interface

is that what you mean by counter to the RFCs?

In my reading this "must do DAD" requirement only comes into affect if
you are trying to assign a unicast address to an interface. It should be
possible to simply not do that for an interface.

> > Can SAA not be disabled directly?
> 
> Nope. The ipv6 core assumes all device want ipv6

IMHO it is entirely reasonable for an admin to desire that an interface
has nothing at all to do with IPv6. At which point all of the
requirements for multicast which flow from enabling IPv6 disappear.

> >>  since using this can create an issue if a user
> >> decides to enable multicast on the backend interfaces
> >
> > Please explain what this issue is.
> 
> I explained this on the cover letter but should have elaborated more
> here. The *known* and *reported* issue is that xen-backend interfaces
> can end up  SLAAC and you'd obviously end up in some situations where
> the MAC address and IP address clash, despite the architecture of IPv6
> to randomize time requests for neighbor solicitations, and DAD.
> Ultimately a series of services can end up filling your log messages
> with tons of warnings.

Right, this makes sense, but it seems like the solution should be to
stop SLAAC from happening directly and not by playing tricks with
multicast that happen to have the side effect of disabling SLAAC.

> Another not reported issue, but I suspect critical and it can bite
> both xen and kvm in the ass is described on Appendex A on RFC 4862 [2]
> which considers the issues of getting duplicates of packets on the
> same link with the same link layer address. I think to address that we
> can also consider dev->type into all the different cases.

We should never actually be generating any traffic with this address
FWIW, all the generated traffic will have the guest's actual MAC. (at
least in the bridging case, perhaps with with routing or NAT things are
different, but I think in that case the traffic would appear to come
from the hosts outgoing interface, not the vif device)

> My preference, rather than trying to simply disable ipv6 is actually
> seeing how xen-netback interfaces (and kvm TAP topology) can be
> simplified further). As I see it there is tons of code which could
> trigger being used on these xen-netback interfaces (and TAP for kvm)
> which is simply not needed for the use case of just doing sending data
> back and forth between host and guest: ipv6 is not needed at all, and
> I tried to test removing ipv4, but ran into issues.

Bridging is not the only way to provide VM network connectivity. It
should also be possible to do routing and even NAT by configuring
appropriate p2p links and routing tables in the host. For that to work I
think the tap and vif devices do need some sort of IPv[46] capability,
so you can't just nuke that stuff completely. (Maybe/likely it also
requires them to have a sensible MAC address, I'm not sure).

> [2] http://tools.ietf.org/html/rfc4862#appendix-A
> [3[ https://gitorious.org/opensuse/kernel-source/source/8e16582178a29b03e850468004a47e7be5ed3005:patches.xen/ipv6-no-autoconf
> 
> > Also how can a user enable multicast on the b/e?
> 
> ip set multicast on dev <devname>
> ip set multicast off dev <devname>
> 
> > AFAIK only Solaris ever
> > implemented the m/c bits of the Xen PV network protocol (not that I
> > wouldn't welcome attempts to add it to other platforms)
> 
> Do you mean kernel configuration multicast ? Or networking ?

I meant the PV protocol extension which allows guests (netfront) to
register to receive multicast frames across the PV ring -- i.e. for
multicast to work from the guests PoV.

(maybe that was just an optimisation though and the default is to flood
everything, it was a long time ago)

Ian.

^ permalink raw reply

* [PATCH net-next] ipv6: do not set "u" bit for temporary addresses
From: Florent Fourcot @ 2014-02-12 11:08 UTC (permalink / raw)
  To: netdev; +Cc: Florent Fourcot

The bit 6 of interface identifier was before the "universal/local bit",
indicating local significance only. This rule is now obsoleted by the
RFC 7136, removing all significance of bits in interface identifier.

The new rule is "In all cases, the bits in an IID have no generic
semantics; in other words, they have opaque values.", so we can remove
the setting of bit 6, it will improve the entropy of random addresses.

Signed-off-by: Florent Fourcot <florent.fourcot@enst-bretagne.fr>
---
 net/ipv6/addrconf.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index ad23569..0b2a18e 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1878,7 +1878,6 @@ static void __ipv6_regen_rndid(struct inet6_dev *idev)
 {
 regen:
 	get_random_bytes(idev->rndid, sizeof(idev->rndid));
-	idev->rndid[0] &= ~0x02;
 
 	/*
 	 * <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
-- 
1.8.5.3

^ permalink raw reply related

* [net-next 3/3] cfg80211: add MPLS and 802.21 classification
From: Simon Wunderlich @ 2014-02-12 10:53 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh,
	Simon Wunderlich
In-Reply-To: <1392202386-8826-1-git-send-email-sw-2YrNx6rUIHYiY0qSoAWiAoQuADTiUCJX@public.gmane.org>

MPLS labels may contain traffic control information, which should be
evaluated and used by the wireless subsystem if present.

Also check for IEEE 802.21 which is always network control traffic.

Signed-off-by: Simon Wunderlich <sw-2YrNx6rUIHYiY0qSoAWiAoQuADTiUCJX@public.gmane.org>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh@public.gmane.org>
---
 net/wireless/util.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/net/wireless/util.c b/net/wireless/util.c
index d39c371..98e3b11 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -11,6 +11,7 @@
 #include <net/ip.h>
 #include <net/dsfield.h>
 #include <linux/if_vlan.h>
+#include <uapi/linux/mpls.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -710,6 +711,29 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
 			return vlan_priority;
 	}
 
+	if (skb_headlen(skb) >= sizeof(struct ethhdr)) {
+		struct ethhdr *eh = (struct ethhdr *) skb->data;
+		struct mpls_label_stack mpls_tmp, *mpls;
+
+		switch (eh->h_proto) {
+		case __constant_htons(ETH_P_MPLS_UC):
+		case __constant_htons(ETH_P_MPLS_MC):
+			/* MPLS */
+			mpls = skb_header_pointer(skb, sizeof(*eh),
+						  sizeof(*mpls), &mpls_tmp);
+			if (!mpls)
+				break;
+
+			return (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
+				>> MPLS_LS_TC_SHIFT;
+		case __constant_htons(ETH_P_80221):
+			/* 802.21 is always network control traffic */
+			return 7;
+		default:
+			break;
+		}
+	}
+
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
 		dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [net-next 2/3] UAPI: add MPLS label stack definition
From: Simon Wunderlich @ 2014-02-12 10:53 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh,
	Simon Wunderlich
In-Reply-To: <1392202386-8826-1-git-send-email-sw-2YrNx6rUIHYiY0qSoAWiAoQuADTiUCJX@public.gmane.org>

Labels for the Multiprotocol Label Switching are defined in RFC 3032
which was superseded by RFC 5462. Add the definition to UAPI.

Signed-off-by: Simon Wunderlich <sw-2YrNx6rUIHYiY0qSoAWiAoQuADTiUCJX@public.gmane.org>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh@public.gmane.org>
---
 include/uapi/linux/mpls.h |   34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 include/uapi/linux/mpls.h

diff --git a/include/uapi/linux/mpls.h b/include/uapi/linux/mpls.h
new file mode 100644
index 0000000..15c8260
--- /dev/null
+++ b/include/uapi/linux/mpls.h
@@ -0,0 +1,34 @@
+#ifndef _UAPI_MPLS_H
+#define _UAPI_MPLS_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+/* Reference: RFC 5462, RFC 3032
+ *
+ *  0                   1                   2                   3
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                Label                  | TC  |S|       TTL     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *	Label:  Label Value, 20 bits
+ *	TC:     Traffic Class field, 3 bits
+ *	S:      Bottom of Stack, 1 bit
+ *	TTL:    Time to Live, 8 bits
+ */
+
+struct mpls_label_stack {
+	__be32 entry;
+};
+
+#define MPLS_LS_LABEL_MASK      0xFFFFF000
+#define MPLS_LS_LABEL_SHIFT     12
+#define MPLS_LS_TC_MASK         0x00000E00
+#define MPLS_LS_TC_SHIFT        9
+#define MPLS_LS_S_MASK          0x00000100
+#define MPLS_LS_S_SHIFT         8
+#define MPLS_LS_TTL_MASK        0x000000FF
+#define MPLS_LS_TTL_SHIFT       0
+
+#endif /* _UAPI_MPLS_H */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [net-next 1/3] if_ether.h: add IEEE 802.21 Ethertype
From: Simon Wunderlich @ 2014-02-12 10:53 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh,
	Simon Wunderlich
In-Reply-To: <1392202386-8826-1-git-send-email-sw-2YrNx6rUIHYiY0qSoAWiAoQuADTiUCJX@public.gmane.org>

Add the Ethertype for IEEE Std 802.21 - Media Independent Handover
Protocol. This Ethertype is used for network control messages.

Signed-off-by: Simon Wunderlich <sw-2YrNx6rUIHYiY0qSoAWiAoQuADTiUCJX@public.gmane.org>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh@public.gmane.org>
---
 include/uapi/linux/if_ether.h |    1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
index 2ce0f6a..2e27208 100644
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -89,6 +89,7 @@
 #define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
 #define ETH_P_TDLS	0x890D          /* TDLS */
 #define ETH_P_FIP	0x8914		/* FCoE Initialization Protocol */
+#define ETH_P_80221	0x8917		/* IEEE 802.21 Media Independent Handover Protocol */
 #define ETH_P_QINQ1	0x9100		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ3	0x9300		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [net-next 0/3] 802.21 and MPLS headers and classification
From: Simon Wunderlich @ 2014-02-12 10:53 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	mathias.kretschmer-8LS2qeF34IpklNlQbfROjRvVK+yQ3ZXh,
	Simon Wunderlich

Hi,

this series contains a header file proposal for MPLS labels. These
labels do not seem to be properly defined in the kernel so far. We are
developing a wired/wireless 802.21/MPLS switch and need to check the
MPLS labels to use the traffic control info for transmissions over
802.11 networks.

Please let me know if I should send these patches to somewhere else - I
can certainly resend the 3rd patch to linux-wireless separately but
figured it would be better like this to keep the context.

Thanks,
     Simon

Simon Wunderlich (3):
  if_ether.h: add IEEE 802.21 Ethertype
  UAPI: add MPLS label stack definition
  cfg80211: add MPLS and 802.21 classification

 include/uapi/linux/if_ether.h |    1 +
 include/uapi/linux/mpls.h     |   34 ++++++++++++++++++++++++++++++++++
 net/wireless/util.c           |   24 ++++++++++++++++++++++++
 3 files changed, 59 insertions(+)
 create mode 100644 include/uapi/linux/mpls.h

-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 09/28] Remove ATHEROS_AR231X
From: Sergey Ryazanov @ 2014-02-12 10:50 UTC (permalink / raw)
  To: John W. Linville
  Cc: Oleksij Rempel, Richard Weinberger, Jonathan Bither,
	OpenWrt Development List, Hauke Mehrtens, Jiri Slaby,
	Nick Kossifidis, Luis R. Rodriguez,
	open list:ATHEROS ATH5K WIR..., open list:ATHEROS ATH5K WIR...,
	open, list@hauke-m.de:NETWORKING DRIVERS, open list,
	antonynpavlov@gmail.com, Florian Fainelli
In-Reply-To: <CAHNKnsRACSo=DfOyiHxqV3acv_wfZmz4tMnYAW0wo4OCibwdfA@mail.gmail.com>

2014-02-11 3:43 GMT+04:00 Sergey Ryazanov <ryazanov.s.a@gmail.com>:
> 2014-02-11 2:37 GMT+04:00 Florian Fainelli <florian@openwrt.org>:
>> 2014-02-10 4:38 GMT-08:00 Sergey Ryazanov <ryazanov.s.a@gmail.com>:
>>> 2014-02-10 16:17 GMT+04:00 Oleksij Rempel <linux@rempel-privat.de>:
>>>> Am 10.02.2014 13:05, schrieb Sergey Ryazanov:
>>>>> 2014-02-10 0:03 GMT+04:00 Richard Weinberger <richard@nod.at>:
>>>>>> Am 09.02.2014 20:18, schrieb Hauke Mehrtens:
>>>>>>> On 02/09/2014 07:47 PM, Richard Weinberger wrote:
>>>>>>>> The symbol is an orphan, get rid of it.
>>>>>>>>
>>>>>>>> Signed-off-by: Richard Weinberger <richard@nod.at>
>>>>>>>> ---
>>>>>>>>  drivers/net/wireless/ath/ath5k/Kconfig | 10 +++++-----
>>>>>>>>  drivers/net/wireless/ath/ath5k/ath5k.h | 28 ----------------------------
>>>>>>>>  drivers/net/wireless/ath/ath5k/base.c  | 14 --------------
>>>>>>>>  drivers/net/wireless/ath/ath5k/led.c   |  7 -------
>>>>>>>>  4 files changed, 5 insertions(+), 54 deletions(-)
>>>>>>>>
>>>>>>>
>>>>>>> This code is used in OpenWrt with an out of tree arch code for the
>>>>>>> Atheros 231x/531x SoC. [0] I do not think anyone is working on adding
>>>>>>> this code to mainline Linux kernel, because of lack of time/interest.
>>>>>>
>>>>>> Sorry, we don't maintain out of tree code.
>>>>>>
>>>>>
>>>>> Oleksij, Jonathan do you still working to make ar231x devices work
>>>>> with upstream, since your posts [1, 2]? Or may be someone from OpenWRT
>>>>> team would like to add upstream support?
>>>>>
>>>>> 1. https://lkml.org/lkml/2013/5/13/321
>>>>> 2. https://lkml.org/lkml/2013/5/13/358
>>>>>
>>>>
>>>> Hi,
>>>> my current target was to provide barebox and openocd support.
>>>> - ar2313 is already upstream on barebox.
>>>> - ar2315-2318 (barebox) awaiting review by Anthony Pavlov.
>>>> - openocd (EJTAG) support is ready and i'll push it ASUP.
>>>>
>>> WOW, Impressive.
>>
>> That's a nice toy project, although since there are is an existing
>> bootloader with sources, I would have shifted the priority towards
>> getting the kernel support merged such that the bootloader can be used
>> for something. BTW I sent a few devices to Jonathan, not sure if he
>> ever got those...
>>
>>>
>>>> I hope Jonathan do kernel part. If not, i can provide some work, since i
>>>> have testing boards and expiriance on this hardware.
>>>>
>>> If you need, I can test kernel part, or even do some porting work. I
>>> have some AR231x based boards, e.g. Ubnt LS2 and NS2.
>>
>> I guess you could start splitting the OpenWrt patches into a format
>> that makes them suitable for being merged upstream and starting with
>> the MIPS parts. There might be a bunch of checkpatch.pl cleanup work
>> to do before getting those submitted.
>
> I will do that if Jonathan does not have a working solution, which he
> would like to push upstream. So, let's wait for his reply.
>

John, can you delay the merging of this patch for a few months, I will
try to prepare the necessary patches to add AR231x architecture to the
kernel and send them to linux-mips.

-- 
BR,
Sergey

^ permalink raw reply

* [PATCH 3/3] be2net: refactor multi-channel config code for Skyhawk-R chip
From: Somnath Kotur @ 2014-02-12 10:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, Vasundhara Volam, Sathya Perla, Somnath Kotur

From: Vasundhara Volam <vasundhara.volam@emulex.com>

Currently multi-channel configuration is read via the QUERY_FW_CONFIG cmd.
This method has been deprecated by the Skyhawk-R FW. Instead,
GET_PROFILE_CONFIG::port-desc must be used to query this configuration.

This patch also:
a) introduces a few macros to identify certain categories of multi-channel
configs
2) re-factors the be_cmd_set_profile_config() code to be able to read any kind
of desc (and not just the nic-desc.)

Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be.h      |   12 +++-
 drivers/net/ethernet/emulex/benet/be_cmds.c |   20 ++++++
 drivers/net/ethernet/emulex/benet/be_cmds.h |   36 +++++++++---
 drivers/net/ethernet/emulex/benet/be_hw.h   |    4 +-
 drivers/net/ethernet/emulex/benet/be_main.c |   87 ++++++++++++++++++++------
 5 files changed, 127 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 6c05f57..a150401 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -88,7 +88,6 @@ static inline char *nic_name(struct pci_dev *pdev)
 #define BE_MIN_MTU		256
 
 #define BE_NUM_VLANS_SUPPORTED	64
-#define BE_UMC_NUM_VLANS_SUPPORTED	15
 #define BE_MAX_EQD		128u
 #define	BE_MAX_TX_FRAG_COUNT	30
 
@@ -293,7 +292,7 @@ struct be_rx_compl_info {
 	u8 ip_csum;
 	u8 l4_csum;
 	u8 ipv6;
-	u8 vtm;
+	u8 qnq;
 	u8 pkt_type;
 	u8 ip_frag;
 };
@@ -465,6 +464,7 @@ struct be_adapter {
 
 	u32 port_num;
 	bool promiscuous;
+	u8 mc_type;
 	u32 function_mode;
 	u32 function_caps;
 	u32 rx_fc;		/* Rx flow control */
@@ -534,6 +534,14 @@ static inline u16 be_max_qs(struct be_adapter *adapter)
 	return min_t(u16, num, num_online_cpus());
 }
 
+/* Is BE in pvid_tagging mode */
+#define be_pvid_tagging_enabled(adapter)	(adapter->pvid)
+
+/* Is BE in QNQ multi-channel mode */
+#define be_is_qnq_mode(adapter)		(adapter->mc_type == FLEX10 ||  \
+					 adapter->mc_type == vNIC1 ||	\
+					 adapter->mc_type == UFP)
+
 #define lancer_chip(adapter)	(adapter->pdev->device == OC_DEVICE_ID3 || \
 				 adapter->pdev->device == OC_DEVICE_ID4)
 
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index a8106b3..72bde5d 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -3296,6 +3296,21 @@ static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf,
 	return NULL;
 }
 
+static struct be_port_res_desc *be_get_port_desc(u8 *buf, u32 desc_count)
+{
+	struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf;
+	int i;
+
+	for (i = 0; i < desc_count; i++) {
+		if (hdr->desc_type == PORT_RESOURCE_DESC_TYPE_V1)
+			return (struct be_port_res_desc *)hdr;
+
+		hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0;
+		hdr = (void *)hdr + hdr->desc_len;
+	}
+	return NULL;
+}
+
 static void be_copy_nic_desc(struct be_resources *res,
 			     struct be_nic_res_desc *desc)
 {
@@ -3439,6 +3454,7 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 {
 	struct be_cmd_resp_get_profile_config *resp;
 	struct be_pcie_res_desc *pcie;
+	struct be_port_res_desc *port;
 	struct be_nic_res_desc *nic;
 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	struct be_dma_mem cmd;
@@ -3466,6 +3482,10 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 	if (pcie)
 		res->max_vfs = le16_to_cpu(pcie->num_vfs);
 
+	port = be_get_port_desc(resp->func_param, desc_count);
+	if (port)
+		adapter->mc_type = port->mc_type;
+
 	nic = be_get_nic_desc(resp->func_param, desc_count);
 	if (nic)
 		be_copy_nic_desc(res, nic);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 3959566..d0ab980 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1098,14 +1098,6 @@ struct be_cmd_resp_query_fw_cfg {
 	u32 function_caps;
 };
 
-/* Is BE in a multi-channel mode */
-static inline bool be_is_mc(struct be_adapter *adapter)
-{
-	return adapter->function_mode & FLEX10_MODE ||
-		adapter->function_mode & VNIC_MODE ||
-		adapter->function_mode & UMC_ENABLED;
-}
-
 /******************** RSS Config ****************************************/
 /* RSS type		Input parameters used to compute RX hash
  * RSS_ENABLE_IPV4	SRC IPv4, DST IPv4
@@ -1828,6 +1820,7 @@ struct be_cmd_req_set_ext_fat_caps {
 #define NIC_RESOURCE_DESC_TYPE_V0		0x41
 #define PCIE_RESOURCE_DESC_TYPE_V1		0x50
 #define NIC_RESOURCE_DESC_TYPE_V1		0x51
+#define PORT_RESOURCE_DESC_TYPE_V1		0x55
 #define MAX_RESOURCE_DESC			264
 
 /* QOS unit number */
@@ -1891,6 +1884,33 @@ struct be_nic_res_desc {
 	u32 rsvd8[7];
 } __packed;
 
+/************ Multi-Channel type ***********/
+enum mc_type {
+	MC_NONE = 0x01,
+	UMC = 0x02,
+	FLEX10 = 0x03,
+	vNIC1 = 0x04,
+	nPAR = 0x05,
+	UFP = 0x06,
+	vNIC2 = 0x07
+};
+
+struct be_port_res_desc {
+	struct be_res_desc_hdr hdr;
+	u8 rsvd0;
+	u8 flags;
+	u8 rsvd1;
+	u8 mc_type;
+	u16 rsvd2;
+	u32 rsvd3[20];
+} __packed;
+
+/* Is BE in a multi-channel mode */
+static inline bool be_is_mc(struct be_adapter *adapter)
+{
+	return adapter->mc_type > MC_NONE;
+}
+
 struct be_cmd_req_get_func_config {
 	struct be_cmd_req_hdr hdr;
 };
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index effa272..28ac8dd 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -368,7 +368,7 @@ struct amap_eth_rx_compl_v0 {
 	u8 numfrags[3];		/* dword 1 */
 	u8 rss_flush;		/* dword 2 */
 	u8 cast_enc[2];		/* dword 2 */
-	u8 vtm;			/* dword 2 */
+	u8 qnq;			/* dword 2 */
 	u8 rss_bank;		/* dword 2 */
 	u8 rsvd1[23];		/* dword 2 */
 	u8 lro_pkt;		/* dword 2 */
@@ -401,7 +401,7 @@ struct amap_eth_rx_compl_v1 {
 	u8 numfrags[3];		/* dword 1 */
 	u8 rss_flush;		/* dword 2 */
 	u8 cast_enc[2];		/* dword 2 */
-	u8 vtm;			/* dword 2 */
+	u8 qnq;			/* dword 2 */
 	u8 rss_bank;		/* dword 2 */
 	u8 port[2];		/* dword 2 */
 	u8 vntagp;		/* dword 2 */
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 816d67b..a8cf03e 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -945,9 +945,9 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
 	}
 
 	/* If vlan tag is already inlined in the packet, skip HW VLAN
-	 * tagging in UMC mode
+	 * tagging in pvid-tagging mode
 	 */
-	if ((adapter->function_mode & UMC_ENABLED) &&
+	if (be_pvid_tagging_enabled(adapter) &&
 	    veh->h_vlan_proto == htons(ETH_P_8021Q))
 			*skip_hw_vlan = true;
 
@@ -1660,7 +1660,7 @@ static void be_parse_rx_compl_v1(struct be_eth_rx_compl *compl,
 	rxcp->rss_hash =
 		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, rsshash, compl);
 	if (rxcp->vlanf) {
-		rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm,
+		rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, qnq,
 					  compl);
 		rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
 					       compl);
@@ -1690,7 +1690,7 @@ static void be_parse_rx_compl_v0(struct be_eth_rx_compl *compl,
 	rxcp->rss_hash =
 		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, rsshash, compl);
 	if (rxcp->vlanf) {
-		rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm,
+		rxcp->qnq = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, qnq,
 					  compl);
 		rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
 					       compl);
@@ -1723,9 +1723,11 @@ static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
 		rxcp->l4_csum = 0;
 
 	if (rxcp->vlanf) {
-		/* vlanf could be wrongly set in some cards.
-		 * ignore if vtm is not set */
-		if ((adapter->function_mode & FLEX10_MODE) && !rxcp->vtm)
+		/* In QNQ modes, if qnq bit is not set, then the packet was
+		 * tagged only with the transparent outer vlan-tag and must
+		 * not be treated as a vlan packet by host
+		 */
+		if (be_is_qnq_mode(adapter) && !rxcp->qnq)
 			rxcp->vlanf = 0;
 
 		if (!lancer_chip(adapter))
@@ -3109,6 +3111,22 @@ err:
 	return status;
 }
 
+/* Converting function_mode bits on BE3 to SH mc_type enums */
+
+static u8 be_convert_mc_type(u32 function_mode)
+{
+	if (function_mode & VNIC_MODE && function_mode & FLEX10_MODE)
+		return vNIC1;
+	else if (function_mode & FLEX10_MODE)
+		return FLEX10;
+	else if (function_mode & VNIC_MODE)
+		return vNIC2;
+	else if (function_mode & UMC_ENABLED)
+		return UMC;
+	else
+		return MC_NONE;
+}
+
 /* On BE2/BE3 FW does not suggest the supported limits */
 static void BEx_get_resources(struct be_adapter *adapter,
 			      struct be_resources *res)
@@ -3129,12 +3147,23 @@ static void BEx_get_resources(struct be_adapter *adapter,
 	else
 		res->max_uc_mac = BE_VF_UC_PMAC_COUNT;
 
-	if (adapter->function_mode & FLEX10_MODE)
-		res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
-	else if (adapter->function_mode & UMC_ENABLED)
-		res->max_vlans = BE_UMC_NUM_VLANS_SUPPORTED;
-	else
+	adapter->mc_type = be_convert_mc_type(adapter->function_mode);
+
+	if (be_is_mc(adapter)) {
+		/* Assuming that there are 4 channels per port,
+		 * when multi-channel is enabled
+		 */
+		if (be_is_qnq_mode(adapter))
+			res->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+		else
+			/* In a non-qnq multichannel mode, the pvid
+			 * takes up one vlan entry
+			 */
+			res->max_vlans = (BE_NUM_VLANS_SUPPORTED / 4) - 1;
+	} else {
 		res->max_vlans = BE_NUM_VLANS_SUPPORTED;
+	}
+
 	res->max_mcast_mac = BE_MAX_MC;
 
 	/* For BE3 1Gb ports, F/W does not properly support multiple TXQs */
@@ -4417,14 +4446,32 @@ static bool be_reset_required(struct be_adapter *adapter)
 
 static char *mc_name(struct be_adapter *adapter)
 {
-	if (adapter->function_mode & FLEX10_MODE)
-		return "FLEX10";
-	else if (adapter->function_mode & VNIC_MODE)
-		return "vNIC";
-	else if (adapter->function_mode & UMC_ENABLED)
-		return "UMC";
-	else
-		return "";
+	char *str = "";	/* default */
+
+	switch (adapter->mc_type) {
+	case UMC:
+		str = "UMC";
+		break;
+	case FLEX10:
+		str = "FLEX10";
+		break;
+	case vNIC1:
+		str = "vNIC-1";
+		break;
+	case nPAR:
+		str = "nPAR";
+		break;
+	case UFP:
+		str = "UFP";
+		break;
+	case vNIC2:
+		str = "vNIC-2";
+		break;
+	default:
+		str = "";
+	}
+
+	return str;
 }
 
 static inline char *func_name(struct be_adapter *adapter)
-- 
1.5.6.1

^ permalink raw reply related

* [PATCH 2/3] be2net: Update copyright year
From: Somnath Kotur @ 2014-02-12 10:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, Vasundhara Volam, Sathya Perla, Somnath Kotur

From: Vasundhara Volam <vasundhara.volam@emulex.com>

Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be.h         |    2 +-
 drivers/net/ethernet/emulex/benet/be_cmds.c    |    2 +-
 drivers/net/ethernet/emulex/benet/be_cmds.h    |    2 +-
 drivers/net/ethernet/emulex/benet/be_ethtool.c |    2 +-
 drivers/net/ethernet/emulex/benet/be_hw.h      |    2 +-
 drivers/net/ethernet/emulex/benet/be_main.c    |    2 +-
 drivers/net/ethernet/emulex/benet/be_roce.c    |    2 +-
 drivers/net/ethernet/emulex/benet/be_roce.h    |    2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 8d09615..6c05f57 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 48076a6..a8106b3 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index fc4e076..3959566 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index e775ba0..507177a 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index dc88782..effa272 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 7057545..816d67b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c
index 9cd5415..a5dae4a 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.c
+++ b/drivers/net/ethernet/emulex/benet/be_roce.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
diff --git a/drivers/net/ethernet/emulex/benet/be_roce.h b/drivers/net/ethernet/emulex/benet/be_roce.h
index 2cd1129..a3ef8f8 100644
--- a/drivers/net/ethernet/emulex/benet/be_roce.h
+++ b/drivers/net/ethernet/emulex/benet/be_roce.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2013 Emulex
+ * Copyright (C) 2005 - 2014 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
-- 
1.5.6.1

^ permalink raw reply related

* [PATCH 1/3] be2net: Log a kernel message when UE is detected in BE & Skyhawk
From: Somnath Kotur @ 2014-02-12 10:37 UTC (permalink / raw)
  To: netdev; +Cc: davem, Somnath Kotur

This patch logs a kernel message when a HW error(SLIPORT_ERROR in Lancer and UE
in BEx/Skyhawk) is detected. The log message for BE3 was missing earlier.
This patch also refactors the code by segregating error-detection and reporting
code for Lancer and BEx/SH.

Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com>
---
 drivers/net/ethernet/emulex/benet/be_main.c |   82 +++++++++++++-------------
 1 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 04ac9c6..7057545 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2423,6 +2423,9 @@ void be_detect_error(struct be_adapter *adapter)
 	u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0;
 	u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
 	u32 i;
+	bool error_detected = false;
+	struct device *dev = &adapter->pdev->dev;
+	struct net_device *netdev = adapter->netdev;
 
 	if (be_hw_error(adapter))
 		return;
@@ -2434,6 +2437,21 @@ void be_detect_error(struct be_adapter *adapter)
 					SLIPORT_ERROR1_OFFSET);
 			sliport_err2 = ioread32(adapter->db +
 					SLIPORT_ERROR2_OFFSET);
+			adapter->hw_error = true;
+			/* Do not log error messages if its a FW reset */
+			if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
+			    sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
+				dev_info(dev, "Firmware update in progress\n");
+			} else {
+				error_detected = true;
+				dev_err(dev, "Error detected in the card\n");
+				dev_err(dev, "ERR: sliport status 0x%x\n",
+					sliport_status);
+				dev_err(dev, "ERR: sliport error1 0x%x\n",
+					sliport_err1);
+				dev_err(dev, "ERR: sliport error2 0x%x\n",
+					sliport_err2);
+			}
 		}
 	} else {
 		pci_read_config_dword(adapter->pdev,
@@ -2447,51 +2465,33 @@ void be_detect_error(struct be_adapter *adapter)
 
 		ue_lo = (ue_lo & ~ue_lo_mask);
 		ue_hi = (ue_hi & ~ue_hi_mask);
-	}
-
-	/* On certain platforms BE hardware can indicate spurious UEs.
-	 * Allow the h/w to stop working completely in case of a real UE.
-	 * Hence not setting the hw_error for UE detection.
-	 */
-	if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
-		adapter->hw_error = true;
-		/* Do not log error messages if its a FW reset */
-		if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
-		    sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
-			dev_info(&adapter->pdev->dev,
-				 "Firmware update in progress\n");
-			return;
-		} else {
-			dev_err(&adapter->pdev->dev,
-				"Error detected in the card\n");
-		}
-	}
 
-	if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
-		dev_err(&adapter->pdev->dev,
-			"ERR: sliport status 0x%x\n", sliport_status);
-		dev_err(&adapter->pdev->dev,
-			"ERR: sliport error1 0x%x\n", sliport_err1);
-		dev_err(&adapter->pdev->dev,
-			"ERR: sliport error2 0x%x\n", sliport_err2);
-	}
-
-	if (ue_lo) {
-		for (i = 0; ue_lo; ue_lo >>= 1, i++) {
-			if (ue_lo & 1)
-				dev_err(&adapter->pdev->dev,
-				"UE: %s bit set\n", ue_status_low_desc[i]);
-		}
-	}
+		/* On certain platforms BE hardware can indicate spurious UEs.
+		 * Allow HW to stop working completely in case of a real UE.
+		 * Hence not setting the hw_error for UE detection.
+		 */
 
-	if (ue_hi) {
-		for (i = 0; ue_hi; ue_hi >>= 1, i++) {
-			if (ue_hi & 1)
-				dev_err(&adapter->pdev->dev,
-				"UE: %s bit set\n", ue_status_hi_desc[i]);
+		if (ue_lo || ue_hi) {
+			error_detected = true;
+			dev_err(dev,
+				"Unrecoverable Error detected in the adapter");
+			dev_err(dev, "Please reboot server to recover");
+			if (skyhawk_chip(adapter))
+				adapter->hw_error = true;
+			for (i = 0; ue_lo; ue_lo >>= 1, i++) {
+				if (ue_lo & 1)
+					dev_err(dev, "UE: %s bit set\n",
+						ue_status_low_desc[i]);
+			}
+			for (i = 0; ue_hi; ue_hi >>= 1, i++) {
+				if (ue_hi & 1)
+					dev_err(dev, "UE: %s bit set\n",
+						ue_status_hi_desc[i]);
+			}
 		}
 	}
-
+	if (error_detected)
+		netif_carrier_off(netdev);
 }
 
 static void be_msix_disable(struct be_adapter *adapter)
-- 
1.5.6.1

^ permalink raw reply related

* [PATCH net-next] be2net patches
From: Somnath Kotur @ 2014-02-12 10:37 UTC (permalink / raw)
  To: netdev; +Cc: davem, Somnath Kotur

Please apply.

Somnath Kotur (1):
  be2net: This patch logs a kernel message when a HW
    error(SLIPORT_ERROR in Lancer and UE in BEx/Skyhawk)

Vasundhara Volam (2):
  be2net: Update copyright year
  be2net: refactor multi-channel config code for Skyhawk-R chip

 drivers/net/ethernet/emulex/benet/be.h         |   14 ++-
 drivers/net/ethernet/emulex/benet/be_cmds.c    |   22 +++-
 drivers/net/ethernet/emulex/benet/be_cmds.h    |   38 ++++--
 drivers/net/ethernet/emulex/benet/be_ethtool.c |    2 +-
 drivers/net/ethernet/emulex/benet/be_hw.h      |    6 +-
 drivers/net/ethernet/emulex/benet/be_main.c    |  171 +++++++++++++++---------
 drivers/net/ethernet/emulex/benet/be_roce.c    |    2 +-
 drivers/net/ethernet/emulex/benet/be_roce.h    |    2 +-
 8 files changed, 176 insertions(+), 81 deletions(-)

^ permalink raw reply

* pull-request: can 2014-02-12
From: Marc Kleine-Budde @ 2014-02-12 10:35 UTC (permalink / raw)
  To: netdev; +Cc: davem, linux-can, kernel

Hello David,

this is a pull request with one patch for net/master, for the current release
cycle. Olivier Sobrie noticed and fixed that the kvaser_usb driver doesn't
check the number of channels value from the hardware, which may result in
writing over the bounds of an array in the driver.

regards,
Marc

---

The following changes since commit 738b52bb9845da183b6ff46a8f685b56a63379d1:

  Merge tag 'microblaze-3.14-rc3' of git://git.monstr.eu/linux-2.6-microblaze (2014-02-11 12:24:35 -0800)

are available in the git repository at:


  git://gitorious.org/linux-can/linux-can.git tags/linux-can-fixes-for-3.14-20140212

for you to fetch changes up to 862474f8b46f6c1e600d4934e40ba40646c696ec:

  can: kvaser_usb: check number of channels returned by HW (2014-02-12 10:42:02 +0100)

----------------------------------------------------------------
linux-can-fixes-for-3.14-20140212

----------------------------------------------------------------
Olivier Sobrie (1):
      can: kvaser_usb: check number of channels returned by HW

 drivers/net/can/usb/kvaser_usb.c | 2 ++
 1 file changed, 2 insertions(+)

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox