Lines Matching refs:inm

141 static int	inm_get_source(struct in_multi *inm, const in_addr_t haddr,
187 struct in_multi inm; /* in_multi */
264 inm_is_ifp_detached(const struct in_multi *inm)
266 VERIFY(inm->inm_ifma != NULL);
267 VERIFY(inm->inm_ifp == inm->inm_ifma->ifma_ifp);
269 return (!ifnet_is_attached(inm->inm_ifp, 0));
544 struct in_multi *inm;
548 IN_LOOKUP_MULTI(group, ifp, inm);
549 if (inm != NULL) {
550 INM_LOCK(inm);
551 VERIFY(inm->inm_reqcnt >= 1);
552 inm->inm_reqcnt++;
553 VERIFY(inm->inm_reqcnt != 0);
554 *pinm = inm;
555 INM_UNLOCK(inm);
558 * We already joined this group; return the inm
583 if ((inm = ifma->ifma_protospec) != NULL) {
586 INM_ADDREF(inm); /* for caller */
588 INM_LOCK(inm);
589 VERIFY(inm->inm_ifma == ifma);
590 VERIFY(inm->inm_ifp == ifp);
591 VERIFY(in_hosteq(inm->inm_addr, *group));
592 if (inm->inm_debug & IFD_ATTACHED) {
593 VERIFY(inm->inm_reqcnt >= 1);
594 inm->inm_reqcnt++;
595 VERIFY(inm->inm_reqcnt != 0);
596 *pinm = inm;
597 INM_UNLOCK(inm);
603 * been joined; return the inm with a refcount
610 * the inm referring to the ifma has been detached, thus we
612 * inm with a refcount held for the caller.
614 in_multi_attach(inm);
615 VERIFY((inm->inm_debug &
617 *pinm = inm;
618 INM_UNLOCK(inm);
632 inm = in_multi_alloc(M_WAITOK);
633 if (inm == NULL) {
638 INM_LOCK(inm);
639 inm->inm_addr = *group;
640 inm->inm_ifp = ifp;
641 inm->inm_igi = IGMP_IFINFO(ifp);
642 VERIFY(inm->inm_igi != NULL);
643 IGI_ADDREF(inm->inm_igi);
644 inm->inm_ifma = ifma; /* keep refcount from if_addmulti() */
645 inm->inm_state = IGMP_NOT_MEMBER;
649 inm->inm_scq.ifq_maxlen = IGMP_MAX_STATE_CHANGES;
650 inm->inm_st[0].iss_fmode = MCAST_UNDEFINED;
651 inm->inm_st[1].iss_fmode = MCAST_UNDEFINED;
652 RB_INIT(&inm->inm_srcs);
653 *pinm = inm;
654 in_multi_attach(inm);
655 VERIFY((inm->inm_debug & (IFD_ATTACHED | IFD_TRASHED)) == IFD_ATTACHED);
656 INM_ADDREF_LOCKED(inm); /* for caller */
657 INM_UNLOCK(inm);
661 ifma->ifma_protospec = inm;
674 inm_clear_recorded(struct in_multi *inm)
678 INM_LOCK_ASSERT_HELD(inm);
680 RB_FOREACH(ims, ip_msource_tree, &inm->inm_srcs) {
683 --inm->inm_st[1].iss_rec;
686 VERIFY(inm->inm_st[1].iss_rec == 0);
693 * inm is the group descriptor.
708 inm_record_source(struct in_multi *inm, const in_addr_t naddr)
713 INM_LOCK_ASSERT_HELD(inm);
716 ims = RB_FIND(ip_msource_tree, &inm->inm_srcs, &find);
720 if (inm->inm_nsrc == in_mcast_maxgrpsrc)
726 RB_INSERT(ip_msource_tree, &inm->inm_srcs, nims);
727 ++inm->inm_nsrc;
736 ++inm->inm_st[1].iss_rec;
957 * inm is the group descriptor to work with.
965 inm_get_source(struct in_multi *inm, const in_addr_t haddr,
973 INM_LOCK_ASSERT_HELD(inm);
976 ims = RB_FIND(ip_msource_tree, &inm->inm_srcs, &find);
978 if (inm->inm_nsrc == in_mcast_maxgrpsrc)
984 RB_INSERT(ip_msource_tree, &inm->inm_srcs, nims);
985 ++inm->inm_nsrc;
1007 ims_get_mode(const struct in_multi *inm, const struct ip_msource *ims,
1010 INM_LOCK_ASSERT_HELD(INM_CAST_TO_NONCONST(inm));
1013 if (inm->inm_st[t].iss_ex > 0 &&
1014 inm->inm_st[t].iss_ex == ims->ims_st[t].ex)
1072 inm_merge(struct in_multi *inm, /*const*/ struct in_mfilter *imf)
1079 INM_LOCK_ASSERT_HELD(inm);
1097 error = inm_get_source(inm, lims->ims_haddr, 0, &nims);
1110 (void) inm_get_source(inm, lims->ims_haddr, 1, &bims);
1125 IGMP_PRINTF(("%s: --in on inm at t1\n", __func__));
1126 --inm->inm_st[1].iss_in;
1136 IGMP_PRINTF(("%s: --ex on inm at t1\n", __func__));
1137 --inm->inm_st[1].iss_ex;
1139 IGMP_PRINTF(("%s: --in on inm at t1\n", __func__));
1140 --inm->inm_st[1].iss_in;
1144 IGMP_PRINTF(("%s: ex++ on inm at t1\n", __func__));
1145 inm->inm_st[1].iss_ex++;
1147 IGMP_PRINTF(("%s: in++ on inm at t1\n", __func__));
1148 inm->inm_st[1].iss_in++;
1153 * Track inm filter state in terms of listener counts.
1160 if (inm->inm_st[1].iss_ex > 0) {
1162 inm->inm_st[1].iss_fmode = MCAST_EXCLUDE;
1163 } else if (inm->inm_st[1].iss_in > 0) {
1165 inm->inm_st[1].iss_fmode = MCAST_INCLUDE;
1168 inm->inm_st[1].iss_fmode = MCAST_UNDEFINED;
1175 IGMP_PRINTF(("%s: --asm on inm at t1\n", __func__));
1176 --inm->inm_st[1].iss_asm;
1182 IGMP_PRINTF(("%s: asm++ on inm at t1\n", __func__));
1183 inm->inm_st[1].iss_asm++;
1186 IGMP_PRINTF(("%s: merged imf %p to inm %p\n", __func__, imf, inm));
1187 inm_print(inm);
1192 inm_reap(inm);
1202 inm_commit(struct in_multi *inm)
1206 INM_LOCK_ASSERT_HELD(inm);
1208 IGMP_PRINTF(("%s: commit inm %p\n", __func__, inm));
1210 inm_print(inm);
1212 RB_FOREACH(ims, ip_msource_tree, &inm->inm_srcs) {
1215 inm->inm_st[0] = inm->inm_st[1];
1222 inm_reap(struct in_multi *inm)
1226 INM_LOCK_ASSERT_HELD(inm);
1228 RB_FOREACH_SAFE(ims, ip_msource_tree, &inm->inm_srcs, tims) {
1234 RB_REMOVE(ip_msource_tree, &inm->inm_srcs, ims);
1236 inm->inm_nsrc--;
1244 inm_purge(struct in_multi *inm)
1248 INM_LOCK_ASSERT_HELD(inm);
1250 RB_FOREACH_SAFE(ims, ip_msource_tree, &inm->inm_srcs, tims) {
1252 RB_REMOVE(ip_msource_tree, &inm->inm_srcs, ims);
1254 inm->inm_nsrc--;
1261 * Only preserves atomicity at inm level.
1272 struct in_multi *inm = NULL;
1289 error = in_getmulti(ifp, gina, &inm);
1295 IGMP_PRINTF(("%s: merge inm state\n", __func__));
1297 INM_LOCK(inm);
1298 error = inm_merge(inm, imf);
1300 IGMP_PRINTF(("%s: failed to merge inm state\n", __func__));
1305 error = igmp_change_state(inm);
1313 IGMP_PRINTF(("%s: dropping ref on %p\n", __func__, inm));
1314 INM_UNLOCK(inm);
1315 INM_REMREF(inm);
1317 INM_UNLOCK(inm);
1318 *pinm = inm; /* keep refcount from in_getmulti() */
1328 * Only preserves atomicity at inm level.
1334 in_leavegroup(struct in_multi *inm, /*const*/ struct in_mfilter *imf)
1341 INM_LOCK_ASSERT_NOTHELD(inm);
1344 INM_LOCK(inm);
1346 IGMP_PRINTF(("%s: leave inm %p, %s/%s%d, imf %p\n", __func__,
1347 inm, inet_ntoa(inm->inm_addr),
1348 (inm_is_ifp_detached(inm) ? "null" : inm->inm_ifp->if_name),
1349 inm->inm_ifp->if_unit, imf));
1367 IGMP_PRINTF(("%s: merge inm state\n", __func__));
1369 error = inm_merge(inm, imf);
1370 KASSERT(error == 0, ("%s: failed to merge inm state\n", __func__));
1373 error = igmp_change_state(inm);
1378 lastref = in_multi_detach(inm);
1379 VERIFY(!lastref || (!(inm->inm_debug & IFD_ATTACHED) &&
1380 inm->inm_reqcnt == 0));
1381 INM_UNLOCK(inm);
1385 INM_REMREF(inm); /* for in_multihead list */
1415 in_delmulti(struct in_multi *inm)
1418 (void) in_leavegroup(inm, NULL);
1439 struct in_multi *inm;
1542 inm = imo->imo_membership[idx];
1589 INM_LOCK(inm);
1590 IGMP_PRINTF(("%s: merge inm state\n", __func__));
1591 error = inm_merge(inm, imf);
1593 IGMP_PRINTF(("%s: failed to merge inm state\n", __func__));
1594 INM_UNLOCK(inm);
1599 error = igmp_change_state(inm);
1600 INM_UNLOCK(inm);
2052 struct in_multi *inm = NULL;
2178 inm = imo->imo_membership[idx];
2292 VERIFY(inm == NULL);
2293 error = in_joingroup(ifp, &gsa->sin.sin_addr, imf, &inm);
2294 VERIFY(inm != NULL || error != 0);
2297 imo->imo_membership[idx] = inm; /* from in_joingroup() */
2299 IGMP_PRINTF(("%s: merge inm state\n", __func__));
2300 INM_LOCK(inm);
2301 error = inm_merge(inm, imf);
2303 IGMP_PRINTF(("%s: failed to merge inm state\n",
2305 INM_UNLOCK(inm);
2309 error = igmp_change_state(inm);
2310 INM_UNLOCK(inm);
2331 VERIFY(inm == NULL);
2358 struct in_multi *inm = NULL;
2477 inm = imo->imo_membership[idx];
2527 (void) in_leavegroup(inm, imf);
2529 IGMP_PRINTF(("%s: merge inm state\n", __func__));
2530 INM_LOCK(inm);
2531 error = inm_merge(inm, imf);
2533 IGMP_PRINTF(("%s: failed to merge inm state\n",
2535 INM_UNLOCK(inm);
2540 error = igmp_change_state(inm);
2544 INM_UNLOCK(inm);
2557 VERIFY(inm == imo->imo_membership[idx]);
2559 INM_REMREF(inm);
2674 struct in_multi *inm;
2742 inm = imo->imo_membership[idx];
2827 INM_LOCK(inm);
2828 IGMP_PRINTF(("%s: merge inm state\n", __func__));
2829 error = inm_merge(inm, imf);
2831 IGMP_PRINTF(("%s: failed to merge inm state\n", __func__));
2832 INM_UNLOCK(inm);
2837 error = igmp_change_state(inm);
2838 INM_UNLOCK(inm);
3104 struct in_multi *inm;
3146 IN_FIRST_MULTI(step, inm);
3147 while (inm != NULL) {
3148 INM_LOCK(inm);
3149 if (inm->inm_ifp != ifp)
3152 if (!in_hosteq(inm->inm_addr, group))
3155 fmode = inm->inm_st[1].iss_fmode;
3158 INM_UNLOCK(inm);
3161 RB_FOREACH(ims, ip_msource_tree, &inm->inm_srcs) {
3171 if (fmode != ims_get_mode(inm, ims, 1)) {
3179 break; /* process next inm */
3182 INM_UNLOCK(inm);
3183 IN_NEXT_MULTI(step, inm);
3275 struct in_multi *inm;
3277 inm = (how == M_WAITOK) ? zalloc(inm_zone) : zalloc_noblock(inm_zone);
3278 if (inm != NULL) {
3279 bzero(inm, inm_size);
3280 lck_mtx_init(&inm->inm_lock, in_multihead_lock_grp,
3282 inm->inm_debug |= IFD_ALLOC;
3284 inm->inm_debug |= IFD_DEBUG;
3285 inm->inm_trace = inm_trace;
3288 return (inm);
3292 in_multi_free(struct in_multi *inm)
3294 INM_LOCK(inm);
3295 if (inm->inm_debug & IFD_ATTACHED) {
3296 panic("%s: attached inm=%p is being freed", __func__, inm);
3298 } else if (inm->inm_ifma != NULL) {
3299 panic("%s: ifma not NULL for inm=%p", __func__, inm);
3301 } else if (!(inm->inm_debug & IFD_ALLOC)) {
3302 panic("%s: inm %p cannot be freed", __func__, inm);
3304 } else if (inm->inm_refcount != 0) {
3305 panic("%s: non-zero refcount inm=%p", __func__, inm);
3307 } else if (inm->inm_reqcnt != 0) {
3308 panic("%s: non-zero reqcnt inm=%p", __func__, inm);
3313 IF_DRAIN(&inm->inm_scq);
3315 inm->inm_debug &= ~IFD_ALLOC;
3316 if ((inm->inm_debug & (IFD_DEBUG | IFD_TRASHED)) ==
3319 TAILQ_REMOVE(&inm_trash_head, (struct in_multi_dbg *)inm,
3322 inm->inm_debug &= ~IFD_TRASHED;
3324 INM_UNLOCK(inm);
3326 lck_mtx_destroy(&inm->inm_lock, in_multihead_lock_grp);
3327 zfree(inm_zone, inm);
3331 in_multi_attach(struct in_multi *inm)
3334 INM_LOCK_ASSERT_HELD(inm);
3336 if (inm->inm_debug & IFD_ATTACHED) {
3337 panic("%s: Attempt to attach an already attached inm=%p",
3338 __func__, inm);
3340 } else if (inm->inm_debug & IFD_TRASHED) {
3341 panic("%s: Attempt to reattach a detached inm=%p",
3342 __func__, inm);
3346 inm->inm_reqcnt++;
3347 VERIFY(inm->inm_reqcnt == 1);
3348 INM_ADDREF_LOCKED(inm);
3349 inm->inm_debug |= IFD_ATTACHED;
3354 if ((inm->inm_debug & (IFD_DEBUG | IFD_TRASHED)) ==
3357 INM_CONVERT_LOCK(inm);
3359 TAILQ_REMOVE(&inm_trash_head, (struct in_multi_dbg *)inm,
3362 inm->inm_debug &= ~IFD_TRASHED;
3365 LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
3369 in_multi_detach(struct in_multi *inm)
3372 INM_LOCK_ASSERT_HELD(inm);
3374 if (inm->inm_reqcnt == 0) {
3375 panic("%s: inm=%p negative reqcnt", __func__, inm);
3379 --inm->inm_reqcnt;
3380 if (inm->inm_reqcnt > 0)
3383 if (!(inm->inm_debug & IFD_ATTACHED)) {
3384 panic("%s: Attempt to detach an unattached record inm=%p",
3385 __func__, inm);
3387 } else if (inm->inm_debug & IFD_TRASHED) {
3388 panic("%s: inm %p is already in trash list", __func__, inm);
3395 inm->inm_debug &= ~IFD_ATTACHED;
3396 LIST_REMOVE(inm, inm_link);
3398 if (inm->inm_debug & IFD_DEBUG) {
3400 INM_CONVERT_LOCK(inm);
3403 (struct in_multi_dbg *)inm, inm_trash_link);
3405 inm->inm_debug |= IFD_TRASHED;
3412 inm_addref(struct in_multi *inm, int locked)
3415 INM_LOCK_SPIN(inm);
3417 INM_LOCK_ASSERT_HELD(inm);
3419 if (++inm->inm_refcount == 0) {
3420 panic("%s: inm=%p wraparound refcnt", __func__, inm);
3422 } else if (inm->inm_trace != NULL) {
3423 (*inm->inm_trace)(inm, TRUE);
3426 INM_UNLOCK(inm);
3430 inm_remref(struct in_multi *inm, int locked)
3436 INM_LOCK_SPIN(inm);
3438 INM_LOCK_ASSERT_HELD(inm);
3440 if (inm->inm_refcount == 0 || (inm->inm_refcount == 1 && locked)) {
3441 panic("%s: inm=%p negative/missing refcnt", __func__, inm);
3443 } else if (inm->inm_trace != NULL) {
3444 (*inm->inm_trace)(inm, FALSE);
3447 --inm->inm_refcount;
3448 if (inm->inm_refcount > 0) {
3450 INM_UNLOCK(inm);
3455 * Synchronization with in_getmulti(). In the event the inm has been
3458 * the only way to find this inm is via ifma_protospec. To avoid
3459 * race conditions between the last inm_remref() of that inm and its
3462 * before acquiring in_multihead lock. To prevent the inm from being
3465 ++inm->inm_refcount;
3466 INM_UNLOCK(inm);
3468 INM_LOCK_SPIN(inm);
3469 --inm->inm_refcount;
3470 if (inm->inm_refcount > 0) {
3471 /* We've lost the race, so abort since inm is still in use */
3472 INM_UNLOCK(inm);
3476 INM_LOCK(inm);
3479 inm_purge(inm);
3480 ifma = inm->inm_ifma;
3481 inm->inm_ifma = NULL;
3482 inm->inm_ifp = NULL;
3483 igi = inm->inm_igi;
3484 inm->inm_igi = NULL;
3485 INM_UNLOCK(inm);
3491 in_multi_free(inm);
3501 inm_trace(struct in_multi *inm, int refhold)
3503 struct in_multi_dbg *inm_dbg = (struct in_multi_dbg *)inm;
3508 if (!(inm->inm_debug & IFD_DEBUG)) {
3509 panic("%s: inm %p has no debug structure", __func__, inm);
3621 inm_print(const struct in_multi *inm)
3625 INM_LOCK_ASSERT_HELD(INM_CAST_TO_NONCONST(inm));
3630 printf("%s: --- begin inm %p ---\n", __func__, inm);
3632 inet_ntoa(inm->inm_addr),
3633 inm->inm_ifp,
3634 inm->inm_ifp->if_name,
3635 inm->inm_ifp->if_unit,
3636 inm->inm_ifma);
3638 inm->inm_timer,
3639 inm_state_str(inm->inm_state),
3640 inm->inm_refcount,
3641 inm->inm_scq.ifq_len);
3643 inm->inm_igi,
3644 inm->inm_nsrc,
3645 inm->inm_sctimer,
3646 inm->inm_scrv);
3649 inm_mode_str(inm->inm_st[t].iss_fmode),
3650 inm->inm_st[t].iss_asm,
3651 inm->inm_st[t].iss_ex,
3652 inm->inm_st[t].iss_in,
3653 inm->inm_st[t].iss_rec);
3655 printf("%s: --- end inm %p ---\n", __func__, inm);
3661 inm_print(__unused const struct in_multi *inm)