s_addr = htonl(INADDR_ALLHOSTS_GROUP); error = in_joingroup(ifp, &allhosts_addr, NULL, @@ -789,7 +789,7 @@ in_difaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct ucred *cred if (iaIsLast && (ifp->if_flags & IFF_MULTICAST)) { struct in_ifinfo *ii; - ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]); + ii = (struct in_ifinfo *)ifp->if_inet; if (ii->ii_allhosts) { (void)in_leavegroup(ii->ii_allhosts, NULL); ii->ii_allhosts = NULL; @@ -1329,26 +1329,62 @@ in_ifnet_broadcast(struct in_addr in, struct ifnet *ifp) return (false); } + +static struct lltable *in_lltattach(struct ifnet *); +void +in_ifattach(void *arg __unused, struct ifnet *ifp) +{ + struct in_ifinfo *ii; + + ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO); + ii->ii_llt = in_lltattach(ifp); + ii->ii_igmp = igmp_domifattach(ifp); + ifp->if_inet = ii; +} +EVENTHANDLER_DEFINE(ifnet_arrival_event, in_ifattach, NULL, + EVENTHANDLER_PRI_ANY); + /* * On interface removal, clean up IPv4 data structures hung off of the ifnet. */ -void -in_ifdetach(struct ifnet *ifp) +static void +in_ifdetach(void *arg __unused, struct ifnet *ifp) { - IN_MULTI_LOCK(); - in_pcbpurgeif0(&V_ripcbinfo, ifp); - in_pcbpurgeif0(&V_udbinfo, ifp); - in_pcbpurgeif0(&V_ulitecbinfo, ifp); - in_purgemaddrs(ifp); - IN_MULTI_UNLOCK(); + struct in_ifinfo *ii = ifp->if_inet; +#ifdef VIMAGE /* - * Make sure all multicast deletions invoking if_ioctl() are - * completed before returning. Else we risk accessing a freed - * ifnet structure pointer. + * On VNET shutdown abort here as the stack teardown will do all + * the work top-down for us. XXXGL: this logic is copied from + * if_detach() before dom_ifattach removal. Ideally we'd like to have + * same logic for VNET shutdown and normal detach. This means that + * interfaces should be detach before protocols destroyed during VNET + * shutdown. */ - inm_release_wait(NULL); + if (!VNET_IS_SHUTTING_DOWN(ifp->if_vnet)) +#endif + { + IN_MULTI_LOCK(); + in_pcbpurgeif0(&V_ripcbinfo, ifp); + in_pcbpurgeif0(&V_udbinfo, ifp); + in_pcbpurgeif0(&V_ulitecbinfo, ifp); + in_purgemaddrs(ifp); + IN_MULTI_UNLOCK(); + + /* + * Make sure all multicast deletions invoking if_ioctl() are + * completed before returning. Else we risk accessing a freed + * ifnet structure pointer. + */ + inm_release_wait(NULL); + } + + igmp_domifdetach(ifp); + lltable_free(ii->ii_llt); + free(ii, M_IFADDR); } +EVENTHANDLER_DEFINE(ifnet_departure_event, in_ifdetach, NULL, + EVENTHANDLER_PRI_ANY); static void in_ifnet_event(void *arg __unused, struct ifnet *ifp, int event) @@ -1862,35 +1898,9 @@ in_lltattach(struct ifnet *ifp) struct lltable * in_lltable_get(struct ifnet *ifp) { - struct lltable *llt = NULL; - - void *afdata_ptr = ifp->if_afdata[AF_INET]; - if (afdata_ptr != NULL) - llt = ((struct in_ifinfo *)afdata_ptr)->ii_llt; - return (llt); -} - -void * -in_domifattach(struct ifnet *ifp) -{ - struct in_ifinfo *ii; - - ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO); - - ii->ii_llt = in_lltattach(ifp); - ii->ii_igmp = igmp_domifattach(ifp); - - return (ii); -} - -void -in_domifdetach(struct ifnet *ifp, void *aux) -{ - struct in_ifinfo *ii = (struct in_ifinfo *)aux; - - MPASS(ifp->if_afdata[AF_INET] == NULL); + /* XXXGL: ??? */ + if (ifp->if_inet == NULL) + return (NULL); - igmp_domifdetach(ifp); - lltable_free(ii->ii_llt); - free(ii, M_IFADDR); + return (((struct in_ifinfo *)ifp->if_inet)->ii_llt); } diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 3f2c388548ec..0cd55bd1e409 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -684,7 +684,6 @@ int inet_aton(const char *, struct in_addr *); /* in libkern */ char *inet_ntoa_r(struct in_addr ina, char *buf); /* in libkern */ char *inet_ntop(int, const void *, char *, socklen_t); /* in libkern */ int inet_pton(int af, const char *, void *); /* in libkern */ -void in_ifdetach(struct ifnet *); static inline bool in_broadcast(struct in_addr in) diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index ba112afbf002..131e72780ebe 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -500,7 +500,7 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group, IN_MULTI_LOCK_ASSERT(); - ii = (struct in_ifinfo *)ifp->if_afdata[AF_INET]; + ii = (struct in_ifinfo *)ifp->if_inet; IN_MULTI_LIST_LOCK(); inm = inm_lookup(ifp, *group); if (inm != NULL) { diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 3ec515d216fa..ff3040bfc7b1 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -76,8 +76,6 @@ struct domain inetdomain = { #ifdef VIMAGE .dom_rtdetach = in_detachhead, #endif - .dom_ifattach = in_domifattach, - .dom_ifdetach = in_domifdetach, .dom_nprotosw = 14, .dom_protosw = { &tcp_protosw, diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 1f6f6edb9219..311d82da4605 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -102,8 +102,7 @@ struct in_ifaddr { ((((d).s_addr ^ (a).s_addr) & (m).s_addr)) == 0 ) #endif -#define LLTABLE(ifp) \ - ((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt +#define LLTABLE(ifp) ((struct in_ifinfo *)(ifp)->if_inet)->ii_llt /* * Hash table for IP addresses. */ @@ -471,9 +470,9 @@ void ip_input(struct mbuf *); void ip_direct_input(struct mbuf *); void in_ifadown(struct ifaddr *ifa, int); struct mbuf *ip_tryforward(struct mbuf *); -void *in_domifattach(struct ifnet *); -void in_domifdetach(struct ifnet *, void *); struct rib_head *in_inithead(uint32_t fibnum); +void in_ifattach(void *, struct ifnet *); + #ifdef VIMAGE void in_detachhead(struct rib_head *rh); #endif diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 6ddec6726428..2e0635f8e482 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -352,6 +352,7 @@ VNET_SYSINIT(ip_vnet_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, static void ip_init(const void *unused __unused) { + struct ifnet *ifp; ipreass_init(); @@ -376,6 +377,14 @@ ip_init(const void *unused __unused) #ifdef RSS netisr_register(&ip_direct_nh); #endif + /* + * XXXGL: we use SYSINIT() here, but go over V_ifnet. It was the same + * way before dom_ifattach removal. This worked because when any + * non-default vnet is created, there are no interfaces inside. + * Eventually this needs to be fixed. + */ + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) + in_ifattach(NULL, ifp); } SYSINIT(ip_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip_init, NULL); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 158129258587..a953bb5546d6 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -478,7 +478,7 @@ in6_control_ioctl(u_long cmd, void *data, /* FALLTHROUGH */ case SIOCGIFSTAT_IN6: case SIOCGIFSTAT_ICMP6: - if (ifp->if_afdata[AF_INET6] == NULL) { + if (ifp->if_inet6 == NULL) { error = EPFNOSUPPORT; goto out; } @@ -525,15 +525,13 @@ in6_control_ioctl(u_long cmd, void *data, break; case SIOCGIFSTAT_IN6: - COUNTER_ARRAY_COPY(((struct in6_ifextra *) - ifp->if_afdata[AF_INET6])->in6_ifstat, + COUNTER_ARRAY_COPY(ifp->if_inet6->in6_ifstat, &ifr->ifr_ifru.ifru_stat, sizeof(struct in6_ifstat) / sizeof(uint64_t)); break; case SIOCGIFSTAT_ICMP6: - COUNTER_ARRAY_COPY(((struct in6_ifextra *) - ifp->if_afdata[AF_INET6])->icmp6_ifstat, + COUNTER_ARRAY_COPY(ifp->if_inet6->icmp6_ifstat, &ifr->ifr_ifru.ifru_icmp6stat, sizeof(struct icmp6_ifstat) / sizeof(uint64_t)); break; @@ -2567,16 +2565,14 @@ in6_lltattach(struct ifnet *ifp) struct lltable * in6_lltable_get(struct ifnet *ifp) { - struct lltable *llt = NULL; + if (ifp->if_inet6 == NULL) + return (NULL); - void *afdata_ptr = ifp->if_afdata[AF_INET6]; - if (afdata_ptr != NULL) - llt = ((struct in6_ifextra *)afdata_ptr)->lltable; - return (llt); + return (ifp->if_inet6->lltable); } -void * -in6_domifattach(struct ifnet *ifp) +void +in6_ifarrival(void *arg __unused, struct ifnet *ifp) { struct in6_ifextra *ext; @@ -2584,7 +2580,8 @@ in6_domifattach(struct ifnet *ifp) switch (ifp->if_type) { case IFT_PFLOG: case IFT_PFSYNC: - return (NULL); + ifp->if_inet6 = NULL; + return; } ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK); bzero(ext, sizeof(*ext)); @@ -2606,8 +2603,10 @@ in6_domifattach(struct ifnet *ifp) ext->mld_ifinfo = mld_domifattach(ifp); - return ext; + ifp->if_inet6 = ext; } +EVENTHANDLER_DEFINE(ifnet_arrival_event, in6_ifarrival, NULL, + EVENTHANDLER_PRI_ANY); uint32_t in6_ifmtu(struct ifnet *ifp) @@ -2615,26 +2614,6 @@ in6_ifmtu(struct ifnet *ifp) return (IN6_LINKMTU(ifp)); } -void -in6_domifdetach(struct ifnet *ifp, void *aux) -{ - struct in6_ifextra *ext = (struct in6_ifextra *)aux; - - MPASS(ifp->if_afdata[AF_INET6] == NULL); - - mld_domifdetach(ifp); - scope6_ifdetach(ext->scope6_id); - nd6_ifdetach(ifp, ext->nd_ifinfo); - lltable_free(ext->lltable); - COUNTER_ARRAY_FREE(ext->in6_ifstat, - sizeof(struct in6_ifstat) / sizeof(uint64_t)); - free(ext->in6_ifstat, M_IFADDR); - COUNTER_ARRAY_FREE(ext->icmp6_ifstat, - sizeof(struct icmp6_ifstat) / sizeof(uint64_t)); - free(ext->icmp6_ifstat, M_IFADDR); - free(ext, M_IFADDR); -} - /* * Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be * v4 mapped addr or v4 compat addr @@ -2736,7 +2715,7 @@ in6_purge_proxy_ndp(struct ifnet *ifp) struct lltable *llt; bool need_purge; - if (ifp->if_afdata[AF_INET6] == NULL) + if (ifp->if_inet6 == NULL) return; llt = LLTABLE6(ifp); diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 090ba610460b..a2d236cccc41 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -783,7 +784,8 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) { struct in6_ifaddr *ia; - if (ifp->if_afdata[AF_INET6] == NULL) + /* XXXGL: can this happen after IFT_PFLOG and IFT_PFSYNC are gone? */ + if (ifp->if_inet6 == NULL) return; /* * quirks based on interface type @@ -857,7 +859,8 @@ _in6_ifdetach(struct ifnet *ifp, int purgeulp) { struct ifaddr *ifa, *next; - if (ifp->if_afdata[AF_INET6] == NULL) + /* XXXGL: can this happen after IFT_PFLOG and IFT_PFSYNC are gone? */ + if (ifp->if_inet6 == NULL) return; /* @@ -895,6 +898,38 @@ in6_ifdetach(struct ifnet *ifp) _in6_ifdetach(ifp, 1); } +static void +in6_ifdeparture(void *arg __unused, struct ifnet *ifp) +{ + struct in6_ifextra *ext = ifp->if_inet6; + + /* XXXGL: can this happen after IFT_PFLOG and IFT_PFSYNC are gone? */ + if (ifp->if_inet6 == NULL) + return; + +#ifdef VIMAGE + /* + * On VNET shutdown abort here as the stack teardown will do all + * the work top-down for us. XXXGL: see comment in in.c:in_ifdetach(). + */ + if (!VNET_IS_SHUTTING_DOWN(ifp->if_vnet)) +#endif + _in6_ifdetach(ifp, 1); + mld_domifdetach(ifp); + scope6_ifdetach(ext->scope6_id); + nd6_ifdetach(ifp, ext->nd_ifinfo); + lltable_free(ext->lltable); + COUNTER_ARRAY_FREE(ext->in6_ifstat, + sizeof(struct in6_ifstat) / sizeof(uint64_t)); + free(ext->in6_ifstat, M_IFADDR); + COUNTER_ARRAY_FREE(ext->icmp6_ifstat, + sizeof(struct icmp6_ifstat) / sizeof(uint64_t)); + free(ext->icmp6_ifstat, M_IFADDR); + free(ext, M_IFADDR); +} +EVENTHANDLER_DEFINE(ifnet_departure_event, in6_ifdeparture, NULL, + EVENTHANDLER_PRI_ANY); + void in6_ifdetach_destroy(struct ifnet *ifp) { diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c index 613bd14428bb..4075e75eac85 100644 --- a/sys/netinet6/in6_mcast.c +++ b/sys/netinet6/in6_mcast.c @@ -400,7 +400,7 @@ in6_getmulti(struct ifnet *ifp, const struct in6_addr *group, /* * Does ifp support IPv6 multicasts? */ - if (ifp->if_afdata[AF_INET6] == NULL) + if (ifp->if_inet6 == NULL) error = ENODEV; else inm = in6m_lookup_locked(ifp, group); diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index f3ed72719abf..dbbe7c4b3eca 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -111,8 +111,6 @@ struct domain inet6domain = { #ifdef VIMAGE .dom_rtdetach = in6_detachhead, #endif - .dom_ifattach = in6_domifattach, - .dom_ifdetach = in6_domifdetach, .dom_nprotosw = 14, .dom_protosw = { &tcp6_protosw, diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index 1210937a5dc4..0cfdde652c0a 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -109,8 +109,8 @@ struct in6_ifextra { u_int dad_failures; /* DAD failures when using RFC 7217 stable addresses */ }; -#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable) -#define DAD_FAILURES(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->dad_failures) +#define LLTABLE6(ifp) ((ifp)->if_inet6->lltable) +#define DAD_FAILURES(ifp) ((ifp)->if_inet6->dad_failures) #ifdef _KERNEL @@ -545,8 +545,7 @@ extern struct rmlock in6_ifaddr_lock; #define in6_ifstat_inc(ifp, tag) \ do { \ if (ifp) \ - counter_u64_add(((struct in6_ifextra *) \ - ((ifp)->if_afdata[AF_INET6]))->in6_ifstat[ \ + counter_u64_add((ifp)->if_inet6->in6_ifstat[ \ offsetof(struct in6_ifstat, tag) / sizeof(uint64_t)], 1);\ } while (/*CONSTCOND*/ 0) #endif /* _KERNEL */ @@ -867,8 +866,6 @@ 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 *); -void in6_domifdetach(struct ifnet *, void *); uint32_t in6_ifmtu(struct ifnet *); struct rib_head *in6_inithead(uint32_t fibnum); void in6_detachhead(struct rib_head *rh); @@ -893,6 +890,8 @@ int in6_src_ioctl(u_long, caddr_t); void in6_newaddrmsg(struct in6_ifaddr *, int); void in6_purge_proxy_ndp(struct ifnet *); +void in6_ifarrival(void *, struct ifnet *); + /* * Extended API for IPv6 FIB support. */ diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 380391fd71f4..29fa4741a509 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -286,6 +286,7 @@ VNET_SYSINIT(ip6_vnet_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, static void ip6_init(void *arg __unused) { + struct ifnet *ifp; /* * Register statically those protocols that are unlikely to ever go @@ -312,6 +313,12 @@ ip6_init(void *arg __unused) #ifdef RSS netisr_register(&ip6_direct_nh); #endif + /* + * XXXGL: we use SYSINIT() here, but go over V_ifnet. See comment + * in sys/netinet/ip_input.c:ip_init(). + */ + CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) + in6_ifarrival(NULL, ifp); } SYSINIT(ip6_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_init, NULL); diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index 8ade50b13568..eb5a3a971ea0 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -2920,7 +2920,7 @@ ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt, if (ifp == NULL) return (ENXIO); } - if (ifp != NULL && (ifp->if_afdata[AF_INET6] == NULL || + if (ifp != NULL && (ifp->if_inet6 == NULL || (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)) return (ENETDOWN); diff --git a/sys/netinet6/mld6_var.h b/sys/netinet6/mld6_var.h index 96b841f1564b..d75ac2450c10 100644 --- a/sys/netinet6/mld6_var.h +++ b/sys/netinet6/mld6_var.h @@ -155,8 +155,7 @@ struct mld_ifsoftc { /* * Per-link MLD context. */ *** 133 LINES SKIPPED ***