Add support for ingress policing.
authorJustin Pettit <jpettit@nicira.com>
Sat, 4 Apr 2009 07:06:43 +0000 (00:06 -0700)
committerJustin Pettit <jpettit@nicira.com>
Sat, 4 Apr 2009 07:06:43 +0000 (00:06 -0700)
This adds support for ingress policing to vswitchd.  This allows a user
to limit the rate of traffic entering the switch on a particular port.
This is configured on the physical port, so this a system-wide
configuration value handled through vswitchd.

lib/netdev.c
lib/netdev.h
vswitchd/automake.mk
vswitchd/port.c [new file with mode: 0644]
vswitchd/port.h [new file with mode: 0644]
vswitchd/vswitchd.c
vswitchd/vswitchd.conf.5.in

index 1dd33b88b09076ecd8f73b941be0c3ced4ea8ae5..aa4c47ebdeb47a7262c0821608175d27b18baa86 100644 (file)
@@ -1143,6 +1143,61 @@ netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
     return error;
 }
 
+#define POLICE_ADD_CMD "/sbin/tc qdisc add dev %s handle ffff: ingress"
+#define POLICE_CONFIG_CMD "/sbin/tc filter add dev %s parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate %dkbit burst %dk drop flowid :1"
+#define POLICE_DEL_CMD "/sbin/tc qdisc del dev %s handle ffff: ingress"
+
+/* Attempts to set input rate limiting (policing) policy. */
+int
+netdev_nodev_set_policing(const char *netdev_name, uint32_t kbits_rate,
+                          uint32_t kbits_burst)
+{
+    char command[1024];
+
+    init_netdev();
+
+    if (kbits_rate) {
+        if (!kbits_burst) {
+            /* Default to 10 kilobits if not specified. */
+            kbits_burst = 10;
+        }
+
+        /* xxx This should be more careful about only adding if it
+         * xxx actually exists, as opposed to always deleting it. */
+        snprintf(command, sizeof(command), POLICE_DEL_CMD, netdev_name);
+        system(command);
+
+        snprintf(command, sizeof(command), POLICE_ADD_CMD, netdev_name);
+        if (system(command) != 0) {
+            VLOG_WARN_RL(&rl, "%s: problem adding policing", netdev_name);
+            return -1;
+        }
+
+        snprintf(command, sizeof(command), POLICE_CONFIG_CMD, netdev_name,
+                kbits_rate, kbits_burst);
+        if (system(command) != 0) {
+            VLOG_WARN_RL(&rl, "%s: problem configuring policing", 
+                    netdev_name);
+            return -1;
+        }
+    } else {
+        snprintf(command, sizeof(command), POLICE_DEL_CMD, netdev_name);
+        if (system(command) != 0) {
+            VLOG_WARN_RL(&rl, "%s: problem removing policing", netdev_name);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int
+netdev_set_policing(struct netdev *netdev, uint32_t kbits_rate,
+                    uint32_t kbits_burst)
+{
+    return netdev_nodev_set_policing(netdev->name, kbits_rate, kbits_burst);
+}
+
 /* Initializes 'svec' with a list of the names of all known network devices. */
 void
 netdev_enumerate(struct svec *svec)
index 4afaff6554862c9dbaac2ab722e21878fc910e50..2e69e8aec712fce72e26a78016c9a792c30f7e85 100644 (file)
@@ -118,11 +118,15 @@ int netdev_turn_flags_on(struct netdev *, enum netdev_flags, bool permanent);
 int netdev_turn_flags_off(struct netdev *, enum netdev_flags, bool permanent);
 int netdev_arp_lookup(const struct netdev *, uint32_t ip, uint8_t mac[6]);
 int netdev_get_stats(const struct netdev *, struct netdev_stats *);
+int netdev_set_policing(struct netdev *, uint32_t kbits_rate, 
+                        uint32_t kbits_burst);
 
 void netdev_enumerate(struct svec *);
 int netdev_nodev_get_flags(const char *netdev_name, enum netdev_flags *);
 int netdev_nodev_set_etheraddr(const char *name, const uint8_t mac[6]);
 int netdev_nodev_get_etheraddr(const char *netdev_name, uint8_t mac[6]);
+int netdev_nodev_set_policing(const char *netdev_name, uint32_t kbits_rate, 
+                              uint32_t kbits_burst);
 
 int netdev_get_vlan_vid(const char *netdev_name, int *vlan_vid);
 
index 833fd0068fc3eed0b09bf45a8d181e724e95ec52..3f87d54cde29a520bc3cd19ede0e2f4f44976dad 100644 (file)
@@ -11,6 +11,8 @@ vswitchd_vswitchd_SOURCES = \
        vswitchd/bridge.h \
        vswitchd/mgmt.c \
        vswitchd/mgmt.h \
+       vswitchd/port.c \
+       vswitchd/port.h \
        vswitchd/vswitchd.c \
        vswitchd/vswitchd.h \
        vswitchd/xenserver.c \
diff --git a/vswitchd/port.c b/vswitchd/port.c
new file mode 100644 (file)
index 0000000..7b4a9e7
--- /dev/null
@@ -0,0 +1,107 @@
+/* Copyright (c) 2009  Nicira Networks
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, Nicira Networks gives permission
+ * to link the code of its release of vswitchd with the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the same
+ * license as the "OpenSSL" library), and distribute the linked
+ * executables.  You must obey the GNU General Public License in all
+ * respects for all of the code used other than "OpenSSL".  If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so.  If you do not wish to do so,
+ * delete this exception statement from your version.
+ *
+ */
+
+#include <config.h>
+
+#include "cfg.h"
+#include "netdev.h"
+#include "port.h"
+#include "svec.h"
+#include "vswitchd.h"
+
+#define THIS_MODULE VLM_port
+#include "vlog.h"
+
+static struct svec port_cfg = SVEC_EMPTY_INITIALIZER;
+static struct svec all_ports = SVEC_EMPTY_INITIALIZER;
+
+
+static int
+set_ingress_policing(const char *port_name) 
+{
+    int kbits_rate = cfg_get_int(0, "port.%s.ingress.policing_rate", 
+            port_name);
+    int kbits_burst = cfg_get_int(0, "port.%s.ingress.policing_burst", 
+            port_name);
+
+    return netdev_nodev_set_policing(port_name, kbits_rate, kbits_burst);
+}
+
+static int
+set_port_config(const char *port_name)
+{
+    set_ingress_policing(port_name);
+
+    return 0;
+}
+
+static void
+strip_port_config(const char *port_name)
+{
+    netdev_nodev_set_policing(port_name, 0, 0);
+}
+
+void
+port_init(void)
+{
+    port_reconfigure();
+}
+
+void
+port_reconfigure(void)
+{
+    struct svec new_cfg;
+    struct svec new_ports;
+    int i;
+
+    svec_init(&new_cfg);
+    cfg_get_section(&new_cfg, "port");
+    svec_sort(&new_cfg);
+
+    if (svec_equal(&port_cfg, &new_cfg)) {
+        svec_destroy(&new_cfg);
+        return;
+    }
+
+    svec_init(&new_ports);
+    cfg_get_subsections(&new_ports, "port");
+    for (i=0; i<all_ports.n; i++) {
+        if (!svec_contains(&new_ports, all_ports.names[i])) {
+            strip_port_config(all_ports.names[i]);
+        }
+    }
+
+    for (i=0; i<new_ports.n; i++) {
+        set_port_config(new_ports.names[i]);
+    }
+
+    svec_swap(&new_cfg, &port_cfg);
+    svec_destroy(&new_cfg);
+
+    svec_swap(&new_ports, &all_ports);
+    svec_destroy(&new_ports);
+}
diff --git a/vswitchd/port.h b/vswitchd/port.h
new file mode 100644 (file)
index 0000000..980398d
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (c) 2009  Nicira Networks
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, Nicira Networks gives permission
+ * to link the code of its release of vswitchd with the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the same
+ * license as the "OpenSSL" library), and distribute the linked
+ * executables.  You must obey the GNU General Public License in all
+ * respects for all of the code used other than "OpenSSL".  If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so.  If you do not wish to do so,
+ * delete this exception statement from your version.
+ */
+
+#ifndef VSWITCHD_PORT_H
+#define VSWITCHD_PORT_H 1
+
+void port_init(void);
+void port_reconfigure(void);
+
+#endif /* port.h */
index 669a8c42cd11732cc555b5acdc7aa532e0bea7ef..fc2161685e7a992e68ef9ba8481d48cf6c79e35e 100644 (file)
@@ -43,6 +43,7 @@
 #include "leak-checker.h"
 #include "mgmt.h"
 #include "poll-loop.h"
+#include "port.h"
 #include "process.h"
 #include "signals.h"
 #include "svec.h"
@@ -88,6 +89,7 @@ main(int argc, char *argv[])
     cfg_read();
     mgmt_init();
     bridge_init();
+    port_init();
     mgmt_reconfigure();
 
     need_reconfigure = false;
@@ -117,6 +119,7 @@ reconfigure(void)
     cfg_read();
     bridge_reconfigure();
     mgmt_reconfigure();
+    port_reconfigure();
 }
 
 static void
index 987208534503b248134613a9ca8dd1ef0f001e73..5399ac5042c12b64fdd1b569038be806a93c1527 100644 (file)
@@ -281,6 +281,42 @@ on \fBeth1\fR or \fBeth2\fR to \fBeth3\fR.
         select.src-port = eth2
         output.port = eth3
         
+.fi
+.RE
+.SS "Port Rate-Limiting"
+Traffic policing and shaping are configured on physical ports.  Policing
+defines a hard limit at which traffic that exceeds the specified rate is
+dropped.  Shaping uses queues to delay packets so that egress traffic
+leaves at the specified rate.
+
+.ST "Ingress Policing"
+The rate at which traffic is allowed to enter through a particular
+physical port can be configured with ingress policing.  The rate is 
+specified in kilobits (1000 bits) per second with a maximum burst size 
+specified in kilobits (1000 bits).  The burst size should be at least
+the size of the port's MTU. 
+
+A port may be configured to enforce ingress policing by defining the
+key \fBport.\fIname\fB.ingress.policing_rate\fR with an integer
+indicating the rate.  The port \fIname\fR will only allow traffic to be
+received at the rate specified in kilobits per second.  If the rate is zero 
+or the key is not defined, then ingress policing is disabled.
+
+If ingress policing is enabled, then the burst rate may be set by defining 
+the key \fBport.\fIname\fB.ingress.policing_burst\fR with an integer 
+indicating the burst rate in kilobits.  If a key is not supplied or is 
+zero, then the default burst is 10 kilobits.
+
+.PP
+The following syntax limits port \fBeth1\fR to receiving traffic at
+\fB512\fR kilobits per second with a burst of \fB20\fR kilobits:
+.PP
+.RS
+.nf
+
+port.eth1.ingress.policing_rate=512
+port.eth1.ingress.policing_burst=20
+
 .fi
 .SS "IEEE 802.1D-1998 Spanning Tree Support"
 .PP
@@ -532,7 +568,7 @@ Sets the maximum time between attempts to connect to the controller to
 connection attempts starts at 1 second and doubles on each failing
 attempt until it reaches the maximum.  The default maximum backoff
 time is taken from \fBmgmt.max-backoff\fR.
-.ST "Rate Limit Settings"
+.ST "Controller Rate-Limiting"
 These settings configure how the virtual switch applies a ``token
 bucket'' to limit the rate at which packets in unknown flows are
 forwarded to the OpenFlow controller for flow-setup processing.  This
@@ -551,10 +587,10 @@ Sets the maximum number of unused packet credits that the bridge will
 allow to accumulate during time in which no packets are being
 forwarded to the OpenFlow controller to \fIburst\fR (measured in
 packets).  The default \fIburst\fR is one-quarter of the \fIrate\fR
-specified in the rate limit setting.
+specified in the rate-limit setting.
 .IP
 The first of these that is set takes effect.  This option takes effect
-only when a rate limit is specified.
+only when a rate-limit is specified.
 .ST "Remote Command Execution Settings"
 These settings configure the commands that remote OpenFlow connections
 are allowed to invoke using (e.g.) \fBdpctl execute\fR.  To be