diff --git a/opentrafficshaper/plugins/configmanager.pm b/opentrafficshaper/plugins/configmanager.pm
index 9f0f7a6fcbf74e344cf9358cf2a0ce81abfce81f..a5576859bd34719a590eaf8aef0c2934d7a8266e 100644
--- a/opentrafficshaper/plugins/configmanager.pm
+++ b/opentrafficshaper/plugins/configmanager.pm
@@ -55,7 +55,6 @@ our (@ISA,@EXPORT,@EXPORT_OK);
 	isGroupIDValid
 
 	createTrafficClass
-	changeTrafficClass
 	getTrafficClass
 	getTrafficClasses
 	getInterfaceTrafficClass
@@ -67,7 +66,11 @@ our (@ISA,@EXPORT,@EXPORT_OK);
 	createInterface
 	createInterfaceClass
 	createInterfaceGroup
-	getEffectiveInterfaceTrafficClass
+	changeInterfaceTrafficClass
+	getEffectiveInterfaceTrafficClass2
+	isInterfaceTrafficClassValid
+	setInterfaceTrafficClassShaperState
+	unsetInterfaceTrafficClassShaperState
 
 	createLimit
 
@@ -176,6 +179,19 @@ sub POOL_PERSISTENT_ATTRIBUTES {
 	)
 }
 
+# Class attributes that can be changed (overridden)
+sub CLASS_CHANGE_ATTRIBUTES {
+	qw(
+		CIR Limit
+	)
+}
+
+# Class attributes that can be overidden
+sub CLASS_OVERRIDE_CHANGESET_ATTRIBUTES {
+	qw(
+		CIR Limit
+	)
+}
 
 # Mandatory pool member attributes
 sub POOLMEMBER_REQUIRED_ATTRIBUTES {
@@ -488,8 +504,12 @@ sub plugin_init
 	$globals->{'PoolOverrides'} = { };
 	$globals->{'PoolOverrideIDCounter'} = 1;
 
+	$globals->{'InterfaceTrafficClasses'} = { };
+	$globals->{'InterfaceTrafficClassCounter'} = 1;
+
 	$globals->{'PoolChangeQueue'} = { };
 	$globals->{'PoolMemberChangeQueue'} = { };
+	$globals->{'InterfaceTrafficClassChangeQueue'} = { };
 
 	# If we have global config, use it
 	my $gconfig = { };
@@ -882,6 +902,8 @@ sub plugin_init
 		}
 	}
 
+# TODO - loop and queue init interfaces?
+
 	# Check if we have a state file
 	if (defined(my $statefile = $system->{'file.config'}->{'system'}->{'statefile'})) {
 		$config->{'statefile'} = $statefile;
@@ -1033,6 +1055,40 @@ sub _session_tick
 		$globals->{'LastCleanup'} = $now;
 	}
 
+	# Loop through interface traffic classes
+	while (my ($interfaceTrafficClassID, $interfaceTrafficClass) = each(%{$globals->{'InterfaceTrafficClassChangeQueue'}})) {
+		my $shaperState = getInterfaceTrafficClassShaperState($interfaceTrafficClassID);
+
+		# Traffic class has been changed
+		if ($interfaceTrafficClass->{'Status'} == CFGM_CHANGED) {
+			# If the shaper is live we can go ahead
+			if ($shaperState & SHAPER_LIVE) {
+				$logger->log(LOG_NOTICE,"[CONFIGMANAGER] Interface traffic class [%s] has been modified, sending to shaper",
+						$interfaceTrafficClassID
+				);
+				$kernel->post('shaper' => 'class_change' => $interfaceTrafficClassID);
+				# Set pending online
+				setInterfaceTrafficClassShaperState($interfaceTrafficClassID,SHAPER_PENDING);
+				$interfaceTrafficClass->{'Status'} = CFGM_ONLINE;
+				# Remove from queue
+				delete($globals->{'InterfaceTrafficClassChangeQueue'}->{$interfaceTrafficClassID});
+
+			} else {
+				$logger->log(LOG_ERR,"[CONFIGMANAGER] Interface traffic class [%s] has UNKNOWN state '%s'",
+						$interfaceTrafficClassID,
+						$shaperState
+				);
+			}
+
+		} else {
+			$logger->log(LOG_ERR,"[CONFIGMANAGER] Interface traffic class [%s] has UNKNOWN status '%s'",
+					$interfaceTrafficClassID,
+					$interfaceTrafficClass->{'Status'}
+			);
+		}
+	}
+
+
 	# Loop through pool change queue
 	while (my ($pid, $pool) = each(%{$globals->{'PoolChangeQueue'}})) {
 		my $shaperState = getPoolShaperState($pool->{'ID'});
@@ -1672,22 +1728,55 @@ sub getInterfaceTrafficClass
 	if (!isInterfaceIDValid($interfaceID)) {
 		return;
 	}
-	# Check if t raffic class ID is valid
-	if (!isTrafficClassIDValid($trafficClassID)) {
+	# Check if traffic class ID is valid
+	if (!defined($trafficClassID = isNumber($trafficClassID,ISNUMBER_ALLOW_ZERO))) {
+		return;
+	}
+	if ($trafficClassID && !isTrafficClassIDValid($trafficClassID)) {
 		return;
 	}
 
-	my $class = dclone($globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{$trafficClassID});
+	my $interfaceTrafficClass = dclone($globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{$trafficClassID});
+
+	# Check if the traffic class ID is not 0
+	if ($trafficClassID) {
+		$interfaceTrafficClass->{'Name'} = $globals->{'TrafficClasses'}->{$trafficClassID}->{'Name'};
+	# If if it 0, this is a root class
+	} else {
+		$interfaceTrafficClass->{'Name'} = "Root Class";
+	}
 
-	$class->{'Name'} = $globals->{'TrafficClasses'}->{$trafficClassID};
+	delete($interfaceTrafficClass->{'.applied_overrides'});
 
-	return $class;
+	return $interfaceTrafficClass;
+}
+
+
+
+# Function to get a interface traffic class
+sub getInterfaceTrafficClass2
+{
+	my $interfaceTrafficClassID = shift;
+
+
+	# Check if this interface ID is valid
+	if (!isInterfaceTrafficClassIDValid2($interfaceTrafficClassID)) {
+		return;
+	}
+
+	my $interfaceTrafficClass = dclone($globals->{'InterfaceTrafficClasses'}->{$interfaceTrafficClassID});
+
+	$interfaceTrafficClass->{'Name'} = $globals->{'TrafficClasses'}->{$interfaceTrafficClass->{'TrafficClassID'}};
+
+	delete($interfaceTrafficClass->{'.applied_overrides'});
+
+	return $interfaceTrafficClass;
 }
 
 
 
 # Function to check if traffic class is valid
-sub isInterfaceTrafficClassIDValid
+sub isInterfaceTrafficClassValid
 {
 	my ($interfaceID,$trafficClassID) = @_;
 
@@ -1700,7 +1789,228 @@ sub isInterfaceTrafficClassIDValid
 		return;
 	}
 
-	return $trafficClassID;
+	return $globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{$trafficClassID}->{'ID'};
+}
+
+
+
+# Function to check the interface traffic class ID is valid
+sub isInterfaceTrafficClassIDValid2
+{
+	my $interfaceTrafficClassID = shift;
+
+
+	if (
+			!defined($interfaceTrafficClassID) ||
+			!defined($globals->{'InterfaceTrafficClasses'}->{$interfaceTrafficClassID})
+	) {
+		return;
+	}
+
+	return $interfaceTrafficClassID;
+}
+
+
+
+# Function to create an interface class
+sub createInterfaceTrafficClass
+{
+	my $interfaceTrafficClassData = shift;
+
+
+	my $interfaceTrafficClass;
+
+	# Check if InterfaceID is valid
+	if (!defined($interfaceTrafficClass->{'InterfaceID'} = isInterfaceIDValid($interfaceTrafficClassData->{'InterfaceID'}))) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Failed to add interface traffic class as InterfaceID is invalid");
+		return;
+	}
+
+	# Check if traffic class ID is valid
+	my $interfaceTrafficClassID;
+	if (!defined($interfaceTrafficClassID = isNumber($interfaceTrafficClassData->{'TrafficClassID'},ISNUMBER_ALLOW_ZERO))) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process class change as there is no 'TrafficClassID' attribute");
+		return;
+	}
+	if ($interfaceTrafficClassID && !isTrafficClassIDValid($interfaceTrafficClassData->{'TrafficClassID'})) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process class change as 'TrafficClassID' attribute is invalid");
+		return;
+	}
+	$interfaceTrafficClass->{'TrafficClassID'} = $interfaceTrafficClassID;
+
+	# Check CIR is valid
+	if (!defined($interfaceTrafficClass->{'CIR'} = isNumber($interfaceTrafficClassData->{'CIR'}))) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Failed to add interface as CIR is invalid");
+		return;
+	}
+
+	# Check Limit is valid
+	if (!defined($interfaceTrafficClass->{'Limit'} = isNumber($interfaceTrafficClassData->{'Limit'}))) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Failed to add interface as Limit is invalid");
+		return;
+	}
+
+	# Set ID
+	$interfaceTrafficClass->{'ID'} = $globals->{'InterfaceTrafficClassCounter'}++;
+
+	# Set status
+	$interfaceTrafficClass->{'Status'} = CFGM_NEW;
+
+	# Add interface
+	$globals->{'Interfaces'}->{$interfaceTrafficClass->{'InterfaceID'}}->{'TrafficClasses'}
+			->{$interfaceTrafficClass->{'TrafficClassID'}} = $interfaceTrafficClass;
+
+	# Link to interface traffic classes
+	$globals->{'InterfaceTrafficClasses'}->{$interfaceTrafficClass->{'ID'}} = $interfaceTrafficClass;
+
+	# TODO: Hack, this should set NOTLIVE & NEW and have the shaper create as per note in plugin_init section
+	# Set status on this interface traffic class
+	setInterfaceTrafficClassShaperState($interfaceTrafficClass->{'ID'},SHAPER_LIVE);
+	$interfaceTrafficClass->{'Status'} = CFGM_ONLINE;
+
+	return $interfaceTrafficClass->{'TrafficClassID'};
+}
+
+
+
+# Function to change a traffic class
+sub changeInterfaceTrafficClass
+{
+	my $interfaceTrafficClassData = shift;
+
+
+	# Check interface exists first
+	my $interfaceID;
+	if (!defined($interfaceID = isInterfaceIDValid($interfaceTrafficClassData->{'InterfaceID'}))) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process interface class change as there is no 'InterfaceID' attribute");
+		return;
+	}
+
+	# Check if traffic class ID is valid
+	my $trafficClassID;
+	if (!defined($trafficClassID = isNumber($interfaceTrafficClassData->{'TrafficClassID'},ISNUMBER_ALLOW_ZERO))) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process class change as there is no 'TrafficClassID' attribute");
+		return;
+	}
+	if ($trafficClassID && !isTrafficClassIDValid($interfaceTrafficClassData->{'TrafficClassID'})) {
+		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process class change as 'TrafficClassID' attribute is invalid");
+		return;
+	}
+
+	my $interfaceTrafficClass =  $globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{$trafficClassID};
+
+	my $changes = getHashChanges($interfaceTrafficClass,$interfaceTrafficClassData,[CLASS_CHANGE_ATTRIBUTES]);
+
+	# Bump up changes
+	$globals->{'StateChanged'}++;
+
+	# Flag changed
+	$interfaceTrafficClass->{'Status'} = CFGM_CHANGED;
+
+	# XXX - hack our override in
+	$interfaceTrafficClass->{'.applied_overrides'}->{'change'} = $changes;
+
+	# Add to change queue
+	$globals->{'InterfaceTrafficClassChangeQueue'}->{$interfaceTrafficClass->{'ID'}} = $interfaceTrafficClass;
+
+	# Return what was changed
+	return dclone($changes);
+}
+
+
+
+# Function to return a class with any items changed as per class overrides
+sub getEffectiveInterfaceTrafficClass2
+{
+	my $interfaceTrafficClassID = shift;
+
+
+	my $interfaceTrafficClass;
+	if (!defined($interfaceTrafficClass = getInterfaceTrafficClass2($interfaceTrafficClassID))) {
+		return;
+	}
+
+	my $realInterfaceTrafficClass = $globals->{'InterfaceTrafficClasses'}->{$interfaceTrafficClassID};
+
+	# If we have applied class overrides, check out what changes there may be
+	if (defined(my $appliedClassOverrides = $realInterfaceTrafficClass->{'.applied_overrides'})) {
+		my $interfaceTrafficClassOverrideSet;
+
+		# Loop with class overrides in ascending fashion, least matches to most
+		foreach my $interfaceTrafficClassID (
+				sort { $appliedClassOverrides->{$a} <=> $appliedClassOverrides->{$b} } keys %{$appliedClassOverrides}
+		) {
+			my $interfaceTrafficClassOverride = $appliedClassOverrides->{$interfaceTrafficClassID};
+
+			# Loop with attributes and create our override set
+			foreach my $attr (CLASS_OVERRIDE_CHANGESET_ATTRIBUTES) {
+			# Set class override set attribute if the class override has defined it
+				if (defined($interfaceTrafficClassOverride->{$attr}) && $interfaceTrafficClassOverride->{$attr} ne "") {
+					$interfaceTrafficClassOverrideSet->{$attr} = $interfaceTrafficClassOverride->{$attr};
+				}
+			}
+		}
+		# Set class overrides on pool
+		if (defined($interfaceTrafficClassOverrideSet)) {
+			foreach my $attr (keys %{$interfaceTrafficClassOverrideSet}) {
+				$interfaceTrafficClass->{$attr} = $interfaceTrafficClassOverrideSet->{$attr};
+			}
+		}
+	}
+
+	return $interfaceTrafficClass;
+}
+
+
+
+# Function to set interface traffic class shaper state
+sub setInterfaceTrafficClassShaperState
+{
+	my ($interfaceTrafficClassID,$state) = @_;
+
+
+	# Check interface traffic class exists first
+	if (!isInterfaceTrafficClassIDValid2($interfaceTrafficClassID)) {
+		return;
+	}
+
+	$globals->{'InterfacesTrafficClasses'}->{$interfaceTrafficClassID}->{'.shaper_state'} |= $state;
+
+	return $globals->{'InterfacesTrafficClasses'}->{$interfaceTrafficClassID}->{'.shaper_state'};
+}
+
+
+
+# Function to unset interface traffic class shaper state
+sub unsetInterfaceTrafficClassShaperState
+{
+	my ($interfaceTrafficClassID,$state) = @_;
+
+
+	# Check interface traffic class exists first
+	if (!isInterfaceTrafficClassIDValid2($interfaceTrafficClassID)) {
+		return;
+	}
+
+	$globals->{'InterfacesTrafficClasses'}->{$interfaceTrafficClassID}->{'.shaper_state'} &= ~$state;
+
+	return $globals->{'InterfacesTrafficClasses'}->{$interfaceTrafficClassID}->{'.shaper_state'};
+}
+
+
+
+# Function to get shaper state for a interface traffic class
+sub getInterfaceTrafficClassShaperState
+{
+	my $interfaceTrafficClassID = shift;
+
+
+	# Check interface traffic class exists first
+	if (!isInterfaceTrafficClassIDValid2($interfaceTrafficClassID)) {
+		return;
+	}
+
+	return $globals->{'InterfacesTrafficClasses'}->{$interfaceTrafficClassID}->{'.shaper_state'};
 }
 
 
@@ -1795,6 +2105,14 @@ sub createInterface
 	# Add interface
 	$globals->{'Interfaces'}->{$interface->{'ID'}} = $interface;
 
+	# Create interface main traffic class
+	createInterfaceTrafficClass({
+			'InterfaceID' => $interface->{'ID'},
+			'TrafficClassID' => 0,
+			'CIR' => $interfaceData->{'Limit'},
+			'Limit' => $interfaceData->{'Limit'},
+	});
+
 	return $interface->{'ID'};
 }
 
@@ -1856,141 +2174,6 @@ sub getInterfaceDefaultPool
 
 
 
-# Function to create an interface class
-sub createInterfaceTrafficClass
-{
-	my $trafficClassData = shift;
-
-
-	my $trafficClass;
-
-	# Check if InterfaceID is valid
-	if (!defined($trafficClass->{'InterfaceID'} = isInterfaceIDValid($trafficClassData->{'InterfaceID'}))) {
-		$logger->log(LOG_NOTICE,"[CONFIGMANAGER] Failed to add interface traffic class as InterfaceID is invalid");
-		return;
-	}
-
-	# Check if TrafficClass is valid
-	if (!defined($trafficClass->{'TrafficClassID'} = isTrafficClassIDValid($trafficClassData->{'TrafficClassID'}))) {
-		$logger->log(LOG_NOTICE,"[CONFIGMANAGER] Failed to add interface traffic class as TrafficClassID is invalid");
-		return;
-	}
-
-	# Check CIR is valid
-	if (!defined($trafficClass->{'CIR'} = isNumber($trafficClassData->{'CIR'}))) {
-		$logger->log(LOG_NOTICE,"[CONFIGMANAGER] Failed to add interface as CIR is invalid");
-		return;
-	}
-
-	# Check Limit is valid
-	if (!defined($trafficClass->{'Limit'} = isNumber($trafficClassData->{'Limit'}))) {
-		$logger->log(LOG_NOTICE,"[CONFIGMANAGER] Failed to add interface as Limit is invalid");
-		return;
-	}
-
-	# Add interface
-	$globals->{'Interfaces'}->{$trafficClass->{'InterfaceID'}}->{'TrafficClasses'}
-			->{$trafficClass->{'TrafficClassID'}} = $trafficClass;
-
-	return $trafficClass->{'TrafficClassID'};
-}
-
-
-
-# Function to change a traffic class
-sub changeInterfaceTrafficClass
-{
-	my $classData = shift;
-
-
-	# Check interface exists first
-	if (!isInterfaceIDValid($classData->{'InterfaceID'})) {
-		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process class change as there is no 'InterfaceID' attribute");
-		return;
-	}
-
-	if (
-			!defined(isNumber($classData->{'TrafficClassID'},ISNUMBER_ALLOW_ZERO)) ||
-			($classData->{'TrafficClassID'} && !isTrafficClassIDValid($classData->{'TrafficClassID'}))
-	) {
-		$logger->log(LOG_WARN,"[CONFIGMANAGER] Cannot process class change as there is no 'TrafficClassID' attribute");
-		return;
-	}
-
-	my $interfaceClass = getInterfaceTrafficClass($classData->{'InterfaceID'},$classData->{'TrafficClassID'});
-
-	my $changes = getHashChanges($interfaceClass,$classData,[CLASS_CHANGE_ATTRIBUTES]);
-	# Make changes...
-	foreach my $item (keys %{$changes}) {
-		$interfaceClass->{$item} = $changes->{$item};
-	}
-
-	# Bump up changes
-	$globals->{'StateChanged'}++;
-
-# FIXME - Add to change queue?
-# - Create getEffectiveTrafficClass
-#	$kernel->post('shaper' => 'class_change' => $classData->{'InterfaceID'} => $classData->{'TrafficClassID'});
-
-
-	# Return what was changed
-	return dclone($changes);
-}
-
-
-
-# FIXME
-# Function to return a class with any items changed as per class overrides
-sub getEffectiveInterfaceTrafficClass
-{
-	my ($interfaceID,$trafficClassID) = @_;
-
-
-	# Check everything exists first
-	if (!isInterfaceIDValid($interfaceID)) {
-		return;
-	}
-
-	if (!isTrafficClassIDValid($trafficClassID)) {
-		return;
-	}
-
-	my $class = $globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{$trafficClassID};
-
-	# FIXME
-#	# If we have applied class overrides, check out what changes there may be
-#	if (defined(my $appliedClassOverrides = $class->{'.applied_overrides'})) {
-#		my $classOverrideSet;
-#
-#		# Loop with class overrides in ascending fashion, least matches to most
-#		foreach my $poid ( sort { $appliedClassOverrides->{$a} <=> $appliedClassOverrides->{$b} } keys %{$appliedClassOverrides}) {
-#			my $classOverride = $classOverrides->{$poid};
-#
-#			# Loop with attributes and create our override set
-#			foreach my $attr (CLASS_OVERRIDE_CHANGESET_ATTRIBUTES) {
-#				# Set class override set attribute if the class override has defined it
-#				if (defined($classOverride->{$attr}) && $classOverride->{$attr} ne "") {
-#					$classOverrideSet->{$attr} = $classOverride->{$attr};
-#				}
-#			}
-#		}
-#
-#		# Set class overrides on pool
-#		if (defined($classOverrideSet)) {
-#			foreach my $attr (keys %{$classOverrideSet}) {
-#				$class->{$attr} = $classOverrideSet->{$attr};
-#			}
-#		}
-#	}
-
-	$class->{'InterfaceID'} = $interfaceID;
-	$class->{'TrafficClassID'} = $trafficClassID;
-
-	return $class;
-}
-
-
-
 # Function to create an interface group
 sub createInterfaceGroup
 {
diff --git a/opentrafficshaper/plugins/tc/tc.pm b/opentrafficshaper/plugins/tc/tc.pm
index 93857ae36576337b418846cf387726c7a3f9a3c3..9e5b6f7780a9653047e79f6450862bcbf8544591 100644
--- a/opentrafficshaper/plugins/tc/tc.pm
+++ b/opentrafficshaper/plugins/tc/tc.pm
@@ -59,7 +59,10 @@ use opentrafficshaper::plugins::configmanager qw(
 	getInterface
 	getInterfaces
 	getInterfaceDefaultPool
-	getEffectiveInterfaceTrafficClass
+	getEffectiveInterfaceTrafficClass2
+	isInterfaceTrafficClassValid
+	setInterfaceTrafficClassShaperState
+	unsetInterfaceTrafficClassShaperState
 );
 
 
@@ -247,6 +250,62 @@ sub _session_stop
 }
 
 
+
+# Event handler for changing a class
+sub _session_class_change
+{
+	my ($kernel, $interfaceTrafficClassID) = @_[KERNEL, ARG0, ARG1];
+
+
+	# Grab our effective class
+	my $effectiveInterfaceTrafficClass = getEffectiveInterfaceTrafficClass2($interfaceTrafficClassID);
+
+	# Grab interface ID
+	my $interfaceID = $effectiveInterfaceTrafficClass->{'InterfaceID'};
+	# Grab interface from config manager
+	my $interface = getInterface($interfaceID);
+
+	# Grab traffic class ID
+	my $trafficClassID = $effectiveInterfaceTrafficClass->{'TrafficClassID'};
+
+	$logger->log(LOG_INFO,"[TC] Processing interface class changes for '%s' traffic class ID '%s'",
+			$interface->{'Device'},
+			$trafficClassID
+	);
+
+	# Grab tc interface
+	my $tcInterface = $globals->{'Interfaces'}->{$interfaceID};
+	# Grab interface traffic class
+	my $interfaceTrafficClass = $tcInterface->{'TrafficClasses'}->{$trafficClassID};
+
+	# Grab the traffic class
+	my $majorTcClass = $tcInterface->{'TcClass'};
+	my $minorTcClass = $interfaceTrafficClass->{"TcClass"};
+
+	# Generate changeset
+	my $changeSet = TC::ChangeSet->new();
+
+	# If we're a normal class we are treated differently than if we're a main/root class below (interface main speed)
+	if ($minorTcClass > 1) {
+		_tc_class_change($changeSet,$interfaceID,$majorTcClass,"",$minorTcClass,
+				$effectiveInterfaceTrafficClass->{'CIR'},
+				$effectiveInterfaceTrafficClass->{'Limit'}
+		);
+	# XXX: This will be the actual interface, we set limit and burst to the same
+	} else {
+		_tc_class_change($changeSet,$interfaceID,TC_ROOT_CLASS,"",$minorTcClass,$effectiveInterfaceTrafficClass->{'Limit'});
+	}
+
+	# Post changeset
+	$kernel->post("_tc" => "queue" => $changeSet);
+
+	# Mark as live
+	unsetInterfaceTrafficClassShaperState($interfaceTrafficClassID,SHAPER_NOTLIVE|SHAPER_PENDING);
+	setInterfaceTrafficClassShaperState($interfaceTrafficClassID,SHAPER_LIVE);
+}
+
+
+
 # Event handler for adding a pool
 sub _session_pool_add
 {
@@ -272,8 +331,8 @@ sub _session_pool_add
 	my $changeSet = TC::ChangeSet->new();
 
 	# Grab some things we need from the main pool
-	my $txInterface = getPoolTxInterface($pool->{'ID'});
-	my $rxInterface = getPoolRxInterface($pool->{'ID'});
+	my $txInterfaceID = getPoolTxInterface($pool->{'ID'});
+	my $rxInterfaceID = getPoolRxInterface($pool->{'ID'});
 
 	# Grab effective config
 	my $trafficClassID = $effectivePool->{'TrafficClassID'};
@@ -284,28 +343,28 @@ sub _session_pool_add
 	my $trafficPriority = getTrafficClassPriority($effectivePool->{'TrafficClassID'});
 
 	# Get the Tx traffic classes TC class
-	my $tcClass_TxTrafficClass = _getTcClassFromTrafficClassID($txInterface,$trafficClassID);
+	my $tcClass_TxTrafficClass = _getTcClassFromTrafficClassID($txInterfaceID,$trafficClassID);
 	# Generate our pools Tx TC class
-	my $tcClass_TxPool = _reserveTcClassByPoolID($txInterface,$pool->{'ID'});
+	my $tcClass_TxPool = _reserveMinorTcClassByPoolID($txInterfaceID,$pool->{'ID'});
 	# Add the main Tx TC class for this pool
-	_tc_class_add($changeSet,$txInterface,TC_ROOT_CLASS,$tcClass_TxTrafficClass,$tcClass_TxPool,$txCIR,
+	_tc_class_add($changeSet,$txInterfaceID,TC_ROOT_CLASS,$tcClass_TxTrafficClass,$tcClass_TxPool,$txCIR,
 			$txLimit,$trafficPriority
 	);
 	# Add Tx TC optimizations
-	_tc_class_optimize($changeSet,$txInterface,$tcClass_TxPool,$txCIR);
+	_tc_class_optimize($changeSet,$txInterfaceID,$tcClass_TxPool,$txCIR);
 	# Set Tx TC class
 	setPoolAttribute($pool->{'ID'},'tc.txclass',$tcClass_TxPool);
 
 	# Get the Rx traffic classes TC class
-	my $tcClass_RxTrafficClass = _getTcClassFromTrafficClassID($rxInterface,$trafficClassID);
+	my $tcClass_RxTrafficClass = _getTcClassFromTrafficClassID($rxInterfaceID,$trafficClassID);
 	# Generate our pools Rx TC class
-	my $tcClass_RxPool = _reserveTcClassByPoolID($rxInterface,$pool->{'ID'});
+	my $tcClass_RxPool = _reserveMinorTcClassByPoolID($rxInterfaceID,$pool->{'ID'});
 	# Add the main Rx TC class for this pool
-	_tc_class_add($changeSet,$rxInterface,TC_ROOT_CLASS,$tcClass_RxTrafficClass,$tcClass_RxPool,$rxCIR,
+	_tc_class_add($changeSet,$rxInterfaceID,TC_ROOT_CLASS,$tcClass_RxTrafficClass,$tcClass_RxPool,$rxCIR,
 			$rxLimit,$trafficPriority
 	);
 	# Add Rx TC optimizations
-	_tc_class_optimize($changeSet,$rxInterface,$tcClass_RxPool,$rxCIR);
+	_tc_class_optimize($changeSet,$rxInterfaceID,$tcClass_RxPool,$rxCIR);
 	# Set Rx TC
 	setPoolAttribute($pool->{'ID'},'tc.rxclass',$tcClass_RxPool);
 
@@ -356,8 +415,8 @@ sub _session_pool_remove
 	);
 
 	# Grab our interfaces
-	my $txInterface = getPoolTxInterface($pool->{'ID'});
-	my $rxInterface = getPoolRxInterface($pool->{'ID'});
+	my $txInterfaceID = getPoolTxInterface($pool->{'ID'});
+	my $rxInterfaceID = getPoolRxInterface($pool->{'ID'});
 	# Grab the traffic class from the pool
 	my $txPoolTcClass = getPoolAttribute($pool->{'ID'},'tc.txclass');
 	my $rxPoolTcClass = getPoolAttribute($pool->{'ID'},'tc.rxclass');
@@ -365,19 +424,22 @@ sub _session_pool_remove
 	# Grab current class ID
 	my $trafficClassID = getPoolAttribute($pool->{'ID'},'shaper.live.ClassID');
 	# Grab our minor classes
-	my $txTrafficClassTcClass = _getTcClassFromTrafficClassID($txInterface,$trafficClassID);
-	my $rxTrafficClassTcClass = _getTcClassFromTrafficClassID($rxInterface,$trafficClassID);
+	my $txTrafficClassTcClass = _getTcClassFromTrafficClassID($txInterfaceID,$trafficClassID);
+	my $rxTrafficClassTcClass = _getTcClassFromTrafficClassID($rxInterfaceID,$trafficClassID);
+
+	my $txInterface = getInterface($txInterfaceID);
+	my $rxInterface = getInterface($rxInterfaceID);
 
 	# Clear up the class
 	$changeSet->add([
 			'/sbin/tc','class','del',
-				'dev',$txInterface,
+				'dev',$txInterface->{'Device'},
 				'parent',"1:$txTrafficClassTcClass",
 				'classid',"1:$txPoolTcClass",
 	]);
 	$changeSet->add([
 			'/sbin/tc','class','del',
-				'dev',$rxInterface,
+				'dev',$rxInterface->{'Device'},
 				'parent',"1:$rxTrafficClassTcClass",
 				'classid',"1:$rxPoolTcClass",
 	]);
@@ -424,8 +486,8 @@ sub _session_pool_change
 	my $effectivePool = getEffectivePool($pool->{'ID'});
 
 	# Grab our interfaces
-	my $txInterface = getPoolTxInterface($pool->{'ID'});
-	my $rxInterface = getPoolRxInterface($pool->{'ID'});
+	my $txInterfaceID = getPoolTxInterface($pool->{'ID'});
+	my $rxInterfaceID = getPoolRxInterface($pool->{'ID'});
 	# Grab the traffic class from the pool
 	my $txPoolTcClass = getPoolAttribute($pool->{'ID'},'tc.txclass');
 	my $rxPoolTcClass = getPoolAttribute($pool->{'ID'},'tc.rxclass');
@@ -439,15 +501,15 @@ sub _session_pool_change
 	my $trafficPriority = getTrafficClassPriority($trafficClassID);
 
 	# Grab our minor classes
-	my $txTrafficClassTcClass = _getTcClassFromTrafficClassID($txInterface,$trafficClassID);
-	my $rxTrafficClassTcClass = _getTcClassFromTrafficClassID($rxInterface,$trafficClassID);
+	my $txTrafficClassTcClass = _getTcClassFromTrafficClassID($txInterfaceID,$trafficClassID);
+	my $rxTrafficClassTcClass = _getTcClassFromTrafficClassID($rxInterfaceID,$trafficClassID);
 
 	# Generate changeset
 	my $changeSet = TC::ChangeSet->new();
 
-	_tc_class_change($changeSet,$txInterface,TC_ROOT_CLASS,$txTrafficClassTcClass,$txPoolTcClass,$txCIR,
+	_tc_class_change($changeSet,$txInterfaceID,TC_ROOT_CLASS,$txTrafficClassTcClass,$txPoolTcClass,$txCIR,
 			$txLimit,$trafficPriority);
-	_tc_class_change($changeSet,$rxInterface,TC_ROOT_CLASS,$rxTrafficClassTcClass,$rxPoolTcClass,$rxCIR,
+	_tc_class_change($changeSet,$rxInterfaceID,TC_ROOT_CLASS,$rxTrafficClassTcClass,$rxPoolTcClass,$rxCIR,
 			$rxLimit,$trafficPriority);
 
 	# Post changeset
@@ -501,47 +563,47 @@ sub _session_poolmember_add
 	}
 
 	# Grab some variables we going to need below
-	my $txInterface = getPoolTxInterface($pool->{'ID'});
-	my $rxInterface = getPoolRxInterface($pool->{'ID'});
+	my $txInterfaceID = getPoolTxInterface($pool->{'ID'});
+	my $rxInterfaceID = getPoolRxInterface($pool->{'ID'});
 	my $trafficPriority = getTrafficClassPriority($pool->{'TrafficClassID'});
 	my $matchPriority = getPoolMemberMatchPriority($poolMember->{'ID'});
 
 	# Check if we have a entry for the /8, if not we must create our 2nd level hash table and link it
-	if (!defined($globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1})) {
+	if (!defined($globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1})) {
 		# Grab filter ID's for 2nd level
-		my $filterID = _reserveTcFilter($txInterface,$matchPriority,$pool->{'ID'});
+		my $filterID = _reserveTcFilter($txInterfaceID,$matchPriority,$pool->{'ID'});
 		# Track our mapping
-		$globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{'id'} = $filterID;
+		$globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{'id'} = $filterID;
 		$logger->log(LOG_DEBUG,"[TC] Linking 2nd level TX hash table to '%s' to '%s.0.0.0/8', priority '%s'",
 				$filterID,
 				$ip1,
 				$matchPriority
 		);
-		_tc_filter_add_dstlink($changeSet,$txInterface,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},800,"",
+		_tc_filter_add_dstlink($changeSet,$txInterfaceID,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},800,"",
 				"$ip1.0.0.0/8","00ff0000");
 	}
-	if (!defined($globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1})) {
+	if (!defined($globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1})) {
 		# Grab filter ID's for 2nd level
-		my $filterID = _reserveTcFilter($rxInterface,$matchPriority,$pool->{'ID'});
+		my $filterID = _reserveTcFilter($rxInterfaceID,$matchPriority,$pool->{'ID'});
 		# Track our mapping
-		$globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{'id'} = $filterID;
+		$globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{'id'} = $filterID;
 		$logger->log(LOG_DEBUG,"[TC] Linking 2nd level RX hash table to '%s' to '%s.0.0.0/8', priority '%s'",
 				$filterID,
 				$ip1,
 				$matchPriority
 		);
-		_tc_filter_add_srclink($changeSet,$rxInterface,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},800,"",
+		_tc_filter_add_srclink($changeSet,$rxInterfaceID,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},800,"",
 				"$ip1.0.0.0/8","00ff0000");
 	}
 
 	# Check if we have our /16 hash entry, if not we must create the 3rd level hash table
-	if (!defined($globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2})) {
+	if (!defined($globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2})) {
 		# Grab filter ID's for 3rd level
-		my $filterID = _reserveTcFilter($txInterface,$matchPriority,$pool->{'ID'});
+		my $filterID = _reserveTcFilter($txInterfaceID,$matchPriority,$pool->{'ID'});
 		# Track our mapping
-		$globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'} = $filterID;
+		$globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'} = $filterID;
 		# Grab some hash table ID's we need
-		my $ip1HtHex = $globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{'id'};
+		my $ip1HtHex = $globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{'id'};
 		# And hex our IP component
 		my $ip2Hex = toHex($ip2);
 		$logger->log(LOG_DEBUG,"[TC] Linking 3rd level TX hash table to '%s' to '%s.%s.0.0/16', priority '%s'",
@@ -550,16 +612,16 @@ sub _session_poolmember_add
 				$ip2,
 				$matchPriority
 		);
-		_tc_filter_add_dstlink($changeSet,$txInterface,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip1HtHex,
+		_tc_filter_add_dstlink($changeSet,$txInterfaceID,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip1HtHex,
 				$ip2Hex,"$ip1.$ip2.0.0/16","0000ff00");
 	}
-	if (!defined($globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{$ip2})) {
+	if (!defined($globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{$ip2})) {
 		# Grab filter ID's for 3rd level
-		my $filterID = _reserveTcFilter($rxInterface,$matchPriority,$pool->{'ID'});
+		my $filterID = _reserveTcFilter($rxInterfaceID,$matchPriority,$pool->{'ID'});
 		# Track our mapping
-		$globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'} = $filterID;
+		$globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'} = $filterID;
 		# Grab some hash table ID's we need
-		my $ip1HtHex = $globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{'id'};
+		my $ip1HtHex = $globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{'id'};
 		# And hex our IP component
 		my $ip2Hex = toHex($ip2);
 		$logger->log(LOG_DEBUG,"[TC] Linking 3rd level RX hash table to '%s' to '%s.%s.0.0/16', priority '%s'",
@@ -568,18 +630,18 @@ sub _session_poolmember_add
 				$ip2,
 				$matchPriority
 		);
-		_tc_filter_add_srclink($changeSet,$rxInterface,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip1HtHex,
+		_tc_filter_add_srclink($changeSet,$rxInterfaceID,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip1HtHex,
 				$ip2Hex,"$ip1.$ip2.0.0/16","0000ff00");
 	}
 
 	# Check if we have our /24 hash entry, if not we must create the 4th level hash table
-	if (!defined($globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3})) {
+	if (!defined($globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3})) {
 		# Grab filter ID's for 4th level
-		my $filterID = _reserveTcFilter($txInterface,$matchPriority,$pool->{'ID'});
+		my $filterID = _reserveTcFilter($txInterfaceID,$matchPriority,$pool->{'ID'});
 		# Track our mapping
-		$globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'} = $filterID;
+		$globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'} = $filterID;
 		# Grab some hash table ID's we need
-		my $ip2HtHex = $globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'};
+		my $ip2HtHex = $globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'};
 		# And hex our IP component
 		my $ip3Hex = toHex($ip3);
 		$logger->log(LOG_DEBUG,"[TC] Linking 4th level TX hash table to '%s' to '%s.%s.%s.0/24', priority '%s'",
@@ -589,16 +651,16 @@ sub _session_poolmember_add
 				$ip3,
 				$matchPriority
 		);
-		_tc_filter_add_dstlink($changeSet,$txInterface,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip2HtHex,
+		_tc_filter_add_dstlink($changeSet,$txInterfaceID,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip2HtHex,
 				$ip3Hex,"$ip1.$ip2.$ip3.0/24","000000ff");
 	}
-	if (!defined($globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3})) {
+	if (!defined($globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3})) {
 		# Grab filter ID's for 4th level
-		my $filterID = _reserveTcFilter($rxInterface,$matchPriority,$pool->{'ID'});
+		my $filterID = _reserveTcFilter($rxInterfaceID,$matchPriority,$pool->{'ID'});
 		# Track our mapping
-		$globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'} = $filterID;
+		$globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'} = $filterID;
 		# Grab some hash table ID's we need
-		my $ip2HtHex = $globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'};
+		my $ip2HtHex = $globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{'id'};
 		# And hex our IP component
 		my $ip3Hex = toHex($ip3);
 		$logger->log(LOG_DEBUG,"[TC] Linking 4th level RX hash table to '%s' to '%s.%s.%s.0/24', priority '%s'",
@@ -608,7 +670,7 @@ sub _session_poolmember_add
 				$ip3,
 				$matchPriority
 		);
-		_tc_filter_add_srclink($changeSet,$rxInterface,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip2HtHex,
+		_tc_filter_add_srclink($changeSet,$rxInterfaceID,TC_ROOT_CLASS,$matchPriority,$filterID,$config->{'ip_protocol'},$ip2HtHex,
 				$ip3Hex,"$ip1.$ip2.$ip3.0/24","000000ff");
 	}
 
@@ -621,7 +683,7 @@ sub _session_poolmember_add
 		# Get the TX class
 		my $tcClass_trafficClass = getPoolAttribute($pool->{'ID'},'tc.txclass');
 		# Grab some hash table ID's we need
-		my $ip3HtHex = $globals->{'TcFilterMappings'}->{$txInterface}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'};
+		my $ip3HtHex = $globals->{'TcFilterMappings'}->{$txInterfaceID}->{'dst'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'};
 		# And hex our IP component
 		my $ip4Hex = toHex($ip4);
 		$logger->log(LOG_DEBUG,"[TC] Linking pool member IP '%s' to class '%s' at hash endpoint '%s:%s'",
@@ -632,8 +694,8 @@ sub _session_poolmember_add
 		);
 
 		# Link filter to traffic flow (class)
-		_tc_filter_add_flowlink($changeSet,$txInterface,TC_ROOT_CLASS,$trafficPriority,$config->{'ip_protocol'},$ip3HtHex,$ip4Hex,
-				"dst",16,$poolMember->{'IPAddress'},$tcClass_trafficClass);
+		_tc_filter_add_flowlink($changeSet,$txInterfaceID,TC_ROOT_CLASS,$trafficPriority,$config->{'ip_protocol'},$ip3HtHex,
+				$ip4Hex,"dst",16,$poolMember->{'IPAddress'},$tcClass_trafficClass);
 
 		# Save pool member filter ID
 		setPoolMemberAttribute($poolMember->{'ID'},'tc.txfilter',"${ip3HtHex}:${ip4Hex}:1");
@@ -643,7 +705,7 @@ sub _session_poolmember_add
 		# Generate our limit TC class
 		my $tcClass_trafficClass = getPoolAttribute($pool->{'ID'},'tc.rxclass');
 		# Grab some hash table ID's we need
-		my $ip3HtHex = $globals->{'TcFilterMappings'}->{$rxInterface}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'};
+		my $ip3HtHex = $globals->{'TcFilterMappings'}->{$rxInterfaceID}->{'src'}->{$matchPriority}->{$ip1}->{$ip2}->{$ip3}->{'id'};
 		# And hex our IP component
 		my $ip4Hex = toHex($ip4);
 		$logger->log(LOG_DEBUG,"[TC] Linking RX IP '%s' to class '%s' at hash endpoint '%s:%s'",
@@ -654,8 +716,8 @@ sub _session_poolmember_add
 		);
 
 		# Link filter to traffic flow (class)
-		_tc_filter_add_flowlink($changeSet,$rxInterface,TC_ROOT_CLASS,$trafficPriority,$config->{'ip_protocol'},$ip3HtHex,$ip4Hex,
-				"src",12,$poolMember->{'IPAddress'},$tcClass_trafficClass);
+		_tc_filter_add_flowlink($changeSet,$rxInterfaceID,TC_ROOT_CLASS,$trafficPriority,$config->{'ip_protocol'},$ip3HtHex,
+				$ip4Hex,"src",12,$poolMember->{'IPAddress'},$tcClass_trafficClass);
 
 		# Save pool member filter ID
 		setPoolMemberAttribute($poolMember->{'ID'},'tc.rxfilter',"${ip3HtHex}:${ip4Hex}:1");
@@ -706,8 +768,8 @@ sub _session_poolmember_remove
 	);
 
 	# Grab our interfaces
-	my $txInterface = getPoolTxInterface($pool->{'ID'});
-	my $rxInterface = getPoolRxInterface($pool->{'ID'});
+	my $txInterfaceID = getPoolTxInterface($pool->{'ID'});
+	my $rxInterfaceID = getPoolRxInterface($pool->{'ID'});
 	# Grab the filter ID's from the pool member which is linked to the traffic class
 	my $txFilter = getPoolMemberAttribute($poolMember->{'ID'},'tc.txfilter');
 	my $rxFilter = getPoolMemberAttribute($poolMember->{'ID'},'tc.rxfilter');
@@ -716,13 +778,15 @@ sub _session_poolmember_remove
 	my $trafficClassID = getPoolAttribute($pool->{'ID'},'shaper.live.ClassID');
 	my $trafficPriority = getTrafficClassPriority($trafficClassID);
 
+	my $txInterface = getInterface($txInterfaceID);
+	my $rxInterface = getInterface($rxInterfaceID);
 
 	my $changeSet = TC::ChangeSet->new();
 
 	# Clear up the filter
 	$changeSet->add([
 			'/sbin/tc','filter','del',
-				'dev',$txInterface,
+				'dev',$txInterface->{'Device'},
 				'parent','1:',
 				'prio',$trafficPriority,
 				'handle',$txFilter,
@@ -731,7 +795,7 @@ sub _session_poolmember_remove
 	]);
 	$changeSet->add([
 			'/sbin/tc','filter','del',
-				'dev',$rxInterface,
+				'dev',$rxInterface->{'Device'},
 				'parent','1:',
 				'prio',$trafficPriority,
 				'handle',$rxFilter,
@@ -819,6 +883,7 @@ sub _tc_iface_init
 	# Grab our interface rate
 	my $interface = getInterface($interfaceID);
 
+### --- Interface Setup
 
 	# Clear the qdisc from the interface
 	$changeSet->add([
@@ -828,13 +893,20 @@ sub _tc_iface_init
 	]);
 
 	# Initialize the major TC class
-	my $interfaceRootTcClas = _reserveMajorTcClass($interfaceID,"root");
+	my $interfaceTcClass = _reserveMajorTcClass($interfaceID,"root");
+
+	# Set interface RootClass
+	$globals->{'Interfaces'}->{$interfaceID} = {
+		'TcClass' => $interfaceTcClass
+	};
+
+### --- Interface Traffic Class Setup
 
 	# Reserve our parent TC classes
 	my @trafficClasses = getAllTrafficClasses();
 	foreach my $trafficClassID (sort {$a <=> $b} @trafficClasses) {
-		# We don't really need the result, we just need the class created
-		_reserveTcClassByTrafficClassID($interfaceID,$trafficClassID);
+		# Record the class we get for this interface traffic class ID
+		my $interfaceTrafficClassTcClass = _reserveMinorTcClassByTrafficClassID($interfaceID,$trafficClassID);
 	}
 
 	# Do we have a default pool? if so we must direct traffic there
@@ -847,6 +919,9 @@ sub _tc_iface_init
 		push(@qdiscOpts,'default',$defaultPoolTcClass);
 	}
 
+
+### --- Interface Setup Part 2
+
 	# Add root qdisc
 	$changeSet->add([
 			'/sbin/tc','qdisc','add',
@@ -868,10 +943,20 @@ sub _tc_iface_init
 					'burst',"$interface->{'Limit'}kb",
 	]);
 
+	# Class 0 is our interface, it points to 1 (the major TcClass)) : 1 (class below)
+	$globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{'0'} = {
+		'TcClass' => '1',
+		'CIR' => $interface->{'Limit'},
+		'Limit' => $interface->{'Limit'}
+	};
+
+
+### --- Setup each class
 
 	# Setup the classes
 	foreach my $trafficClassID (@trafficClasses) {
-		my $interfaceTrafficClass = getEffectiveInterfaceTrafficClass($interfaceID,$trafficClassID);
+		my $interfaceTrafficClassID = isInterfaceTrafficClassValid($interfaceID,$trafficClassID);
+		my $interfaceTrafficClass = getEffectiveInterfaceTrafficClass2($interfaceTrafficClassID);
 		my $tcClass = _getTcClassFromTrafficClassID($interfaceID,$trafficClassID);
 		my $trafficPriority = getTrafficClassPriority($trafficClassID);
 
@@ -887,11 +972,19 @@ sub _tc_iface_init
 						'prio',$trafficPriority,
 						'burst', "$interfaceTrafficClass->{'Limit'}kb",
 		]);
+
+		# Setup interface traffic class details
+		$globals->{'Interfaces'}->{$interfaceID}->{'TrafficClasses'}->{$trafficClassID} = {
+			'TcClass' => $tcClass,
+			'CIR' => $interfaceTrafficClass->{'CIR'},
+			'Limit' => $interfaceTrafficClass->{'Limit'}
+		};
 	}
 
 	# Process our default pool traffic optimizations
 	if (defined($defaultPool)) {
-		my $interfaceTrafficClass = getEffectiveInterfaceTrafficClass($interfaceID,$defaultPool);
+		my $interfaceTrafficClassID = isInterfaceTrafficClassValid($interfaceID,$defaultPool);
+		my $interfaceTrafficClass = getEffectiveInterfaceTrafficClass2($interfaceTrafficClassID);
 
 
 		# If we have a rate for this iface, then use it
@@ -1473,8 +1566,21 @@ sub _tc_class_change
 
 	my $interface = getInterface($interfaceID);
 
-	# Set burst to a sane value
-	my $burst = int($ceil / 8 / 5);
+	my @args = ();
+
+	# Based on if ceil is avaiable, set burst
+	my $burst;
+	if (defined($ceil)) {
+		$burst = int($ceil / 8 / 5);
+	} else {
+		# If ceil is not available, set burst and ceil
+		$burst = $ceil = $rate;
+	}
+
+	# Check if we have a priority
+	if (defined($trafficPriority)) {
+		push(@args,'prio',$trafficPriority);
+	}
 
 	# Create main rate limiting classes
 	$changeSet->add([
@@ -1485,15 +1591,15 @@ sub _tc_class_change
 				'htb',
 					'rate', "${rate}kbit",
 					'ceil', "${ceil}kbit",
-					'prio', $trafficPriority,
 					'burst', "${burst}kb",
+					@args
 	]);
 }
 
 
 
 # Get a pool TC class from pool ID
-sub _reserveTcClassByPoolID
+sub _reserveMinorTcClassByPoolID
 {
 	my ($interfaceID,$pid) = @_;
 
@@ -1503,7 +1609,7 @@ sub _reserveTcClassByPoolID
 
 
 # Get a traffic class TC class
-sub _reserveTcClassByTrafficClassID
+sub _reserveMinorTcClassByTrafficClassID
 {
 	my ($interfaceID,$trafficClassID) = @_;
 
diff --git a/opentrafficshaper/plugins/webserver/pages/configmanager.pm b/opentrafficshaper/plugins/webserver/pages/configmanager.pm
index 138ad11072737e4aee9cf19083744018eaa61acc..6b2ef0bc12397582f160cb3734a114894f5c5672 100644
--- a/opentrafficshaper/plugins/webserver/pages/configmanager.pm
+++ b/opentrafficshaper/plugins/webserver/pages/configmanager.pm
@@ -49,15 +49,16 @@ use opentrafficshaper::logger;
 use opentrafficshaper::plugins;
 use opentrafficshaper::plugins::configmanager qw(
 	getInterfaces
-	getInterfaceTrafficClass
 	getInterface
 
 	getTrafficClass
 	getAllTrafficClasses
 
+	getInterfaceTrafficClass
+	changeInterfaceTrafficClass
+
 	isInterfaceIDValid
 
-	changeTrafficClass
 	isTrafficClassIDValid
 );
 
@@ -91,45 +92,27 @@ sub default
 }
 
 
+
 # Admin configuration
 sub admin_config
 {
 	my ($kernel,$globals,$client_session_id,$request) = @_;
 
 
-	# Items for our form...
-	my @formElements = qw(
-		FriendlyName
-		Identifier
-		ClassID
-		TrafficLimitTx TrafficLimitTxBurst
-		TrafficLimitRx TrafficLimitRxBurst
-		Notes
-	);
-
 	# Grab stuff we need
-	my $interfaces = getInterfaces();
+	my @interfaces = getInterfaces();
+
 
+	# Errors to display above the form
+	my @errors;
 
 	# Build content
 	my $content = "";
 
-	# Header
+	# Form header
 	$content .=<<EOF;
-		<!-- Config Tabs -->
-		<ul class="nav nav-tabs" id="configTabs">
-			<li class="active"><a href="#interfaces" data-toggle="tab">Interfaces</a></li>
-			<li><a href="#system" data-toggle="tab">System (TODO)</a></li>
-		</ul>
-		<!-- Tab panes -->
-		<div class="tab-content">
-			<div class="tab-pane active" id="interfaces">
+		<legend>Interface Rate Setup</legend>
 EOF
-
-
-	# Title of the form, by default its an add form
-	my $formType = "Add";
-	my $formNoEdit = "";
 	# Form data
 	my $formData;
 
@@ -138,11 +121,87 @@ EOF
 	if ($request->method eq "POST") {
 		# Parse form data
 		my $form = parseFormContent($request->content);
-		use Data::Dumper; warn "CONTENTDATA: ".Dumper($request->content);
-		use Data::Dumper; warn "FORMDATA: ".Dumper($form);
+
+		# Loop with rate changes
+		my $rateChanges = { };
+		foreach my $elementName (keys %{$form}) {
+			my $rateChange = $form->{$elementName};
+
+			# Skip over blanks
+			if ($rateChange->{'value'} =~ /^\s*$/) {
+				next;
+			}
+			# Split off the various components of the element name
+			my ($item,$interfaceID,$trafficClassID) = ($elementName =~ /^((?:CIR|Limit))\[([a-z0-9:.]+)\]\[([0-9]+)\]$/);
+			# Make sure everything is defined
+			if (!defined($item) || !defined($interfaceID) || !defined($trafficClassID)) {
+				push(@errors,"Invalid data received");
+				last;
+			}
+
+			# Check interface exists
+			if (!defined($interfaceID = isInterfaceIDValid($interfaceID))) {
+				push(@errors,"Invalid data received, interface ID is invalid");
+				last;
+			}
+			# Check class is valid
+			if (
+					!defined($trafficClassID = isNumber($trafficClassID,ISNUMBER_ALLOW_ZERO)) ||
+					($trafficClassID && !isTrafficClassIDValid($trafficClassID))
+			) {
+				push(@errors,"Invalid class ID received for interface [$interfaceID]");
+				last;
+			}
+			# Check value is valid
+			if (!defined($rateChange->{'value'} = isNumber($rateChange->{'value'}))) {
+				push(@errors,"Invalid value received for interface [$interfaceID], class [$trafficClassID]");
+				last;
+			}
+
+			$rateChanges->{$interfaceID}->{$trafficClassID}->{$item} = $rateChange->{'value'};
+		}
+# FIXME - check speed does not exceed inteface speed
+		# Check if there are no errors
+		if (!@errors) {
+			# Loop with interfaces
+			foreach my $interfaceID (keys %{$rateChanges}) {
+				my $trafficClasses = $rateChanges->{$interfaceID};
+
+				# Loop with traffic classes
+				foreach my $trafficClassID (keys %{$trafficClasses}) {
+					my $trafficClass = $trafficClasses->{$trafficClassID};
+
+					# Set some additional items we need
+					$trafficClass->{'InterfaceID'} = $interfaceID;
+					$trafficClass->{'TrafficClassID'} = $trafficClassID;
+					# Push changes
+					changeInterfaceTrafficClass($trafficClass);
+				}
+			}
+
+			return (HTTP_TEMPORARY_REDIRECT,"/configmanager");
+		}
 	}
 
 
+	# Header
+	$content .=<<EOF;
+		<!-- Config Tabs -->
+		<ul class="nav nav-tabs" id="configTabs">
+			<li class="active"><a href="#interfaces" data-toggle="tab">Interfaces</a></li>
+		</ul>
+		<!-- Tab panes -->
+		<div class="tab-content">
+			<div class="tab-pane active" id="interfaces">
+EOF
+
+	# Spit out errors if we have any
+	if (@errors > 0) {
+		foreach my $error (@errors) {
+			$content .= '<div class="alert alert-danger">'.encode_entities($error).'</div>';
+		}
+	}
+
 	# Interfaces tab setup
 	$content .=<<EOF;
 				<br />
@@ -150,14 +209,21 @@ EOF
 				<ul class="nav nav-tabs" id="configInterfaceTabs">
 EOF
 	my $firstPaneActive = " active";
-	foreach my $interface (@{$interfaces}) {
+	foreach my $interfaceID (@interfaces) {
+		my $interface = getInterface($interfaceID);
+		my $encodedInterfaceID = encode_entities($interfaceID);
+		my $encodedInterfaceName = encode_entities($interface->{'Name'});
+
+
 		$content .=<<EOF;
-					<li class="$firstPaneActive"><a href="#interface$interface" data-toggle="tab">Interface: $interface</a></li>
+					<li class="$firstPaneActive">
+						<a href="#interface$encodedInterfaceID" data-toggle="tab">
+							Interface: $encodedInterfaceName
+						</a>
+					</li>
 EOF
 		# No longer the first pane
 		$firstPaneActive = "";
-
-		$formData->{"MainTrafficLimitTx[$interface]"} = getInterfaceRate($interface);
 	}
 	$content .=<<EOF;
 				</ul>
@@ -167,17 +233,26 @@ EOF
 
 	# Suck in list of interfaces
 	$firstPaneActive = " active";
-	foreach my $interface (@{$interfaces}) {
+	foreach my $interfaceID (@interfaces) {
+		my $interface = getInterface($interfaceID);
+		my $encodedInterfaceID = encode_entities($interfaceID);
+		my $encodedInterfaceName = encode_entities($interface->{'Name'});
+		my $encodedInterfaceLimit = encode_entities($interface->{'Limit'});
+
+
 		# Interface tab
 		$content .=<<EOF;
-					<div class="tab-pane$firstPaneActive" id="interface$interface">
+					<div class="tab-pane$firstPaneActive" id="interface$encodedInterfaceID">
 EOF
 		# No longer the first pane
 		$firstPaneActive = "";
 
 		# Sanitize params if we need to
-		foreach my $item (@formElements) {
-			$formData->{$item} = defined($formData->{$item}) ? encode_entities($formData->{$item}) : "";
+		if (defined($formData->{"Limit[$encodedInterfaceID][0]"})) {
+		   $formData->{"Limit[$encodedInterfaceID][0]"} =
+				   encode_entities($formData->{"Limit[$encodedInterfaceID][0]"});
+		} else {
+		   $formData->{"Limit[$encodedInterfaceID][0]"} = "";
 		}
 
 
@@ -192,52 +267,70 @@ EOF
 		#
 		$content .=<<EOF;
 							<br />
-							<legend>Main: $interface</legend>
+							<legend>Main: $encodedInterfaceName</legend>
 							<div class="form-group">
-								<label for="TrafficLimitTx" class="col-md-1 control-label">CIR</label>
+								<label for="Limit" class="col-md-1 control-label">Speed</label>
 								<div class="row">
 									<div class="col-md-3">
 										<div class="input-group">
-											<input name="MainTrafficLimitTx[$interface]" type="text" placeholder="CIR" class="form-control" value="$formData->{"MainTrafficLimitTx[$interface]"}" />
+											<input name="Limit[$encodedInterfaceID][0]" type="text"
+													placeholder="$encodedInterfaceLimit" class="form-control"
+													value="$formData->{"Limit[$encodedInterfaceID][0]"}" />
 											<span class="input-group-addon">Kbps *<span>
 										</div>
 									</div>
-
-									<label for="TrafficLimitTxBurst" class="col-md-1 control-label">Limit</label>
-									<div class="col-md-3">
-										<div class="input-group">
-											<input name="MainTrafficLimitTxBurst[$interface]" type="text" placeholder="Limit" class="form-control" value="$formData->{'TrafficLimitTxBurst'}" />
-											<span class="input-group-addon">Kbps<span>
-										</div>
-									</div>
 								</div>
 							</div>
 EOF
 
-		my $classes = getInterfaceTrafficClasses($interface);
-		foreach my $class (sort { $a <=> $b } keys %{$classes}) {
-			my $className = getTrafficClassName($class);
-			my $classNameStr = encode_entities($className);
+		# Grab classes and loop
+		my @trafficClasses = getAllTrafficClasses();
+		foreach my $trafficClassID (sort { $a <=> $b } @trafficClasses) {
+			my $trafficClass = getTrafficClass($trafficClassID);
+			my $encodedTrafficClassID = encode_entities($trafficClassID);
+			my $encodedTrafficClassName = encode_entities($trafficClass->{'Name'});
+			my $interfaceTrafficClass = getInterfaceTrafficClass($interfaceID,$trafficClassID);
+			my $encodedInterfaceTrafficClassCIR = encode_entities($interfaceTrafficClass->{'CIR'});
+			my $encodedInterfaceTrafficClassLimit = encode_entities($interfaceTrafficClass->{'Limit'});
+
+
+			# Sanitize params if we need to
+			if (defined($formData->{"CIR[$encodedInterfaceID][$encodedTrafficClassID]"})) {
+			   $formData->{"CIR[$encodedInterfaceID][$encodedTrafficClassID]"} =
+					   encode_entities($formData->{"CIR[$encodedInterfaceID][$encodedTrafficClassID]"});
+			} else {
+			   $formData->{"CIR[$encodedInterfaceID][$encodedTrafficClassID]"} = "";
+			}
+			if (defined($formData->{"Limit[$encodedInterfaceID][$encodedTrafficClassID]"})) {
+			   $formData->{"Limit[$encodedInterfaceID][$encodedTrafficClassID]"} =
+					   encode_entities($formData->{"Limit[$encodedInterfaceID][$encodedTrafficClassID]"});
+			} else {
+			   $formData->{"Limit[$encodedInterfaceID][$encodedTrafficClassID]"} = "";
+			}
 
 			#
 			# Page content
 			#
 			$content .=<<EOF;
-							<legend>Class: $interface - $classNameStr</legend>
+							<legend>Class: $encodedInterfaceName - $encodedTrafficClassName</legend>
 							<div class="form-group">
-								<label for="TrafficLimitTx" class="col-md-1 control-label">CIR</label>
+								<label for="TxCIR" class="col-md-1 control-label">CIR</label>
 								<div class="row">
 									<div class="col-md-3">
 										<div class="input-group">
-											<input name="ClassTrafficLimitTx[$interface] x y [$class]" type="text" placeholder="CIR" class="form-control" value="$formData->{'TrafficLimitTx'}" />
+											<input name="CIR[$encodedInterfaceID][$encodedTrafficClassID]" type="text"
+													placeholder="$encodedInterfaceTrafficClassCIR" class="form-control"
+													value="$formData->{"CIR[$encodedInterfaceID][$encodedTrafficClassID]"}" />
 											<span class="input-group-addon">Kbps *<span>
 										</div>
 									</div>
 
-									<label for="TrafficLimitTxBurst" class="col-md-1 control-label">Limit</label>
+									<label for="TxLimit" class="col-md-1 control-label">Limit</label>
 									<div class="col-md-3">
 										<div class="input-group">
-											<input name="ClassTrafficLimitTxBurst[$interface][$class]" type="text" placeholder="Limit" class="form-control" value="$formData->{'TrafficLimitTxBurst'}" />
+											<input name="Limit[$encodedInterfaceID][$encodedTrafficClassID]" type="text"
+													placeholder="$encodedInterfaceTrafficClassLimit" class="form-control"
+													value="$formData->{"Limit[$encodedInterfaceID][$encodedTrafficClassID]"}" />
 											<span class="input-group-addon">Kbps<span>
 										</div>
 									</div>