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;
 };
 
 /*

Reply via email to