[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#139117: marked as done (Bandwidth throttling for redir'd connections [patch])



Your message dated Wed, 20 Mar 2002 01:15:14 +0100
with message-id <20020320001514.GA31848@atterer.net>
and subject line Duh, not wnpp...
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Debian bug tracking system administrator
(administrator, Debian Bugs database)

--------------------------------------
Received: (at submit) by bugs.debian.org; 19 Mar 2002 23:01:31 +0000
>From atterer@in.tum.de Tue Mar 19 17:01:31 2002
Return-path: <atterer@in.tum.de>
Received: from mailrelay2.lrz-muenchen.de [129.187.254.102] 
	by master.debian.org with esmtp (Exim 3.12 1 (Debian))
	id 16nSbi-0004td-00; Tue, 19 Mar 2002 17:01:31 -0600
Received: from [212.224.54.157] by mailrelay2.lrz-muenchen.de with ESMTP for submit@bugs.debian.org; Wed, 20 Mar 2002 00:01:22 +0100
Received: by elessar.lan (Postfix, from userid 1000)
	id 6E8D73A9A2; Tue, 19 Mar 2002 22:34:38 +0100 (CET)
Date: Tue, 19 Mar 2002 22:34:38 +0100
From: Richard Atterer <atterer@debian.org>
To: submit@bugs.debian.org
Subject: Bandwidth throttling for redir'd connections [patch]
Message-Id: <[🔎] 20020319213437.GA26460@atterer.net>
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-15
Content-Transfer-Encoding: Quoted-Printable
Content-Disposition: inline
Delivered-To: submit@bugs.debian.org

Package: wnpp
Version: 2.1-2
Severity: wishlist
Tags: patch

Hi Bernd,

I've hacked redir to accept a --bandwidth switch to limit the
bandwidth of redirected connections to a certain amount, e.g. with
--bandwidth=3D1Mbit or --bandwidth=3D10kbyte. I've successfully used my
hacked version with and without --inetd.

Possible uses:

- Limit bandwidth of connections made from localhost to localhost. The
  kernel traffic shaping features don't work in that case. (That's
  what I'm using it for; to test my download manager app on a machine
  which is not connected to any network most of the time...;)

- Limit traffic if you don't have root on a machine.

The attached patch must be applied on top of the Debian one. Please
also forward this upstream. Hm, the manpage should also be changed to
include the new switch...

Cheers,

  Richard

--=20
  __   _
  |_) /|  Richard Atterer
  | \/=AF|  http://atterer.net
  =AF '` =AF

--- redir.c.orig=09Mon Mar 18 21:50:47 2002
+++ redir.c=09Tue Mar 19 11:10:12 2002
@@ -52,9 +52,21 @@
  *  has connected.
  */
=20
+/* 2002-03-19
+ *
+ * New features:
+ *  - Limit bandwidth to desired amount in mbit/kbit/bit/mbyte/kbyte/byte:=

+ *    --bandwidth 768kbit, --bandwidth 100kbyte
+ *  - Increased size of internal buffer, resulting in larger throughput
+ *    and less CPU usage.
+ *
+ * Added by Richard Atterer <richard at atterer.net>
+ */
+
 #define  VERSION "2.0"
=20
 #include <stdio.h>
+#include <ctype.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
@@ -69,6 +81,7 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 #include <errno.h>
+#include <time.h>
=20
 #ifdef USE_TCP_WRAPPERS
 #include <tcpd.h>
@@ -88,6 +101,7 @@
 int ftp =3D 0;
 int transproxy =3D 0;
 char * ident =3D NULL;
+int bandwidth =3D 0; /* Bandwidth limit in bytes per sec, or 0=3D=3Dinfini=
te */
=20
 #ifdef USE_TCP_WRAPPERS
 struct request_info request;
@@ -141,10 +155,24 @@
     fprintf(stderr, "\t\t--bind_addr=3DIP\tbind() outgoing IP to given add=
r\n");
     fprintf(stderr, "\t\t--ftp\t\tredirect passive ftp connections\n");
     fprintf(stderr, "\t\t--transproxy\trun in linux's transparent proxy mo=
de\n");
+    fprintf(stderr, "\t\t--bandwidth infinite|x{bit|kbit|mbit|byte|kbyte|m=
byte}\n");
+    fprintf(stderr, "\t\t            \tlimit amount of data forwarded per =
second\n");
     fprintf(stderr, "\n\tVersion %s - $Id$\n", VERSION);
     exit(2);
 }
=20
+/* Case-insensitive comparison. b must be all lowercase. */
+int
+strequals(const char* a,
+          const char* b)
+{
+    while (1) {
+        if (*a =3D=3D '\0' && *b =3D=3D '\0') return 1;
+        if (tolower(*a) !=3D *b) return 0;
+        ++a; ++b;
+    }
+}
+
 void
 parse_args(int argc,
 =09   char * argv[],
@@ -158,7 +186,8 @@
 =09   int * dosyslog,
 =09   char ** bind_addr,
 =09   int * ftp,
-=09   int * transproxy)
+=09   int * transproxy,
+=09   int * bandwidth)
 {
      static struct option long_options[] =3D {
 =09  {"lport", required_argument, 0, 'l'},
@@ -174,6 +203,7 @@
 =09  {"syslog",   no_argument,       0, 's'},
 =09  {"ftp",      no_argument,       0, 'f'},
 =09  {"transproxy", no_argument,     0, 'p'},
+=09  {"bandwidth", required_argument, 0, 'w'},
 =09  {0,0,0,0}=09=09/* End marker */
      };
     =20
@@ -188,6 +218,7 @@
     *target_addr =3D NULL;
     *target_port =3D 0;
     *local_port =3D 0;
+    *bandwidth =3D 0;
=20
     while ((opt =3D getopt_long(argc, argv, "disfpn:t:b:a:l:r:c:",=20
 =09=09=09      long_options, &option_index)) !=3D -1) {
@@ -241,6 +272,23 @@
 =09     (*transproxy)++;
 =09     break;
=20
+        case 'w': {
+            char* p =3D optarg;
+            *bandwidth =3D 0;
+            if (strequals(p, "infinite")) break;
+            while (*p >=3D '0' && *p <=3D '9')
+                *bandwidth =3D *bandwidth * 10 + (*p++ - '0');
+            if (strequals(p, "bit")) *bandwidth /=3D 8;
+            else if (strequals(p, "kbit")) *bandwidth =3D *bandwidth*1000/=
8;
+            else if (strequals(p, "mbit")) *bandwidth =3D *bandwidth*10000=
00/8;
+            else if (strequals(p, "byte")) ;
+            else if (strequals(p, "kbyte")) *bandwidth *=3D 1024;
+            else if (strequals(p, "mbyte")) *bandwidth *=3D 1024*1024;
+            else { redir_usage(argv[0]); exit(1); }
+            if (*bandwidth =3D=3D 0) *bandwidth =3D 1;
+            break;
+        }
+
 =09default:
 =09    redir_usage(argv[0]);
 =09    exit(1);
@@ -392,11 +440,16 @@
     fd_set c_iofds;
     int max_fd;=09=09=09/* Maximum numbered fd used */
     struct timeval timeout;
+    struct timeval time_prev, time_now;
+    signed long max_bucketsize =3D bandwidth * 5 * 1000; /* 5 sec */
+    signed long bucketsize =3D 0; /* Contains nr of bytes * 1000 */
     unsigned long bytes;
     unsigned long bytes_in =3D 0;
     unsigned long bytes_out =3D 0;
     unsigned int start_time, end_time;
-    char buf[4096];
+    int buf_size =3D (bandwidth =3D=3D 0 || bandwidth/4 + 1 > 65536
+                    ? 65536 : bandwidth/4 + 1);
+    char buf[65536];
=20
     /* Record start time */
     start_time =3D (unsigned int) time(NULL);
@@ -410,6 +463,8 @@
     FD_SET(insock, &iofds);
     FD_SET(outsock, &iofds);
=20
+    /* Init bandwidth limiting */
+    if (gettimeofday(&time_prev, NULL)) perror("gettimeofday");
    =20
     if (insock > outsock) {
 =09max_fd =3D insock;
@@ -431,15 +486,16 @@
 =09    break;
 =09}
=20
+        bytes =3D 0;
 =09if(FD_ISSET(insock, &c_iofds)) {
-=09    if((bytes =3D read(insock, buf, sizeof(buf))) <=3D 0)
+=09    if((bytes =3D read(insock, buf, buf_size)) <=3D 0)
 =09=09break;
 =09    if(write(outsock, buf, bytes) !=3D bytes)
 =09=09break;
 =09    bytes_out +=3D bytes;
 =09}
 =09if(FD_ISSET(outsock, &c_iofds)) {
-=09    if((bytes =3D read(outsock, buf, sizeof(buf))) <=3D 0)
+=09    if((bytes =3D read(outsock, buf, buf_size)) <=3D 0)
 =09=09break;
 =09    /* if we're correcting for PASV on ftp redirections, then
 =09       fix buf and bytes to have the new address, among other
@@ -451,6 +507,31 @@
 =09=09      break;
 =09    bytes_in +=3D bytes;
 =09}
+        if (bytes > 0 && bandwidth > 0) {
+            /* Throttle bandwidth */
+            unsigned long msec_elapsed;
+            if (gettimeofday(&time_now, NULL)) perror("gettimeofday");
+            msec_elapsed =3D (time_now.tv_sec - time_prev.tv_sec) * 1000;
+            if (time_now.tv_usec >=3D time_prev.tv_usec)
+              msec_elapsed +=3D (time_now.tv_usec - time_prev.tv_usec) / 1=
000;
+            else
+              msec_elapsed -=3D (time_prev.tv_usec - time_now.tv_usec) / 1=
000;
+            time_prev =3D time_now;
+            bucketsize +=3D msec_elapsed * bandwidth;
+            if (bucketsize > max_bucketsize) bucketsize =3D max_bucketsize=
;
+            if (bytes * 1000 <=3D bucketsize) {
+                bucketsize -=3D bytes * 1000; /* OK - no throttling */
+            } else {
+                /* +bandwidth/2 would be correct, but /4 gives
+                   slightly better results in practice. */
+                unsigned long msec_sleep =3D ((bytes * 1000 - bucketsize)
+                                            + bandwidth/4) / bandwidth;
+                /*debug1("Bandwidth exceeded - sleeping for %ld millisecs\=
n",
+                         msec_sleep);*/
+                usleep(msec_sleep * 1000);
+                bucketsize =3D -msec_sleep * bandwidth;
+            }
+        }
     }
     debug("Leaving main copyloop\n");
=20
@@ -739,7 +820,7 @@
     debug("parse args\n");
     parse_args(argc, argv, &target_addr, &target_port, &local_addr,=20
 =09       &local_port, &timeout, &dodebug, &inetd, &dosyslog, &bind_addr,
-=09       &ftp, &transproxy);
+=09       &ftp, &transproxy, &bandwidth);
=20
     /* Set up target */
     target.sin_family =3D AF_INET;

---------------------------------------
Received: (at 139117-done) by bugs.debian.org; 20 Mar 2002 11:36:19 +0000
>From atterer@in.tum.de Wed Mar 20 05:36:19 2002
Return-path: <atterer@in.tum.de>
Received: from mailrelay2.lrz-muenchen.de [129.187.254.102] 
	by master.debian.org with esmtp (Exim 3.12 1 (Debian))
	id 16neOB-00020X-00; Wed, 20 Mar 2002 05:36:19 -0600
Received: from [131.159.130.18] by mailrelay2.lrz-muenchen.de with ESMTP for 139117-done@bugs.debian.org; Wed, 20 Mar 2002 12:35:48 +0100
Received: by elessar.lan (Postfix, from userid 1000)
	id D50873A994; Wed, 20 Mar 2002 01:15:14 +0100 (CET)
Date: Wed, 20 Mar 2002 01:15:14 +0100
From: Richard Atterer <atterer@debian.org>
To: 139117-done@bugs.debian.org
Subject: Duh, not wnpp...
Message-Id: <20020320001514.GA31848@atterer.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Delivered-To: 139117-done@bugs.debian.org

Oops, wrong package name...



Reply to: