예제 #1
0
/*
 * struct rm_class *
 * cbq_class_create(cbq_mod_state_t *cbqp, struct cbq_add_class *acp,
 *		struct rm_class *parent, struct rm_class *borrow)
 *
 * This function create a new traffic class in the CBQ class hierarchy of
 * given paramters.  The class that created is either the root, default,
 * or a new dynamic class.  If CBQ is not initilaized, the the root class
 * will be created.
 */
static int
cbq_class_create(cbq_state_t *cbqp, struct cbq_add_class *acp,
    struct rm_class *parent, struct rm_class *borrow)
{
	struct rm_class	*cl;
	cbq_class_spec_t *spec = &acp->cbq_class;
	u_int32_t	chandle;
	int		i, error;

	/*
	 * allocate class handle
	 */
	for (i = 1; i < CBQ_MAX_CLASSES; i++)
		if (cbqp->cbq_class_tbl[i] == NULL)
			break;
	if (i == CBQ_MAX_CLASSES)
		return (EINVAL);
	chandle = i;	/* use the slot number as class handle */

	/*
	 * create a class.  if this is a root class, initialize the
	 * interface.
	 */
	if ((spec->flags & CBQCLF_CLASSMASK) == CBQCLF_ROOTCLASS) {
		error = rmc_init(cbqp->ifnp.ifq_, &cbqp->ifnp,
		    spec->nano_sec_per_byte, cbqrestart, spec->maxq,
		    RM_MAXQUEUED, spec->maxidle, spec->minidle, spec->offtime,
		    spec->flags);
		if (error)
			return (error);
		cl = cbqp->ifnp.root_;
	} else {
		cl = rmc_newclass(spec->priority,
				  &cbqp->ifnp, spec->nano_sec_per_byte,
				  rmc_delay_action, spec->maxq, parent, borrow,
				  spec->maxidle, spec->minidle, spec->offtime,
				  spec->pktsize, spec->flags);
	}
	if (cl == NULL)
		return (ENOMEM);

	/* return handle to user space. */
	acp->cbq_class_handle = chandle;

	cl->stats_.handle = chandle;
	cl->stats_.depth = cl->depth_;

	/* save the allocated class */
	cbqp->cbq_class_tbl[i] = cl;

	if ((spec->flags & CBQCLF_CLASSMASK) == CBQCLF_DEFCLASS)
		cbqp->ifnp.default_ = cl;
	if ((spec->flags & CBQCLF_CLASSMASK) == CBQCLF_CTLCLASS)
		cbqp->ifnp.ctl_ = cl;

	return (0);
}
예제 #2
0
파일: altq_cbq.c 프로젝트: Alkzndr/freebsd
int
cbq_add_queue(struct pf_altq *a)
{
	struct rm_class	*borrow, *parent;
	cbq_state_t	*cbqp;
	struct rm_class	*cl;
	struct cbq_opts	*opts;
	int		i;

	if ((cbqp = a->altq_disc) == NULL)
		return (EINVAL);
	if (a->qid == 0)
		return (EINVAL);

	/*
	 * find a free slot in the class table.  if the slot matching
	 * the lower bits of qid is free, use this slot.  otherwise,
	 * use the first free slot.
	 */
	i = a->qid % CBQ_MAX_CLASSES;
	if (cbqp->cbq_class_tbl[i] != NULL) {
		for (i = 0; i < CBQ_MAX_CLASSES; i++)
			if (cbqp->cbq_class_tbl[i] == NULL)
				break;
		if (i == CBQ_MAX_CLASSES)
			return (EINVAL);
	}

	opts = &a->pq_u.cbq_opts;
	/* check parameters */
	if (a->priority >= CBQ_MAXPRI)
		return (EINVAL);

	/* Get pointers to parent and borrow classes.  */
	parent = clh_to_clp(cbqp, a->parent_qid);
	if (opts->flags & CBQCLF_BORROW)
		borrow = parent;
	else
		borrow = NULL;

	/*
	 * A class must borrow from it's parent or it can not
	 * borrow at all.  Hence, borrow can be null.
	 */
	if (parent == NULL && (opts->flags & CBQCLF_ROOTCLASS) == 0) {
		printf("cbq_add_queue: no parent class!\n");
		return (EINVAL);
	}

	if ((borrow != parent)  && (borrow != NULL)) {
		printf("cbq_add_class: borrow class != parent\n");
		return (EINVAL);
	}

	/*
	 * check parameters
	 */
	switch (opts->flags & CBQCLF_CLASSMASK) {
	case CBQCLF_ROOTCLASS:
		if (parent != NULL)
			return (EINVAL);
		if (cbqp->ifnp.root_)
			return (EINVAL);
		break;
	case CBQCLF_DEFCLASS:
		if (cbqp->ifnp.default_)
			return (EINVAL);
		break;
	case 0:
		if (a->qid == 0)
			return (EINVAL);
		break;
	default:
		/* more than two flags bits set */
		return (EINVAL);
	}

	/*
	 * create a class.  if this is a root class, initialize the
	 * interface.
	 */
	if ((opts->flags & CBQCLF_CLASSMASK) == CBQCLF_ROOTCLASS) {
		rmc_init(cbqp->ifnp.ifq_, &cbqp->ifnp, opts->ns_per_byte,
		    cbqrestart, a->qlimit, RM_MAXQUEUED,
		    opts->maxidle, opts->minidle, opts->offtime,
		    opts->flags);
		cl = cbqp->ifnp.root_;
	} else {
		cl = rmc_newclass(a->priority,
				  &cbqp->ifnp, opts->ns_per_byte,
				  rmc_delay_action, a->qlimit, parent, borrow,
				  opts->maxidle, opts->minidle, opts->offtime,
				  opts->pktsize, opts->flags);
	}
	if (cl == NULL)
		return (ENOMEM);

	/* return handle to user space. */
	cl->stats_.handle = a->qid;
	cl->stats_.depth = cl->depth_;

	/* save the allocated class */
	cbqp->cbq_class_tbl[i] = cl;

	if ((opts->flags & CBQCLF_CLASSMASK) == CBQCLF_DEFCLASS)
		cbqp->ifnp.default_ = cl;

	return (0);
}
예제 #3
0
void
rmc_init(struct ifaltq *ifq, struct rm_ifdat *ifd, u_int nsecPerByte,
         void (*restart)(struct ifaltq *), int maxq, int maxqueued, u_int maxidle,
	 int minidle, u_int offtime, int flags)
{
	int i, mtu;

	/*
	 * Initialize the CBQ tracing/debug facility.
	 */
	CBQTRACEINIT();

	bzero(ifd, sizeof (*ifd));
	mtu = ifq->altq_ifp->if_mtu;
	ifd->ifq_ = ifq;
	ifd->restart = restart;
	ifd->maxqueued_ = maxqueued;
	ifd->ns_per_byte_ = nsecPerByte;
	ifd->maxpkt_ = mtu;
	ifd->wrr_ = (flags & RMCF_WRR) ? 1 : 0;
	ifd->efficient_ = (flags & RMCF_EFFICIENT) ? 1 : 0;
#if 1
	ifd->maxiftime_ = mtu * nsecPerByte / 1000 * 16;
	if (mtu * nsecPerByte > 10 * 1000000)
		ifd->maxiftime_ /= 4;
#endif

	reset_cutoff(ifd);
	CBQTRACE(rmc_init, 'INIT', ifd->cutoff_);

	/*
	 * Initialize the CBQ's WRR state.
	 */
	for (i = 0; i < RM_MAXPRIO; i++) {
		ifd->alloc_[i] = 0;
		ifd->M_[i] = 0;
		ifd->num_[i] = 0;
		ifd->na_[i] = 0;
		ifd->active_[i] = NULL;
	}

	/*
	 * Initialize current packet state.
	 */
	ifd->qi_ = 0;
	ifd->qo_ = 0;
	for (i = 0; i < RM_MAXQUEUED; i++) {
		ifd->class_[i] = NULL;
		ifd->curlen_[i] = 0;
		ifd->borrowed_[i] = NULL;
	}

	/*
	 * Create the root class of the link-sharing structure.
	 */
	ifd->root_ = rmc_newclass(0, ifd, nsecPerByte, rmc_root_overlimit,
				  maxq, 0, 0, maxidle, minidle, offtime, 0, 0);
	if (ifd->root_ == NULL) {
		kprintf("rmc_init: root class not allocated\n");
		return ;
	}
	ifd->root_->depth_ = 0;
}