summaryrefslogtreecommitdiff
path: root/sys/altq/altq_hfsc.c
diff options
context:
space:
mode:
authorKenjiro Cho <kjc@cvs.openbsd.org>2002-12-16 09:18:07 +0000
committerKenjiro Cho <kjc@cvs.openbsd.org>2002-12-16 09:18:07 +0000
commitb832c86cc52bdbf120e78217d21df3af5977a61a (patch)
treeffa7692cbbba583d4becd2d93be35cbe22f09192 /sys/altq/altq_hfsc.c
parent322f5fb510ece19f248fa04cf2639fabfa5b74ea (diff)
switchover to pf-based altq.
- remove files which are no longer used, or we don't have plans to support in pf in the near future. - remove altq ioctl related stuff. - convert the PRIQ, HFSC and RIO modules to pf-based altq. (these are not enabled in GENERIC, CDNR is not converted yet.)
Diffstat (limited to 'sys/altq/altq_hfsc.c')
-rw-r--r--sys/altq/altq_hfsc.c1092
1 files changed, 478 insertions, 614 deletions
diff --git a/sys/altq/altq_hfsc.c b/sys/altq/altq_hfsc.c
index 5646337e007..f29989b476f 100644
--- a/sys/altq/altq_hfsc.c
+++ b/sys/altq/altq_hfsc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: altq_hfsc.c,v 1.7 2002/11/29 07:52:31 kjc Exp $ */
-/* $KAME: altq_hfsc.c,v 1.13 2002/05/16 11:02:58 kjc Exp $ */
+/* $OpenBSD: altq_hfsc.c,v 1.8 2002/12/16 09:18:05 kjc Exp $ */
+/* $KAME: altq_hfsc.c,v 1.17 2002/11/29 07:48:33 kjc Exp $ */
/*
* Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
@@ -38,41 +38,39 @@
* "A Hierarchical Fair Service Curve Algorithm for Link-Sharing,
* Real-Time and Priority Service"
* by Ion Stoica, Hui Zhang, and T. S. Eugene Ng.
+ *
+ * Oleg Cherevko <olwi@aq.ml.com.ua> added the upperlimit for link-sharing.
+ * when a class has an upperlimit, the fit-time is computed from the
+ * upperlimit service curve. the link-sharing scheduler does not schedule
+ * a class whose fit-time exceeds the current time.
*/
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
-#include <sys/sockio.h>
#include <sys/systm.h>
-#include <sys/proc.h>
#include <sys/errno.h>
-#include <sys/kernel.h>
#include <sys/queue.h>
#include <net/if.h>
-#include <net/if_types.h>
+#include <netinet/in.h>
+#include <net/pfvar.h>
#include <altq/altq.h>
-#include <altq/altq_conf.h>
#include <altq/altq_hfsc.h>
/*
* function prototypes
*/
-static struct hfsc_if *hfsc_attach(struct ifaltq *, u_int);
-static int hfsc_detach(struct hfsc_if *);
static int hfsc_clear_interface(struct hfsc_if *);
static int hfsc_request(struct ifaltq *, int, void *);
static void hfsc_purge(struct hfsc_if *);
static struct hfsc_class *hfsc_class_create(struct hfsc_if *,
- struct service_curve *, struct hfsc_class *, int, int);
+ struct service_curve *, struct service_curve *, struct service_curve *,
+ struct hfsc_class *, int, int);
static int hfsc_class_destroy(struct hfsc_class *);
-static int hfsc_class_modify(struct hfsc_class *,
- struct service_curve *, struct service_curve *);
static struct hfsc_class *hfsc_nextclass(struct hfsc_class *);
-
static int hfsc_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
static struct mbuf *hfsc_dequeue(struct ifaltq *, int);
@@ -81,25 +79,27 @@ static struct mbuf *hfsc_getq(struct hfsc_class *);
static struct mbuf *hfsc_pollq(struct hfsc_class *);
static void hfsc_purgeq(struct hfsc_class *);
+static void update_cfmin(struct hfsc_class *);
static void set_active(struct hfsc_class *, int);
static void set_passive(struct hfsc_class *);
static void init_ed(struct hfsc_class *, int);
static void update_ed(struct hfsc_class *, int);
static void update_d(struct hfsc_class *, int);
-static void init_v(struct hfsc_class *, int);
-static void update_v(struct hfsc_class *, int);
+static void init_vf(struct hfsc_class *, int);
+static void update_vf(struct hfsc_class *, int, u_int64_t);
static ellist_t *ellist_alloc(void);
static void ellist_destroy(ellist_t *);
static void ellist_insert(struct hfsc_class *);
static void ellist_remove(struct hfsc_class *);
static void ellist_update(struct hfsc_class *);
-struct hfsc_class *ellist_get_mindl(ellist_t *);
+struct hfsc_class *ellist_get_mindl(ellist_t *, u_int64_t);
static actlist_t *actlist_alloc(void);
static void actlist_destroy(actlist_t *);
static void actlist_insert(struct hfsc_class *);
static void actlist_remove(struct hfsc_class *);
static void actlist_update(struct hfsc_class *);
+static struct hfsc_class *actlist_firstfit(struct hfsc_class *, u_int64_t);
static __inline u_int64_t seg_x2y(u_int64_t, u_int64_t);
static __inline u_int64_t seg_y2x(u_int64_t, u_int64_t);
@@ -117,39 +117,45 @@ static u_int64_t rtsc_x2y(struct runtime_sc *, u_int64_t);
static void rtsc_min(struct runtime_sc *, struct internal_sc *,
u_int64_t, u_int64_t);
-int hfscopen(dev_t, int, int, struct proc *);
-int hfscclose(dev_t, int, int, struct proc *);
-int hfscioctl(dev_t, ioctlcmd_t, caddr_t, int, struct proc *);
-static int hfsccmd_if_attach(struct hfsc_attach *);
-static int hfsccmd_if_detach(struct hfsc_interface *);
-static int hfsccmd_add_class(struct hfsc_add_class *);
-static int hfsccmd_delete_class(struct hfsc_delete_class *);
-static int hfsccmd_modify_class(struct hfsc_modify_class *);
-static int hfsccmd_add_filter(struct hfsc_add_filter *);
-static int hfsccmd_delete_filter(struct hfsc_delete_filter *);
-static int hfsccmd_class_stats(struct hfsc_class_stats *);
-static void get_class_stats(struct class_stats *, struct hfsc_class *);
-static struct hfsc_class *clh_to_clp(struct hfsc_if *, u_long);
-static u_long clp_to_clh(struct hfsc_class *);
+static void get_class_stats(struct hfsc_classstats *, struct hfsc_class *);
+static struct hfsc_class *clh_to_clp(struct hfsc_if *, u_int32_t);
/*
* macros
*/
#define is_a_parent_class(cl) ((cl)->cl_children != NULL)
-/* hif_list keeps all hfsc_if's allocated. */
-static struct hfsc_if *hif_list = NULL;
+#define HT_INFINITY 0xffffffffffffffffLL /* infinite time value */
-static struct hfsc_if *
-hfsc_attach(ifq, bandwidth)
- struct ifaltq *ifq;
- u_int bandwidth;
+int
+hfsc_pfattach(struct pf_altq *a)
+{
+ struct ifnet *ifp;
+ int s, error;
+
+ if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL)
+ return (EINVAL);
+ s = splimp();
+ error = altq_attach(&ifp->if_snd, ALTQT_HFSC, a->altq_disc,
+ hfsc_enqueue, hfsc_dequeue, hfsc_request, NULL, NULL);
+ splx(s);
+ return (error);
+}
+
+int
+hfsc_add_altq(struct pf_altq *a)
{
struct hfsc_if *hif;
+ struct ifnet *ifp;
struct service_curve root_sc;
+ if ((ifp = ifunit(a->ifname)) == NULL)
+ return (EINVAL);
+ if (!ALTQ_IS_READY(&ifp->if_snd))
+ return (ENODEV);
+
MALLOC(hif, struct hfsc_if *, sizeof(struct hfsc_if),
- M_DEVBUF, M_WAITOK);
+ M_DEVBUF, M_WAITOK);
if (hif == NULL)
return (NULL);
bzero(hif, sizeof(struct hfsc_if));
@@ -160,47 +166,37 @@ hfsc_attach(ifq, bandwidth)
return NULL;
}
- hif->hif_ifq = ifq;
+ hif->hif_ifq = &ifp->if_snd;
/*
* create root class
*/
- root_sc.m1 = bandwidth;
+ root_sc.m1 = a->ifbandwidth;
root_sc.d = 0;
- root_sc.m2 = bandwidth;
- if ((hif->hif_rootclass =
- hfsc_class_create(hif, &root_sc, NULL, 0, 0)) == NULL) {
+ root_sc.m2 = a->ifbandwidth;
+ if ((hif->hif_rootclass = hfsc_class_create(hif,
+ &root_sc, &root_sc, NULL, NULL, 0, 0)) == NULL) {
FREE(hif, M_DEVBUF);
- return (NULL);
+ return (ENOMEM);
}
- /* add this state to the hfsc list */
- hif->hif_next = hif_list;
- hif_list = hif;
+ /* keep the state in pf_altq */
+ a->altq_disc = hif;
- return (hif);
+ return (0);
}
-static int
-hfsc_detach(hif)
- struct hfsc_if *hif;
+int
+hfsc_remove_altq(struct pf_altq *a)
{
- (void)hfsc_clear_interface(hif);
- (void)hfsc_class_destroy(hif->hif_rootclass);
+ struct hfsc_if *hif;
- /* remove this interface from the hif list */
- if (hif_list == hif)
- hif_list = hif->hif_next;
- else {
- struct hfsc_if *h;
+ if ((hif = a->altq_disc) == NULL)
+ return (EINVAL);
+ a->altq_disc = NULL;
- for (h = hif_list; h != NULL; h = h->hif_next)
- if (h->hif_next == hif) {
- h->hif_next = hif->hif_next;
- break;
- }
- ASSERT(h != NULL);
- }
+ (void)hfsc_clear_interface(hif);
+ (void)hfsc_class_destroy(hif->hif_rootclass);
ellist_destroy(hif->hif_eligible);
@@ -209,6 +205,83 @@ hfsc_detach(hif)
return (0);
}
+int
+hfsc_add_queue(struct pf_altq *a)
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl, *parent;
+ struct hfsc_opts *opts;
+ struct service_curve rtsc, lssc, ulsc;
+
+ if ((hif = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ opts = &a->pq_u.hfsc_opts;
+
+ parent = clh_to_clp(hif, a->parent_qid);
+ if (parent == NULL)
+ return (EINVAL);
+ rtsc.m1 = opts->rtsc_m1;
+ rtsc.d = opts->rtsc_d;
+ rtsc.m2 = opts->rtsc_m2;
+ lssc.m1 = opts->lssc_m1;
+ lssc.d = opts->lssc_d;
+ lssc.m2 = opts->lssc_m2;
+ ulsc.m1 = opts->ulsc_m1;
+ ulsc.d = opts->ulsc_d;
+ ulsc.m2 = opts->ulsc_m2;
+
+ cl = hfsc_class_create(hif, &rtsc, &lssc, &ulsc,
+ parent, a->qlimit, opts->flags);
+ if (cl == NULL)
+ return (ENOMEM);
+
+ /* return handle to user space. */
+ a->qid = cl->cl_handle;
+
+ return (0);
+}
+
+int
+hfsc_remove_queue(struct pf_altq *a)
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+
+ if ((hif = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ if ((cl = clh_to_clp(hif, a->qid)) == NULL)
+ return (EINVAL);
+
+ return (hfsc_class_destroy(cl));
+}
+
+int
+hfsc_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+ struct hfsc_classstats stats;
+ int error = 0;
+
+ if ((hif = altq_lookup(a->ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(hif, a->qid)) == NULL)
+ return (EINVAL);
+
+ if (*nbytes < sizeof(stats))
+ return (EINVAL);
+
+ get_class_stats(&stats, cl);
+
+ if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
+ return (error);
+ *nbytes = sizeof(stats);
+ return (0);
+}
+
/*
* bring the interface back to the initial state by discarding
* all the filters and classes except the root class.
@@ -219,9 +292,6 @@ hfsc_clear_interface(hif)
{
struct hfsc_class *cl;
- /* free the filters for this interface */
- acc_discard_filters(&hif->hif_classifier, NULL, 1);
-
/* clear out the classes */
while ((cl = hif->hif_rootclass->cl_children) != NULL) {
/*
@@ -270,14 +340,14 @@ hfsc_purge(hif)
}
struct hfsc_class *
-hfsc_class_create(hif, sc, parent, qlimit, flags)
+hfsc_class_create(hif, rsc, fsc, usc, parent, qlimit, flags)
struct hfsc_if *hif;
- struct service_curve *sc;
+ struct service_curve *rsc, *fsc, *usc;
struct hfsc_class *parent;
int qlimit, flags;
{
struct hfsc_class *cl, *p;
- int s;
+ int i, s, chandle;
#ifndef ALTQ_RED
if (flags & HFCF_RED) {
@@ -288,6 +358,14 @@ hfsc_class_create(hif, sc, parent, qlimit, flags)
}
#endif
+ /* find a free class slot. */
+ for (i = 0; i < HFSC_MAX_CLASSES; i++)
+ if (hif->hif_class_tbl[i] == NULL)
+ break;
+ if (i == HFSC_MAX_CLASSES)
+ return (NULL);
+ chandle = i + 1;
+
MALLOC(cl, struct hfsc_class *, sizeof(struct hfsc_class),
M_DEVBUF, M_WAITOK);
if (cl == NULL)
@@ -313,6 +391,15 @@ hfsc_class_create(hif, sc, parent, qlimit, flags)
#ifdef ALTQ_RED
if (flags & (HFCF_RED|HFCF_RIO)) {
int red_flags, red_pkttime;
+ u_int m2;
+
+ m2 = 0;
+ if (rsc != NULL && rsc->m2 > m2)
+ m2 = rsc->m2;
+ if (fsc != NULL && fsc->m2 > m2)
+ m2 = fsc->m2;
+ if (usc != NULL && usc->m2 > m2)
+ m2 = usc->m2;
red_flags = 0;
if (flags & HFCF_ECN)
@@ -321,21 +408,21 @@ hfsc_class_create(hif, sc, parent, qlimit, flags)
if (flags & HFCF_CLEARDSCP)
red_flags |= RIOF_CLEARDSCP;
#endif
- if (sc->m2 < 8)
+ if (m2 < 8)
red_pkttime = 1000 * 1000 * 1000; /* 1 sec */
else
red_pkttime = (int64_t)hif->hif_ifq->altq_ifp->if_mtu
- * 1000 * 1000 * 1000 / (sc->m2 / 8);
+ * 1000 * 1000 * 1000 / (m2 / 8);
if (flags & HFCF_RED) {
cl->cl_red = red_alloc(0, 0, 0, 0,
- red_flags, red_pkttime);
+ red_flags, red_pkttime);
if (cl->cl_red != NULL)
qtype(cl->cl_q) = Q_RED;
}
#ifdef ALTQ_RIO
else {
cl->cl_red = (red_t *)rio_alloc(0, NULL,
- red_flags, red_pkttime);
+ red_flags, red_pkttime);
if (cl->cl_red != NULL)
qtype(cl->cl_q) = Q_RIO;
}
@@ -343,32 +430,40 @@ hfsc_class_create(hif, sc, parent, qlimit, flags)
}
#endif /* ALTQ_RED */
- if (sc != NULL && (sc->m1 != 0 || sc->m2 != 0)) {
+ if (rsc != NULL && (rsc->m1 != 0 || rsc->m2 != 0)) {
MALLOC(cl->cl_rsc, struct internal_sc *,
- sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
+ sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
if (cl->cl_rsc == NULL)
goto err_ret;
- bzero(cl->cl_rsc, sizeof(struct internal_sc));
- sc2isc(sc, cl->cl_rsc);
+ sc2isc(rsc, cl->cl_rsc);
rtsc_init(&cl->cl_deadline, cl->cl_rsc, 0, 0);
rtsc_init(&cl->cl_eligible, cl->cl_rsc, 0, 0);
-
+ }
+ if (fsc != NULL && (fsc->m1 != 0 || fsc->m2 != 0)) {
MALLOC(cl->cl_fsc, struct internal_sc *,
- sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
+ sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
if (cl->cl_fsc == NULL)
goto err_ret;
- bzero(cl->cl_fsc, sizeof(struct internal_sc));
- sc2isc(sc, cl->cl_fsc);
+ sc2isc(fsc, cl->cl_fsc);
rtsc_init(&cl->cl_virtual, cl->cl_fsc, 0, 0);
}
+ if (usc != NULL && (usc->m1 != 0 || usc->m2 != 0)) {
+ MALLOC(cl->cl_usc, struct internal_sc *,
+ sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
+ if (cl->cl_usc == NULL)
+ goto err_ret;
+ sc2isc(usc, cl->cl_usc);
+ rtsc_init(&cl->cl_ulimit, cl->cl_usc, 0, 0);
+ }
cl->cl_id = hif->hif_classid++;
- cl->cl_handle = (u_long)cl; /* XXX: just a pointer to this class */
+ cl->cl_handle = chandle;
cl->cl_hif = hif;
cl->cl_parent = parent;
s = splimp();
hif->hif_classes++;
+ hif->hif_class_tbl[chandle - 1] = cl;
if (flags & HFCF_DEFAULTCLASS)
hif->hif_defaultclass = cl;
@@ -404,6 +499,8 @@ hfsc_class_create(hif, sc, parent, qlimit, flags)
FREE(cl->cl_fsc, M_DEVBUF);
if (cl->cl_rsc != NULL)
FREE(cl->cl_rsc, M_DEVBUF);
+ if (cl->cl_usc != NULL)
+ FREE(cl->cl_usc, M_DEVBUF);
if (cl->cl_q != NULL)
FREE(cl->cl_q, M_DEVBUF);
FREE(cl, M_DEVBUF);
@@ -421,9 +518,6 @@ hfsc_class_destroy(cl)
s = splimp();
- /* delete filters referencing to this class */
- acc_discard_filters(&cl->cl_hif->hif_classifier, cl, 0);
-
if (!qempty(cl->cl_q))
hfsc_purgeq(cl);
@@ -442,6 +536,7 @@ hfsc_class_destroy(cl)
} while ((p = p->cl_siblings) != NULL);
ASSERT(p != NULL);
}
+ cl->cl_hif->hif_class_tbl[cl->cl_handle - 1] = NULL;
cl->cl_hif->hif_classes--;
splx(s);
@@ -457,6 +552,8 @@ hfsc_class_destroy(cl)
red_destroy(cl->cl_red);
#endif
}
+ if (cl->cl_usc != NULL)
+ FREE(cl->cl_usc, M_DEVBUF);
if (cl->cl_fsc != NULL)
FREE(cl->cl_fsc, M_DEVBUF);
if (cl->cl_rsc != NULL)
@@ -467,68 +564,6 @@ hfsc_class_destroy(cl)
return (0);
}
-static int
-hfsc_class_modify(cl, rsc, fsc)
- struct hfsc_class *cl;
- struct service_curve *rsc, *fsc;
-{
- struct internal_sc *rsc_tmp, *fsc_tmp;
- int s;
-
- if (rsc != NULL && (rsc->m1 != 0 || rsc->m2 != 0) &&
- cl->cl_rsc == NULL) {
- MALLOC(rsc_tmp, struct internal_sc *,
- sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
- if (rsc_tmp == NULL)
- return (ENOMEM);
- }
- if (fsc != NULL && (fsc->m1 != 0 || fsc->m2 != 0) &&
- cl->cl_fsc == NULL) {
- MALLOC(fsc_tmp, struct internal_sc *,
- sizeof(struct internal_sc), M_DEVBUF, M_WAITOK);
- if (fsc_tmp == NULL)
- return (ENOMEM);
- }
-
- s = splimp();
- if (!qempty(cl->cl_q))
- hfsc_purgeq(cl);
-
- if (rsc != NULL) {
- if (rsc->m1 == 0 && rsc->m2 == 0) {
- if (cl->cl_rsc != NULL) {
- FREE(cl->cl_rsc, M_DEVBUF);
- cl->cl_rsc = NULL;
- }
- } else {
- if (cl->cl_rsc == NULL)
- cl->cl_rsc = rsc_tmp;
- bzero(cl->cl_rsc, sizeof(struct internal_sc));
- sc2isc(rsc, cl->cl_rsc);
- rtsc_init(&cl->cl_deadline, cl->cl_rsc, 0, 0);
- rtsc_init(&cl->cl_eligible, cl->cl_rsc, 0, 0);
- }
- }
-
- if (fsc != NULL) {
- if (fsc->m1 == 0 && fsc->m2 == 0) {
- if (cl->cl_fsc != NULL) {
- FREE(cl->cl_fsc, M_DEVBUF);
- cl->cl_fsc = NULL;
- }
- } else {
- if (cl->cl_fsc == NULL)
- cl->cl_fsc = fsc_tmp;
- bzero(cl->cl_fsc, sizeof(struct internal_sc));
- sc2isc(fsc, cl->cl_fsc);
- rtsc_init(&cl->cl_virtual, cl->cl_fsc, 0, 0);
- }
- }
- splx(s);
-
- return (0);
-}
-
/*
* hfsc_nextclass returns the next class in the tree.
* usage:
@@ -566,12 +601,21 @@ hfsc_enqueue(ifq, m, pktattr)
{
struct hfsc_if *hif = (struct hfsc_if *)ifq->altq_disc;
struct hfsc_class *cl;
+ struct m_tag *t;
int len;
/* grab class set by classifier */
- if (pktattr == NULL || (cl = pktattr->pattr_class) == NULL)
+ t = m_tag_find(m, PACKET_TAG_PF_QID, NULL);
+ if (t == NULL ||
+ (cl = clh_to_clp(hif, ((struct altq_tag *)(t+1))->qid)) == NULL ||
+ is_a_parent_class(cl)) {
cl = hif->hif_defaultclass;
- cl->cl_pktattr = pktattr; /* save proto hdr used by ECN */
+ if (cl == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ cl->cl_pktattr = NULL;
+ }
len = m_pktlen(m);
if (hfsc_addq(cl, m) != 0) {
@@ -586,9 +630,6 @@ hfsc_enqueue(ifq, m, pktattr)
if (qlen(cl->cl_q) == 1)
set_active(cl, m_pktlen(m));
-#ifdef HFSC_PKTLOG
- /* put the logging_hook here */
-#endif
return (0);
}
@@ -611,39 +652,58 @@ hfsc_dequeue(ifq, op)
struct mbuf *m;
int len, next_len;
int realtime = 0;
+ u_int64_t cur_time;
if (hif->hif_packets == 0)
/* no packet in the tree */
return (NULL);
+ cur_time = read_machclk();
+
if (op == ALTDQ_REMOVE && hif->hif_pollcache != NULL) {
- u_int64_t cur_time;
cl = hif->hif_pollcache;
hif->hif_pollcache = NULL;
/* check if the class was scheduled by real-time criteria */
- if (cl->cl_rsc != NULL) {
- cur_time = read_machclk();
+ if (cl->cl_rsc != NULL)
realtime = (cl->cl_e <= cur_time);
- }
} else {
/*
* if there are eligible classes, use real-time criteria.
* find the class with the minimum deadline among
* the eligible classes.
*/
- if ((cl = ellist_get_mindl(hif->hif_eligible)) != NULL) {
+ if ((cl = ellist_get_mindl(hif->hif_eligible, cur_time))
+ != NULL) {
realtime = 1;
} else {
+#ifdef ALTQ_DEBUG
+ int fits = 0;
+#endif
/*
* use link-sharing criteria
* get the class with the minimum vt in the hierarchy
*/
cl = hif->hif_rootclass;
while (is_a_parent_class(cl)) {
- cl = actlist_first(cl->cl_actc);
- if (cl == NULL)
+
+ cl = actlist_firstfit(cl, cur_time);
+ if (cl == NULL) {
+#ifdef ALTQ_DEBUG
+ if (fits > 0)
+ printf("%d fit but none found\n",fits);
+#endif
return (NULL);
+ }
+ /*
+ * update parent's cl_cvtmin.
+ * don't update if the new vt is smaller.
+ */
+ if (cl->cl_parent->cl_cvtmin < cl->cl_vt)
+ cl->cl_parent->cl_cvtmin = cl->cl_vt;
+#ifdef ALTQ_DEBUG
+ fits++;
+#endif
}
}
@@ -655,12 +715,14 @@ hfsc_dequeue(ifq, op)
}
m = hfsc_getq(cl);
+ if (m == NULL)
+ panic("hfsc_dequeue:");
len = m_pktlen(m);
cl->cl_hif->hif_packets--;
IFQ_DEC_LEN(ifq);
PKTCNTR_ADD(&cl->cl_stats.xmit_cnt, len);
- update_v(cl, len);
+ update_vf(cl, len, cur_time);
if (realtime)
cl->cl_cumul += len;
@@ -679,10 +741,6 @@ hfsc_dequeue(ifq, op)
set_passive(cl);
}
-#ifdef HFSC_PKTLOG
- /* put the logging_hook here */
-#endif
-
return (m);
}
@@ -748,9 +806,12 @@ hfsc_purgeq(cl)
while ((m = _getq(cl->cl_q)) != NULL) {
PKTCNTR_ADD(&cl->cl_stats.drop_cnt, m_pktlen(m));
m_freem(m);
+ cl->cl_hif->hif_packets--;
+ IFQ_DEC_LEN(cl->cl_hif->hif_ifq);
}
ASSERT(qlen(cl->cl_q) == 0);
+ update_vf(cl, 0, 0); /* remove cl from the actlist */
set_passive(cl);
}
@@ -762,7 +823,7 @@ set_active(cl, len)
if (cl->cl_rsc != NULL)
init_ed(cl, len);
if (cl->cl_fsc != NULL)
- init_v(cl, len);
+ init_vf(cl, len);
cl->cl_stats.period++;
}
@@ -774,19 +835,10 @@ set_passive(cl)
if (cl->cl_rsc != NULL)
ellist_remove(cl);
- if (cl->cl_fsc != NULL) {
- while (cl->cl_parent != NULL) {
- if (--cl->cl_nactive == 0) {
- /* remove this class from the vt list */
- actlist_remove(cl);
- } else
- /* still has active children */
- break;
-
- /* go up to the parent class */
- cl = cl->cl_parent;
- }
- }
+ /*
+ * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
+ * needs to be called explicitly to remove a class from actlist
+ */
}
static void
@@ -839,78 +891,207 @@ update_d(cl, next_len)
}
static void
-init_v(cl, len)
+init_vf(cl, len)
struct hfsc_class *cl;
int len;
{
- struct hfsc_class *min_cl, *max_cl;
+ struct hfsc_class *max_cl, *p;
+ u_int64_t vt, f, cur_time;
+ int go_active;
- while (cl->cl_parent != NULL) {
+ cur_time = 0;
+ go_active = 1;
+ for ( ; cl->cl_parent != NULL; cl = cl->cl_parent) {
- if (cl->cl_nactive++ > 0)
- /* already active */
- break;
-
- /*
- * if parent became idle while this class was idle.
- * reset vt and the runtime service curve.
- */
- if (cl->cl_parent->cl_nactive == 0 ||
- cl->cl_parent->cl_vtperiod != cl->cl_parentperiod) {
- cl->cl_vt = 0;
- rtsc_init(&cl->cl_virtual, cl->cl_fsc,
- 0, cl->cl_total);
- }
- min_cl = actlist_first(cl->cl_parent->cl_actc);
- if (min_cl != NULL) {
- u_int64_t vt;
+ if (go_active && cl->cl_nactive++ == 0)
+ go_active = 1;
+ else
+ go_active = 0;
- /*
- * set vt to the average of the min and max classes.
- * if the parent's period didn't change,
- * don't decrease vt of the class.
- */
+ if (go_active) {
max_cl = actlist_last(cl->cl_parent->cl_actc);
- vt = (min_cl->cl_vt + max_cl->cl_vt) / 2;
- if (cl->cl_parent->cl_vtperiod != cl->cl_parentperiod
- || vt > cl->cl_vt)
- cl->cl_vt = vt;
+ if (max_cl != NULL) {
+ /*
+ * set vt to the average of the min and max
+ * classes. if the parent's period didn't
+ * change, don't decrease vt of the class.
+ */
+ vt = max_cl->cl_vt;
+ if (cl->cl_parent->cl_cvtmin != 0)
+ vt = (cl->cl_parent->cl_cvtmin + vt)/2;
+
+ if (cl->cl_parent->cl_vtperiod !=
+ cl->cl_parentperiod || vt > cl->cl_vt)
+ cl->cl_vt = vt;
+ } else {
+ /*
+ * first child for a new parent backlog period.
+ * add parent's cvtmax to vtoff of children
+ * to make a new vt (vtoff + vt) larger than
+ * the vt in the last period for all children.
+ */
+ vt = cl->cl_parent->cl_cvtmax;
+ for (p = cl->cl_parent->cl_children; p != NULL;
+ p = p->cl_siblings)
+ p->cl_vtoff += vt;
+ cl->cl_vt = 0;
+ cl->cl_parent->cl_cvtmax = 0;
+ cl->cl_parent->cl_cvtmin = 0;
+ }
+ cl->cl_initvt = cl->cl_vt;
+
+ /* update the virtual curve */
+ vt = cl->cl_vt + cl->cl_vtoff;
+ rtsc_min(&cl->cl_virtual, cl->cl_fsc, vt, cl->cl_total);
+ if (cl->cl_virtual.x == vt) {
+ cl->cl_virtual.x -= cl->cl_vtoff;
+ cl->cl_vtoff = 0;
+ }
+ cl->cl_vtadj = 0;
+
+ cl->cl_vtperiod++; /* increment vt period */
+ cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;
+ if (cl->cl_parent->cl_nactive == 0)
+ cl->cl_parentperiod++;
+ cl->cl_f = 0;
+
+ actlist_insert(cl);
+
+ if (cl->cl_usc != NULL) {
+ /* class has upper limit curve */
+ if (cur_time == 0)
+ cur_time = read_machclk();
+
+ /* update the ulimit curve */
+ rtsc_min(&cl->cl_ulimit, cl->cl_usc, cur_time,
+ cl->cl_total);
+ /* compute myf */
+ cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
+ cl->cl_total);
+ cl->cl_myfadj = 0;
+ }
}
- /* update the virtual curve */
- rtsc_min(&cl->cl_virtual, cl->cl_fsc, cl->cl_vt, cl->cl_total);
-
- cl->cl_vtperiod++; /* increment vt period */
- cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;
- if (cl->cl_parent->cl_nactive == 0)
- cl->cl_parentperiod++;
-
- actlist_insert(cl);
-
- /* go up to the parent class */
- cl = cl->cl_parent;
+ if (cl->cl_myf > cl->cl_cfmin)
+ f = cl->cl_myf;
+ else
+ f = cl->cl_cfmin;
+ if (f != cl->cl_f) {
+ cl->cl_f = f;
+ update_cfmin(cl->cl_parent);
+ }
}
}
static void
-update_v(cl, len)
+update_vf(cl, len, cur_time)
struct hfsc_class *cl;
int len;
+ u_int64_t cur_time;
{
- while (cl->cl_parent != NULL) {
+ u_int64_t f, myf_bound, delta;
+ int go_passive;
+
+ go_passive = qempty(cl->cl_q);
+
+ for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
cl->cl_total += len;
- if (cl->cl_fsc != NULL) {
- cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total);
+ if (cl->cl_fsc == NULL || cl->cl_nactive == 0)
+ continue;
+
+ if (go_passive && --cl->cl_nactive == 0)
+ go_passive = 1;
+ else
+ go_passive = 0;
+
+ if (go_passive) {
+ /* no more active child, going passive */
+
+ /* update cvtmax of the parent class */
+ if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
+ cl->cl_parent->cl_cvtmax = cl->cl_vt;
+
+ /* remove this class from the vt list */
+ actlist_remove(cl);
+
+ update_cfmin(cl->cl_parent);
- /* update the vt list */
- actlist_update(cl);
+ continue;
}
- /* go up to the parent class */
- cl = cl->cl_parent;
+ /*
+ * update vt and f
+ */
+ cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
+ - cl->cl_vtoff + cl->cl_vtadj;
+
+ /*
+ * if vt of the class is smaller than cvtmin,
+ * the class was skipped in the past due to non-fit.
+ * if so, we need to adjust vtadj.
+ */
+ if (cl->cl_vt < cl->cl_parent->cl_cvtmin) {
+ cl->cl_vtadj += cl->cl_parent->cl_cvtmin - cl->cl_vt;
+ cl->cl_vt = cl->cl_parent->cl_cvtmin;
+ }
+
+ /* update the vt list */
+ actlist_update(cl);
+
+ if (cl->cl_usc != NULL) {
+ cl->cl_myf = cl->cl_myfadj
+ + rtsc_y2x(&cl->cl_ulimit, cl->cl_total);
+
+ /*
+ * if myf lags behind by more than one clock tick
+ * from the current time, adjust myfadj to prevent
+ * a rate-limited class from going greedy.
+ * in a steady state under rate-limiting, myf
+ * fluctuates within one clock tick.
+ */
+ myf_bound = cur_time - machclk_per_tick;
+ if (cl->cl_myf < myf_bound) {
+ delta = cur_time - cl->cl_myf;
+ cl->cl_myfadj += delta;
+ cl->cl_myf += delta;
+ }
+ }
+
+ /* cl_f is max(cl_myf, cl_cfmin) */
+ if (cl->cl_myf > cl->cl_cfmin)
+ f = cl->cl_myf;
+ else
+ f = cl->cl_cfmin;
+ if (f != cl->cl_f) {
+ cl->cl_f = f;
+ update_cfmin(cl->cl_parent);
+ }
+ }
+}
+
+static void
+update_cfmin(cl)
+ struct hfsc_class *cl;
+{
+ struct hfsc_class *p;
+ u_int64_t cfmin;
+
+ if (TAILQ_EMPTY(cl->cl_actc)) {
+ cl->cl_cfmin = 0;
+ return;
+ }
+ cfmin = HT_INFINITY;
+ TAILQ_FOREACH(p, cl->cl_actc, cl_actlist) {
+ if (p->cl_f == 0) {
+ cl->cl_cfmin = 0;
+ return;
+ }
+ if (p->cl_f < cfmin)
+ cfmin = p->cl_f;
}
+ cl->cl_cfmin = cfmin;
}
/*
@@ -1011,13 +1192,11 @@ ellist_update(cl)
/* find the class with the minimum deadline among the eligible classes */
struct hfsc_class *
-ellist_get_mindl(head)
+ellist_get_mindl(head, cur_time)
ellist_t *head;
+ u_int64_t cur_time;
{
struct hfsc_class *p, *cl = NULL;
- u_int64_t cur_time;
-
- cur_time = read_machclk();
TAILQ_FOREACH(p, head, cl_ellist) {
if (p->cl_e > cur_time)
@@ -1090,7 +1269,7 @@ actlist_update(cl)
* if the next entry has a larger virtual time, nothing to do.
*/
p = TAILQ_NEXT(cl, cl_actlist);
- if (p == NULL || cl->cl_vt <= p->cl_vt)
+ if (p == NULL || cl->cl_vt < p->cl_vt)
return;
/* check the last entry */
@@ -1116,6 +1295,20 @@ actlist_update(cl)
ASSERT(0); /* should not reach here */
}
+static struct hfsc_class *
+actlist_firstfit(cl, cur_time)
+ struct hfsc_class *cl;
+ u_int64_t cur_time;
+{
+ struct hfsc_class *p;
+
+ TAILQ_FOREACH(p, cl->cl_actc, cl_actlist) {
+ if (p->cl_f <= cur_time)
+ return (p);
+ }
+ return (NULL);
+}
+
/*
* service curve support functions
*
@@ -1132,7 +1325,7 @@ actlist_update(cl)
* speed. SM_SHIFT and ISM_SHIFT are selected to have at least 3 effective
* digits in decimal using the following table.
*
- * bits/set 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps
+ * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps
* ----------+-------------------------------------------------------
* bytes/nsec 12.5e-6 125e-6 1250e-6 12500e-6 125000e-6
* sm(500MHz) 25.0e-6 250e-6 2500e-6 25000e-6 250000e-6
@@ -1145,8 +1338,8 @@ actlist_update(cl)
#define SM_SHIFT 24
#define ISM_SHIFT 10
-#define SC_LARGEVAL (1LL << 32)
-#define SC_INFINITY 0xffffffffffffffffLL
+#define SM_MASK ((1LL << SM_SHIFT) - 1)
+#define ISM_MASK ((1LL << ISM_SHIFT) - 1)
static __inline u_int64_t
seg_x2y(x, sm)
@@ -1155,10 +1348,12 @@ seg_x2y(x, sm)
{
u_int64_t y;
- if (x < SC_LARGEVAL)
- y = x * sm >> SM_SHIFT;
- else
- y = (x >> SM_SHIFT) * sm;
+ /*
+ * compute
+ * y = x * sm >> SM_SHIFT
+ * but divide it for the upper and lower bits to avoid overflow
+ */
+ y = (x >> SM_SHIFT) * sm + (((x & SM_MASK) * sm) >> SM_SHIFT);
return (y);
}
@@ -1171,12 +1366,12 @@ seg_y2x(y, ism)
if (y == 0)
x = 0;
- else if (ism == SC_INFINITY)
- x = SC_INFINITY;
- else if (y < SC_LARGEVAL)
- x = y * ism >> ISM_SHIFT;
- else
- x = (y >> ISM_SHIFT) * ism;
+ else if (ism == HT_INFINITY)
+ x = HT_INFINITY;
+ else {
+ x = (y >> ISM_SHIFT) * ism
+ + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
+ }
return (x);
}
@@ -1197,7 +1392,7 @@ m2ism(m)
u_int64_t ism;
if (m == 0)
- ism = SC_INFINITY;
+ ism = HT_INFINITY;
else
ism = ((u_int64_t)machclk_freq << ISM_SHIFT) * 8 / m;
return (ism);
@@ -1379,345 +1574,13 @@ rtsc_min(rtsc, isc, x, y)
return;
}
-/*
- * hfsc device interface
- */
-int
-hfscopen(dev, flag, fmt, p)
- dev_t dev;
- int flag, fmt;
- struct proc *p;
-{
- if (machclk_freq == 0)
- init_machclk();
-
- if (machclk_freq == 0) {
- printf("hfsc: no cpu clock available!\n");
- return (ENXIO);
- }
-
- /* everything will be done when the queueing scheme is attached. */
- return 0;
-}
-
-int
-hfscclose(dev, flag, fmt, p)
- dev_t dev;
- int flag, fmt;
- struct proc *p;
-{
- struct hfsc_if *hif;
- int err, error = 0;
-
- while ((hif = hif_list) != NULL) {
- /* destroy all */
- if (ALTQ_IS_ENABLED(hif->hif_ifq))
- altq_disable(hif->hif_ifq);
-
- err = altq_detach(hif->hif_ifq);
- if (err == 0)
- err = hfsc_detach(hif);
- if (err != 0 && error == 0)
- error = err;
- }
-
- return error;
-}
-
-int
-hfscioctl(dev, cmd, addr, flag, p)
- dev_t dev;
- ioctlcmd_t cmd;
- caddr_t addr;
- int flag;
- struct proc *p;
-{
- struct hfsc_if *hif;
- struct hfsc_interface *ifacep;
- int error = 0;
-
- /* check super-user privilege */
- switch (cmd) {
- case HFSC_GETSTATS:
- break;
- default:
-#if (__FreeBSD_version > 400000)
- if ((error = suser(p)) != 0)
- return (error);
-#else
- if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
- return (error);
-#endif
- break;
- }
-
- switch (cmd) {
-
- case HFSC_IF_ATTACH:
- error = hfsccmd_if_attach((struct hfsc_attach *)addr);
- break;
-
- case HFSC_IF_DETACH:
- error = hfsccmd_if_detach((struct hfsc_interface *)addr);
- break;
-
- case HFSC_ENABLE:
- case HFSC_DISABLE:
- case HFSC_CLEAR_HIERARCHY:
- ifacep = (struct hfsc_interface *)addr;
- if ((hif = altq_lookup(ifacep->hfsc_ifname,
- ALTQT_HFSC)) == NULL) {
- error = EBADF;
- break;
- }
-
- switch (cmd) {
-
- case HFSC_ENABLE:
- if (hif->hif_defaultclass == NULL) {
-#ifdef ALTQ_DEBUG
- printf("hfsc: no default class\n");
-#endif
- error = EINVAL;
- break;
- }
- error = altq_enable(hif->hif_ifq);
- break;
-
- case HFSC_DISABLE:
- error = altq_disable(hif->hif_ifq);
- break;
-
- case HFSC_CLEAR_HIERARCHY:
- hfsc_clear_interface(hif);
- break;
- }
- break;
-
- case HFSC_ADD_CLASS:
- error = hfsccmd_add_class((struct hfsc_add_class *)addr);
- break;
-
- case HFSC_DEL_CLASS:
- error = hfsccmd_delete_class((struct hfsc_delete_class *)addr);
- break;
-
- case HFSC_MOD_CLASS:
- error = hfsccmd_modify_class((struct hfsc_modify_class *)addr);
- break;
-
- case HFSC_ADD_FILTER:
- error = hfsccmd_add_filter((struct hfsc_add_filter *)addr);
- break;
-
- case HFSC_DEL_FILTER:
- error = hfsccmd_delete_filter((struct hfsc_delete_filter *)addr);
- break;
-
- case HFSC_GETSTATS:
- error = hfsccmd_class_stats((struct hfsc_class_stats *)addr);
- break;
-
- default:
- error = EINVAL;
- break;
- }
- return error;
-}
-
-static int
-hfsccmd_if_attach(ap)
- struct hfsc_attach *ap;
-{
- struct hfsc_if *hif;
- struct ifnet *ifp;
- int error;
-
- if ((ifp = ifunit(ap->iface.hfsc_ifname)) == NULL)
- return (ENXIO);
-
- if ((hif = hfsc_attach(&ifp->if_snd, ap->bandwidth)) == NULL)
- return (ENOMEM);
-
- /*
- * set HFSC to this ifnet structure.
- */
- if ((error = altq_attach(&ifp->if_snd, ALTQT_HFSC, hif,
- hfsc_enqueue, hfsc_dequeue, hfsc_request,
- &hif->hif_classifier, acc_classify)) != 0)
- (void)hfsc_detach(hif);
-
- return (error);
-}
-
-static int
-hfsccmd_if_detach(ap)
- struct hfsc_interface *ap;
-{
- struct hfsc_if *hif;
- int error;
-
- if ((hif = altq_lookup(ap->hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- if (ALTQ_IS_ENABLED(hif->hif_ifq))
- altq_disable(hif->hif_ifq);
-
- if ((error = altq_detach(hif->hif_ifq)))
- return (error);
-
- return hfsc_detach(hif);
-}
-
-static int
-hfsccmd_add_class(ap)
- struct hfsc_add_class *ap;
-{
- struct hfsc_if *hif;
- struct hfsc_class *cl, *parent;
-
- if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- if ((parent = clh_to_clp(hif, ap->parent_handle)) == NULL) {
- if (ap->parent_handle == HFSC_ROOTCLASS_HANDLE)
- parent = hif->hif_rootclass;
- else
- return (EINVAL);
- }
-
- if ((cl = hfsc_class_create(hif, &ap->service_curve, parent,
- ap->qlimit, ap->flags)) == NULL)
- return (ENOMEM);
-
- /* return a class handle to the user */
- ap->class_handle = clp_to_clh(cl);
- return (0);
-}
-
-static int
-hfsccmd_delete_class(ap)
- struct hfsc_delete_class *ap;
-{
- struct hfsc_if *hif;
- struct hfsc_class *cl;
-
- if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- if ((cl = clh_to_clp(hif, ap->class_handle)) == NULL)
- return (EINVAL);
-
- return hfsc_class_destroy(cl);
-}
-
-static int
-hfsccmd_modify_class(ap)
- struct hfsc_modify_class *ap;
-{
- struct hfsc_if *hif;
- struct hfsc_class *cl;
- struct service_curve *rsc = NULL;
- struct service_curve *fsc = NULL;
-
- if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- if ((cl = clh_to_clp(hif, ap->class_handle)) == NULL)
- return (EINVAL);
-
- if (ap->sctype & HFSC_REALTIMESC)
- rsc = &ap->service_curve;
- if (ap->sctype & HFSC_LINKSHARINGSC)
- fsc = &ap->service_curve;
-
- return hfsc_class_modify(cl, rsc, fsc);
-}
-
-static int
-hfsccmd_add_filter(ap)
- struct hfsc_add_filter *ap;
-{
- struct hfsc_if *hif;
- struct hfsc_class *cl;
-
- if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- if ((cl = clh_to_clp(hif, ap->class_handle)) == NULL)
- return (EINVAL);
-
- if (is_a_parent_class(cl)) {
-#ifdef ALTQ_DEBUG
- printf("hfsccmd_add_filter: not a leaf class!\n");
-#endif
- return (EINVAL);
- }
-
- return acc_add_filter(&hif->hif_classifier, &ap->filter,
- cl, &ap->filter_handle);
-}
-
-static int
-hfsccmd_delete_filter(ap)
- struct hfsc_delete_filter *ap;
-{
- struct hfsc_if *hif;
-
- if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- return acc_delete_filter(&hif->hif_classifier,
- ap->filter_handle);
-}
-
-static int
-hfsccmd_class_stats(ap)
- struct hfsc_class_stats *ap;
-{
- struct hfsc_if *hif;
- struct hfsc_class *cl;
- struct class_stats stats, *usp;
- int n, nclasses, error;
-
- if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
- return (EBADF);
-
- ap->cur_time = read_machclk();
- ap->hif_classes = hif->hif_classes;
- ap->hif_packets = hif->hif_packets;
-
- /* skip the first N classes in the tree */
- nclasses = ap->nskip;
- for (cl = hif->hif_rootclass, n = 0; cl != NULL && n < nclasses;
- cl = hfsc_nextclass(cl), n++)
- ;
- if (n != nclasses)
- return (EINVAL);
-
- /* then, read the next N classes in the tree */
- nclasses = ap->nclasses;
- usp = ap->stats;
- for (n = 0; cl != NULL && n < nclasses; cl = hfsc_nextclass(cl), n++) {
-
- get_class_stats(&stats, cl);
-
- if ((error = copyout((caddr_t)&stats, (caddr_t)usp++,
- sizeof(stats))) != 0)
- return (error);
- }
-
- ap->nclasses = n;
-
- return (0);
-}
-
-static void get_class_stats(sp, cl)
- struct class_stats *sp;
+static void
+get_class_stats(sp, cl)
+ struct hfsc_classstats *sp;
struct hfsc_class *cl;
{
sp->class_id = cl->cl_id;
- sp->class_handle = clp_to_clh(cl);
+ sp->class_handle = cl->cl_handle;
if (cl->cl_rsc != NULL) {
sp->rsc.m1 = sm2m(cl->cl_rsc->sm1);
@@ -1737,6 +1600,15 @@ static void get_class_stats(sp, cl)
sp->fsc.d = 0;
sp->fsc.m2 = 0;
}
+ if (cl->cl_usc != NULL) {
+ sp->usc.m1 = sm2m(cl->cl_usc->sm1);
+ sp->usc.d = dx2d(cl->cl_usc->dx);
+ sp->usc.m2 = sm2m(cl->cl_usc->sm2);
+ } else {
+ sp->usc.m1 = 0;
+ sp->usc.d = 0;
+ sp->usc.m2 = 0;
+ }
sp->total = cl->cl_total;
sp->cumul = cl->cl_cumul;
@@ -1744,8 +1616,25 @@ static void get_class_stats(sp, cl)
sp->d = cl->cl_d;
sp->e = cl->cl_e;
sp->vt = cl->cl_vt;
+ sp->f = cl->cl_f;
+
+ sp->initvt = cl->cl_initvt;
+ sp->vtperiod = cl->cl_vtperiod;
+ sp->parentperiod = cl->cl_parentperiod;
+ sp->nactive = cl->cl_nactive;
+ sp->vtoff = cl->cl_vtoff;
+ sp->cvtmax = cl->cl_cvtmax;
+ sp->myf = cl->cl_myf;
+ sp->cfmin = cl->cl_cfmin;
+ sp->cvtmin = cl->cl_cvtmin;
+ sp->myfadj = cl->cl_myfadj;
+ sp->vtadj = cl->cl_vtadj;
+
+ sp->cur_time = read_machclk();
+ sp->machclk_freq = machclk_freq;
sp->qlength = qlen(cl->cl_q);
+ sp->qlimit = qlimit(cl->cl_q);
sp->xmit_cnt = cl->cl_stats.xmit_cnt;
sp->drop_cnt = cl->cl_stats.drop_cnt;
sp->period = cl->cl_stats.period;
@@ -1765,39 +1654,14 @@ static void get_class_stats(sp, cl)
static struct hfsc_class *
clh_to_clp(hif, chandle)
struct hfsc_if *hif;
- u_long chandle;
+ u_int32_t chandle;
{
- struct hfsc_class *cl;
+ int idx;
- cl = (struct hfsc_class *)chandle;
- if (chandle != ALIGN(cl)) {
-#ifdef ALTQ_DEBUG
- printf("clh_to_cl: unaligned pointer %p\n", cl);
-#endif
+ if (chandle == 0)
return (NULL);
- }
-
- if (cl == NULL || cl->cl_handle != chandle || cl->cl_hif != hif)
+ idx = chandle - 1;
+ if (idx >= HFSC_MAX_CLASSES)
return (NULL);
-
- return (cl);
-}
-
-/* convert a class pointer to the corresponding class handle */
-static u_long
-clp_to_clh(cl)
- struct hfsc_class *cl;
-{
- if (cl->cl_parent == NULL)
- return (HFSC_ROOTCLASS_HANDLE); /* XXX */
- return (cl->cl_handle);
+ return (hif->hif_class_tbl[idx]);
}
-
-#ifdef KLD_MODULE
-
-static struct altqsw hfsc_sw =
- {"hfsc", hfscopen, hfscclose, hfscioctl};
-
-ALTQ_MODULE(altq_hfsc, ALTQT_HFSC, &hfsc_sw);
-
-#endif /* KLD_MODULE */