From 1c046c878259a1af25c52fb122b47dc8494edcad Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Sat, 4 Apr 2009 00:06:43 -0700 Subject: [PATCH] Add support for ingress policing. 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 | 55 ++++++++++++++++++ lib/netdev.h | 4 ++ vswitchd/automake.mk | 2 + vswitchd/port.c | 107 ++++++++++++++++++++++++++++++++++++ vswitchd/port.h | 33 +++++++++++ vswitchd/vswitchd.c | 3 + vswitchd/vswitchd.conf.5.in | 42 +++++++++++++- 7 files changed, 243 insertions(+), 3 deletions(-) create mode 100644 vswitchd/port.c create mode 100644 vswitchd/port.h diff --git a/lib/netdev.c b/lib/netdev.c index 1dd33b88..aa4c47eb 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -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) diff --git a/lib/netdev.h b/lib/netdev.h index 4afaff65..2e69e8ae 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -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); diff --git a/vswitchd/automake.mk b/vswitchd/automake.mk index 833fd006..3f87d54c 100644 --- a/vswitchd/automake.mk +++ b/vswitchd/automake.mk @@ -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 index 00000000..7b4a9e7b --- /dev/null +++ b/vswitchd/port.c @@ -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 . + * + * 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 + +#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. + * + * 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 */ diff --git a/vswitchd/vswitchd.c b/vswitchd/vswitchd.c index 669a8c42..fc216168 100644 --- a/vswitchd/vswitchd.c +++ b/vswitchd/vswitchd.c @@ -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 diff --git a/vswitchd/vswitchd.conf.5.in b/vswitchd/vswitchd.conf.5.in index 98720853..5399ac50 100644 --- a/vswitchd/vswitchd.conf.5.in +++ b/vswitchd/vswitchd.conf.5.in @@ -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 -- 2.30.2