#!/bin/bash

IPTABLES=/sbin/iptables

# Enable FTP connection tracking
modprobe nf_conntrack_ftp

# Enable Internet connection sharing
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

# clear out existing rules and set policies
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD DROP
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
$IPTABLES -t filter -F

# Allow all traffic to the loopback device
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT

# Create and flush internet chain
# This is used to authenticate users who have already signed up
$IPTABLES -N internet -t nat 2>/dev/null
$IPTABLES -F internet -t nat


# Setup very restrictive eth1 firewall for Mess Office
# Allow mess office through internet chain so that doesn't get dropped later
$IPTABLES -t nat -A internet -i eth1 -j ACCEPT
# The following rules allow a restricted set of protocols
# Allow DNS lookups
$IPTABLES -A INPUT -i eth1 -m udp -p udp --dport 53 -j ACCEPT
$IPTABLES -A OUTPUT -o eth1 -m udp -p udp --sport 53 -j ACCEPT
# Accept port 80 traffic (HTTP)
$IPTABLES -A FORWARD -i eth1 -o ppp0 -p tcp --dport 80 -j ACCEPT
$IPTABLES -A FORWARD -i ppp0 -o eth1 -p tcp --sport 80 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Accept port 443 traffic (HTTPS)
$IPTABLES -A FORWARD -i eth1 -o ppp0 -p tcp --dport 443 -j ACCEPT
$IPTABLES -A FORWARD -i ppp0 -o eth1 -p tcp --sport 443 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Accept 993 (secure server email)
$IPTABLES -A FORWARD -i eth1 -o ppp0 -p tcp --dport 993 -j ACCEPT
$IPTABLES -A FORWARD -i ppp0 -o eth1 -p tcp --sport 993 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Accept SSH
$IPTABLES -A INPUT -i eth1 -p tcp --dport 22 -j ACCEPT
$IPTABLES -A OUTPUT -o eth1 -p tcp --sport 22 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow port 25 (SMTP)
$IPTABLES -A INPUT -i eth1 -p tcp --dport 25 -j ACCEPT
$IPTABLES -A OUTPUT -o eth1 -p tcp --sport 25 -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow all ICMP traffic
$IPTABLES -A INPUT -i eth1 -p icmp -j ACCEPT
$IPTABLES -A FORWARD -i eth1 -p icmp -j ACCEPT
$IPTABLES -A FORWARD -o eth1 -p icmp -j ACCEPT
$IPTABLES -A OUTPUT -o eth1 -p icmp -j ACCEPT
# Log all dropped internet traffic
#$IPTABLES -A INPUT -i eth1 -j LOG
# Drop all local traffic
$IPTABLES -A INPUT -i eth1 -j DROP
$IPTABLES -A OUTPUT -o eth1 -j DROP
# All other forwarded traffic is dropped by default



# Create ipset for storing ip addresses of p2p users
# Set timeout to 60 seconds meaning their address will
# be cleared after 60 seconds of inactivity of p2p
#
# The current IP addresses in the IP Set can be monitored
# with the 'ipset -L' comand from the bash prompt
#
ipset -X p2p
ipset -N p2p iptree --timeout 60

# Accept all local traffic - **is this needed** ??
#iptables -t nat -A PREROUTING -i eth0 --destination 10.0.0.0/16 -j ACCEPT

# Send all traffic via internet chain
# At the prerouting NAT stage this will DNAT them to the local
# webserver for them to signup if they aren't authorised
# Packets for unauthorised users are marked for dropping later
iptables -t nat -A PREROUTING -j internet

###### INTERNET CHAIN ##########
# Allow authorised hosts in, redirect all others to login webserver
# Add known users to the NAT table to stop their dest being rewritten
# Ignore MAC address with a * - these users are blocked
awk 'BEGIN { FS="\t"; } { if ($5 !~ /\*/) { system("iptables -t nat -A internet -m mac --mac-source "$5" -j RETURN"); } }' /var/lib/users
# MAC address not found. Mark the packet 99. Will be dropped later.
iptables -t nat -A internet -j MARK --set-mark 99
# Redirects web requests from Unauthorised users to logon Web Page
iptables -t nat -A internet -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
################################

# Drop invalid packets
iptables -t mangle -A PREROUTING -p tcp -i eth0 -m conntrack --ctstate INVALID -j DROP  # drop invalid connections

# Accept ping and ssh coming in to local server from any interface
iptables -t filter -A INPUT -p icmp --icmp-type 8 -j ACCEPT
iptables -t filter -A INPUT -p ICMP --icmp-type 11 -j ACCEPT
iptables -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Accept traffic to Squid, DNS and Apache from local network
# These will not be MARKed
iptables -t filter -A INPUT -i eth0 -p udp --dport 53 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p udp --dport 69 -j ACCEPT # TFTPD
# NFS port numbers. See http://wiki.debian.org/SecuringNFS
iptables -t filter -A INPUT -i eth0 -p udp --dport 111 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p tcp --dport 111 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p udp --dport 2049 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p tcp --dport 2049 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p udp --dport 32765:32769 -j ACCEPT
iptables -t filter -A INPUT -i eth0 -p tcp --dport 32765:32769 -j ACCEPT
#iptables -t filter -A OUTPUT -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT


iptables -t filter -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
# But do not allow anything marked 99 as far as Squid
iptables -t filter -A INPUT -m mark --mark 99 -j DROP
iptables -t filter -A INPUT -i eth0 -p tcp --dport 3128 -j ACCEPT

# Drop any marked 99 packets. These are unauthorised users
iptables -t filter -A FORWARD -m mark --mark 99 -j DROP

# accept NTP time requests
# we allow these for any PC regardless of whether they are logged
# on to the network because the Internet Suite PCs use NTP to set
# their clocks BEFORE they are authorised to use the Internet
# These packets will not be MARKed
iptables -t filter -A FORWARD -p UDP --dport 123 -j ACCEPT

# Stop DoS attacks on DNS-BL
iptables -t filter -A FORWARD -i eth0 --destination 216.168.28.50 -j DROP

# Do not allow outgoing internet SMTP connections
# This is essential to stop the many viruses that sit on
# people's computers and attempt to send spam (using bandwidth up)
# This can be changed on a per user basis if required as per the example
iptables -t filter -A FORWARD -p tcp -i eth0 --dport 25 -m mac --mac-source 00:19:D1:02:1B:02 -j ACCEPT
iptables -t filter -A FORWARD -p tcp -i eth0 --dport 25 -j DROP


############ MARK traffic for shaping ###################

# Ignore '99' packets. This will be dropped later
iptables -t mangle -A FORWARD -m mark --mark 99 -j ACCEPT
# Set default mark for forwarded packets
iptables -t mangle -A FORWARD -j MARK --set-mark 40

# MARK locally generated traffic as appropriate. This applies only to DNS requests
# Squid should be set to use the qos_flows parameter to mark non-cache hits
iptables -t mangle -A OUTPUT -m udp -p udp --dport 53 -o ppp0 -j MARK --set-mark 10
# DNS replies to requests (local traffic)
iptables -t mangle -A OUTPUT -m udp -p udp --sport 53 -o eth0 -j MARK --set-mark 10
#### Squid must be configured to mark all packets 30 (except cache hits) #####
# Re-mark large downloads from squid (local traffic)
# This assumes packets have already been marked as 30 by Squid
iptables -t mangle -A OUTPUT -p tcp --sport 3128 -o eth0 -j MARK --set-mark 30
iptables -t mangle -A OUTPUT -p tcp -m mark --mark 30 -m connbytes --connbytes 1048576: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 50

# MARK forwarded traffic
# SSH
iptables -t mangle -A FORWARD -p tcp --sport 22 -i ppp0 -j MARK --set-mark 10
iptables -t mangle -A FORWARD -p tcp --dport 22 -o ppp0 -j MARK --set-mark 10
# IMAP
iptables -t mangle -A FORWARD -p tcp --sport 993 -i ppp0 -j MARK --set-mark 30
iptables -t mangle -A FORWARD -p tcp --dport 993 -o ppp0 -j MARK --set-mark 30
# HTTPS
iptables -t mangle -A FORWARD -p tcp --sport 443 -i ppp0 -j MARK --set-mark 30
iptables -t mangle -A FORWARD -p tcp --dport 443 -o ppp0 -j MARK --set-mark 30
# Mark large downloads (> 500kb)
iptables -t mangle -A FORWARD -m connbytes --connbytes 1048576: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 50
# To speed up downloads while an upload is going on, put short ACK
# packets in their own class:
iptables -t mangle -A FORWARD -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK ACK -m length --length :64 -j MARK --set-mark 20

# The next few lines pick out P2P packets
# These are characterised by lots of connections to high port numbers
# First look for the packets and log to IPSET p2p
# Detects traffic from users using >8 ports above 1024
# and adds the source address to the P2P list.
iptables -t mangle -A FORWARD -o ppp0 -p tcp --dport 1024: \
	-m connlimit --connlimit-above 8 -j SET --add-set p2p src 
# Detects traffic from users using >4 UDP ports above 1024
# and adds the source address to the P2P list.
iptables -t mangle -A FORWARD -o ppp0 -p udp --dport 1024: \
	-m connlimit --connlimit-above 4 -j SET --add-set p2p src 
# Detects traffic to users using >8 ports above 1024
# and adds the dst address (ie the user) to the P2P list.
iptables -t mangle -A FORWARD -i ppp0 -p tcp --sport 1024: \
	-m connlimit --connlimit-above 8 -j SET --add-set p2p dst
# Detects traffic to users using >4 UDP ports above 1024
# and adds the dst address (ie the user) to the P2P list.
iptables -t mangle -A FORWARD -i ppp0 -p udp --sport 1024: \
	-m connlimit --connlimit-above 4 -j SET --add-set p2p dst
# Once a user is in the p2p IPSET, these rules mark their packets
# Any packets above 1024 are marked as the lowest priority
iptables -t mangle -A FORWARD -o ppp0 -p tcp --dport 1024: \
	-m set --set p2p src -j MARK --set-mark 666
iptables -t mangle -A FORWARD -i ppp0 -p tcp --sport 1024: \
	-m set --set p2p dst -j MARK --set-mark 666
iptables -t mangle -A FORWARD -o ppp0 -p udp --dport 1024: \
	-m set --set p2p src -j MARK --set-mark 666
iptables -t mangle -A FORWARD -i ppp0 -p udp --sport 1024: \
	-m set --set p2p dst -j MARK --set-mark 666



# Force all traffic via web proxy to speed up some traffic
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 ! -d 10.0.0.1 -j REDIRECT --to-port 3128

# Blocks outgoing traffic from local host on unused ports.
# Allow known ports out
iptables -t mangle -A OUTPUT -p tcp --dport 80 -o ppp0 -j ACCEPT  # Accept web proxy traffic
iptables -t mangle -A OUTPUT -p tcp --dport 25 -o ppp0 -j ACCEPT # Accept outgoing mail 
iptables -t mangle -A OUTPUT -p tcp --dport 21 -o ppp0 -j ACCEPT # Accept outgoing ftp
iptables -t mangle -A OUTPUT -p tcp --dport 22 -o ppp0 -j ACCEPT # Accept outgoing ssh
iptables -t mangle -A OUTPUT -p tcp --dport 25 -o ppp0 -j ACCEPT # Accept outgoing mail
iptables -t mangle -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t mangle -A OUTPUT -o ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t mangle -A OUTPUT -p icmp -o ppp0 --icmp-type 8 -j ACCEPT #Accept ping commamnds
iptables -t mangle -A OUTPUT -p ICMP -o ppp0 --icmp-type 11 -j ACCEPT #Accept ping commands
iptables -t mangle -A OUTPUT -m udp -p udp --dport 53 -j ACCEPT   # DNS
iptables -t mangle -A OUTPUT -o ppp0 -j DROP # Drops all other outputs from the local machine


# Enable Internet connection sharing
$IPTABLES -A FORWARD -i ppp0 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i eth0 -o ppp0 -j ACCEPT
$IPTABLES -t nat -A POSTROUTING -o ppp0 -j MASQUERADE




#
# ACK_rate
# --------
# To utilize the DOWNSTREAM bandwidth, it is very important to reserve
# enough bandwidth to ACK packets.
#
# The latency of the ACK packets also influences the downstream
# utilization (due to the bandwidth-delay product and default window
# size).  The assure low latency using HTB, the ACK class must never
# be backlogged.  This is achived by reserving a big enough RATE to
# the class and assigning a "high" priority.
#
# The ACK_rate can be (calculated or) estimated based on the
# downstream capacity.
#
#  downstream_capacity / data_packet_size = num_data_packets
#
#  num_data_packets / ACK_packets_per_data_packet = Num_ACK_packets
#
#  num_ACK_packets * ACK_packet_size = Required_ACK_rate
#
#
function ACK_rate_calc() {
    if [ -z "$1" ]; then
        echo "[$FUNCNAME] ERROR need to know downstream capacity (in Kbit/s)."
        exit 1;
    fi
    local DOWNSTREAM_=$1

    # Delayed ACK factor, ACK_factor:
    # -------------------------------
    # The minimum delayed ACK factor is 1, since at most one ACK should be
    # sent for each data packet [rfc1122, rfc2581].  "Normal" behavior of
    # TCP bulk transfers is to ACK every second data packet.
    # (notice: ACK_scale=10  =>  10=1  16=1.6)
    #ACK_factor=12
    ACK_factor=15
    ACK_scale=10

    # ACK_size
    # --------
    # The ACK size on ADSL with ATM link-layer is two ATM cells (2*53)
    #
    # With out cell headers, only payload 2*48
    #ACK_size=96
    # Complete ATM cells with headers 2*53
    ACK_size=106

    # Data packet size
    # ----------------
    # The (average) data packet size.
    #
    Data_size=1500

    # Precision factor, doing integer part divisions we lose the
    # fractional part of the number.  To avoid this we "move" the decimal
    # point, when doing fixed point arithmetic
    scale=100000

    # Round off loss
    round_off_bonus=1

    # Old calc:
    # ACK_rate=$[ ($DOWNSTREAM_*$scale)/$Data_size/$ACK_factor * $ACK_size \
    #           * $ACK_scale / $scale ]

    # New calc: (multiply first, then divide, avoiding div loss)
    ACK_rate=$[ $DOWNSTREAM_ * $ACK_size * $ACK_scale \
                / $Data_size / $ACK_factor ]

    if [ $ACK_rate -lt 0 ]; then
        echo "ERROR negative ACK rate \"$ACK_rate\""
        exit 2
    fi

    if [ -n "${CEIL}" ]; then
        local RATE_=$[${CEIL}-${ACK_rate}]
        if [ ${RATE_} -lt 0 ]; then
            echo "ERROR ACK rate ($ACK_rate) greater that ceil ($CEIL)"
            echo "      Resulting in negative rate ($RATE_) to classes!"
            exit 2
        fi
    fi
    ACK_rate=$[ $ACK_rate + $round_off_bonus ]
}




##############################################################################
# Now set up traffic shaping based on the marks given to each packet

# Delete all old stuff first
tc qdisc del dev ppp0 root    2> /dev/null > /dev/null
tc qdisc del dev ifb0 root   2> /dev/null > /dev/null
tc qdisc del dev ifb0 ingress   2> /dev/null > /dev/null
tc qdisc del dev ppp0 root 2> /dev/null > /dev/null
tc qdisc del dev ifb0 root 2> /dev/null > /dev/null
tc qdisc del dev ppp0 ingress 2> /dev/null > /dev/null
tc qdisc del dev eth0 root 2> /dev/null > /dev/null
tc qdisc del dev eth0 ingress 2> /dev/null > /dev/null

# Set variables
# The downlink should be slightly less than the ADSL line
# All the classes below should add up to this
DOWNLINK=3800
# Same for the uplink
UPLINK=680





# ===================================================
#  Packet overhead per TCP/IP packet due to ATM/AAL5 
# ===================================================
#
# Overhead per AAL5 packet 
#  AAL5 tail    : 8 bytes per packet (incl. 4 bytes checksum)
#
aal5_tail=8

# AAL5 SSCS headers (SSCS = Service Specific Common Sublayer)
# -----------------
#
# VC (Virtual Circuit) vs. LLC (Logical Link Control) 
#  There is a basic choice between LLC and VC when configuring
#  the encapsulation mode on ADSL.  LLC gives more overhead.  

# Routed modes:
overhead_PPPoA_VC=2
overhead_PPPoA_LLC=6
#
overhead_rfc2684R_VC=0
overhead_rfc2684R_LLC=8

# Bridged modes:
#  There is a special feature bridged mode which some equipment 
#  support where the MAC-checksum (FCS) can be dropped, which   
#  reduces the overhead by 4 bytes.
#
overhead_rfc2684B_VC=20
overhead_rfc2684B_VC_noFCS=16
overhead_rfc2684B_LCC=28
overhead_rfc2684B_LCC_noFCS=24
#
overhead_PPPoE_VC=28
overhead_PPPoE_VC_noFCS=24
overhead_PPPoE_LLC=36
overhead_PPPoE_LLC_noFCS=32

# ***************************************************
# *** Choose the SSCS overhead encapsulation mode ***
# ***************************************************
overhead_SSCS=${overhead_PPPoA_VC}

# Encapsulation overhead:
# -----------------------
if [ -z "$overhead" ]; then
    overhead=$[ ${overhead_SSCS} + ${aal5_tail} ]
fi

linklayer="linklayer atm"


LINE_DOWNSTREAM=3800
CEIL=680


# Calculate the ACK_rate from the $DOWNLINK
# ----------------------   
if [ -z "$ACK_rate" -a -n "$DOWNLINK" ]; then
    # Will set the variable $ACK_rate
    ACK_rate_calc $DOWNLINK
    #echo "ACK rate calculated to: $ACK_rate "
    #echo "(for a $LINE_DOWNSTREAM Kbit downstream link)"
fi
 
# Set ACK_rate to 1kbit if not set (zero makes tc command fail)
if [ -z "$ACK_rate" ]; then
    # echo "Cannot determine ACK rate to reserve, need more input"
    ACK_rate=1
fi

#ACK_ceil=$CEIL
ACK_ceil=$[90*${UPLINK}/100] 
#ACK_ceil=$[2*${ACK_rate}]
  
# Rate bandwidth left for Classes
# 
RATE=$[${UPLINK}-${ACK_rate}]

RATE=$DOWNLINK

##############################################################################
## downlink via eth0 ##

DEV=eth0

# A qdisc is a whole set of shaping rules that we apply
# Here we add a HTB qdisc to the interface eth0
# This is known as the root for the interface
# We don't set a default class to stop us shaping local eth0 traffic
# We have to shape at eth0 and not ppp0 as we can only do egress shaping
#tc qdisc add dev eth0 root handle 1: htb

# Then we add to the root some overall rate limits
#tc class add dev eth0 parent 1: classid 1:1 htb rate ${DOWNLINK}kbit

#tc qdisc add dev ${DEV} root        handle 1: htb default 50 r2q 1
tc qdisc add dev ${DEV} root        handle 1: htb r2q 1

tc class add dev ${DEV} parent 1: classid 1:1 htb \
    rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit \
    overhead $overhead $linklayer


# Then we go through and add a number of classes to the
# root qdisc. With some qdiscs the classes are automatically
# created. With HTB they are not so we add 4 in total
# with different rate limits each

# [[[ example to divide between $[8*$DOWNLINK/10]kbit ]]]


##########################################
# Class:  1:10
# Mark :  10  
# Description: Interactive traffic
##########################################
procent=20
ceil_procent=20
tc class add dev ${DEV} parent 1:1 classid 1:10 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${DOWNLINK}/100]kbit \
    prio 0 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:10 handle 4210: \
    sfq perturb 10 limit 50

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 10 handle 10 fw flowid 1:10


##########################################
# Class:  1:20
# Mark :  20  
# Description: ACK "class"
##########################################
tc class add dev ${DEV} parent 1:1 classid 1:20 htb \
    rate ${ACK_rate}kbit \
    ceil ${ACK_ceil}kbit \
    prio 1 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:20 handle 4220: \
    sfq perturb 10 limit 50

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 20 handle 20 fw flowid 1:20


##########################################
# Class:  1:30
# Mark :  30  
# Description: Good traffic
##########################################
procent=28
ceil_procent=80
tc class add dev ${DEV} parent 1:1 classid 1:30 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${DOWNLINK}/100]kbit \
    prio 4 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:30 handle 4230: \
    sfq perturb 10 limit 64

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 30 handle 30 fw flowid 1:30



# web browsing
#tc class add dev ppp0 parent 1:1  classid 1:30 htb \
#        rate 300kbit ceil 300kbit prio 1
#        
#tc qdisc add dev ppp0 parent 1:30 handle 30: sfq perturb 10
#tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 30 fw flowid 1:30

##########################################
# Class:  1:40
# Mark :  40  
# Description: Default traffic
##########################################
procent=22
ceil_procent=80
tc class add dev ${DEV} parent 1:1 classid 1:40 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${DOWNLINK}/100]kbit \
    prio 4 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:40 handle 4240: \
    sfq perturb 10 limit 128

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 40 handle 40 fw flowid 1:40



##########################################
# Class:  1:50
# Mark :  50  
# Description: Bulk
##########################################
procent=20
ceil_procent=95
tc class add dev ${DEV} parent 1:1 classid 1:50 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${DOWNLINK}/100]kbit \
    prio 4 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:50 handle 4250: \
    sfq perturb 10 limit 64

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 50 handle 50 fw flowid 1:50


##########################################
# Class: 1:666 
# Mark : 666   
# Description: Bad traffic 
##########################################
procent=10
ceil_procent=100
tc class add dev ${DEV} parent 1:1 classid 1:666 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${DOWNLINK}/100]kbit \
    prio 7 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:666 handle 666: \
    sfq perturb 10 limit 128
    #sfq perturb 10 limit 64

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 666 handle 666 fw flowid 1:666


# experimental hash filters
tc filter add dev eth0 parent 4210: protocol ip handle 10 flow hash keys nfct-dst divisor 1024
tc filter add dev eth0 parent 4220: protocol ip handle 20 flow hash keys nfct-dst divisor 1024
tc filter add dev eth0 parent 4230: protocol ip handle 30 flow hash keys nfct-dst divisor 1024
tc filter add dev eth0 parent 4240: protocol ip handle 40 flow hash keys nfct-dst divisor 1024
tc filter add dev eth0 parent 4250: protocol ip handle 50 flow hash keys nfct-dst divisor 1024
tc filter add dev eth0 parent 666: protocol ip handle 666 flow hash keys nfct-dst divisor 1024

########################################## End of downlink configuration ##########################################



###################################################################################################################
## uplink via ppp0 ##

DEV=ppp0

# Calculate the ACK_rate from the $DOWNLINK
# ----------------------   
if [ -z "$ACK_rate" -a -n "$DOWNLINK" ]; then
    # Will set the variable $ACK_rate
    ACK_rate_calc $DOWNLINK
    #echo "ACK rate calculated to: $ACK_rate "
    #echo "(for a $LINE_DOWNSTREAM Kbit downstream link)"
fi
 
# Set ACK_rate to 1kbit if not set (zero makes tc command fail)
if [ -z "$ACK_rate" ]; then
    # echo "Cannot determine ACK rate to reserve, need more input"
    ACK_rate=1
fi

#ACK_ceil=$CEIL
ACK_ceil=$[90*${UPLINK}/100] 
#ACK_ceil=$[2*${ACK_rate}]
  
# Rate bandwidth left for Classes
# 
RATE=$[${UPLINK}-${ACK_rate}]

# A qdisc is a whole set of shaping rules that we apply
# Here we add a HTB qdisc to the interface ppp0
# This is known as the root for the interface
# Default class is 40
#tc qdisc add dev ppp0 root handle 1: htb default 40

# Then we add to the root some overall rate limits
#tc class add dev ppp0 parent 1: classid 1:1 htb rate ${UPLINK}kbit

tc qdisc add dev ${DEV} root        handle 1: htb default 50 r2q 1

tc class add dev ${DEV} parent 1: classid 1:1 htb \
    rate ${UPLINK}kbit ceil ${UPLINK}kbit \
    overhead $overhead $linklayer

# Then we go through and add a number of classes to the
# root qdisc. With some qdiscs the classes are automatically
# created. With HTB they are not so we add 4 in total
# with different rate limits each


# [[[ example to divide between $[8*$DOWNLINK/10]kbit ]]]

##########################################
# Class:  1:10
# Mark :  10  
# Description: Interactive traffic
##########################################
procent=20
ceil_procent=20
tc class add dev ${DEV} parent 1:1 classid 1:10 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${UPLINK}/100]kbit \
    prio 0 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:10 handle 4210: \
    sfq perturb 10 limit 50

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 10 handle 10 fw flowid 1:10


##########################################
# Class:  1:20
# Mark :  20  
# Description: ACK "class"
##########################################
tc class add dev ${DEV} parent 1:1 classid 1:20 htb \
    rate ${ACK_rate}kbit \
    ceil ${ACK_ceil}kbit \
    prio 1 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:20 handle 4220: \
    sfq perturb 10 limit 50

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 20 handle 20 fw flowid 1:20


##########################################
# Class:  1:30
# Mark :  30  
# Description: Good traffic
##########################################
procent=28
ceil_procent=80
tc class add dev ${DEV} parent 1:1 classid 1:30 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${UPLINK}/100]kbit \
    prio 4 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:30 handle 4230: \
    sfq perturb 10 limit 64

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 30 handle 30 fw flowid 1:30



# web browsing
#tc class add dev ppp0 parent 1:1  classid 1:30 htb \
#        rate 300kbit ceil 300kbit prio 1
#        
#tc qdisc add dev ppp0 parent 1:30 handle 30: sfq perturb 10
#tc filter add dev ppp0 parent 1:0 prio 0 protocol ip handle 30 fw flowid 1:30

##########################################
# Class:  1:40
# Mark :  40  
# Description: Default traffic
##########################################
procent=22
ceil_procent=80
tc class add dev ${DEV} parent 1:1 classid 1:40 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${UPLINK}/100]kbit \
    prio 4 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:40 handle 4240: \
    sfq perturb 10 limit 128

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 40 handle 40 fw flowid 1:40



##########################################
# Class:  1:50
# Mark :  50  
# Description: Bulk
##########################################
procent=20
ceil_procent=95
tc class add dev ${DEV} parent 1:1 classid 1:50 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${UPLINK}/100]kbit \
    prio 4 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:50 handle 4250: \
    sfq perturb 10 limit 64

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 50 handle 50 fw flowid 1:50


##########################################
# Class: 1:666 
# Mark : 666   
# Description: Bad traffic 
##########################################
procent=10
ceil_procent=100
tc class add dev ${DEV} parent 1:1 classid 1:666 htb \
    rate $[${procent}*${RATE}/100]kbit \
    ceil $[${ceil_procent}*${UPLINK}/100]kbit \
    prio 7 \
    overhead $overhead $linklayer

tc qdisc add dev ${DEV} parent 1:666 handle 666: \
    sfq perturb 10 limit 128
    #sfq perturb 10 limit 64

tc filter add dev ${DEV} parent 1:0 protocol ip \
    prio 666 handle 666 fw flowid 1:666




tc filter add dev ppp0 parent 4210: protocol ip handle 10 flow hash keys nfct-src divisor 1024
tc filter add dev ppp0 parent 4220: protocol ip handle 20 flow hash keys nfct-src divisor 1024
tc filter add dev ppp0 parent 4230: protocol ip handle 30 flow hash keys nfct-src divisor 1024
tc filter add dev ppp0 parent 4240: protocol ip handle 40 flow hash keys nfct-src divisor 1024
tc filter add dev ppp0 parent 4250: protocol ip handle 50 flow hash keys nfct-src divisor 1024
tc filter add dev ppp0 parent 666: protocol ip handle 666 flow hash keys nfct-src divisor 1024

################################# End of uplink configuration #####################################################

