* Perform the final leave for a multicast address. * * When leaving a group: * MLDv1 sends a DONE message, if and only if we are the reporter. * MLDv2 enqueues a state-change report containing a transition * to INCLUDE {} for immediate transmission. */
| 2187 | * to INCLUDE {} for immediate transmission. |
| 2188 | */ |
| 2189 | static void |
| 2190 | mld_final_leave(struct in6_multi *inm, struct mld_ifsoftc *mli) |
| 2191 | { |
| 2192 | struct epoch_tracker et; |
| 2193 | int syncstates; |
| 2194 | #ifdef KTR |
| 2195 | char ip6tbuf[INET6_ADDRSTRLEN]; |
| 2196 | #endif |
| 2197 | |
| 2198 | syncstates = 1; |
| 2199 | |
| 2200 | CTR4(KTR_MLD, "%s: final leave %s on ifp %p(%s)", |
| 2201 | __func__, ip6_sprintf(ip6tbuf, &inm->in6m_addr), |
| 2202 | inm->in6m_ifp, if_name(inm->in6m_ifp)); |
| 2203 | |
| 2204 | IN6_MULTI_LIST_LOCK_ASSERT(); |
| 2205 | MLD_LOCK_ASSERT(); |
| 2206 | |
| 2207 | switch (inm->in6m_state) { |
| 2208 | case MLD_NOT_MEMBER: |
| 2209 | case MLD_SILENT_MEMBER: |
| 2210 | case MLD_LEAVING_MEMBER: |
| 2211 | /* Already leaving or left; do nothing. */ |
| 2212 | CTR1(KTR_MLD, |
| 2213 | "%s: not kicking state machine for silent group", __func__); |
| 2214 | break; |
| 2215 | case MLD_REPORTING_MEMBER: |
| 2216 | case MLD_IDLE_MEMBER: |
| 2217 | case MLD_G_QUERY_PENDING_MEMBER: |
| 2218 | case MLD_SG_QUERY_PENDING_MEMBER: |
| 2219 | if (mli->mli_version == MLD_VERSION_1) { |
| 2220 | #ifdef INVARIANTS |
| 2221 | if (inm->in6m_state == MLD_G_QUERY_PENDING_MEMBER || |
| 2222 | inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER) |
| 2223 | panic("%s: MLDv2 state reached, not MLDv2 mode", |
| 2224 | __func__); |
| 2225 | #endif |
| 2226 | NET_EPOCH_ENTER(et); |
| 2227 | mld_v1_transmit_report(inm, MLD_LISTENER_DONE); |
| 2228 | NET_EPOCH_EXIT(et); |
| 2229 | inm->in6m_state = MLD_NOT_MEMBER; |
| 2230 | V_current_state_timers_running6 = 1; |
| 2231 | } else if (mli->mli_version == MLD_VERSION_2) { |
| 2232 | /* |
| 2233 | * Stop group timer and all pending reports. |
| 2234 | * Immediately enqueue a state-change report |
| 2235 | * TO_IN {} to be sent on the next fast timeout, |
| 2236 | * giving us an opportunity to merge reports. |
| 2237 | */ |
| 2238 | mbufq_drain(&inm->in6m_scq); |
| 2239 | inm->in6m_timer = 0; |
| 2240 | inm->in6m_scrv = mli->mli_rv; |
| 2241 | CTR4(KTR_MLD, "%s: Leaving %s/%s with %d " |
| 2242 | "pending retransmissions.", __func__, |
| 2243 | ip6_sprintf(ip6tbuf, &inm->in6m_addr), |
| 2244 | if_name(inm->in6m_ifp), inm->in6m_scrv); |
| 2245 | if (inm->in6m_scrv == 0) { |
| 2246 | inm->in6m_state = MLD_NOT_MEMBER; |
no test coverage detected