int cbq_add_altq(struct pf_altq *a) { cbq_state_t *cbqp; struct ifnet *ifp; ifnet_lock(); if ((ifp = ifunit(a->ifname)) == NULL) { ifnet_unlock(); return (EINVAL); } if (!ifq_is_ready(&ifp->if_snd)) { ifnet_unlock(); return (ENODEV); } /* allocate and initialize cbq_state_t */ cbqp = kmalloc(sizeof(*cbqp), M_ALTQ, M_WAITOK | M_ZERO); callout_init(&cbqp->cbq_callout); cbqp->cbq_qlen = 0; cbqp->ifnp.ifq_ = &ifp->if_snd; /* keep the ifq */ ifq_purge_all(&ifp->if_snd); ifnet_unlock(); /* keep the state in pf_altq */ a->altq_disc = cbqp; return (0); }
/* * Create a clone network interface. */ int if_clone_create(char *name, int len, caddr_t params) { struct if_clone *ifc; char *dp; int wildcard, bytoff, bitoff; int unit; int err; ifc = if_clone_lookup(name, &unit); if (ifc == NULL) return (EINVAL); ifnet_lock(); if (ifunit(name) != NULL) { ifnet_unlock(); return (EEXIST); } ifnet_unlock(); bytoff = bitoff = 0; wildcard = (unit < 0); /* * Find a free unit if none was given. */ if (wildcard) { while (bytoff < ifc->ifc_bmlen && ifc->ifc_units[bytoff] == 0xff) bytoff++; if (bytoff >= ifc->ifc_bmlen) return (ENOSPC); while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0) bitoff++; unit = (bytoff << 3) + bitoff; } if (unit > ifc->ifc_maxunit) return (ENXIO); err = (*ifc->ifc_create)(ifc, unit, params); if (err != 0) return (err); if (!wildcard) { bytoff = unit >> 3; bitoff = unit - (bytoff << 3); }
int cbq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes) { cbq_state_t *cbqp; struct rm_class *cl; class_stats_t stats; int error = 0; struct ifaltq *ifq; if (*nbytes < sizeof(stats)) return (EINVAL); ifnet_lock(); /* XXX not MP safe */ if ((cbqp = altq_lookup(a->ifname, ALTQT_CBQ)) == NULL) { ifnet_unlock(); return (EBADF); } ifq = cbqp->ifnp.ifq_; CBQ_LOCK(ifq); if ((cl = clh_to_clp(cbqp, a->qid)) == NULL) { CBQ_UNLOCK(ifq); ifnet_unlock(); return (EINVAL); } get_class_stats(&stats, cl); CBQ_UNLOCK(ifq); ifnet_unlock(); if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0) return (error); *nbytes = sizeof(stats); return (0); }