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;