The branch stable/11 has been updated by donner:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=21e24a8f01f7bd7e0a93ed972b6165e2f9798be5

commit 21e24a8f01f7bd7e0a93ed972b6165e2f9798be5
Author:     Lutz Donnerhacke <don...@freebsd.org>
AuthorDate: 2021-01-27 20:19:14 +0000
Commit:     Lutz Donnerhacke <don...@freebsd.org>
CommitDate: 2021-02-26 12:36:40 +0000

    netgraph/ng_car: Add color marking code
    
    Chained policing should be able to reuse the classification of
    traffic.  A new mbuf_tag type is defined to handle gereral QoS
    marking.  A new subtype is defined to track the color marking.
    
    Reviewed by:    manpages (bcr), melifaro, kp
    Sponsored by:   IKS Service GmbH
    Differential Revision: https://reviews.freebsd.org/D22110
    
    (cherry picked from commit d0d2e523bafb74180f8bebb90788790f0d2f0290)
---
 share/man/man4/ng_car.4 |  9 ++++--
 sys/netgraph/ng_car.c   | 86 +++++++++++++++++++++++++++++++++++++------------
 sys/netgraph/ng_car.h   |  5 ++-
 sys/netgraph/qos.h      | 83 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 156 insertions(+), 27 deletions(-)

diff --git a/share/man/man4/ng_car.4 b/share/man/man4/ng_car.4
index cb1459fe6987..c42f955a106a 100644
--- 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 @@ Traffic shaping is much more polite to the TCP traffic than 
rate limit on
 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 @@ struct ng_car_hookconf {
 /* 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 @@ enum {
     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.c b/sys/netgraph/ng_car.c
index cdbaf5a3c920..3705186f26b0 100644
--- a/sys/netgraph/ng_car.c
+++ b/sys/netgraph/ng_car.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2005 Nuno Antunes <nuno.antu...@gmail.com>
  * Copyright (c) 2007 Alexander Motin <m...@freebsd.org>
+ * Copyright (c) 2019 Lutz Donnerhacke <l...@donnerhacke.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,9 +33,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>
@@ -48,6 +49,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 
*/
 
@@ -259,6 +262,8 @@ ng_car_rcvdata(hook_p hook, item_p item )
 {
        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;
 
@@ -270,15 +275,22 @@ ng_car_rcvdata(hook_p hook, item_p item )
 
        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:                                \
@@ -296,23 +308,34 @@ ng_car_rcvdata(hook_p hook, item_p item )
                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) {
@@ -322,40 +345,51 @@ ng_car_rcvdata(hook_p hook, item_p item )
                /* 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 @@ ng_car_q_event(node_p node, hook_p hook, void *arg, int 
arg2)
 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 @@ ng_car_enqueue(struct hookinfo *hinfo, item_p item)
 
        /* 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.droped_pkts;
diff --git a/sys/netgraph/ng_car.h b/sys/netgraph/ng_car.h
index 3fda67512dd0..09a91df0da87 100644
--- a/sys/netgraph/ng_car.h
+++ b/sys/netgraph/ng_car.h
@@ -101,8 +101,7 @@ struct ng_car_hookconf {
 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) */
@@ -113,7 +112,7 @@ enum {
     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/qos.h b/sys/netgraph/qos.h
new file mode 100644
index 000000000000..0e5dfec479eb
--- /dev/null
+++ b/sys/netgraph/qos.h
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Lutz Donnerhacke <l...@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_ */
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to