From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pg1-f198.google.com (mail-pg1-f198.google.com [209.85.215.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6342F4AC17C for ; Wed, 2 Sep 2026 20:37:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.198 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788381474; cv=none; b=DuaXhCO+hEKlmLcwsNRCXnrVmn6u4o2jBPZDfw+Qs8hfFjmcurTAcgy95+PB3qOsvevJP6WVeqy+ciiwpDWdufjjeJqW6GN0tRF05HIHRTXAYnyGO6+15m0/Z1OaffdQCh50rvi/pNs1BIwA5mlfq0HjTKgKHHC6lTzFKyFpOIs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788381474; c=relaxed/simple; bh=07CeeMsjaKhkGLnXX+1rkSmvKDcqKhorTSpdmWzSDHk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=rcUy0zJzmRyADCz+azwqO3hMtBEG99h7ALBjqFckNbZyV2r5opbGujrt4GhwSENiFhg3h471gSCNdf6cF9dN6ARMYvOhb/WQ2aSYZemxB8J9b3gIUG7bbQukvnBwpsY2Go5BKwrp1Vq3B5zOhi4w6FNTyz4/omLlekwUuaPIZS4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--kuniyu.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=WrUYSBjz; arc=none smtp.client-ip=209.85.215.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--kuniyu.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="WrUYSBjz" Received: by mail-pg1-f198.google.com with SMTP id 41be03b00d2f7-cb6cf425e86so1988536a12.1 for ; Wed, 02 Sep 2026 13:37:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1788381470; x=1788986270; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=A25udRpUEIahmOg/9D+IpoWeNqcb0HHaMxUuhLI3Idk=; b=WrUYSBjzEjSNNsX+s+nATak8JiP5GOazVicN+5z+Z8bKJavgwKYV0SsVOwQEcyKHK3 6jU31SHqvBnetYiF+4DiOPaumkynO7Vs9mNAiP4Rwp4koepDYdBAfgo8izXLRqd7iwg7 RN+EivzoDT8j27hQ5ay67ji49hLuLiJeXYKE+hNX2zOr3m8oFWMBYIEEMfn2aabVD+E/ fJez1fKpHrd42JyGzRn7OJ0eVgX+ZYWuafFpB4/jD1PAEBunehQS415bhKp+96olGZ5u IyQLgcznzFkjB9VW0WWY8m3Xx5qd9gggg8twZEMHXD98eLU/VbfkdOKElBX79cS+7i+3 AEJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788381470; x=1788986270; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=A25udRpUEIahmOg/9D+IpoWeNqcb0HHaMxUuhLI3Idk=; b=g668MHuHJJs/zNXF4k39uONN9q1YwkIyvAo/wqnp+V+2RxKB/qydQPd2E4EAO+/ear mC3gDbBBp/HK4w/55lsAh0CNO8/O10j6tzqf6l0cJXUISoecjmREIzY90GO8+tuhsq23 DWZvZlGtHOiECOZ6EuEJ7ZICdKMmvZQTYh+Zq6Y0m8WYgzZCs8X1nCIRyHxAO7oaolMj cAOUrFWYwOdicfCs+4UB4NB6WZYjZSgQTphaeazWDPUhJGXNGvvJkIjZ4k5x5Z65/mQR Fa+S09kFhqxlHhr+Gn0NrTfNUyZ0LPS/Z4n9WtVmfce/JARZPFZl5wRww32QJcliHZTu +f2Q== X-Forwarded-Encrypted: i=1; AKwUvBxEcFQ95jDJf46SDys49wg03M3Fzjcc7mTvs/9Z8zo1gVT72lBCWqXBhleokd7C1jOqCzAlzOw=@vger.kernel.org X-Gm-Message-State: AFuF++lqZM8LJ/ALg6kwt1/dbcfmG3HkaRpEt8aUuWQ4heI+/bFggHOw g9/sjc+CZgX0mcaWOVljPozEJlr21/1K4wK9QB3GHxVJXy0aed7CBGX+kTTQJxQepHnwCOCzs3G uahS1zQ== X-Received: from pgbm12-n2.prod.google.com ([2002:a05:6a02:618c:20b0:cc4:31fa:cb67]) (user=kuniyu job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:134b:b0:3c4:4272:b400 with SMTP id adf61e73a8af0-3d9ae8e1ee9mr13070985637.18.1788381470353; Wed, 02 Sep 2026 13:37:50 -0700 (PDT) Date: Wed, 2 Sep 2026 20:36:51 +0000 In-Reply-To: <20260902203722.926528-1-kuniyu@google.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260902203722.926528-1-kuniyu@google.com> X-Mailer: git-send-email 2.55.0.970.g62bdec98f9-goog Message-ID: <20260902203722.926528-11-kuniyu@google.com> Subject: [PATCH v6 net-next 10/15] neighbour: Clean up neigh_table_init() and neigh_table_clear(). From: Kuniyuki Iwashima To: Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , David Ahern , Ido Schimmel Cc: Simon Horman , Kuniyuki Iwashima , Kuniyuki Iwashima , netdev@vger.kernel.org, Nikolay Aleksandrov Content-Type: text/plain; charset="UTF-8" Currently, neigh_table_init() and neigh_table_clear() are called once at the boot time, but we will call them for each netns. Let's clean up them. For neigh_table_init(), * Allocate all memory first and unwind on failure * Remove !tbl->entry_size check since it is always true for arp_tbl and nd_tbl * Initialise everything before starting delayed works For neigh_table_clear(), * Reorder function to match neigh_table_init() * Use timer_shutdown_sync() instead of timer_delete_sync() * Remove pneigh_queue_purge() since it is called via neigh_ifdown() * Replace pr_crit() with DEBUG_NET_WARN_ON_ONCE() * Call neigh_hash_free_rcu() directly without call_rcu() In a later patch, neigh_table_clear() will be split so that tbl->{stats,phash_buckets,nht} will be freed only when all neighbour entries are freed. Signed-off-by: Kuniyuki Iwashima Reviewed-by: Nikolay Aleksandrov --- v2: Add __maybe_unused to net in neigh_table_clear() to avoid transient W=1 warning for CONFIG_PROC_FS=n (next patch removes it anyway) --- net/core/neighbour.c | 98 +++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 34da4cdc813d..36488dbd1512 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1810,57 +1810,68 @@ static struct lock_class_key neigh_table_proxy_queue_class; void neigh_table_init(struct neigh_table *tbl) { unsigned long now = jiffies; + struct net *net = &init_net; unsigned long phsize; - INIT_LIST_HEAD(&tbl->parms_list); - INIT_LIST_HEAD(&tbl->gc_list); - INIT_LIST_HEAD(&tbl->managed_list); + RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3)); + if (!tbl->nht) + goto err_hash; - list_add(&tbl->parms.list, &tbl->parms_list); - write_pnet(&tbl->parms.net, &init_net); - refcount_set(&tbl->parms.refcnt, 1); - neigh_set_reach_time(&tbl->parms); - tbl->parms.qlen = 0; + phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); + tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); + if (!tbl->phash_buckets) + goto err_phash; + + tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) + + tbl->key_len, NEIGH_PRIV_ALIGN); tbl->stats = alloc_percpu(struct neigh_statistics); if (!tbl->stats) - panic("cannot create neighbour cache statistics"); + goto err_stats; #ifdef CONFIG_PROC_FS - if (!proc_create_seq_data(tbl->id, 0, init_net.proc_net_stat, - &neigh_stat_seq_ops, tbl)) - panic("cannot create neighbour proc dir entry"); + if (!proc_create_seq_data(tbl->id, 0, net->proc_net_stat, + &neigh_stat_seq_ops, tbl)) + goto err_proc; #endif - RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3)); - - phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *); - tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); - - if (!tbl->nht || !tbl->phash_buckets) - panic("cannot allocate neighbour cache hashes"); - - if (!tbl->entry_size) - tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) + - tbl->key_len, NEIGH_PRIV_ALIGN); - else - WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN); + tbl->parms.tbl = tbl; + tbl->parms.qlen = 0; + INIT_LIST_HEAD(&tbl->parms_list); + list_add(&tbl->parms.list, &tbl->parms_list); + write_pnet(&tbl->parms.net, net); + refcount_set(&tbl->parms.refcnt, 1); + neigh_set_reach_time(&tbl->parms); + tbl->last_flush = now; + tbl->last_rand = now + tbl->parms.reachable_time * 20; spin_lock_init(&tbl->lock); mutex_init(&tbl->phash_lock); + skb_queue_head_init_class(&tbl->proxy_queue, + &neigh_table_proxy_queue_class); + timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0); + INIT_LIST_HEAD(&tbl->gc_list); INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work); queue_delayed_work(system_power_efficient_wq, &tbl->gc_work, - tbl->parms.reachable_time); + tbl->parms.reachable_time); + + INIT_LIST_HEAD(&tbl->managed_list); INIT_DEFERRABLE_WORK(&tbl->managed_work, neigh_managed_work); queue_delayed_work(system_power_efficient_wq, &tbl->managed_work, 0); - timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0); - skb_queue_head_init_class(&tbl->proxy_queue, - &neigh_table_proxy_queue_class); + return; - tbl->last_flush = now; - tbl->last_rand = now + tbl->parms.reachable_time * 20; +#ifdef CONFIG_PROC_FS +err_proc: + free_percpu(tbl->stats); +#endif +err_stats: + kfree(tbl->phash_buckets); +err_phash: + neigh_hash_free_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu); +err_hash: + panic("cannot allocate memory"); } /* @@ -1869,26 +1880,27 @@ void neigh_table_init(struct neigh_table *tbl) */ int neigh_table_clear(struct neigh_table *tbl) { - /* It is not clean... Fix it to unload IPv6 module safely */ + struct net *net __maybe_unused = &init_net; + struct neigh_hash_table *nht; + cancel_delayed_work_sync(&tbl->managed_work); cancel_delayed_work_sync(&tbl->gc_work); - timer_delete_sync(&tbl->proxy_timer); - pneigh_queue_purge(&tbl->proxy_queue, NULL, tbl->family); + timer_shutdown_sync(&tbl->proxy_timer); + neigh_ifdown(tbl, NULL); - if (atomic_read(&tbl->entries)) - pr_crit("neighbour leakage\n"); + DEBUG_NET_WARN_ON_ONCE(atomic_read(&tbl->entries)); - call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu, - neigh_hash_free_rcu); - tbl->nht = NULL; + remove_proc_entry(tbl->id, net->proc_net_stat); + + free_percpu(tbl->stats); + tbl->stats = NULL; kfree(tbl->phash_buckets); tbl->phash_buckets = NULL; - remove_proc_entry(tbl->id, init_net.proc_net_stat); - - free_percpu(tbl->stats); - tbl->stats = NULL; + nht = rcu_dereference_protected(tbl->nht, 1); + tbl->nht = NULL; + neigh_hash_free_rcu(&nht->rcu); return 0; } -- 2.55.0.970.g62bdec98f9-goog