Re: [PATCH 1/2] netfilter: add extended accounting infrastructure over nfnetlink

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Dec 14, 2011 at 05:31:07PM +0100, Patrick McHardy wrote:
> On 14.12.2011 14:18, Pablo Neira Ayuso wrote:
> > On Wed, Dec 14, 2011 at 12:23:21PM +0100, Patrick McHardy wrote:
> > [...]
> >>> +nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
> >>> +	     const struct nlmsghdr *nlh, const struct nlattr * const tb[])
> >>> +{
> >>> +	int ret;
> >>> +	struct nf_acct *acct, *matching = NULL;
> >>> +	char *acct_name;
> >>> +
> >>> +	if (!tb[NFACCT_NAME])
> >>> +		return -EINVAL;
> >>> +
> >>> +	acct_name = nla_data(tb[NFACCT_NAME]);
> >>> +
> >>> +	rcu_read_lock();
> >>> +	list_for_each_entry(acct,&nfnl_acct_list, head) {
> >>
> >> I don't really get the locking concept. All netlink operations happen under
> >> the nfnl mutex, so using RCU for the lookup shouldn't be necessary
> >> (applied to all netlink operations).
> > 
> > If you add one iptables rule with NFACCT, you have to iterate over the
> > list (without the mutex). Very unlikely, but we may delete one
> > accounting object via nfnetlink at the same time of adding the rule
> > that refers to it.
> 
> Sure. But we don't need it for any of the netlink operations.

Indeed. I have removed all rcu_read_[un]lock in the list iterations of
the netlink operations.

> >>> +        }
> >>> +	rcu_read_unlock();
> >>> +
> >>> +	acct = kzalloc(sizeof(struct nf_acct), GFP_KERNEL);
> >>> +	if (acct == NULL) {
> >>> +		ret = -ENOMEM;
> >>> +		goto err;
> >>> +	}
> >>> +	spin_lock_init(&acct->lock);
> >>> +	strncpy(acct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX);
> >>> +	if (tb[NFACCT_BYTES])
> >>> +		acct->bytes = be64_to_cpu(nla_get_u64(tb[NFACCT_BYTES]));
> >>> +	if (tb[NFACCT_PKTS])
> >>> +		acct->pkts = be64_to_cpu(nla_get_u64(tb[NFACCT_PKTS]));
> >>> +
> >>> +	atomic_inc(&acct->refcnt);
> >>> +
> >>> +	/* We are protected by nfnl mutex. */
> >>> +	if (matching) {
> >>
> >> This seems to be a replace operation, so I think you should
> >> require NLM_F_REPLACE. Also it seems you could just
> >> reinitialize the existing counter instead of unconditionally
> >> allocating a new one.
> > 
> > I think it's easier to return -EBUSY as you suggested.
> 
> That was for deletion. For addition supporting replace is fine, but
> we should use the correct netlink flags.

This is what I'm doing now in this case:

        if (matching) {
                if (nlh->nlmsg_flags & NLM_F_REPLACE) {
                        /* reset counters if you request a replacement. */
                        atomic64_set(&cur->pkts, 0);
                        atomic64_set(&cur->bytes, 0);
                        return 0;
                }
                        return -EBUSY;
        }

before that code (in the lookup) you have:

                if (nlh->nlmsg_flags & NLM_F_EXCL)
                        return -EEXIST;

So basically, if one object already exists and you try to create it:

1) with NLM_F_EXCL, you hit EEXIST.

1) with MLM_F_REPLACE, it sets counters to zero.

2) without NLM_F_EXCL and NLM_F_REPLACE, you hit EBUSY.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux