All of lore.kernel.org
 help / color / mirror / Atom feed
From: William Dauchy <william@gandi.net>
To: Ian Campbell <Ian.Campbell@citrix.com>
Cc: Ahmed Amamou <ahmed@gandi.net>, Kamel Haddadou <kamel@gandi.net>,
	Wei Liu <wei.liu2@citrix.com>, William Dauchy <william@gandi.net>,
	xen-devel <xen-devel@lists.xen.org>
Subject: [PATCH v4 1/3] xen netback: add a pseudo pps rate limit
Date: Mon,  5 Aug 2013 17:13:08 +0200	[thread overview]
Message-ID: <1375715590-1539-2-git-send-email-william@gandi.net> (raw)
In-Reply-To: <1375715590-1539-1-git-send-email-william@gandi.net>

This patch provides a new option to limit VMs maximum packets per second
emission rate.
It follows the same credits logic used for throughput shaping. For the
moment we have considered each "txreq" as a packet.
PPS limits is passed to VIF at connection time via xenstore.
PPS credit uses the same usecond period used by rate shaping check.

known limitations:
- by using the same usecond period, PPS shaping depends on throughput
  shaping.
- it is not always true that a "txreq" correspond to a packet
  (fragmentation cases) but as this shaping is meant to avoid DDOS
  (small packets) such an approximation should not impact the results.
- Some help on burst handling will be appreciated.

Signed-off-by: Ahmed Amamou <ahmed@gandi.net>
Signed-off-by: William Dauchy <william@gandi.net>
Signed-off-by: Kamel Haddadou <kamel@gandi.net>
---
 drivers/net/xen-netback/common.h    |    2 ++
 drivers/net/xen-netback/interface.c |    1 +
 drivers/net/xen-netback/netback.c   |   41 +++++++++++++++++++++++++++++++++++
 drivers/net/xen-netback/xenbus.c    |   35 ++++++++++++++++++++++++------
 4 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 8a4d77e..e1a2d4f 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -89,8 +89,10 @@ struct xenvif {
 
 	/* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
 	unsigned long   credit_bytes;
+	unsigned long   credit_packets;
 	unsigned long   credit_usec;
 	unsigned long   remaining_credit;
+	unsigned long   remaining_packets;
 	struct timer_list credit_timeout;
 
 	/* Statistics */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 087d2db..43c2da7 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -295,6 +295,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
 	INIT_LIST_HEAD(&vif->notify_list);
 
 	vif->credit_bytes = vif->remaining_credit = ~0UL;
+	vif->credit_packets = vif->remaining_packets = ~0UL;
 	vif->credit_usec  = 0UL;
 	init_timer(&vif->credit_timeout);
 	/* Initialize 'expires' now: it's used to track the credit window. */
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 64828de..6ab3cb2 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -912,10 +912,16 @@ static void tx_add_credit(struct xenvif *vif)
 	vif->remaining_credit = min(max_credit, max_burst);
 }
 
+static void tx_add_packets(struct xenvif *vif)
+{
+	vif->remaining_packets = vif->credit_packets;
+}
+
 static void tx_credit_callback(unsigned long data)
 {
 	struct xenvif *vif = (struct xenvif *)data;
 	tx_add_credit(vif);
+	tx_add_packets(vif);
 	xen_netbk_check_rx_xenvif(vif);
 }
 
@@ -1426,6 +1432,34 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
 	return false;
 }
 
+static bool tx_packets_exceeded(struct xenvif *vif)
+{
+	unsigned long now = jiffies;
+	unsigned long next_credit =
+		vif->credit_timeout.expires +
+		msecs_to_jiffies(vif->credit_usec / 1000);
+
+	/* Timer could already be pending in rare cases. */
+	if (timer_pending(&vif->credit_timeout))
+		return true;
+
+	/* Passed the point where we can replenish credit? */
+	if (time_after_eq(now, next_credit)) {
+		vif->credit_timeout.expires = now;
+		tx_add_packets(vif);
+	}
+
+	/* Not enough slot to send right now? Set a callback. */
+	if (vif->remaining_packets < 1) {
+		vif->credit_timeout.data = (unsigned long)vif;
+		vif->credit_timeout.function = tx_credit_callback;
+		mod_timer(&vif->credit_timeout, next_credit);
+		return true;
+	}
+
+	return false;
+}
+
 static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 {
 	struct gnttab_copy *gop = netbk->tx_copy_ops, *request_gop;
@@ -1477,6 +1511,12 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 		rmb(); /* Ensure that we see the request before we copy it. */
 		memcpy(&txreq, RING_GET_REQUEST(&vif->tx, idx), sizeof(txreq));
 
+		/* pps-based scheduling. */
+		if(vif->remaining_packets < 1 && tx_packets_exceeded(vif)) {
+			xenvif_put(vif);
+			continue;
+		}
+
 		/* Credit-based scheduling. */
 		if (txreq.size > vif->remaining_credit &&
 		    tx_credit_exceeded(vif, txreq.size)) {
@@ -1485,6 +1525,7 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
 		}
 
 		vif->remaining_credit -= txreq.size;
+		vif->remaining_packets--;
 
 		work_to_do--;
 		vif->tx.req_cons = ++idx;
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 1fe48fe3..2b52a09 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -276,15 +276,18 @@ static void frontend_changed(struct xenbus_device *dev,
 
 
 static void xen_net_read_rate(struct xenbus_device *dev,
-			      unsigned long *bytes, unsigned long *usec)
+			      unsigned long *bytes,
+			      unsigned long *packets,
+			      unsigned long *usec)
 {
 	char *s, *e;
-	unsigned long b, u;
-	char *ratestr;
+	unsigned long b, u, pps;
+	char *ratestr, *ppsstr;
 
 	/* Default to unlimited bandwidth. */
 	*bytes = ~0UL;
 	*usec = 0;
+	*packets = ~0UL;
 
 	ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
 	if (IS_ERR(ratestr))
@@ -293,22 +296,39 @@ static void xen_net_read_rate(struct xenbus_device *dev,
 	s = ratestr;
 	b = simple_strtoul(s, &e, 10);
 	if ((s == e) || (*e != ','))
-		goto fail;
+		goto fail_ratestr;
 
 	s = e + 1;
 	u = simple_strtoul(s, &e, 10);
 	if ((s == e) || (*e != '\0'))
-		goto fail;
+		goto fail_ratestr;
 
 	*bytes = b;
 	*usec = u;
 
+	ppsstr = xenbus_read(XBT_NIL, dev->nodename, "pps", NULL);
+	if (IS_ERR(ppsstr))
+		return;
+	s = ppsstr;
+	pps = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != '\0'))
+		goto fail_ppsstr;
+	*packets = pps;
+
 	kfree(ratestr);
+	kfree(ppsstr);
 	return;
 
- fail:
+ fail_ppsstr:
+	pr_warn("Failed to parse network PPS limit. PPS unlimited.\n");
+	kfree(ppsstr);
+	goto free_ratestr;
+
+ fail_ratestr:
 	pr_warn("Failed to parse network rate limit. Traffic unlimited.\n");
+ free_ratestr:
 	kfree(ratestr);
+	return;
 }
 
 static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
@@ -379,8 +399,9 @@ static void connect(struct backend_info *be)
 	}
 
 	xen_net_read_rate(dev, &be->vif->credit_bytes,
-			  &be->vif->credit_usec);
+			  &be->vif->credit_packets, &be->vif->credit_usec);
 	be->vif->remaining_credit = be->vif->credit_bytes;
+	be->vif->remaining_packets = be->vif->credit_packets;
 
 	unregister_hotplug_status_watch(be);
 	err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
-- 
1.7.9.5

  reply	other threads:[~2013-08-05 15:13 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-05 15:13 [PATCH v4 0/3][xen-netback][toolstack] add a pseudo pps limit to netback William Dauchy
2013-08-05 15:13 ` William Dauchy [this message]
2013-08-09  6:03   ` [PATCH v4 1/3] xen netback: add a pseudo pps rate limit Wei Liu
2013-08-05 15:13 ` [PATCH v4 2/3] handle pps limit parameter William Dauchy
2013-08-09  5:59   ` Wei Liu
2013-08-19 14:18     ` Ian Jackson
2013-08-05 15:13 ` [PATCH v4 3/3] netif documentation William Dauchy
2013-08-09  6:02   ` Wei Liu
2013-08-09  6:00 ` [PATCH v4 0/3][xen-netback][toolstack] add a pseudo pps limit to netback Wei Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1375715590-1539-2-git-send-email-william@gandi.net \
    --to=william@gandi.net \
    --cc=Ian.Campbell@citrix.com \
    --cc=ahmed@gandi.net \
    --cc=kamel@gandi.net \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.