diff --git a/opentrafficshaper/plugins/tc/tc.pm b/opentrafficshaper/plugins/tc/tc.pm
index 652edbd05c14b65f7817e9f89c8594f49d3bb561..510bffdca326a1194c477e555a2a4282f08e3b61 100644
--- a/opentrafficshaper/plugins/tc/tc.pm
+++ b/opentrafficshaper/plugins/tc/tc.pm
@@ -26,6 +26,7 @@ use POE qw( Wheel::Run Filter::Line );
 
 use opentrafficshaper::constants;
 use opentrafficshaper::logger;
+use opentrafficshaper::utils;
 
 
 
@@ -56,14 +57,21 @@ our $pluginInfo = {
 my $globals;
 my $logger;
 
-my $classMaps = {
-	1 => {
-		1 => "Primary Interface",
-	},
-};
-my $classID = 10;
 
+# Our own config stuff
+
+# ID of last class used
+my $classID = 10;
+# Queue of tasks to run
 my @taskQueue = ();
+# Interfaces
+my $rxiface = "eth0";
+my $rxrate = "10240kbit";
+my $txiface = "eth1";
+my $txrate = "10240kbit";
+# TC filters
+my $tcFilters;
+my $lastTcFilter = 900;
 
 
 
@@ -101,7 +109,82 @@ sub init
 		}
 	);
 
-	$logger->log(LOG_NOTICE,"[TC] OpenTrafficShaper tc Integration v".VERSION." - Copyright (c) 2013, AllWorldIT")
+	$logger->log(LOG_NOTICE,"[TC] OpenTrafficShaper tc Integration v".VERSION." - Copyright (c) 2013, AllWorldIT");
+
+
+	# Check our interfaces
+	if (defined(my $rxi = $globals->{'file.config'}->{'plugin.tc'}->{'rxiface'})) {
+		$logger->log(LOG_INFO,"[TC] Set rxiface to '$rxi'");
+		$rxiface = $rxi;
+	}
+	if (defined(my $txi = $globals->{'file.config'}->{'plugin.tc'}->{'txiface'})) {
+		$logger->log(LOG_INFO,"[TC] Set txiface to '$txi'");
+		$txiface = $txi;
+	}
+
+
+	# Initialize TX interface
+	$logger->log(LOG_INFO,"[TC] Queuing tasks to initialize '$txiface'");
+	_tc_task_add_to_queue([
+			'/sbin/tc','qdisc','del',
+				'dev',$txiface,
+				'root'
+	]);
+	_tc_task_add_to_queue([
+			'/sbin/tc','qdisc','add',
+				'dev',$txiface,
+				'root',
+				'handle','1:',
+				'htb'
+	]);
+	_tc_task_add_to_queue([
+			'/sbin/tc','class','add',
+				'dev',$txiface,
+				'parent','1:',
+				'classid','1:1',
+				'htb',
+					'rate',$txrate
+	]);
+	_tc_task_add_to_queue([
+			'/sbin/tc','filter','add',
+				'dev',$txiface,
+				'parent','1:0',
+				'prio','10',
+				'protocol','ip',
+				'u32',
+	]);
+
+	# Initialize RX interface
+	$logger->log(LOG_INFO,"[TC] Queuing tasks to initialize '$rxiface'");
+	_tc_task_add_to_queue([
+			'/sbin/tc','qdisc','del',
+				'dev',$rxiface,
+				'root'
+	]);
+	_tc_task_add_to_queue([
+			'/sbin/tc','qdisc','add',
+				'dev',$rxiface,
+				'root',
+				'handle','1:',
+				'htb'
+	]);
+	_tc_task_add_to_queue([
+			'/sbin/tc','class','add',
+				'dev',$rxiface,
+				'parent','1:',
+				'classid','1:1',
+				'htb',
+					'rate',$rxrate
+	]);
+	_tc_task_add_to_queue([
+			'/sbin/tc','filter','add',
+				'dev',$rxiface,
+				'parent','1:0',
+				'prio','10',
+				'protocol','ip',
+				'u32',
+	]);
+
 }
 
 
@@ -125,35 +208,192 @@ sub do_add {
 	my $users = $globals->{'users'};
 	my $user = $users->{$uid};
 
-	$users->{$uid}->{'shaper.live'} = SHAPER_LIVE;
+	$user->{'shaper.live'} = SHAPER_LIVE;
 	$logger->log(LOG_DEBUG," Add '$user->{'Username'}' [$uid]\n");
 
-#	tc class add dev eth0 parent 1:1  classid 1:aa  htb rate 150kbps ceil 200kbps
-#	tc filter add dev eth0 parent 1:1 protocol ip prio 1 u32 \
-#		match ip dst 10.254.254.235/32 flowid 1:aa
 
-	$classID++;
-	my $classIDHex = sprintf('%x',$classID);
+	my @components = split(/\./,$user->{'IP'});
+
+	# Filter level 2-4
+	my $ip1 = $components[0];
+	my $ip2 = $components[1];
+	my $ip3 = $components[2];
+	my $ip4 = $components[3];
+
+	# Check if we have a entry for the /8, if not we must create our 2nd level hash table and link it
+	if (!defined($tcFilters->{$ip1})) {
+		# Setup IP1's hash table
+		$tcFilters->{$ip1}->{'id'} = ++$lastTcFilter;
+		my $filterIDHex = toHex($lastTcFilter);
+
+
+		$logger->log(LOG_DEBUG,"Linking 2nd level hash table to '$filterIDHex' to $ip1.0.0/8\n");
+
+		# Create second level hash table for $ip1
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'handle',"$filterIDHex:",
+					'protocol','ip',
+					'u32',
+						'divisor','256',
+		]);
+		# Link hash table
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'protocol','ip',
+					'u32',
+						# Root hash table
+						'ht','800::',
+							'match','ip','dst',"$ip1.0.0.0/8",
+						'hashkey','mask','0x00ff0000','at',16,
+						# Link to our hash table
+						'link',"$filterIDHex:"
+		]);
+	}
 
-	$kernel->post("_tc" => "queue" => [
-			'/sbin/tc','class','add',
-				'dev','eth0',
-				'parent','1:1',
-				'classid',"1:$classIDHex",
-				'htb',
-					'rate','150kbps',
-					'ceil','200kbps',
-	]);
-	$kernel->post("_tc" => "queue" => [
-			'/sbin/tc','filter','add',
-				'dev','eth0',
-				'parent','1:1',
-				'protocol','ip',
-				'prio','1',
-				'u32',
-					'match','ip','dst',$user->{'IP'},
-				'flowid',"1:$classIDHex",
-	]);
+	# Check if we have our /16 hash entry, if not we must create the 3rd level hash table
+	if (!defined($tcFilters->{$ip1}->{$ip2})) {
+		$tcFilters->{$ip1}->{$ip2}->{'id'} = ++$lastTcFilter;
+		my $filterIDHex = toHex($lastTcFilter);
+		# Set 2nd level hash table ID
+		my $ip1HtHex = toHex($tcFilters->{$ip1}->{'id'});
+		# Hex of IP2 for hash table
+		my $ip2Hex = toHex($ip2);
+
+
+		$logger->log(LOG_DEBUG,"Linking 3rd level hash table to '$filterIDHex' to $ip1.$ip2.0.0/16\n");
+		# Create second level hash table for $fl1
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'handle',"$filterIDHex:",
+					'protocol','ip',
+					'u32',
+						'divisor','256',
+		]);
+		# Link hash table
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'protocol','ip',
+					'u32',
+						# This is the 2nd level hash table
+						'ht',"${ip1HtHex}:${ip2Hex}:",
+							'match','ip','dst',"$ip1.$ip2.0.0/16",
+						'hashkey','mask','0x0000ff00','at',16,
+						# That we're linking to our hash table
+						'link',"$filterIDHex:"
+		]);
+	}
+
+	# Check if we have our /24 hash entry, if not we must create the 4th level hash table
+	if (!defined($tcFilters->{$ip1}->{$ip2}->{$ip3})) {
+		$tcFilters->{$ip1}->{$ip2}->{$ip3}->{'id'} = ++$lastTcFilter;
+		my $filterIDHex = toHex($lastTcFilter);
+		# Set 3rd level hash table ID
+		my $ip2HtHex = toHex($tcFilters->{$ip1}->{$ip2}->{'id'});
+		# Hex of IP2 for hash table
+		my $ip3Hex = toHex($ip3);
+
+
+		$logger->log(LOG_DEBUG,"Linking 4th level hash table to '$filterIDHex' to $ip1.$ip2.$ip3.0/24\n");
+		# Create second level hash table for $fl1
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'handle',"$filterIDHex:",
+					'protocol','ip',
+					'u32',
+						'divisor','256',
+		]);
+		# Link hash table
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'protocol','ip',
+					'u32',
+						# This is the 3rd level hash table
+						'ht',"${ip2HtHex}:${ip3Hex}:",
+							'match','ip','dst',"$ip1.$ip2.$ip3.0/24",
+						'hashkey','mask','0x000000ff','at',16,
+						# That we're linking to our hash table
+						'link',"$filterIDHex:"
+		]);
+
+	}
+
+
+
+	# Only if we have limits setup process them
+	if (defined($user->{'TrafficLimitTx'}) && defined($user->{'TrafficLimitRx'})) {
+		# Build users tc class ID
+		my $classIDHex = toHex(++$classID);
+		# Set 4th level hash table ID
+		my $ip3HtHex = toHex($tcFilters->{$ip1}->{$ip2}->{$ip3}->{'id'});
+		# Hex of IP2 for hash table
+		my $ip4Hex = toHex($ip4);
+
+
+		# Save user tc class ID
+		$user->{'tc.class'} = $classID;
+
+
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','class','add',
+					'dev',$txiface,
+					'parent','1:1',
+					'classid',"1:$classIDHex",
+					'htb',
+						'rate', $user->{'TrafficLimitTx'},
+						'ceil', $user->{'TrafficLimitTxBurst'},
+		]);
+
+#		$kernel->post("_tc" => "queue" => [
+#				'/sbin/tc','class','add',
+#					'dev',$rxiface,
+#					'parent','1:1',
+#					'classid',"1:$classIDHex",
+#					'htb',
+#						'rate', $user->{'TrafficLimitRx'},
+#						'ceil', $user->{'TrafficLimitRxBurst'},
+#		]);
+
+		$kernel->post("_tc" => "queue" => [
+				'/sbin/tc','filter','add',
+					'dev',$txiface,
+					'parent','1:0',
+					'prio','10',
+					'protocol','ip',
+					'u32',
+						'ht',"${ip3HtHex}:${ip4Hex}:",
+						'match','ip','dst',$user->{'IP'},
+					'flowid',"1:$classIDHex",
+		]);
+#		$kernel->post("_tc" => "queue" => [
+#				'/sbin/tc','filter','add',
+#					'dev',$rxiface,
+#					'parent','1:',
+#					'protocol','ip',
+#					'prio','1',
+#					'u32',
+#						'match','ip','src',$user->{'IP'},
+#					'flowid',"1:$classIDHex",
+#		]);
+	}
 }
 
 # Change event for tc
@@ -193,12 +433,15 @@ sub tc_session_init {
 	my $kernel = $_[KERNEL];
 	# Set our alias
 	$kernel->alias_set("_tc");
+
+	# Fire things up, we trigger this to process the task queue generated during init
+	$kernel->yield("tc_task_run_next");
 }
 
-# Run a task
-sub tc_task_add
+# Add task to queue
+sub _tc_task_add_to_queue
 {
-	my ($kernel,$heap,$cmd) = @_[KERNEL,HEAP,ARG0];
+	my $cmd = shift;
 
 
 	# Build commandline string
@@ -206,6 +449,17 @@ sub tc_task_add
 	# Shove task on list
 	$logger->log(LOG_DEBUG,"[TC] TASK: Queue '$cmdStr'");
 	push(@taskQueue,$cmd);
+}
+
+
+# Run a task
+sub tc_task_add
+{
+	my ($kernel,$heap,$cmd) = @_[KERNEL,HEAP,ARG0];
+
+
+	# Internal function to add command to queue
+	_tc_task_add_to_queue($cmd);
 
 	# Trigger a run if list is empty
 	if (@taskQueue < 2) {