[2/6] QoS: Use the two right hand bytes to mark packets

Message ID 20211004175222.9208-2-michael.tremer@ipfire.org
State Accepted
Commit 45329c0a66d2f1f7bf4d215489ece6bc1714dfe3
Headers
Series [1/6] firewall: Only check relevant bits for NAT fix rules |

Commit Message

Michael Tremer Oct. 4, 2021, 5:52 p.m. UTC
  In order to not deal with any marks from NAT and the IPS, this patch
adds masks to all places where packets are being marked for individual
QoS classes.

Instead of being able to use the "fw" match in tc, we have to use the
u32 to apply the mask.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
---
 config/qos/makeqosscripts.pl | 57 ++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 22 deletions(-)
  

Patch

diff --git a/config/qos/makeqosscripts.pl b/config/qos/makeqosscripts.pl
index cbbbf70f8..3af046ac3 100644
--- a/config/qos/makeqosscripts.pl
+++ b/config/qos/makeqosscripts.pl
@@ -56,6 +56,12 @@  my $portfile = "/var/ipfire/qos/portconfig";
 my $tosfile = "/var/ipfire/qos/tosconfig";
 my $fqcodel_options = "limit 10240 quantum 1514";
 
+# Define iptables MARKs
+my $QOS_INC_MASK = 0x0000ff00;
+my $QOS_INC_SHIFT = 8;
+my $QOS_OUT_MASK = 0x000000ff;
+my $QOS_OUT_SHIFT = 0;
+
 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
 
 $qossettings{'ENABLED'} = 'off';
@@ -74,6 +80,10 @@  $qossettings{'VALID'} = 'yes';
 
 &General::readhash("${General::swroot}/qos/settings", \%qossettings);
 
+my $ACK_MARK = ($qossettings{'ACK'} << $QOS_OUT_SHIFT) . "/$QOS_OUT_MASK";
+my $DEF_OUT_MARK = ($qossettings{'DEFCLASS_OUT'} << $QOS_OUT_SHIFT) . "/$QOS_OUT_MASK";
+my $DEF_INC_MARK = ($qossettings{'DEFCLASS_INC'} << $QOS_INC_SHIFT) . "/$QOS_INC_MASK";
+
 open( FILE, "< $classfile" ) or die "Unable to read $classfile";
 @classes = <FILE>;
 close FILE;
@@ -200,9 +210,11 @@  foreach $classentry (sort @classes)
 	if ($qossettings{'RED_DEV'} eq $classline[0]) {
 		$qossettings{'DEVICE'} = $classline[0];
 		$qossettings{'CLASS'} = $classline[1];
-		print "\ttc filter add dev $qossettings{'DEVICE'} parent 1:0 prio 0 protocol ip handle $qossettings{'CLASS'} fw flowid 1:$qossettings{'CLASS'}\n";
+		print "\ttc filter add dev $qossettings{'DEVICE'} parent 1:0 prio 0 protocol ip";
+		printf(" u32 match mark 0x%x 0x%x flowid 1:%d\n", ($qossettings{'CLASS'} << $QOS_OUT_SHIFT), $QOS_OUT_MASK, $qossettings{'CLASS'});
 	}
 }
+
 print <<END
 
 	### ADD QOS-OUT CHAIN TO THE MANGLE TABLE IN IPTABLES
@@ -213,28 +225,28 @@  print <<END
 	iptables -t mangle -A QOS-OUT -m mark --mark 50 -j RETURN
 
 	### MARK ACKs
-	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags SYN,RST SYN -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags SYN,RST SYN -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags SYN,RST SYN -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p icmp -m length --length 40:100 -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p icmp -m length --length 40:100 -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p icmp -m length --length 40:100 -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p tcp --syn -m length --length 40:68 -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --syn -m length --length 40:68 -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --syn -m length --length 40:68 -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL SYN,ACK -m length --length 40:68 -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL SYN,ACK -m length --length 40:68 -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL SYN,ACK -m length --length 40:68 -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK -m length --length 40:100 -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK -m length --length 40:100 -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK -m length --length 40:100 -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL RST -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL RST -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL RST -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK,RST -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK,RST -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK,RST -j RETURN
 
-	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK,FIN -j MARK --set-mark $qossettings{'ACK'}
+	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK,FIN -j MARK --set-xmark $ACK_MARK
 	iptables -t mangle -A QOS-OUT -p tcp --tcp-flags ALL ACK,FIN -j RETURN
 
 	### SET TOS
@@ -247,7 +259,7 @@  END
 		$qossettings{'TOS'} = abs $tosruleline[2] * 2;
   		if ( $tosruleline[1] eq $qossettings{'RED_DEV'} )
   		{
-			print "\tiptables -t mangle -A QOS-OUT -m tos --tos $qossettings{'TOS'} -j MARK --set-mark $qossettings{'CLASS'}\n";
+			print "\tiptables -t mangle -A QOS-OUT -m tos --tos $qossettings{'TOS'} -j MARK --set-xmark " . ($qossettings{'CLASS'} << $QOS_OUT_SHIFT) . "/$QOS_OUT_MASK\n";
 			print "\tiptables -t mangle -A QOS-OUT -m tos --tos $qossettings{'TOS'} -j RETURN\n";
 		}
 	}
@@ -282,7 +294,7 @@  print "\n\t### SET PORT-RULES\n";
 			if ($qossettings{'DPORT'} ne ''){
 				print "--dport $qossettings{'DPORT'} ";
 			}
-			print "-j MARK --set-mark $qossettings{'CLASS'}\n";
+			print "-j MARK --set-xmark " . ($qossettings{'CLASS'} << $QOS_OUT_SHIFT) . "/$QOS_OUT_MASK\n";
 			print "\tiptables -t mangle -A QOS-OUT ";
 			if ($qossettings{'QIP'} ne ''){
 				print "-s $qossettings{'QIP'} ";
@@ -326,7 +338,7 @@  END
 			if ($qossettings{'DIP'} ne ''){
 				print "-d $qossettings{'DIP'} ";
 			}
-			print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings{'L7PROT'} -j MARK --set-mark $qossettings{'CLASS'}\n";
+			print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings{'L7PROT'} -j MARK --set-xmark " . $qossettings{'CLASS'} << $QOS_OUT_SHIFT . "/$QOS_OUT_MASK\n";
   			print "\tiptables -t mangle -A QOS-OUT ";
 			if ($qossettings{'QIP'} ne ''){
 				print "-s $qossettings{'QIP'} ";
@@ -341,7 +353,7 @@  END
 print <<END
 
 	### REDUNDANT: SET ALL NONMARKED PACKETS TO DEFAULT CLASS
-	iptables -t mangle -A QOS-OUT -m mark --mark 0 -j MARK --set-mark $qossettings{'DEFCLASS_OUT'}
+	iptables -t mangle -A QOS-OUT -m mark --mark 0/$QOS_OUT_MASK -j MARK --set-xmark $DEF_OUT_MARK
 
 	###
 	### $qossettings{'IMQ_DEV'}
@@ -410,7 +422,8 @@  foreach $classentry (sort @classes)
 	if ($qossettings{'IMQ_DEV'} eq $classline[0]) {
 		$qossettings{'DEVICE'} = $classline[0];
 		$qossettings{'CLASS'} = $classline[1];
-		print "\ttc filter add dev $qossettings{'DEVICE'} parent 2:0 prio 0 protocol ip handle $qossettings{'CLASS'} fw flowid 2:$qossettings{'CLASS'}\n";
+		print "\ttc filter add dev $qossettings{'DEVICE'} parent 2:0 prio 0 protocol ip";
+		printf(" u32 match mark 0x%x 0x%x flowid 2:%d\n", ($qossettings{'CLASS'} << $QOS_INC_SHIFT), $QOS_INC_MASK, $qossettings{'CLASS'});
 	}
 }
 print <<END
@@ -420,7 +433,7 @@  print <<END
 	iptables -t mangle -A PREROUTING -i $qossettings{'RED_DEV'} -j QOS-INC
 
 	# If the packet is already marked, then skip the processing
-	iptables -t mangle -A QOS-INC -m mark ! --mark 0 -j RETURN
+	iptables -t mangle -A QOS-INC -m mark ! --mark 0/$QOS_INC_MASK -j RETURN
 
 	### SET TOS
 END
@@ -432,7 +445,7 @@  END
 		$qossettings{'TOS'} = abs $tosruleline[2] * 2;
   		if ( $tosruleline[1] eq $qossettings{'IMQ_DEV'} )
   		{
-			print "\tiptables -t mangle -A QOS-INC -m mark --mark 0 -m tos --tos $qossettings{'TOS'} -j MARK --set-mark $qossettings{'CLASS'}\n";
+			print "\tiptables -t mangle -A QOS-INC -m tos --tos $qossettings{'TOS'} -j MARK --set-xmark " . ($qossettings{'CLASS'} << $QOS_INC_SHIFT) . "/$QOS_INC_MASK\n";
 		}
 
 	}
@@ -450,7 +463,7 @@  print "\n\t### SET PORT-RULES\n";
 			$qossettings{'QPORT'} = $portruleline[4];
 			$qossettings{'DIP'} = $portruleline[5];
 			$qossettings{'DPORT'} = $portruleline[6];
-			print "\tiptables -t mangle -A QOS-INC -m mark --mark 0 ";
+			print "\tiptables -t mangle -A QOS-INC -m mark --mark 0/$QOS_INC_MASK ";
 			if ($qossettings{'QIP'} ne ''){
 				print "-s $qossettings{'QIP'} ";
 			}
@@ -467,7 +480,7 @@  print "\n\t### SET PORT-RULES\n";
 			if ($qossettings{'DPORT'} ne ''){
 				print "--dport $qossettings{'DPORT'} ";
 			}
-			print "-j MARK --set-mark $qossettings{'CLASS'}\n";
+			print "-j MARK --set-xmark " . ($qossettings{'CLASS'} << $QOS_INC_SHIFT) . "/$QOS_INC_MASK\n";
 		}
 	}
 
@@ -486,23 +499,23 @@  END
 			$qossettings{'L7PROT'} = $l7ruleline[2];
 			$qossettings{'QIP'} = $l7ruleline[3];
 			$qossettings{'DIP'} = $l7ruleline[4];
-			print "\tiptables -t mangle -A QOS-INC -m mark --mark 0 ";
+			print "\tiptables -t mangle -A QOS-INC -m mark --mark 0/$QOS_INC_MASK ";
 			if ($qossettings{'QIP'} ne ''){
 				print "-s $qossettings{'QIP'} ";
 			}
 			if ($qossettings{'DIP'} ne ''){
 				print "-d $qossettings{'DIP'} ";
 			}
-			print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings{'L7PROT'} -j MARK --set-mark $qossettings{'CLASS'}\n";
+			print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings{'L7PROT'} -j MARK --set-xmark " . ($qossettings{'CLASS'} << $QOS_INC_SHIFT) . "/$QOS_INC_MASK\n";
   		}
   	}
 
 print <<END
 	### REDUNDANT: SET ALL NONMARKED PACKETS TO DEFAULT CLASS
-	iptables -t mangle -A QOS-INC -m mark --mark 0 -m layer7 ! --l7proto unset -j MARK --set-mark $qossettings{'DEFCLASS_INC'}
+	iptables -t mangle -A QOS-INC -m mark --mark 0/$QOS_INC_MASK -m layer7 ! --l7proto unset -j MARK --set-xmark $DEF_INC_MARK
 
 	# Save mark in connection tracking
-	iptables -t mangle -A QOS-INC -j CONNMARK --save-mark
+	iptables -t mangle -A QOS-INC -m mark --mark 0/$QOS_INC_MASK -j CONNMARK --save-mark
 
 	## STARTING COLLECTOR
 	/usr/local/bin/qosd $qossettings{'RED_DEV'} >/dev/null 2>&1