From patchwork Mon Jun 18 08:20:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 930738 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="HiNeV625"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 418PDZ5lcLz9s3M for ; Mon, 18 Jun 2018 18:20:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935722AbeFRIUo (ORCPT ); Mon, 18 Jun 2018 04:20:44 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:36353 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935702AbeFRIUm (ORCPT ); Mon, 18 Jun 2018 04:20:42 -0400 Received: by mail-wr0-f195.google.com with SMTP id f16-v6so15812218wrm.3 for ; Mon, 18 Jun 2018 01:20:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=8WKqy/eUv2jgprnldyxacJrOgkcRTox7UkebCZQzRJw=; b=HiNeV625xlVadGpl+oK4qzBL9MRz/LJxkcigaNmrC0uE+qDRomlNt8Nu8ok6FMTWi8 syhBT5xRVtKbb9yvSzbVg7wzV1xtvceU+ZPfjAvQMMkKmS6ZOcN/ALdsOr/CFDrawcHr eH9XJo9qr/yeLiww3iz3KykeSl+T4wZpDxZheXJqDidTYl0QVwW/Pm5rBTcwy4L65JY1 Aysem5CYV4ijTuxNUf2EnmViXx+g+dD4S5JfbFFNGobbCNbDkoCKvm5ML1rKF2Wx83Fk 6dBLNZnV6KyNYWxwqQE02WWD7Ev/JLvCxfT43D8wBCq27QwRkR6/1VKkwkm+GTzB7nfi hDxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=8WKqy/eUv2jgprnldyxacJrOgkcRTox7UkebCZQzRJw=; b=Y9skkgtKRtsqr7E4Ola4K+gwKjxp3BQzw2hoZ1VjMNVwULOscLleJYW17N9+Og6RWg HXtwJSg1f1tS184Lv5WD5ZTC7Yf1uuO4wfwLnSPlENrkV8TM5X6lYXzHQOGtXLfngc5k cDesIgmhMjV/2zk+TggM1vXHuysCR5bmctu3JRR1PcN+UxcncdeCuzRHfexye8KgrL9S uUzoeoVChLmkoZSzfFxk8HlAFO+KNSGpcAU+HHw8BmDwJuxyAYFkNm1T0NVcLbPVGWEm X8l+BdTzdjdPPhqOI/ko8hs1z8jsT97oY+BONcemHAKny5HdxryJadJcgBcechpeqcuo FjaA== X-Gm-Message-State: APt69E2/edxW4JCvoTqduKcAQVNBwZ5qckYPVw91PoL0f8KppmdZDCDA du44Upy4Z4QxoOK2SHPftpc2Fpxl X-Google-Smtp-Source: ADUXVKLCf6RWUHpXj8BVulBzRzzJMRnjp2mgCCMhs9XAW3YS07T0px52++i8WuGBFpTPemhpa+IhGg== X-Received: by 2002:adf:a54a:: with SMTP id j10-v6mr10222755wrb.155.1529310040660; Mon, 18 Jun 2018 01:20:40 -0700 (PDT) Received: from ubuntu.localdomain (dhcp102.vr.in-berlin.de. [217.197.81.102]) by smtp.gmail.com with ESMTPSA id h193-v6sm12422363wmd.25.2018.06.18.01.20.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 18 Jun 2018 01:20:39 -0700 (PDT) From: Yi-Hung Wei To: netfilter-devel@vger.kernel.org Cc: Yi-Hung Wei , Florian Westphal Subject: [RFC nf-next 3/7] netfilter: nf_conncount: Early exit in nf_conncount_lookup() and cleanup Date: Mon, 18 Jun 2018 01:20:11 -0700 Message-Id: <1529310015-14507-4-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1529310015-14507-1-git-send-email-yihung.wei@gmail.com> References: <1529310015-14507-1-git-send-email-yihung.wei@gmail.com> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org From: Florian Westphal This patch does the following three tasks. It applies the same early exit technique for nf_conncount_lookup(). Since now we keep the number of connections in 'struct nf_conncount_list', we no longer need to return the count in nf_conncount_lookup(). Moreover, we expose the garbage collection function nf_conncount_gc_list() for nft_connlimit. Signed-off-by: Florian Westphal Signed-off-by: Yi-Hung Wei --- include/net/netfilter/nf_conntrack_count.h | 11 ++++++---- net/netfilter/nf_conncount.c | 34 ++++++++++++++++++------------ net/netfilter/nft_connlimit.c | 9 ++++---- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfilter/nf_conntrack_count.h index e4884e0e4f69..dbec17f674b7 100644 --- a/include/net/netfilter/nf_conntrack_count.h +++ b/include/net/netfilter/nf_conntrack_count.h @@ -21,10 +21,10 @@ unsigned int nf_conncount_count(struct net *net, const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_zone *zone); -unsigned int nf_conncount_lookup(struct net *net, struct nf_conncount_list *list, - const struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_zone *zone, - bool *addit); +void nf_conncount_lookup(struct net *net, struct nf_conncount_list *list, + const struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_zone *zone, + bool *addit); void nf_conncount_list_init(struct nf_conncount_list *list); @@ -32,6 +32,9 @@ bool nf_conncount_add(struct nf_conncount_list *list, const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_zone *zone); +void nf_conncount_gc_list(struct net *net, + struct nf_conncount_list *list); + void nf_conncount_cache_free(struct nf_conncount_list *list); #endif diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c index 6eb52c2332bd..6e77b2a2f851 100644 --- a/net/netfilter/nf_conncount.c +++ b/net/netfilter/nf_conncount.c @@ -111,24 +111,29 @@ static void conn_free(struct nf_conncount_list *list, kmem_cache_free(conncount_conn_cachep, conn); } -unsigned int nf_conncount_lookup(struct net *net, - struct nf_conncount_list *list, - const struct nf_conntrack_tuple *tuple, - const struct nf_conntrack_zone *zone, - bool *addit) +void nf_conncount_lookup(struct net *net, + struct nf_conncount_list *list, + const struct nf_conntrack_tuple *tuple, + const struct nf_conntrack_zone *zone, + bool *addit) { const struct nf_conntrack_tuple_hash *found; struct nf_conncount_tuple *conn, *conn_n; struct nf_conn *found_ct; - unsigned int length = 0; + unsigned int collect = 0; + /* best effort only */ *addit = tuple ? true : false; /* check the saved connections */ list_for_each_entry_safe(conn, conn_n, &list->head, node) { + if (collect > CONNCOUNT_GC_MAX_NODES) + break; + found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple); if (found == NULL) { conn_free(list, conn); + collect++; continue; } @@ -137,9 +142,10 @@ unsigned int nf_conncount_lookup(struct net *net, if (tuple && nf_ct_tuple_equal(&conn->tuple, tuple) && nf_ct_zone_equal(found_ct, zone, zone->dir)) { /* - * Just to be sure we have it only once in the list. * We should not see tuples twice unless someone hooks * this into a table without "-p tcp --syn". + * + * Attempt to avoid a re-add in this case. */ *addit = false; } else if (already_closed(found_ct)) { @@ -149,14 +155,12 @@ unsigned int nf_conncount_lookup(struct net *net, */ nf_ct_put(found_ct); conn_free(list, conn); + collect++; continue; } nf_ct_put(found_ct); - length++; } - - return length; } EXPORT_SYMBOL_GPL(nf_conncount_lookup); @@ -167,8 +171,8 @@ void nf_conncount_list_init(struct nf_conncount_list *list) } EXPORT_SYMBOL_GPL(nf_conncount_list_init); -static void nf_conncount_gc_list(struct net *net, - struct nf_conncount_list *list) +void nf_conncount_gc_list(struct net *net, + struct nf_conncount_list *list) { const struct nf_conntrack_tuple_hash *found; struct nf_conncount_tuple *conn, *conn_n; @@ -200,6 +204,7 @@ static void nf_conncount_gc_list(struct net *net, return; } } +EXPORT_SYMBOL_GPL(nf_conncount_gc_list); static void tree_nodes_free(struct rb_root *root, struct nf_conncount_rb *gc_nodes[], @@ -247,8 +252,9 @@ count_tree(struct net *net, struct rb_root *root, /* same source network -> be counted! */ unsigned int count; - count = nf_conncount_lookup(net, &rbconn->list, tuple, - zone, &addit); + nf_conncount_lookup(net, &rbconn->list, tuple, zone, + &addit); + count = rbconn->list.count; tree_nodes_free(root, gc_nodes, gc_count); if (!addit) diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c index 4f0491a36a1d..37c52ae06741 100644 --- a/net/netfilter/nft_connlimit.c +++ b/net/netfilter/nft_connlimit.c @@ -46,8 +46,9 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv, } spin_lock_bh(&priv->lock); - count = nf_conncount_lookup(nft_net(pkt), &priv->list, tuple_ptr, zone, - &addit); + nf_conncount_lookup(nft_net(pkt), &priv->list, tuple_ptr, zone, + &addit); + count = priv->list.count; if (!addit) goto out; @@ -231,10 +232,10 @@ static void nft_connlimit_destroy_clone(const struct nft_ctx *ctx, static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr) { struct nft_connlimit *priv = nft_expr_priv(expr); - bool addit, ret; + bool ret; spin_lock_bh(&priv->lock); - nf_conncount_lookup(net, &priv->list, NULL, &nf_ct_zone_dflt, &addit); + nf_conncount_gc_list(net, &priv->list); ret = list_empty(&priv->list.head); spin_unlock_bh(&priv->lock);