Re: unlimited HFSC v3: more readable, less hacks
On Mon, Oct 21, 2013 at 12:04:14AM +0200, Martin Pelikan wrote: Hopefully the third time does the charm. The previous union approach to altq/newq bits was wrong, because switching back and forth was racy. This new diff then concatenates these structures like [ifqueue, hfsc_if, altq-bits], has some better names, doesn't need renaming stuff in the old code (it can remain 2 years old), removes the now useless ifq_hfsc pointer. Can't we not just nuke altq? It is going to die anyway so why try to keep it alive? As always, it's being heavily tested. -- Martin Pelikan ? net/hfsc.c.instrumented 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.h12 Oct 2013 12:13:10 - 1.16 +++ altq/if_altq.h20 Oct 2013 21:25:41 - @@ -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.1 diff -u -p -r1.1 hfsc.c --- net/hfsc.c12 Oct 2013 11:39:17 - 1.1 +++ net/hfsc.c20 Oct 2013 21:25:42 - @@ -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); @@ -128,18 +128,49 @@ 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; return (0); } @@ -147,8 +178,11 @@ hfsc_attach(struct ifnet *ifp) int hfsc_detach(struct ifnet *ifp) { - free(ifp-if_snd.ifq_hfsc, M_DEVBUF); - ifp-if_snd.ifq_hfsc = NULL; + struct hfsc_if *hif = ifp-if_snd.ifq_hfsc; + + hif-hif_allocated = hif-hif_classes = 0; + free(hif-hif_class_tbl, M_DEVBUF); + hif-hif_class_tbl = NULL; return (0); } @@ -156,11 +190,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 @@ -185,7 +221,7 @@ hfsc_addqueue(struct pf_queuespec *q) ulsc.d = q-upperlimit.d; ulsc.m2 = q-upperlimit.m2.absolute;
Re: unlimited HFSC v3: more readable, less hacks
* Claudio Jeker cje...@diehard.n-r-g.com [2013-10-21 11:20]: Can't we not just nuke altq? It is going to die anyway so why try to keep it alive? no, sorry. as much as keeping it was a mistake (wearing my programmer hat), the painful work has been done already, and the feedback i got on it is clear. besides, newqueue isn't a 100% replacement yet. last not least RED (or sth similiar) is missing. -- Henning Brauer, h...@bsws.de, henn...@openbsd.org BS Web Services GmbH, http://bsws.de, Full-Service ISP Secure Hosting, Mail and DNS Services. Dedicated Servers, Root to Fully Managed Henning Brauer Consulting, http://henningbrauer.com/
unlimited HFSC v3: more readable, less hacks
Hopefully the third time does the charm. The previous union approach to altq/newq bits was wrong, because switching back and forth was racy. This new diff then concatenates these structures like [ifqueue, hfsc_if, altq-bits], has some better names, doesn't need renaming stuff in the old code (it can remain 2 years old), removes the now useless ifq_hfsc pointer. As always, it's being heavily tested. -- Martin Pelikan ? net/hfsc.c.instrumented 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 - 1.16 +++ altq/if_altq.h 20 Oct 2013 21:25:41 - @@ -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_ENABLED1 +#include net/hfsc.h +#undef ALTQ_IS_ENABLED +/* XXX hack */ + struct ifaltq { /* fields compatible with struct ifqueue */ struct { @@ -45,8 +52,8 @@ structifaltq { 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.1 diff -u -p -r1.1 hfsc.c --- net/hfsc.c 12 Oct 2013 11:39:17 - 1.1 +++ net/hfsc.c 20 Oct 2013 21:25:42 - @@ -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); @@ -128,18 +128,49 @@ 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; return (0); } @@ -147,8 +178,11 @@ hfsc_attach(struct ifnet *ifp) int hfsc_detach(struct ifnet *ifp) { - free(ifp-if_snd.ifq_hfsc, M_DEVBUF); - ifp-if_snd.ifq_hfsc = NULL; + struct hfsc_if *hif = ifp-if_snd.ifq_hfsc; + + hif-hif_allocated = hif-hif_classes = 0; + free(hif-hif_class_tbl, M_DEVBUF); + hif-hif_class_tbl = NULL; return (0); } @@ -156,11 +190,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 @@ -185,7 +221,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)