The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f9e0752e3573e0b60e578e58ee2eac3d42ff533a

commit f9e0752e3573e0b60e578e58ee2eac3d42ff533a
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2021-01-13 00:18:00 +0000
Commit:     Alexander V. Chernikov <melif...@freebsd.org>
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 *);
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to