By hiding H-FSC behind pfq_ops structure similar to the ifq_ops,
we could provide alternative queueing interfaces for use in Pf.

There are no other functional changes here except that the default
H-FSC qlimit assignment happens in hfsc_class_create so there's no
need to do it in the pf_ioctl code.  I did change the order of
elements in hfsc_class_stats a bit to provide some compatibility
between queue stat structures of different traffic conditioners.
This is just to make my life a bit easier.

OK?

diff --git sys/net/hfsc.c sys/net/hfsc.c
index f28b6a5205c..239fd8f36e2 100644
--- sys/net/hfsc.c
+++ sys/net/hfsc.c
@@ -277,10 +277,28 @@ const struct ifq_ops hfsc_ops = {
        hfsc_free,
 };
 
 const struct ifq_ops * const ifq_hfsc_ops = &hfsc_ops;
 
+/*
+ * pf queue glue.
+ */
+
+void           *hfsc_pf_alloc(struct ifnet *);
+int             hfsc_pf_addqueue(void *, struct pf_queuespec *);
+void            hfsc_pf_free(void *);
+int             hfsc_pf_qstats(struct pf_queuespec *, void *, int *);
+
+const struct pfq_ops hfsc_pf_ops = {
+       hfsc_pf_alloc,
+       hfsc_pf_addqueue,
+       hfsc_pf_free,
+       hfsc_pf_qstats
+};
+
+const struct pfq_ops * const pfq_hfsc_ops = &hfsc_pf_ops;
+
 u_int64_t
 hfsc_microuptime(void)
 {
        struct timeval tv;
 
@@ -321,11 +339,11 @@ hfsc_initialize(void)
            IPL_NONE, PR_WAITOK, "hfscclass", NULL);
        pool_init(&hfsc_internal_sc_pl, sizeof(struct hfsc_internal_sc), 0,
            IPL_NONE, PR_WAITOK, "hfscintsc", NULL);
 }
 
-struct hfsc_if *
+void *
 hfsc_pf_alloc(struct ifnet *ifp)
 {
        struct hfsc_if *hif;
 
        KASSERT(ifp != NULL);
@@ -340,12 +358,13 @@ hfsc_pf_alloc(struct ifnet *ifp)
 
        return (hif);
 }
 
 int
-hfsc_pf_addqueue(struct hfsc_if *hif, struct pf_queuespec *q)
+hfsc_pf_addqueue(void *arg, struct pf_queuespec *q)
 {
+       struct hfsc_if *hif = arg;
        struct hfsc_class *cl, *parent;
        struct hfsc_sc rtsc, lssc, ulsc;
 
        KASSERT(hif != NULL);
 
@@ -414,12 +433,14 @@ hfsc_pf_qstats(struct pf_queuespec *q, void *ubuf, int 
*nbytes)
        *nbytes = sizeof(stats);
        return (0);
 }
 
 void
-hfsc_pf_free(struct hfsc_if *hif)
+hfsc_pf_free(void *arg)
 {
+       struct hfsc_if *hif = arg;
+
        hfsc_free(0, hif);
 }
 
 unsigned int
 hfsc_idx(unsigned int nqueues, const struct mbuf *m)
diff --git sys/net/hfsc.h sys/net/hfsc.h
index 88108f60d52..d2e82c807b2 100644
--- sys/net/hfsc.h
+++ sys/net/hfsc.h
@@ -32,13 +32,10 @@
  */
 #ifndef _HFSC_H_
 #define        _HFSC_H_
 
 /* hfsc class flags */
-#define        HFSC_RED                0x0001  /* use RED */
-#define        HFSC_ECN                0x0002  /* use RED/ECN */
-#define        HFSC_RIO                0x0004  /* use RIO */
 #define        HFSC_DEFAULTCLASS       0x1000  /* default class */
 
 struct hfsc_pktcntr {
        u_int64_t       packets;
        u_int64_t       bytes;
@@ -63,10 +60,17 @@ struct hfsc_sc {
 #define        HFSC_LINKSHARINGSC      2
 #define        HFSC_UPPERLIMITSC       4
 #define        HFSC_DEFAULTSC          (HFSC_REALTIMESC|HFSC_LINKSHARINGSC)
 
 struct hfsc_class_stats {
+       struct hfsc_pktcntr     xmit_cnt;
+       struct hfsc_pktcntr     drop_cnt;
+
+       u_int                   qlength;
+       u_int                   qlimit;
+       u_int                   period;
+
        u_int                   class_id;
        u_int32_t               class_handle;
        struct hfsc_sc          rsc;
        struct hfsc_sc          fsc;
        struct hfsc_sc          usc;    /* upper limit service curve */
@@ -89,16 +93,10 @@ struct hfsc_class_stats {
        u_int64_t               myfadj;         /* cl_myfadj */
        u_int64_t               vtadj;          /* cl_vtadj */
        u_int64_t               cur_time;
        u_int32_t               machclk_freq;
 
-       u_int                   qlength;
-       u_int                   qlimit;
-       struct hfsc_pktcntr     xmit_cnt;
-       struct hfsc_pktcntr     drop_cnt;
-       u_int                   period;
-
        u_int                   vtperiod;       /* vt period sequence no */
        u_int                   parentperiod;   /* parent's vt period seqno */
        int                     nactive;        /* number of active children */
 
        /* red and rio related info */
@@ -111,19 +109,15 @@ struct ifnet;
 struct ifqueue;
 struct pf_queuespec;
 struct hfsc_if;
 
 extern const struct ifq_ops * const ifq_hfsc_ops;
+extern const struct pfq_ops * const pfq_hfsc_ops;
 
 #define        HFSC_ENABLED(ifq)       ((ifq)->ifq_ops == ifq_hfsc_ops)
 #define        HFSC_DEFAULT_QLIMIT     50
 
-struct hfsc_if *hfsc_pf_alloc(struct ifnet *);
-int             hfsc_pf_addqueue(struct hfsc_if *, struct pf_queuespec *);
-void            hfsc_pf_free(struct hfsc_if *);
-int             hfsc_pf_qstats(struct pf_queuespec *, void *, int *);
-
 void            hfsc_initialize(void);
 u_int64_t       hfsc_microuptime(void);
 
 #endif /* _KERNEL */
 #endif /* _HFSC_H_ */
diff --git sys/net/pf_ioctl.c sys/net/pf_ioctl.c
index c5ec0026b1f..dec229af8d1 100644
--- sys/net/pf_ioctl.c
+++ sys/net/pf_ioctl.c
@@ -88,11 +88,10 @@ void                         pf_thread_create(void *);
 int                     pfopen(dev_t, int, int, struct proc *);
 int                     pfclose(dev_t, int, int, struct proc *);
 int                     pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
 int                     pf_begin_rules(u_int32_t *, const char *);
 int                     pf_rollback_rules(u_int32_t, char *);
-int                     pf_enable_queues(void);
 void                    pf_remove_queues(void);
 int                     pf_commit_queues(void);
 void                    pf_free_queues(struct pf_queuehead *);
 int                     pf_setup_pfsync_matching(struct pf_ruleset *);
 void                    pf_hash_rule(MD5_CTX *, struct pf_rule *);
@@ -547,72 +546,79 @@ pf_remove_queues(void)
 
                ifp = q->kif->pfik_ifp;
                if (ifp == NULL)
                        continue;
 
-               KASSERT(HFSC_ENABLED(&ifp->if_snd));
-
                ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL);
        }
 }
 
-struct pf_hfsc_queue {
+struct pf_queue_if {
        struct ifnet            *ifp;
-       struct hfsc_if          *hif;
-       struct pf_hfsc_queue    *next;
+       const struct ifq_ops    *ifqops;
+       const struct pfq_ops    *pfqops;
+       void                    *disc;
+       struct pf_queue_if      *next;
 };
 
-static inline struct pf_hfsc_queue *
-pf_hfsc_ifp2q(struct pf_hfsc_queue *list, struct ifnet *ifp)
+static inline struct pf_queue_if *
+pf_ifp2q(struct pf_queue_if *list, struct ifnet *ifp)
 {
-       struct pf_hfsc_queue *phq = list;
+       struct pf_queue_if *qif = list;
 
-       while (phq != NULL) {
-               if (phq->ifp == ifp)
-                       return (phq);
+       while (qif != NULL) {
+               if (qif->ifp == ifp)
+                       return (qif);
 
-               phq = phq->next;
+               qif = qif->next;
        }
 
-       return (phq);
+       return (qif);
 }
 
 int
 pf_create_queues(void)
 {
        struct pf_queuespec     *q;
        struct ifnet            *ifp;
-       struct pf_hfsc_queue    *list = NULL, *phq;
+       struct pf_queue_if              *list = NULL, *qif;
        int                      error;
 
-       /* find root queues and alloc hfsc for these interfaces */
+       /*
+        * Find root queues and allocate traffic conditioner
+        * private data for these interfaces
+        */
        TAILQ_FOREACH(q, pf_queues_active, entries) {
                if (q->parent_qid != 0)
                        continue;
 
                ifp = q->kif->pfik_ifp;
                if (ifp == NULL)
                        continue;
 
-               phq = malloc(sizeof(*phq), M_TEMP, M_WAITOK);
-               phq->ifp = ifp;
-               phq->hif = hfsc_pf_alloc(ifp);
+               qif = malloc(sizeof(*qif), M_TEMP, M_WAITOK);
+               qif->ifp = ifp;
 
-               phq->next = list;
-               list = phq;
+               qif->ifqops = ifq_hfsc_ops;
+               qif->pfqops = pfq_hfsc_ops;
+
+               qif->disc = qif->pfqops->pfq_alloc(ifp);
+
+               qif->next = list;
+               list = qif;
        }
 
        /* and now everything */
        TAILQ_FOREACH(q, pf_queues_active, entries) {
                ifp = q->kif->pfik_ifp;
                if (ifp == NULL)
                        continue;
 
-               phq = pf_hfsc_ifp2q(list, ifp);
-               KASSERT(phq != NULL);
+               qif = pf_ifp2q(list, ifp);
+               KASSERT(qif != NULL);
 
-               error = hfsc_pf_addqueue(phq->hif, q);
+               error = qif->pfqops->pfq_addqueue(qif->disc, q);
                if (error != 0)
                        goto error;
        }
 
        /* find root queues in old list to disable them if necessary */
@@ -622,37 +628,37 @@ pf_create_queues(void)
 
                ifp = q->kif->pfik_ifp;
                if (ifp == NULL)
                        continue;
 
-               phq = pf_hfsc_ifp2q(list, ifp);
-               if (phq != NULL)
+               qif = pf_ifp2q(list, ifp);
+               if (qif != NULL)
                        continue;
 
                ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL);
        }
 
        /* commit the new queues */
        while (list != NULL) {
-               phq = list;
-               list = phq->next;
+               qif = list;
+               list = qif->next;
 
-               ifp = phq->ifp;
+               ifp = qif->ifp;
 
-               ifq_attach(&ifp->if_snd, ifq_hfsc_ops, phq->hif);
-               free(phq, M_TEMP, sizeof(*phq));
+               ifq_attach(&ifp->if_snd, qif->ifqops, qif->disc);
+               free(qif, M_TEMP, sizeof(*qif));
        }
 
        return (0);
 
 error:
        while (list != NULL) {
-               phq = list;
-               list = phq->next;
+               qif = list;
+               list = qif->next;
 
-               hfsc_pf_free(phq->hif);
-               free(phq, M_TEMP, sizeof(*phq));
+               qif->pfqops->pfq_free(qif->disc);
+               free(qif, M_TEMP, sizeof(*qif));
        }
 
        return (error);
 }
 
@@ -1080,11 +1086,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                if (qs == NULL) {
                        error = EBUSY;
                        break;
                }
                bcopy(qs, &pq->queue, sizeof(pq->queue));
-               error = hfsc_pf_qstats(qs, pq->buf, &nbytes);
+               error = pfq_hfsc_ops->pfq_qstats(qs, pq->buf, &nbytes);
                if (error == 0)
                        pq->nbytes = nbytes;
                break;
        }
 
@@ -1115,12 +1121,11 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
struct proc *p)
                        error = ESRCH;
                        break;
                }
                /* XXX resolve bw percentage specs */
                pfi_kif_ref(qs->kif, PFI_KIF_REF_RULE);
-               if (qs->qlimit == 0)
-                       qs->qlimit = HFSC_DEFAULT_QLIMIT;
+
                TAILQ_INSERT_TAIL(pf_queues_inactive, qs, entries);
 
                break;
        }
 
diff --git sys/net/pfvar.h sys/net/pfvar.h
index 7bf8375b450..5eba2776b39 100644
--- sys/net/pfvar.h
+++ sys/net/pfvar.h
@@ -1343,10 +1343,17 @@ struct hfsc_opts {
        u_int           ulsc_d;
        u_int           ulsc_m2;
        int             flags;
 };
 
+struct pfq_ops {
+       void            *(*pfq_alloc)(struct ifnet *);
+       int              (*pfq_addqueue)(void *, struct pf_queuespec *);
+       void             (*pfq_free)(void *);
+       int              (*pfq_qstats)(struct pf_queuespec *, void *, int *);
+};
+
 struct pf_tagname {
        TAILQ_ENTRY(pf_tagname) entries;
        char                    name[PF_TAG_NAME_SIZE];
        u_int16_t               tag;
        int                     ref;

Reply via email to