Page MenuHomeFreeBSD

D22110.diff
No OneTemporary

D22110.diff

diff --git a/share/man/man4/ng_car.4 b/share/man/man4/ng_car.4
--- a/share/man/man4/ng_car.4
+++ b/share/man/man4/ng_car.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 13, 2012
+.Dd January 27, 2021
.Dt NG_CAR 4
.Os
.Sh NAME
@@ -108,6 +108,7 @@
links with bandwidth * delay product less than 6-8 TCP segments, but it
consumes additional system resources for queue processing.
.El
+.Pp
By default, all information rates are measured in bits per second and bursts
are measured in bytes.
But when NG_CAR_COUNT_PACKETS option is enabled,
@@ -138,7 +139,8 @@
/* possible actions (..._action) */
enum {
NG_CAR_ACTION_FORWARD = 1,
- NG_CAR_ACTION_DROP
+ NG_CAR_ACTION_DROP,
+ NG_CAR_ACTION_MARK
};
/* operation modes (mode) */
@@ -149,7 +151,8 @@
NG_CAR_SHAPE
};
-/* mode options (opt) */
+/* mode options (bits for opt) */
+#define NG_CAR_COLOR_AWARE 1
#define NG_CAR_COUNT_PACKETS 2
struct ng_car_bulkconf {
diff --git a/sys/netgraph/ng_car.h b/sys/netgraph/ng_car.h
--- a/sys/netgraph/ng_car.h
+++ b/sys/netgraph/ng_car.h
@@ -103,8 +103,7 @@
enum {
NG_CAR_ACTION_FORWARD = 1,
NG_CAR_ACTION_DROP,
- NG_CAR_ACTION_MARK,
- NG_CAR_ACTION_SET_TOS
+ NG_CAR_ACTION_MARK
};
/* operation modes (mode) */
@@ -115,7 +114,7 @@
NG_CAR_SHAPE
};
-/* mode options (opt) */
+/* mode options (bits in opt) */
#define NG_CAR_COLOR_AWARE 1
#define NG_CAR_COUNT_PACKETS 2
diff --git a/sys/netgraph/ng_car.c b/sys/netgraph/ng_car.c
--- a/sys/netgraph/ng_car.c
+++ b/sys/netgraph/ng_car.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2005 Nuno Antunes <nuno.antunes@gmail.com>
* Copyright (c) 2007 Alexander Motin <mav@freebsd.org>
+ * Copyright (c) 2019 Lutz Donnerhacke <lutz@donnerhacke.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,9 +35,9 @@
*
* TODO:
* - Sanitize input config values (impose some limits)
- * - Implement internal packet painting (possibly using mbuf tags)
- * - Implement color-aware mode
* - Implement DSCP marking for IPv4
+ * - Decouple functionality into a simple classifier (g/y/r)
+ * and various action nodes (i.e. shape, dcsp, pcp)
*/
#include <sys/param.h>
@@ -50,6 +51,8 @@
#include <netgraph/netgraph.h>
#include <netgraph/ng_car.h>
+#include "qos.h"
+
#define NG_CAR_QUEUE_SIZE 100 /* Maximum queue size for SHAPE mode */
#define NG_CAR_QUEUE_MIN_TH 8 /* Minimum RED threshold for SHAPE mode */
@@ -261,6 +264,8 @@
{
struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook);
struct mbuf *m;
+ struct m_qos_color *colp;
+ enum qos_color col;
int error = 0;
u_int len;
@@ -272,15 +277,22 @@
m = NGI_M(item);
-#define NG_CAR_PERFORM_MATCH_ACTION(a) \
+#define NG_CAR_PERFORM_MATCH_ACTION(a,col) \
do { \
switch (a) { \
case NG_CAR_ACTION_FORWARD: \
/* Do nothing. */ \
break; \
case NG_CAR_ACTION_MARK: \
- /* XXX find a way to mark packets (mbuf tag?) */ \
- ++hinfo->stats.errors; \
+ if (colp == NULL) { \
+ colp = (void *)m_tag_alloc( \
+ M_QOS_COOKIE, M_QOS_COLOR, \
+ MTAG_SIZE(m_qos_color), M_NOWAIT); \
+ if (colp != NULL) \
+ m_tag_prepend(m, &colp->tag); \
+ } \
+ if (colp != NULL) \
+ colp->color = col; \
break; \
case NG_CAR_ACTION_DROP: \
default: \
@@ -298,22 +310,33 @@
len = m->m_pkthdr.len;
}
+ /* Determine current color of the packet (default green) */
+ colp = (void *)m_tag_locate(m, M_QOS_COOKIE, M_QOS_COLOR, NULL);
+ if ((hinfo->conf.opt & NG_CAR_COLOR_AWARE) && (colp != NULL))
+ col = colp->color;
+ else
+ col = QOS_COLOR_GREEN;
+
/* Check committed token bucket. */
- if (hinfo->tc - len >= 0) {
+ if (hinfo->tc - len >= 0 && col <= QOS_COLOR_GREEN) {
/* This packet is green. */
++hinfo->stats.green_pkts;
hinfo->tc -= len;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.green_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.green_action,
+ QOS_COLOR_GREEN);
} else {
/* Refill only if not green without it. */
ng_car_refillhook(hinfo);
/* Check committed token bucket again after refill. */
- if (hinfo->tc - len >= 0) {
+ if (hinfo->tc - len >= 0 && col <= QOS_COLOR_GREEN) {
/* This packet is green */
++hinfo->stats.green_pkts;
hinfo->tc -= len;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.green_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.green_action,
+ QOS_COLOR_GREEN);
/* If not green and mode is SHAPE, enqueue packet. */
} else if (hinfo->conf.mode == NG_CAR_SHAPE) {
@@ -323,40 +346,51 @@
/* If not green and mode is RED, calculate probability. */
} else if (hinfo->conf.mode == NG_CAR_RED) {
/* Is packet is bigger then extended burst? */
- if (len - (hinfo->tc - len) > hinfo->conf.ebs) {
+ if (len - (hinfo->tc - len) > hinfo->conf.ebs ||
+ col >= QOS_COLOR_RED) {
/* This packet is definitely red. */
++hinfo->stats.red_pkts;
hinfo->te = 0;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.red_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.red_action,
+ QOS_COLOR_RED);
/* Use token bucket to simulate RED-like drop
probability. */
- } else if (hinfo->te + (len - hinfo->tc) <
- hinfo->conf.ebs) {
+ } else if (hinfo->te + (len - hinfo->tc) < hinfo->conf.ebs &&
+ col <= QOS_COLOR_YELLOW) {
/* This packet is yellow */
++hinfo->stats.yellow_pkts;
hinfo->te += len - hinfo->tc;
/* Go to negative tokens. */
hinfo->tc -= len;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.yellow_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.yellow_action,
+ QOS_COLOR_YELLOW);
} else {
/* This packet is probably red. */
++hinfo->stats.red_pkts;
hinfo->te = 0;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.red_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.red_action,
+ QOS_COLOR_RED);
}
/* If not green and mode is SINGLE/DOUBLE RATE. */
} else {
/* Check extended token bucket. */
- if (hinfo->te - len >= 0) {
+ if (hinfo->te - len >= 0 && col <= QOS_COLOR_YELLOW) {
/* This packet is yellow */
++hinfo->stats.yellow_pkts;
hinfo->te -= len;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.yellow_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.yellow_action,
+ QOS_COLOR_YELLOW);
} else {
/* This packet is red */
++hinfo->stats.red_pkts;
- NG_CAR_PERFORM_MATCH_ACTION(hinfo->conf.red_action);
+ NG_CAR_PERFORM_MATCH_ACTION(
+ hinfo->conf.red_action,
+ QOS_COLOR_RED);
}
}
}
@@ -709,12 +743,21 @@
static void
ng_car_enqueue(struct hookinfo *hinfo, item_p item)
{
- struct mbuf *m;
- int len;
+ struct mbuf *m;
+ int len;
+ struct m_qos_color *colp;
+ enum qos_color col;
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
+ /* Determine current color of the packet (default green) */
+ colp = (void *)m_tag_locate(m, M_QOS_COOKIE, M_QOS_COLOR, NULL);
+ if ((hinfo->conf.opt & NG_CAR_COLOR_AWARE) && (colp != NULL))
+ col = colp->color;
+ else
+ col = QOS_COLOR_GREEN;
+
/* Lock queue mutex. */
mtx_lock(&hinfo->q_mtx);
@@ -725,7 +768,8 @@
/* If queue is overflowed or we have no RED tokens. */
if ((len >= (NG_CAR_QUEUE_SIZE - 1)) ||
- (hinfo->te + len >= NG_CAR_QUEUE_SIZE)) {
+ (hinfo->te + len >= NG_CAR_QUEUE_SIZE) ||
+ (col >= QOS_COLOR_RED)) {
/* Drop packet. */
++hinfo->stats.red_pkts;
++hinfo->stats.dropped_pkts;
diff --git a/sys/netgraph/qos.h b/sys/netgraph/qos.h
new file mode 100644
--- /dev/null
+++ b/sys/netgraph/qos.h
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Lutz Donnerhacke <lutz@donnerhacke.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NETGRAPH_QOS_H_
+#define _NETGRAPH_QOS_H_
+
+#include <sys/mbuf.h>
+
+/* ABI cookie */
+#define M_QOS_COOKIE 1571268051
+#define MTAG_SIZE(X) ( sizeof(struct X) - sizeof(struct m_tag) )
+
+/*
+ * Definition of types within this ABI:
+ * - Choose a type (16bit) by i.e. "echo $((1000+$(date +%s)%64536))"
+ * - Retry if the type is already in use
+ * - Define the structure for the type according to mbuf_tags(9)
+ * struct m_qos_foo {
+ * struct m_tag tag;
+ * ...
+ * };
+ * Preferred usage:
+ * struct m_qos_foo *p = (void *)m_tag_locate(m,
+ * M_QOS_COOKIE, M_QOS_FOO, ...);
+ * or
+ * p = (void *)m_tag_alloc(
+ * M_QOS_COOKIE, M_QOS_FOO, MTAG_SIZE(foo), ...);
+ m_tag_prepend(m, &p->tag);
+ */
+
+/* Color marking type */
+#define M_QOS_COLOR 23568
+/* Keep colors ordered semantically in order to allow use of "<=" or ">=" */
+enum qos_color {
+ QOS_COLOR_GREEN,
+ QOS_COLOR_YELLOW,
+ QOS_COLOR_RED
+};
+struct m_qos_color {
+ struct m_tag tag;
+ enum qos_color color;
+};
+
+/*
+ * Priority class
+ *
+ * Processing per priority requires an overhead, which should
+ * be static (i.e. for alloctating queues) and small (for memory)
+ * So keep your chosen range limited.
+ */
+#define M_QOS_PRIORITY 28858
+struct m_qos_priority {
+ struct m_tag tag;
+ uint8_t priority; /* 0 - lowest */
+};
+
+#endif /* _NETGRAPH_QOS_H_ */

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 13, 12:51 AM (12 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17122720
Default Alt Text
D22110.diff (10 KB)

Event Timeline