[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2] xen-netback: add a pseudo pps rate limit
On Mon, 2013-06-24 at 17:22 +0200, William Dauchy wrote: Sorry for the delay replying. > VM traffic is already limited by a throughput limit, but there is no > control over the maximum packet per second (PPS). > In DDOS attack the major issue is rather PPS than throughput. > With provider offering more bandwidth to VMs, it becames easy to > coordinate a massive attack using VMs. Example: 100Mbits ~ 200kpps using > 64B packets. > 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. So it is in effect a slots-per-second (or requests-per...) limit, which I suppose is pseudo-pps as you say. > 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 paquet "packet" > (fragmentation cases) but as this shaping is meant to avoid DDOS > (small paquets) such an pproximation should not impact the results. and again, plus missing an a on the front of approx... Are you going to provide toolstack side patches to utilise this feature, as well as documentation for the xenstore key? > - Some help on burst handling will be appreciated. > > v2: > - fixing some typo > > 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..097a390 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); This is the same timer as the credit based timeout? How do the two interact? Can I cause my packet credits to be replenished sooner by cleverly manipulating my byte rates or vice versa? > + > + 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; This should be tab indented, you've used spaces after the initial tabs. > + } > + > /* 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--; Interesting that even if credit scoring is disable (== ~0) we will eventually hit zero and have to replenish. This applies to the existing credit stuff too as far as I can tell. I suppose if we replenish to ~0 then it is likely to be mostly harmless. > > 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); What is the format of this string? Please can you document in the Xen tree in xen/include/public/io/netif.h. netif isn't terribly well documented, but we can at least strive to document new stuff. The blkif header is a good example of how things should be. > + 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, _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |