| 3251 | } |
| 3252 | |
| 3253 | static int |
| 3254 | igmp_v3_merge_state_changes(struct in_multi *inm, struct mbufq *scq) |
| 3255 | { |
| 3256 | struct mbufq *gq; |
| 3257 | struct mbuf *m; /* pending state-change */ |
| 3258 | struct mbuf *m0; /* copy of pending state-change */ |
| 3259 | struct mbuf *mt; /* last state-change in packet */ |
| 3260 | int docopy, domerge; |
| 3261 | u_int recslen; |
| 3262 | |
| 3263 | docopy = 0; |
| 3264 | domerge = 0; |
| 3265 | recslen = 0; |
| 3266 | |
| 3267 | IN_MULTI_LIST_LOCK_ASSERT(); |
| 3268 | IGMP_LOCK_ASSERT(); |
| 3269 | |
| 3270 | /* |
| 3271 | * If there are further pending retransmissions, make a writable |
| 3272 | * copy of each queued state-change message before merging. |
| 3273 | */ |
| 3274 | if (inm->inm_scrv > 0) |
| 3275 | docopy = 1; |
| 3276 | |
| 3277 | gq = &inm->inm_scq; |
| 3278 | #ifdef KTR |
| 3279 | if (mbufq_first(gq) == NULL) { |
| 3280 | CTR2(KTR_IGMPV3, "%s: WARNING: queue for inm %p is empty", |
| 3281 | __func__, inm); |
| 3282 | } |
| 3283 | #endif |
| 3284 | |
| 3285 | m = mbufq_first(gq); |
| 3286 | while (m != NULL) { |
| 3287 | /* |
| 3288 | * Only merge the report into the current packet if |
| 3289 | * there is sufficient space to do so; an IGMPv3 report |
| 3290 | * packet may only contain 65,535 group records. |
| 3291 | * Always use a simple mbuf chain concatentation to do this, |
| 3292 | * as large state changes for single groups may have |
| 3293 | * allocated clusters. |
| 3294 | */ |
| 3295 | domerge = 0; |
| 3296 | mt = mbufq_last(scq); |
| 3297 | if (mt != NULL) { |
| 3298 | recslen = m_length(m, NULL); |
| 3299 | |
| 3300 | if ((mt->m_pkthdr.PH_vt.vt_nrecs + |
| 3301 | m->m_pkthdr.PH_vt.vt_nrecs <= |
| 3302 | IGMP_V3_REPORT_MAXRECS) && |
| 3303 | (mt->m_pkthdr.len + recslen <= |
| 3304 | (inm->inm_ifp->if_mtu - IGMP_LEADINGSPACE))) |
| 3305 | domerge = 1; |
| 3306 | } |
| 3307 | |
| 3308 | if (!domerge && mbufq_full(gq)) { |
| 3309 | CTR2(KTR_IGMPV3, |
| 3310 | "%s: outbound queue full, skipping whole packet %p", |
no test coverage detected