Apache module: bwshare
change history

/*-----------------------------------------------------------------------------
Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2008, Alan Kennington.
You may distribute this software under the terms of Alan Kennington's
modified Artistic Licence, as specified in the accompanying LICENCE file.
-----------------------------------------------------------------------------*/
This software package is open and free.
Please read the LICENCE file for precise details.

DISCLAIMER.
The author of this software disclaims any express or implied guarantee of the
fitness of this software for any purpose. In no event shall the author of this
software be held liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to, procurement
of substitute services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence or otherwise) arising in any way out of
the use of this software, even if advised of the possibility of such damage.

mod_bwshare version 0.2.1 (2008-1-31)
  1. Ported mod_bwshare back to Apache 1.3.23.

    Finally I got around to porting mod_bwshare back to Apache 1.x.y, which is what it was written for in the first place. Over the years, it got less and less backwards compatible because I wasn't testing it on Apache 1.x.y any more.

    Now I've tried version 0.2.1 of mod_bwshare on Apache 1.3.23, 2.0.49 and 2.0.55, and it seems to be okay. The really difficult thing is to guess the running sequence of Apache initialize and cleanup operations. They seem to be highly variable and undocumented, and yet they are crucial to ensuring that there are no leaks of semaphores or shared memory. If mod_bwshare does not re-create the semaphores or shared memory sufficiently often, the module does not work. So it's important to keep careful count so as to collect the garbage correctly.

    It is just possible that there may be a new bug in the semaphore or shared memory creation/destruction in mod_bwshare version 0.2.1 on some operating systems for some versions of Apache. Please let me know if there are any problems of this kind. If you do find such a bug, just go back to version 0.2.0.

  2. Additional tracing of internal variables and parameters.

    I added some extra internal variables and parameters for the trace table which is accessed via command lines like bwshare-trace?trace=1.

mod_bwshare version 0.2.0 (2006-8-18)
  1. Removed forced reverse DNS verification.

    Reverse DNS verification (so-called double look-ups) are very slow on web servers which have slow DNS resolvers or a slow link to the DNS resolvers. Therefore forced reverse DNS verification and forced reverse DNS look-up are now removed. Therefore if you have HostnameLookups Off in your Apache server configuration file, you will see no reverse DNS at all in the bwshare-trace screen. If you have HostnameLookups On or HostnameLookups Double you should see the same reverse DNS in bwshare-trace as you see in the Apache server log files. Many thanks to Daniel in Lausanne for generous help to diagnose the problem of slow bwshare DNS look-up.

  2. Removed attempted reverse DNS for IPv6 addresses.

    It didn't seem like this was much used. So I've removed it.

  3. Removed reverse DNS verification failure asterisks.

    Since reverse DNS verification is no longer forced, it makes no sense to maintain the old warning asterisks. These used to appear at the left of reverse DNS names in the bwshare-trace screen.

  4. Renamed distribution zip file to mod_bwshare-0.2.0.zip.

    Also changed the dirctory of the zip file from src/bwshare to mod_bwshare-0.2.0. This is more consistent with real software distributions. (Thanks to Daniel for this suggestion also.)

mod_bwshare version 0.1.9 (2006-5-16)
  1. Fixed compilation failure in the case that IPv6 support is not compiled into Apache 2.

    This happens with some Solaris builds, I've been told. The parameter APR_HAVE_IPV6 in apr.h tells you whether IPv6 is compiled into Apache. So I just commented out the bwshare lines which refer to IPv6 if the symbol APR_HAVE_IPV6 is false.

  2. Changed user/group id of semaphore array and shared memory to child process uid/gid.

    Previously the semaphore array and shared memory of bwshare were owned by root. Therefore they had to be world readable and writeable, which is clearly a local security issue. Now the uid and gid are set to the right values for the child process, and the ugo permissions are set to rw------- (octal umask 0600).

  3. Added commas to indicate factors of a thousand in total data sent field.

    It's very difficult to count digits in large numbers sometimes. So in both the bwshare-trace and bwshare-info web pages, the 64-bit total data sent value is represented with English-style commas. Example: 3,213,166,315 bytes instead of 3213166315 bytes.

mod_bwshare version 0.1.8 (2006-5-15)
  1. Added per-subnet bandwidth limitation for each client IPv4 subnets.

    For each subnet of HTTP client IP addresses, a separate set of bandwidth limit parameters may be specified: TX1 cred rate, TX1 debt max, TX2 cred rate, TX2 debt max. Example syntax in Apache configuration file:

    <IfModule mod_bwshare.c>
        # Local network.
        BW_subnet_limit net = 192.168.1.0/24 \
            tx1rate =   80.00 files/min  tx1max =      200 files \
            tx2rate = 1000000 bits/sec   tx2max = 10000000 bytes
    
        # Google.com.
        BW_subnet_limit net = 66.249.66.65/24 \
            tx1rate =   24.00 files/min  tx1max = 80.0 files \
            tx2rate =  120000 bits/sec   tx2max = 4000000 bytes
    </IfModule>
    

    For details, see configuration details on the README page.

  2. Added a new parameter limits for the bwshare-trace URL to request the per-IP-address bandwidth parameters to be displayed.
  3. Added quotation marks around HTML colour fields in the bwshare-info and bwshare-trace web pages.
  4. Fixed the problem of non-detached shared memory hanging around after a restart of the Apache server.
  5. Rearranged the bwshare-info web page to make it look nicer.

mod_bwshare version 0.1.7 (2006-5-13)
  1. Changed the HTTP status code for server overload from 200 to 503.

    Reason: Originally I set the overload status code to 503, which is the correct code to return under such circumstances. However, I noticed that many exploitative download software just goes faster when it detects an overload. The thinking of the programmers is purely selfish. They think that if there is an overload, they should try harder to get a bigger share of a scarce resource. In this case, though, the congestion is caused by the selfish downloader. So the more selfish they behave, the worse the congestion becomes. Therefore I changed the return code to 200. That ensured that selfish rampant download programs would just get a big hunk of junk. A human user would see the congestion warnings on web pages and slow down. So that seemed like a good idea.

    The problem with using the status code 200 is that some search robots will fill their indexes with junk. That's not good if you actually want to be indexed. At first, this was not a problem because the reputable search robots were well behaved. However, some time in 2005, Googlebot changed their moderate download rates (about 2 or 4 downloads per minute) to the worst possible rampant download behaviour. They simply tried to download entire web sites at the absolute maximum download rate. As a result, the Google search results were polluted by listings of bwshare congestion warning pages. Although Google does have a service to reduce load on web servers if you send them a nice e-mail, my last request for civilized behaviour fell on deaf ears. Googlebot continued to get worse and worse, frequently filling its index with hundreds of junk pages instead of my real web pages.

    Now I've finally changed the HTTP result code for bwshare congestion back to 503. Googlebot sort of behaves correctly now. Googlebot sees the 503 code and slows down for a short while. Then when it gets a 200 status, it goes very fast again. So now its behaviour alternates between slow and fast. It doesn't adjust in a really efficient manner. It still behaves as selfishly as possible. However, this is better than nothing. If you set the download rate to 8 files per minute, Googlebot downloads at an efficiency of around 50%. That is, Googlebot downloads about 50% real files and about 50% warning messages with the 503 return code.

  2. Fixed a semaphore leak.

    This bug arose in version 0.1.5 because someone sent me a bug fix for a problem where the configuration file parameters were not being read correctly in Apache 2. The old code before version 0.1.5 worked fine in Apache version 1, but the abysmal Apache 2 module developer documentation made it difficult for me to fix the configuration error. So I just added the bug fix without checking to see if it was correct by my usual method of code analysis. I used the primitive technique of code testing to establish that it seemed to do no harm.

    However, I later noticed that the linux kernel was experiencing exhaustion of semaphore arrays. This made is necessary to re-boot the machine to clear the semaphore arrays because I didn't know how to determine which semaphores were orphan semaphores. Now I know how to clear out the orphan semaphores manually. But it's best to not generate the orphans in the first place. The semaphore leaks were occurring every time I ran apachetl to stop, start or restart the Apache server, or even to just get information on the status of the running process.

    So now I've fixed the bug. It was just a matter of activating some old features in the code which were waiting to be activated.

mod_bwshare version 0.1.6 (2005-10-3)
  1. Added a configuration parameter BW_throttle_off.

    This is a per-server parameter which effectively makes the debt max parameters infinite. This permits the leaky bucket debt values to become arbitrarily large. Therefore the bandwidth congestion limitation is not enforced. This freedom applies only to the virtual server in which the parameter BW_throttle_off is set to 1. If a visitor to the web-site then tries to browse other virtual servers on the same real server, the accumulated leaky bucket debt prevents access to the other virtual servers.

mod_bwshare version 0.1.5 (2005-10-3)
  1. Moved shared-memory initialization to create-server handler function.

    This change was suggested by someone as a solution to the fact that bwshare version 0.1.4 did not take any notice of the configuration parameters in the Apache 2 configuration files. The reason why these parameters were ignored was that the shared-momory block in bwshare was created too late in the server initialization sequence. According to the woefully inadequate Apache 2.0 module developer documentation, ap_hook_post_config: this is where the old _init routines get registered. I followed that advice when porting from Apache 1 to 2, but it turned out to be incorrect. (The Apache 2 module documentation is both woefully incomplete and woefully inaccurate. You really have to read the source code to even start to make sense of it.)

    It turns out that the ap_hook_post_config hook is too late in the Apache server initialization sequence for creating and attaching shared memory. The Apache 2 configuration parameters are read long before the ap_hook_post_config hook functions are called. I can't find any ap_hook_pre_config hook. (Maybe I'll grep for this some day in the source.) So it is necessary to do a work-around. The work-around which someone sent me by e-mail was to move my bwshare_init() function call from my bwshare_init_handler() function (which is called at the correct time in Apache 1 but is called too late in Apache 2) to my bwshare_create_server() function (which is called when virtual servers are encounterd in configuration files).

    As a result of this change, the bwshare shared memory block (which hold state information which is common to all processes in the Apache process group) ended up being created once for each virtual server, which is very bad. To protect against this, I kept track of how many copies of the memory there were, and this meant that only one copy ended being created. However, as a side-effect, the semaphores were created too many times. This led to semaphore leakage, which has now been fixed in bwshare version 0.1.7.

    The end result of this change was that finally the Apache 2 module did read the parameters in the configuration files, but the cost of this benefit was a very serious semaphore leakage.

mod_bwshare version 0.1.4 (2005-7-29)
  1. Modified bandwidth measurement rules.

    After the change, request_rec::bytes_sent is used instead of request_rec::read_length. When reqeust_rec::sent_bodyct is zero, it is now assumed that zero bytes have been transmitted.

    Before these changes, the bwshare module in the Apache 2 server used to count as transmitted bytes the full size of a file even when the HTTP client was only requesting the HEAD information for the file. In the case of downloading large files such as tarballs, this often had the effect of blocking all access from certain kinds of badly-designed browsers.

  2. Modified appearance of bwshare-trace and bwshare-info web pages.

    Added DOCTYPE and other HTML header improvements. Rearranged the HTML tables of bwshare parameters and run-time variables. Removed bwshare hash table stats from the bwshare-trace page.

  3. Changed function declarations to ANSI C convention for void parameter list.

mod_bwshare version 0.1.3 (2003-2-28)
  1. Added hook function for ap_hook_post_config.

    Created function bwshare_init_handler() as the event handler for the ap_hook_post_config hook. This function adds a string to the Apache 2 self-description string for the server version. It also calls my function bwshare_init() to initialize the bwshare module. Unfortunately, it turned out later that this is too late in the server initialization sequence to create the shared-memory block to receive the server configuration parameters. This was fixed in version 0.1.5 in a kludgy sort of way, which caused a more serious bug, which was finally fixed in version 0.1.7.

mod_bwshare version 0.1.2 (2002-10-19)
  1. Ported mod_bwshare to Apache version 2.

    This was done mostly by trial and error, and by consulting the Apache 2 source, because the Apache 2 documentation is woefully inadequate.

  2. Added configuration parameters for bwshare traffic limitation.
  3. Made some changes to handling of reverse DNS addresses for HTTP clients.

mod_bwshare version 0.1.1 (2000-12-6)
  1. Ported the bwshare module to BSD.

    This required only the removal of the union semun declaration.

  2. Changed leaky bucket debt variables from 32-bit integer-ratios to double-float.

    Originally integer fractions were used for speed for all leaky bucket debt calculations. But it turned out that in practice, even for slow CPUs, the speed of double-float arithmetic was about the same as integer arithmetic.

  3. Added numerous sort options for displaying HTTP client records.
  4. Changed the HTTP status code for congestion warning pages from 503 to 200.

    This was changed back to 503 in version 0.1.7. The reason for the change from 503 to 200 was that many rampant download HTTP client programs used to go crazy and go faster and faster when they saw that the web server was congested. That's totally selfish, but an awful lot of software used to do that. So I just changed from 503 to 200 to reduce the amount of garbage in the web server log files.


Go to bwshare Apache module main web page.
Go to bwshare Apache module things-to-do list.
Go to some notes on Apache server software.
Go to Alan Kennington's home page.