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;