* Perform the initial join for an MLD group. * * When joining a group: * If the group should have its MLD traffic suppressed, do nothing. * MLDv1 starts sending MLDv1 host membership reports. * MLDv2 will schedule an MLDv2 state-change report containing the * initial state of the membership. * * If the delay argument is non-zero, then we must delay sending the * initial state change f
| 1970 | * initial state change for delay ticks (in units of PR_FASTHZ). |
| 1971 | */ |
| 1972 | static int |
| 1973 | mld_initial_join(struct in6_multi *inm, struct mld_ifsoftc *mli, |
| 1974 | const int delay) |
| 1975 | { |
| 1976 | struct epoch_tracker et; |
| 1977 | struct ifnet *ifp; |
| 1978 | struct mbufq *mq; |
| 1979 | int error, retval, syncstates; |
| 1980 | int odelay; |
| 1981 | #ifdef KTR |
| 1982 | char ip6tbuf[INET6_ADDRSTRLEN]; |
| 1983 | #endif |
| 1984 | |
| 1985 | CTR4(KTR_MLD, "%s: initial join %s on ifp %p(%s)", |
| 1986 | __func__, ip6_sprintf(ip6tbuf, &inm->in6m_addr), |
| 1987 | inm->in6m_ifp, if_name(inm->in6m_ifp)); |
| 1988 | |
| 1989 | error = 0; |
| 1990 | syncstates = 1; |
| 1991 | |
| 1992 | ifp = inm->in6m_ifp; |
| 1993 | |
| 1994 | IN6_MULTI_LIST_LOCK_ASSERT(); |
| 1995 | MLD_LOCK_ASSERT(); |
| 1996 | |
| 1997 | KASSERT(mli && mli->mli_ifp == ifp, ("%s: inconsistent ifp", __func__)); |
| 1998 | |
| 1999 | /* |
| 2000 | * Groups joined on loopback or marked as 'not reported', |
| 2001 | * enter the MLD_SILENT_MEMBER state and |
| 2002 | * are never reported in any protocol exchanges. |
| 2003 | * All other groups enter the appropriate state machine |
| 2004 | * for the version in use on this link. |
| 2005 | * A link marked as MLIF_SILENT causes MLD to be completely |
| 2006 | * disabled for the link. |
| 2007 | */ |
| 2008 | if ((ifp->if_flags & IFF_LOOPBACK) || |
| 2009 | (mli->mli_flags & MLIF_SILENT) || |
| 2010 | !mld_is_addr_reported(&inm->in6m_addr)) { |
| 2011 | CTR1(KTR_MLD, |
| 2012 | "%s: not kicking state machine for silent group", __func__); |
| 2013 | inm->in6m_state = MLD_SILENT_MEMBER; |
| 2014 | inm->in6m_timer = 0; |
| 2015 | } else { |
| 2016 | /* |
| 2017 | * Deal with overlapping in_multi lifecycle. |
| 2018 | * If this group was LEAVING, then make sure |
| 2019 | * we drop the reference we picked up to keep the |
| 2020 | * group around for the final INCLUDE {} enqueue. |
| 2021 | */ |
| 2022 | if (mli->mli_version == MLD_VERSION_2 && |
| 2023 | inm->in6m_state == MLD_LEAVING_MEMBER) { |
| 2024 | inm->in6m_refcount--; |
| 2025 | MPASS(inm->in6m_refcount > 0); |
| 2026 | } |
| 2027 | inm->in6m_state = MLD_REPORTING_MEMBER; |
| 2028 | |
| 2029 | switch (mli->mli_version) { |
no test coverage detected