Wednesday, July 15, 2009

Script for Xbox Live: Detect and Disable Bittorrent

Goal

When you are playing games on Xbox Live, you usually need every bit of ping speed possible. For us with DSL, when the line is saturated, the ping times drop. If you run a bittorrent client around the clock, then even small amounts of seeding or large amounts of downloading can noticeably slow your ping times. Most modern connections are good enough to not drop packets, but only fractionally delay them. When that one packet is your sniper rifle bullet, any delay can have dire consequences. This whole subject can apply to PS3 or any other service of your liking. You could also use some of the commands for PC gaming.

Best solution

The best solution I have discovered by trial and error is to always decrease the load on the line. Prioritizing packets at the router does not always ensure that the modem can imediately send them as requested. We need to detect that an Xbox live connection is active and reduce the bandwith load at the source, which in this example is uTorrent.

How to detect Xbox Live

Well it turns out this can be fairly difficult to do accurately, as the service is always changing. The easiest and most reliable way is to just detect that the Xbox unit is active on the LAN, and assume that Xbox Live is active. Other methods may work, but this is the easiest and most reliable.

check=`ip neighbor | grep 192.168.1.6 > /dev/null; echo $?`

First we need to make sure the Xbox has a static IP, or a static DHCP so we can detect it. Then we use "ip neighbor" to see if it is listed as active in the ip tables for the router. This command should find it immediately as soon as the Xbox comes online. When it turns off, there will be a delay before it disappears. The reason for using a variable is in case we have more than one Xbox.

Running a command once it is detected

Once you have detected the IP is active, then you need to run some sort of command to tell something to cut off your bittorrent bandwidth. One way is to use routing to cut of the IP of your bittorrent machine, but a more elegant way is to send a command to the bittorrent client to have it gracefully ease the traffic. uTorrent has a nice web-ui that you can send commands to change its settings. The settings we are concerned with are restricting upload, download, and total number of connections. The reason for restricting the connections is that some modems bog down with too many connections, regardless of the throughput. And in an unrelated note, it is always good to have lots of connections for good bittorrent speeds. The wget command tries to get a webpage, this one includes sending the request for the desired settings. There must also be a command to reset the settings back to default for when the Xbox goes offline, in this example, it is "max_ul_rate\&v\=0", which means unlimited bandwidth.

Update: uTorrent 2.x now enables a new authentication measure by default, which is not compatible with this script. Simply turn it off as mentioned in this thread. Access Options...Preferences...Advanced then set webui.token_auth to false.

if [ $check -eq "0" ]; then
wget -O /dev/null http\://username\:password\@192.168.1.3:9999/gui/\?action\=setsetting\&s\=max_ul_rate\&v\=5\&s=max_dl_rate\&v=5\&s=conns_globally\&v=50 2> /dev/null
else
wget -O /dev/null http\://username\:password\@192.168.1.3:9999/gui/\?action\=setsetting\&s\=max_ul_rate\&v\=0\&s=max_dl_rate\&v=0\&s=conns_globally\&v=300 2> /dev/null
fi


Multiple Xbox's

You can setup more than Xbox as well, as long as they have their static IP's set.


check=`ip neighbor | grep 192.168.1.6 > /dev/null; echo $?`
check2=`ip neighbor | grep 192.168.1.55 > /dev/null; echo $?`
if [[ $check == "0" || $check2 == "0" ]]; then


My whole script

Here is my script in its entirety. It runs every 1 minute on my Linksys WRT54GL running Tomato Linux.

check=`ip neighbor | grep 192.168.1.6 > /dev/null; echo $?`
if [[ $check == "0" ]]; then
wget -O /dev/null http\://username\:password\@192.168.1.3:9999/gui/\?action\=setsetting\&s\=max_ul_rate\&v\=5\&s=max_dl_rate\&v=5\&s=conns_globally\&v=50 2> /dev/null
else
wget -O /dev/null http\://username\:password\@192.168.1.3:9999/gui/\?action\=setsetting\&s\=max_ul_rate\&v\=0\&s=max_dl_rate\&v=0\&s=conns_globally\&v=300 2> /dev/null
fi


Source of information

The original thread that I discussed and got ideas from is below. Thanks for your help!
LinksysInfo Forums: Script for Xbox Live: Detect and Make QoS Changes


Updates for using on Ubuntu

I switched from running on my router to running on my Ubuntu box.  I added a cron script to run every minute, and since the box does not actively interface with the switch and Xbox, I added a ping to the script.  This changes what gets listed in the ip neighbor results, so I simply changed it to detect the MAC of my Xbox instead of the IP.

Updated part of script:
#!/bin/bash
ping 192.168.1.14 -c 1
check=`ip neighbor | grep 00:dd:d8:dd:2f:5a > /dev/null; echo $?`