|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 1/3][xen-netback] add a pseudo pps rate limit
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 paquets) such an approximation should not impact the results.
- Some help on burst handling will be appreciated.
Signed-off-by: Ahmed Amamou <ahmed@xxxxxxxxx>
Signed-off-by: William Dauchy <william@xxxxxxxxx>
Signed-off-by: Kamel Haddadou <kamel@xxxxxxxxx>
---
drivers/net/xen-netback/common.h | 2 ++
drivers/net/xen-netback/interface.c | 1 +
drivers/net/xen-netback/netback.c | 46 +++++++++++++++++++++++++++++++++++
drivers/net/xen-netback/xenbus.c | 25 ++++++++++++++++---
4 files changed, 70 insertions(+), 4 deletions(-)
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 9d7f172..fefa79a 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -85,8 +85,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 d984141..06257dd 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -273,6 +273,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 8c20935..172a6de 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -905,10 +905,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);
}
@@ -1419,6 +1425,38 @@ 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;
@@ -1470,6 +1508,13 @@ 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)) {
@@ -1478,6 +1523,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 410018c..7c55bed 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -267,15 +267,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 *packet,
+ 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;
+ *packet = ~0UL;
ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
if (IS_ERR(ratestr))
@@ -295,11 +298,24 @@ static void xen_net_read_rate(struct xenbus_device *dev,
*usec = u;
kfree(ratestr);
+ 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 fail2;
+ *packet = pps;
+ kfree(ppsstr);
return;
fail:
pr_warn("Failed to parse network rate limit. Traffic unlimited.\n");
kfree(ratestr);
+ return;
+fail2:
+ pr_warn("Failed to parse network PPS limit. PPS unlimited.\n");
+ kfree(ppsstr);
}
static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
@@ -370,8 +386,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
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |