Same as v3, only it applies to -current. ok?
Index: altq/if_altq.h =================================================================== RCS file: /cvs/src/sys/altq/if_altq.h,v retrieving revision 1.16 diff -u -p -r1.16 if_altq.h --- altq/if_altq.h 12 Oct 2013 12:13:10 -0000 1.16 +++ altq/if_altq.h 31 Oct 2013 11:35:22 -0000 @@ -36,6 +36,13 @@ struct altq_pktattr; struct oldtb_regula /* * Structure defining a queue for a network interface. */ + +/* XXX hack, because we need the structure definition */ +#define ALTQ_IS_ENABLED 1 +#include <net/hfsc.h> +#undef ALTQ_IS_ENABLED +/* XXX hack */ + struct ifaltq { /* fields compatible with struct ifqueue */ struct { @@ -45,8 +52,8 @@ struct ifaltq { int ifq_len; int ifq_maxlen; int ifq_drops; - struct hfsc_if *ifq_hfsc; struct timeout *ifq_congestion; + struct hfsc_if ifq_hfsc; /* alternate queueing related fields */ int altq_type; /* discipline type */ Index: net/hfsc.c =================================================================== RCS file: /cvs/src/sys/net/hfsc.c,v retrieving revision 1.2 diff -u -p -r1.2 hfsc.c --- net/hfsc.c 31 Oct 2013 08:52:44 -0000 1.2 +++ net/hfsc.c 31 Oct 2013 11:35:23 -0000 @@ -63,7 +63,7 @@ /* * function prototypes */ -struct hfsc_class *hfsc_class_create(struct hfsc_if *, +struct hfsc_class *hfsc_class_create(struct ifqueue *, struct hfsc_sc *, struct hfsc_sc *, struct hfsc_sc *, struct hfsc_class *, int, int, int); @@ -129,18 +129,50 @@ hfsc_microuptime(void) HFSC_CLK_SHIFT); } +/* + * The new table will be exactly one page larger, so in the most + * common case of 8B pointers and 4KB pages it's 512 more classes. + * Returns the amount of classes, so all new pages are 100% utilized. + */ +static inline u_int +hfsc_more_slots(u_int current) +{ + u_int was_pages = current * sizeof(void *) / PAGE_SIZE; + u_int n = ((was_pages + 1) * PAGE_SIZE) / sizeof(void *); + + return (n); +} + +static void +hfsc_grow_class_tbl(struct hfsc_if *hif) +{ + struct hfsc_class **newtbl, **old = hif->hif_class_tbl; + const u_int slots = hfsc_more_slots(hif->hif_allocated); + + newtbl = malloc(slots * sizeof(void *), M_DEVBUF, M_WAITOK | M_ZERO); + memcpy(newtbl, old, hif->hif_allocated * sizeof(void *)); + + hif->hif_allocated = slots; + hif->hif_class_tbl = newtbl; + + free(old, M_DEVBUF); +} + int hfsc_attach(struct ifnet *ifp) { - struct hfsc_if *hif; + const u_int slots = hfsc_more_slots(0); + const size_t sz = slots * sizeof(void *); + struct hfsc_if *hif = &ifp->if_snd.ifq_hfsc; - if (ifp->if_snd.ifq_hfsc != NULL) + if (hif->hif_class_tbl != NULL) return (0); - hif = malloc(sizeof(struct hfsc_if), M_DEVBUF, M_WAITOK|M_ZERO); + hif->hif_class_tbl = malloc(sz, M_DEVBUF, M_WAITOK | M_ZERO); + hif->hif_allocated = slots; + hif->hif_classes = 0; hif->hif_eligible = hfsc_ellist_alloc(); - hif->hif_ifq = (struct ifqueue *)&ifp->if_snd; /* XXX cast temp */ - ifp->if_snd.ifq_hfsc = hif; + timeout_set(&hif->hif_defer, hfsc_deferred, ifp); /* XXX HRTIMER don't schedule it yet, only when some packets wait. */ timeout_add(&hif->hif_defer, 1); @@ -151,9 +183,12 @@ hfsc_attach(struct ifnet *ifp) int hfsc_detach(struct ifnet *ifp) { - timeout_del(&ifp->if_snd.ifq_hfsc->hif_defer); - free(ifp->if_snd.ifq_hfsc, M_DEVBUF); - ifp->if_snd.ifq_hfsc = NULL; + struct hfsc_if *hif = &ifp->if_snd.ifq_hfsc; + + timeout_del(&hif->hif_defer); + hif->hif_allocated = hif->hif_classes = 0; + free(hif->hif_class_tbl, M_DEVBUF); + hif->hif_class_tbl = NULL; return (0); } @@ -161,11 +196,13 @@ hfsc_detach(struct ifnet *ifp) int hfsc_addqueue(struct pf_queuespec *q) { - struct hfsc_if *hif; + /* XXX remove the cast when ifaltq is gone. */ + struct ifqueue *ifq = (struct ifqueue *)&q->kif->pfik_ifp->if_snd; + struct hfsc_if *hif = &ifq->ifq_hfsc; struct hfsc_class *cl, *parent; struct hfsc_sc rtsc, lssc, ulsc; - if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL) + if (hif->hif_allocated == 0) return (EINVAL); if (q->parent_qid == HFSC_NULLCLASS_HANDLE && @@ -190,7 +227,7 @@ hfsc_addqueue(struct pf_queuespec *q) ulsc.d = q->upperlimit.d; ulsc.m2 = q->upperlimit.m2.absolute; - cl = hfsc_class_create(hif, &rtsc, &lssc, &ulsc, + cl = hfsc_class_create(ifq, &rtsc, &lssc, &ulsc, parent, q->qlimit, q->flags, q->qid); if (cl == NULL) return (ENOMEM); @@ -201,10 +238,10 @@ hfsc_addqueue(struct pf_queuespec *q) int hfsc_delqueue(struct pf_queuespec *q) { - struct hfsc_if *hif; + struct hfsc_if *hif = &q->kif->pfik_ifp->if_snd.ifq_hfsc; struct hfsc_class *cl; - if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL) + if (hif->hif_allocated == 0) return (EINVAL); if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL) @@ -216,12 +253,12 @@ hfsc_delqueue(struct pf_queuespec *q) int hfsc_qstats(struct pf_queuespec *q, void *ubuf, int *nbytes) { - struct hfsc_if *hif; + struct hfsc_if *hif = &q->kif->pfik_ifp->if_snd.ifq_hfsc; struct hfsc_class *cl; struct hfsc_class_stats stats; int error = 0; - if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL) + if (hif->hif_allocated == 0) return (EBADF); if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL) @@ -241,25 +278,26 @@ hfsc_qstats(struct pf_queuespec *q, void void hfsc_purge(struct ifqueue *ifq) { - struct hfsc_if *hif = ifq->ifq_hfsc; + struct hfsc_if *hif = &ifq->ifq_hfsc; struct hfsc_class *cl; for (cl = hif->hif_rootclass; cl != NULL; cl = hfsc_nextclass(cl)) if (cl->cl_q->qlen > 0) hfsc_purgeq(cl); - hif->hif_ifq->ifq_len = 0; + ifq->ifq_len = 0; } struct hfsc_class * -hfsc_class_create(struct hfsc_if *hif, struct hfsc_sc *rsc, +hfsc_class_create(struct ifqueue *ifq, struct hfsc_sc *rsc, struct hfsc_sc *fsc, struct hfsc_sc *usc, struct hfsc_class *parent, int qlimit, int flags, int qid) { + struct hfsc_if *hif = &ifq->ifq_hfsc; struct hfsc_class *cl, *p; int i, s; - if (hif->hif_classes >= HFSC_MAX_CLASSES) - return (NULL); + if (hif->hif_classes >= hif->hif_allocated) + hfsc_grow_class_tbl(hif); cl = malloc(sizeof(struct hfsc_class), M_DEVBUF, M_WAITOK|M_ZERO); cl->cl_q = malloc(sizeof(struct hfsc_classq), M_DEVBUF, @@ -290,7 +328,7 @@ hfsc_class_create(struct hfsc_if *hif, s if (m2 < 8) red_pkttime = 1000 * 1000 * 1000; /* 1 sec */ else - red_pkttime = (int64_t)hif->hif_ifq->altq_ifp->if_mtu + red_pkttime = (int64_t)ifq->altq_ifp->if_mtu * 1000 * 1000 * 1000 / (m2 / 8); if (flags & HFSC_RED) { cl->cl_red = red_alloc(0, 0, @@ -324,7 +362,7 @@ hfsc_class_create(struct hfsc_if *hif, s cl->cl_id = hif->hif_classid++; cl->cl_handle = qid; - cl->cl_hif = hif; + cl->cl_ifq = ifq; cl->cl_parent = parent; s = splnet(); @@ -335,16 +373,16 @@ hfsc_class_create(struct hfsc_if *hif, s * the lower bits of qid is free, use this slot. otherwise, * use the first free slot. */ - i = qid % HFSC_MAX_CLASSES; + i = qid % hif->hif_allocated; if (hif->hif_class_tbl[i] == NULL) hif->hif_class_tbl[i] = cl; else { - for (i = 0; i < HFSC_MAX_CLASSES; i++) + for (i = 0; i < hif->hif_allocated; i++) if (hif->hif_class_tbl[i] == NULL) { hif->hif_class_tbl[i] = cl; break; } - if (i == HFSC_MAX_CLASSES) { + if (i == hif->hif_allocated) { splx(s); goto err_ret; } @@ -393,6 +431,7 @@ err_ret: int hfsc_class_destroy(struct hfsc_class *cl) { + struct hfsc_if *hif = &cl->cl_ifq->ifq_hfsc; int i, s; if (cl == NULL) @@ -419,13 +458,13 @@ hfsc_class_destroy(struct hfsc_class *cl } while ((p = p->cl_siblings) != NULL); } - for (i = 0; i < HFSC_MAX_CLASSES; i++) - if (cl->cl_hif->hif_class_tbl[i] == cl) { - cl->cl_hif->hif_class_tbl[i] = NULL; + for (i = 0; i < hif->hif_allocated; i++) + if (hif->hif_class_tbl[i] == cl) { + hif->hif_class_tbl[i] = NULL; break; } - cl->cl_hif->hif_classes--; + hif->hif_classes--; splx(s); hfsc_actlist_destroy(cl->cl_actc); @@ -437,10 +476,10 @@ hfsc_class_destroy(struct hfsc_class *cl } #endif - if (cl == cl->cl_hif->hif_rootclass) - cl->cl_hif->hif_rootclass = NULL; - if (cl == cl->cl_hif->hif_defaultclass) - cl->cl_hif->hif_defaultclass = NULL; + if (cl == cl->cl_ifq->ifq_hfsc.hif_rootclass) + cl->cl_ifq->ifq_hfsc.hif_rootclass = NULL; + if (cl == cl->cl_ifq->ifq_hfsc.hif_defaultclass) + cl->cl_ifq->ifq_hfsc.hif_defaultclass = NULL; if (cl->cl_usc != NULL) free(cl->cl_usc, M_DEVBUF); @@ -481,7 +520,7 @@ hfsc_nextclass(struct hfsc_class *cl) int hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m) { - struct hfsc_if *hif = ifq->ifq_hfsc; + struct hfsc_if *hif = &ifq->ifq_hfsc; struct hfsc_class *cl; if ((cl = hfsc_clh2cph(hif, m->m_pkthdr.pf.qid)) == NULL || @@ -501,7 +540,7 @@ hfsc_enqueue(struct ifqueue *ifq, struct return (ENOBUFS); } IFQ_INC_LEN(ifq); - cl->cl_hif->hif_packets++; + cl->cl_ifq->ifq_hfsc.hif_packets++; m->m_pkthdr.pf.prio = IFQ_MAXPRIO; /* successfully queued. */ @@ -514,7 +553,7 @@ hfsc_enqueue(struct ifqueue *ifq, struct struct mbuf * hfsc_dequeue(struct ifqueue *ifq, int remove) { - struct hfsc_if *hif = ifq->ifq_hfsc; + struct hfsc_if *hif = &ifq->ifq_hfsc; struct hfsc_class *cl, *tcl; struct mbuf *m; int next_len, realtime = 0; @@ -583,7 +622,7 @@ hfsc_dequeue(struct ifqueue *ifq, int re if (m == NULL) panic("hfsc_dequeue"); - cl->cl_hif->hif_packets--; + cl->cl_ifq->ifq_hfsc.hif_packets--; IFQ_DEC_LEN(ifq); PKTCNTR_INC(&cl->cl_stats.xmit_cnt, m->m_pkthdr.len); @@ -621,7 +660,7 @@ hfsc_deferred(void *arg) splx(s); /* XXX HRTIMER nearest virtual/fit time is likely less than 1/HZ. */ - timeout_add(&ifp->if_snd.ifq_hfsc->hif_defer, 1); + timeout_add(&ifp->if_snd.ifq_hfsc.hif_defer, 1); } int @@ -682,8 +721,8 @@ hfsc_purgeq(struct hfsc_class *cl) while ((m = hfsc_getq(cl)) != NULL) { PKTCNTR_INC(&cl->cl_stats.drop_cnt, m->m_pkthdr.len); m_freem(m); - cl->cl_hif->hif_packets--; - IFQ_DEC_LEN(cl->cl_hif->hif_ifq); + cl->cl_ifq->ifq_hfsc.hif_packets--; + IFQ_DEC_LEN(cl->cl_ifq); } hfsc_update_vf(cl, 0, 0); /* remove cl from the actlist */ @@ -976,7 +1015,7 @@ hfsc_ellist_destroy(hfsc_ellist_t *head) void hfsc_ellist_insert(struct hfsc_class *cl) { - struct hfsc_if *hif = cl->cl_hif; + struct hfsc_if *hif = &cl->cl_ifq->ifq_hfsc; struct hfsc_class *p; /* check the last entry first */ @@ -997,7 +1036,7 @@ hfsc_ellist_insert(struct hfsc_class *cl void hfsc_ellist_remove(struct hfsc_class *cl) { - struct hfsc_if *hif = cl->cl_hif; + struct hfsc_if *hif = &cl->cl_ifq->ifq_hfsc; TAILQ_REMOVE(hif->hif_eligible, cl, cl_ellist); } @@ -1005,7 +1044,7 @@ hfsc_ellist_remove(struct hfsc_class *cl void hfsc_ellist_update(struct hfsc_class *cl) { - struct hfsc_if *hif = cl->cl_hif; + struct hfsc_if *hif = &cl->cl_ifq->ifq_hfsc; struct hfsc_class *p, *last; /* @@ -1475,10 +1514,10 @@ hfsc_clh2cph(struct hfsc_if *hif, u_int3 * first, try the slot corresponding to the lower bits of the handle. * if it does not match, do the linear table search. */ - i = chandle % HFSC_MAX_CLASSES; + i = chandle % hif->hif_allocated; if ((cl = hif->hif_class_tbl[i]) != NULL && cl->cl_handle == chandle) return (cl); - for (i = 0; i < HFSC_MAX_CLASSES; i++) + for (i = 0; i < hif->hif_allocated; i++) if ((cl = hif->hif_class_tbl[i]) != NULL && cl->cl_handle == chandle) return (cl); Index: net/hfsc.h =================================================================== RCS file: /cvs/src/sys/net/hfsc.h,v retrieving revision 1.2 diff -u -p -r1.2 hfsc.h --- net/hfsc.h 31 Oct 2013 08:52:44 -0000 1.2 +++ net/hfsc.h 31 Oct 2013 11:35:23 -0000 @@ -57,7 +57,6 @@ struct hfsc_sc { /* special class handles */ #define HFSC_NULLCLASS_HANDLE 0 -#define HFSC_MAX_CLASSES 64 /* service curve types */ #define HFSC_REALTIMESC 1 @@ -170,7 +169,7 @@ typedef TAILQ_ENTRY(hfsc_class) hfsc_act struct hfsc_class { u_int cl_id; /* class id (just for debug) */ u_int32_t cl_handle; /* class handle */ - struct hfsc_if *cl_hif; /* back pointer to struct hfsc_if */ + struct ifqueue *cl_ifq; /* back pointer to our ifqueue */ int cl_flags; /* misc flags */ struct hfsc_class *cl_parent; /* parent class */ @@ -232,13 +231,12 @@ struct hfsc_class { * hfsc interface state */ struct hfsc_if { - struct hfsc_if *hif_next; /* interface state list */ - struct ifqueue *hif_ifq; /* backpointer to ifq */ + struct hfsc_class **hif_class_tbl; struct hfsc_class *hif_rootclass; /* root class */ struct hfsc_class *hif_defaultclass; /* default class */ - struct hfsc_class *hif_class_tbl[HFSC_MAX_CLASSES]; struct hfsc_class *hif_pollcache; /* cache for poll operation */ + u_int hif_allocated; /* how many slots above */ u_int hif_classes; /* # of classes in the tree */ u_int hif_packets; /* # of packets in the tree */ u_int hif_classid; /* class id sequence number */ @@ -251,7 +249,7 @@ struct hfsc_if { #define HFSC_FREQ (1000000 << HFSC_CLK_SHIFT) #define HFSC_CLK_PER_TICK (HFSC_FREQ / hz) -#define HFSC_ENABLED(ifq) ((ifq)->ifq_hfsc != NULL) +#define HFSC_ENABLED(ifq) ((ifq)->ifq_hfsc.hif_class_tbl != NULL) #define HFSC_DEFAULT_QLIMIT 50 /* XXX hack */ Index: net/if.h =================================================================== RCS file: /cvs/src/sys/net/if.h,v retrieving revision 1.150 diff -u -p -r1.150 if.h --- net/if.h 21 Oct 2013 15:10:29 -0000 1.150 +++ net/if.h 31 Oct 2013 11:35:23 -0000 @@ -184,8 +184,8 @@ struct ifqueue { int ifq_len; int ifq_maxlen; int ifq_drops; - struct hfsc_if *ifq_hfsc; struct timeout *ifq_congestion; + struct hfsc_if ifq_hfsc; }; /*