From owner-dev-commits-src-main@freebsd.org Sun Jan 17 20:32:33 2021 Return-Path: Delivered-To: dev-commits-src-main@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 060914D740F; Sun, 17 Jan 2021 20:32:33 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DJmnD6qcRz4TWC; Sun, 17 Jan 2021 20:32:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D2EAB27A2D; Sun, 17 Jan 2021 20:32:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 10HKWWth045958; Sun, 17 Jan 2021 20:32:32 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 10HKWWAi045957; Sun, 17 Jan 2021 20:32:32 GMT (envelope-from git) Date: Sun, 17 Jan 2021 20:32:32 GMT Message-Id: <202101172032.10HKWWAi045957@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: "Alexander V. Chernikov" Subject: git: f9e0752e3573 - main - Create new in6_purgeifaddr() which purges bound ifa prefix if it gets unused. MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: melifaro X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: f9e0752e3573e0b60e578e58ee2eac3d42ff533a Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-main@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for the main branch of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Jan 2021 20:32:33 -0000 The branch main has been updated by melifaro: URL: https://cgit.FreeBSD.org/src/commit/?id=f9e0752e3573e0b60e578e58ee2eac3d42ff533a commit f9e0752e3573e0b60e578e58ee2eac3d42ff533a Author: Alexander V. Chernikov AuthorDate: 2021-01-13 00:18:00 +0000 Commit: Alexander V. Chernikov CommitDate: 2021-01-17 20:32:25 +0000 Create new in6_purgeifaddr() which purges bound ifa prefix if it gets unused. Currently if_purgeifaddrs() uses in6_purgeaddr() to remove IPv6 ifaddrs. in6_purgeaddr() does not trrigger prefix removal if number of linked ifas goes to 0, as this is a low-level function. As a result, if_purgeifaddrs() purges all IPv4/IPv6 addresses but keeps corresponding IPv6 prefixes. Fix this by creating higher-level wrapper which handles unused prefix usecase and use it in if_purgeifaddrs(). Differential revision: https://reviews.freebsd.org/D28128 --- sys/net/if.c | 2 +- sys/netinet6/in6.c | 53 +++++++++++++++++++++++++++++--------------------- sys/netinet6/in6_var.h | 1 + 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/sys/net/if.c b/sys/net/if.c index 68ed4cf65dc1..74fdd066fd2d 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1077,7 +1077,7 @@ if_purgeaddrs(struct ifnet *ifp) #endif /* INET */ #ifdef INET6 if (ifa->ifa_addr->sa_family == AF_INET6) { - in6_purgeaddr(ifa); + in6_purgeifaddr((struct in6_ifaddr *)ifa); /* ifp_addrhead is already updated */ continue; } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index b42cc16cdb6f..48fa8dd2efc6 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -696,31 +696,10 @@ aifaddr_out: } case SIOCDIFADDR_IN6: - { - struct nd_prefix *pr; - - /* - * If the address being deleted is the only one that owns - * the corresponding prefix, expire the prefix as well. - * XXX: theoretically, we don't have to worry about such - * relationship, since we separate the address management - * and the prefix management. We do this, however, to provide - * as much backward compatibility as possible in terms of - * the ioctl operation. - * Note that in6_purgeaddr() will decrement ndpr_addrcnt. - */ - pr = ia->ia6_ndpr; - in6_purgeaddr(&ia->ia_ifa); - if (pr != NULL && pr->ndpr_addrcnt == 0) { - ND6_WLOCK(); - nd6_prefix_unlink(pr, NULL); - ND6_WUNLOCK(); - nd6_prefix_del(pr); - } + in6_purgeifaddr(ia); EVENTHANDLER_INVOKE(ifaddr_event_ext, ifp, &ia->ia_ifa, IFADDR_EVENT_DEL); break; - } default: if (ifp->if_ioctl == NULL) { @@ -1364,6 +1343,36 @@ in6_purgeaddr(struct ifaddr *ifa) in6_unlink_ifa(ia, ifp); } +/* + * Removes @ia from the corresponding interfaces and unlinks corresponding + * prefix if no addresses are using it anymore. + */ +void +in6_purgeifaddr(struct in6_ifaddr *ia) +{ + struct nd_prefix *pr; + + /* + * If the address being deleted is the only one that owns + * the corresponding prefix, expire the prefix as well. + * XXX: theoretically, we don't have to worry about such + * relationship, since we separate the address management + * and the prefix management. We do this, however, to provide + * as much backward compatibility as possible in terms of + * the ioctl operation. + * Note that in6_purgeaddr() will decrement ndpr_addrcnt. + */ + pr = ia->ia6_ndpr; + in6_purgeaddr(&ia->ia_ifa); + if (pr != NULL && pr->ndpr_addrcnt == 0) { + ND6_WLOCK(); + nd6_prefix_unlink(pr, NULL); + ND6_WUNLOCK(); + nd6_prefix_del(pr); + } +} + + static void in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) { diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index f5e6a931ae64..5f4364c6fba0 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -887,6 +887,7 @@ int in6_update_ifa(struct ifnet *, struct in6_aliasreq *, void in6_prepare_ifra(struct in6_aliasreq *, const struct in6_addr *, const struct in6_addr *); void in6_purgeaddr(struct ifaddr *); +void in6_purgeifaddr(struct in6_ifaddr *); int in6if_do_dad(struct ifnet *); void in6_savemkludge(struct in6_ifaddr *); void *in6_domifattach(struct ifnet *);