Hi,
Since only leaf queues can have packets assigned to them, H-FSC
needs a dedicated placeholder root queue. Right now we conjure
it up behind the user's back, but userland doesn't really have
to deal with this and can let kernel take care of it itself.
If you take a look at what troubles pfctl has to go into to get
it right and how much code we actually need for it in the kernel,
it becomes rather clear where this should be done. This also
makes it easier to do further queueing modifications.
Some programs in ports might need adjustments similar to the
pftop.c hunk below.
OK?
diff --git sbin/pfctl/pfctl.c sbin/pfctl/pfctl.c
index 0ede855616d..e347698de73 100644
--- sbin/pfctl/pfctl.c
+++ sbin/pfctl/pfctl.c
@@ -1340,11 +1340,11 @@ pfctl_load_queue(struct pfctl *pf, u_int32_t ticket,
struct pfctl_qsitem *qi)
}
int
pfctl_load_queues(struct pfctl *pf)
{
- struct pfctl_qsitem *qi, *tempqi, rqi;
+ struct pfctl_qsitem *qi, *tempqi;
u_int32_t ticket;
TAILQ_FOREACH(qi, &qspecs, entries) {
if (qi->matches == 0)
errx(1, "queue %s: parent %s not found\n", qi->qs.qname,
@@ -1360,27 +1360,11 @@ pfctl_load_queues(struct pfctl *pf)
if ((pf->opts & PF_OPT_NOACTION) == 0)
ticket = pfctl_get_ticket(pf->trans, PF_TRANS_RULESET, "");
TAILQ_FOREACH_SAFE(qi, &rootqs, entries, tempqi) {
TAILQ_REMOVE(&rootqs, qi, entries);
-
- /*
- * We must have a hidden root queue below the user-
- * specified/visible root queue, due to the way the
- * dequeueing works far down there... don't ask.
- * the _ namespace is reserved for these.
- */
- bzero(&rqi, sizeof(rqi));
- TAILQ_INIT(&rqi.children);
- TAILQ_INSERT_TAIL(&rqi.children, qi, entries);
- snprintf(rqi.qs.qname, PF_QNAME_SIZE, "_root_%s",
- qi->qs.ifname);
- strlcpy(rqi.qs.ifname, qi->qs.ifname, sizeof(rqi.qs.ifname));
- strlcpy(qi->qs.parent, rqi.qs.qname, sizeof(qi->qs.parent));
-
- pfctl_load_queue(pf, ticket, &rqi);
-
+ pfctl_load_queue(pf, ticket, qi);
TAILQ_INSERT_HEAD(&rootqs, qi, entries);
}
return (0);
}
diff --git sbin/pfctl/pfctl_queue.c sbin/pfctl/pfctl_queue.c
index 3b5a47d114b..6c07e587fea 100644
--- sbin/pfctl/pfctl_queue.c
+++ sbin/pfctl/pfctl_queue.c
@@ -137,22 +137,18 @@ pfctl_update_qstats(int dev)
pqs.nbytes = sizeof(qstats.data);
if (ioctl(dev, DIOCGETQSTATS, &pqs)) {
warn("DIOCGETQSTATS");
return (-1);
}
-// if (pqs.queue.qname[0] != '_') {
-// if (pqs.queue.parent[0] && pqs.queue.parent[0] == '_')
-// pqs.queue.parent[0] = 0;
- if ((node = pfctl_find_queue_node(pqs.queue.qname,
- pqs.queue.ifname)) != NULL) {
- memcpy(&node->qstats.data, &qstats.data,
- sizeof(qstats.data));
- update_avg(&node->qstats);
- } else {
- pfctl_insert_queue_node(pqs.queue, qstats);
- }
-// }
+ if ((node = pfctl_find_queue_node(pqs.queue.qname,
+ pqs.queue.ifname)) != NULL) {
+ memcpy(&node->qstats.data, &qstats.data,
+ sizeof(qstats.data));
+ update_avg(&node->qstats);
+ } else {
+ pfctl_insert_queue_node(pqs.queue, qstats);
+ }
}
return (mnr);
}
void
diff --git sys/net/hfsc.c sys/net/hfsc.c
index a71da8ac6a9..b46411599d6 100644
--- sys/net/hfsc.c
+++ sys/net/hfsc.c
@@ -347,14 +347,16 @@ hfsc_pf_addqueue(struct hfsc_if *hif, struct pf_queuespec
*q)
struct hfsc_class *cl, *parent;
struct hfsc_sc rtsc, lssc, ulsc;
KASSERT(hif != NULL);
- if (q->parent_qid == HFSC_NULLCLASS_HANDLE &&
- hif->hif_rootclass == NULL)
- parent = NULL;
- else if ((parent = hfsc_clh2cph(hif, q->parent_qid)) == NULL)
+ if (q->parent_qid == 0 && hif->hif_rootclass == NULL) {
+ parent = hfsc_class_create(hif, NULL, NULL, NULL, NULL,
+ 0, 0, HFSC_ROOT_CLASS | q->qid);
+ if (parent == NULL)
+ return (EINVAL);
+ } else if ((parent = hfsc_clh2cph(hif, q->parent_qid)) == NULL)
return (EINVAL);
if (q->qid == 0)
return (EINVAL);
@@ -444,21 +446,26 @@ hfsc_alloc(unsigned int idx, void *q)
void
hfsc_free(unsigned int idx, void *q)
{
struct hfsc_if *hif = q;
- int i;
+ struct hfsc_class *cl;
+ int i, restart;
KERNEL_ASSERT_LOCKED();
KASSERT(idx == 0); /* when hfsc is enabled we only use the first ifq */
timeout_del(&hif->hif_defer);
- i = hif->hif_allocated;
- do
- hfsc_class_destroy(hif, hif->hif_class_tbl[--i]);
- while (i > 0);
+ do {
+ restart = 0;
+ for (i = 0; i < hif->hif_allocated; i++) {
+ cl = hif->hif_class_tbl[i];
+ if (hfsc_class_destroy(hif, cl) == EBUSY)
+ restart++;
+ }
+ } while (restart > 0);
free(hif->hif_class_tbl, M_DEVBUF, hif->hif_allocated * sizeof(void *));
free(hif, M_DEVBUF, sizeof(*hif));
}
diff --git sys/net/hfsc.h sys/net/hfsc.h
index 544d9df6259..0c30f4958bd 100644
--- sys/net/hfsc.h
+++ sys/net/hfsc.h
@@ -52,11 +52,11 @@ struct hfsc_sc {
u_int d; /* the x-projection of the first segment in msec */
u_int m2; /* slope of the second segment in bits/sec */
};
/* special class handles */
-#define HFSC_NULLCLASS_HANDLE 0
+#define HFSC_ROOT_CLASS 0x10000
#define HFSC_DEFAULT_CLASSES 64
#define HFSC_MAX_CLASSES 65535
/* service curve types */
#define HFSC_REALTIMESC 1
diff --git usr.bin/systat/pftop.c usr.bin/systat/pftop.c
index 1a193eb7da5..0128ab3737a 100644
--- usr.bin/systat/pftop.c
+++ usr.bin/systat/pftop.c
@@ -1542,26 +1542,21 @@ pfctl_update_qstats(void)
pqs.nbytes = sizeof(qstats.data);
if (ioctl(pf_dev, DIOCGETQSTATS, &pqs)) {
error("DIOCGETQSTATS: %s", strerror(errno));
return (-1);
}
- if (pqs.queue.qname[0] != '_') {
- if (pqs.queue.parent[0] && pqs.queue.parent[0] == '_')
- pqs.queue.parent[0] = '\0';
- qstats.valid = 1;
- gettimeofday(&qstats.timestamp, NULL);
- if ((node = pfctl_find_queue_node(pqs.queue.qname,
- pqs.queue.ifname)) != NULL) {
- memcpy(&node->qstats_last, &node->qstats,
- sizeof(struct queue_stats));
- memcpy(&node->qstats, &qstats,
- sizeof(struct queue_stats));
- } else {
- pfctl_insert_queue_node(pqs.queue, qstats);
- }
- } else
- num_queues--;
+ qstats.valid = 1;
+ gettimeofday(&qstats.timestamp, NULL);
+ if ((node = pfctl_find_queue_node(pqs.queue.qname,
+ pqs.queue.ifname)) != NULL) {
+ memcpy(&node->qstats_last, &node->qstats,
+ sizeof(struct queue_stats));
+ memcpy(&node->qstats, &qstats,
+ sizeof(struct queue_stats));
+ } else {
+ pfctl_insert_queue_node(pqs.queue, qstats);
+ }
}
return (0);
}
int