iopsys-feed/qosmngr/files/common/lib/qos/ebtables.sh

405 lines
10 KiB
Bash
Executable file

#!/bin/sh
# Install ebtables rules
BR_RULE=""
BR6_RULE=""
init_broute_rule() {
BR_RULE=""
BR6_RULE=""
}
broute_filter_on_src_if() {
BR_RULE="$BR_RULE --in-if $1"
}
broute_filter_on_src_mac() {
BR_RULE="$BR_RULE --src $1"
}
broute_filter_on_dst_mac() {
BR_RULE="$BR_RULE --dst $1"
}
broute_filter_on_pcp() {
# 5.04 onwards the vlan extension in ebtables is used for classification
# on the basis of vlan params which needs proto to be defined as 802_1Q in
# order to add a rule, now, proto can also be defined by specifying proto uci
# option as well as the rule may have a vlan id as well in which case the
# proto will already be present, hence, this check to not add --proto more
# than once
case "$BR_RULE" in
*proto*)
BR_RULE="$BR_RULE --vlan-prio $1"
;;
*)
BR_RULE="$BR_RULE --proto 802_1Q --vlan-prio $1"
;;
esac
}
broute_filter_on_ether_type() {
BR_RULE="$BR_RULE --proto $1"
}
broute_filter_on_ether_type6() {
BR6_RULE="$BR6_RULE --proto IPv6"
}
ebt_match_src_ip() {
BR_RULE="$BR_RULE --ip-src $1"
}
ebt_match_dst_ip() {
BR_RULE="$BR_RULE --ip-dst $1"
}
ebt_match_ipv6_src_ip() {
BR_RULE="$BR_RULE --ip6-src $1"
}
ebt_match_ipv6_dst_ip() {
BR_RULE="$BR_RULE --ip6-dst $1"
}
ebt_match_ip_src_port() {
BR_RULE="$BR_RULE --ip-source-port $1"
}
ebt_match_ip_dst_port() {
BR_RULE="$BR_RULE --ip-destination-port $1"
}
ebt_match_ipv6_src_port() {
#when ethertype is not configured by user then both proto rules of ipv4
#and ipv6 to be installed so update BR6_RULE string as well otherwise
#update BR_RULE only for installation of ipv6 proto rule only.
if [ -n "$BR6_RULE" ]; then
BR6_RULE="$BR6_RULE --ip6-source-port $1"
else
BR_RULE="$BR_RULE --ip6-source-port $1"
fi
}
ebt_match_ipv6_dst_port() {
#when ethertype is not configured by user then both proto rules of ipv4
#and ipv6 to be installed so update BR6_RULE string as well otherwise
#update BR_RULE only for installation of ipv6 proto rule only.
if [ -n "$BR6_RULE" ]; then
BR6_RULE="$BR6_RULE --ip6-destination-port $1"
else
BR_RULE="$BR_RULE --ip6-destination-port $1"
fi
}
ebt_match_ip_protocol() {
BR_RULE="$BR_RULE --ip-proto $1"
}
ebt_match_ipv6_protocol() {
#when ethertype is not configured by user then both proto rules of ipv4
#and ipv6 to be installed so update BR6_RULE string as well otherwise
#update BR_RULE only for installation of ipv6 proto rule only.
if [ -n "$BR6_RULE" ]; then
BR6_RULE="$BR6_RULE --ip6-proto $1"
else
BR_RULE="$BR_RULE --ip6-proto $1"
fi
}
broute_filter_on_vid() {
if [ -z "$1" ] || [ "$1" -lt 0 ]; then
return
fi
case "$BR_RULE" in
*proto*)
BR_RULE="$BR_RULE --vlan-id $1"
;;
*)
BR_RULE="$BR_RULE --proto 802_1Q --vlan-id $1"
;;
esac
}
broute_append_rule() {
#when ethertype is not configured by user then both proto rules of ipv4
#and ipv6 to be installed otherwise install ipv6 proto rule only.
echo "ebtables -t broute -A qos $BR_RULE" >> /tmp/qos/classify.ebtables
if [ -n "$BR6_RULE" ]; then
echo "ebtables -t broute -A qos $BR6_RULE" >> /tmp/qos/classify.ebtables
fi
}
set_ip_addr()
{
local cid="$1"
local match_src_ip_func="$2"
local match_dst_ip_func="$3"
config_get src_ip "$cid" "src_ip"
config_get dst_ip "$cid" "dest_ip"
if [ -n "$src_ip" ]; then
$match_src_ip_func "$src_ip"
fi
if [ -n "$dst_ip" ]; then
$match_dst_ip_func "$dst_ip"
fi
}
set_ports()
{
local cid="$1"
local match_src_port_func="$2"
local match_dst_port_func="$3"
local src_port=""
local dst_port=""
local src_port_range=""
local dst_port_range=""
config_get src_port "$cid" "src_port"
config_get dst_port "$cid" "dest_port"
config_get src_port_range "$cid" "src_port_range"
config_get dst_port_range "$cid" "dest_port_range"
if [ -n "$src_port" ] && [ -n "$src_port_range" ] ; then
$match_src_port_func "$src_port:$src_port_range"
elif [ -n "$src_port" ] ; then
$match_src_port_func "$src_port"
fi
if [ -n "$dst_port" ] && [ -n "$dst_port_range" ] ; then
$match_dst_port_func "$dst_port:$dst_port_range"
elif [ -n "$dst_port" ] ; then
$match_dst_port_func "$dst_port"
fi
}
protocol_string_to_num()
{
local value="-1"
case "$1" in
*[0-9]*)
value="$1"
;;
TCP|tcp)
value=6
;;
UDP|udp)
value=17
;;
ICMP|icmp)
value=1
;;
ICMPv6|icmpv6)
value=58
;;
IGMP|igmp)
value=2
;;
SCTP|sctp)
value=132
;;
*)
value=-1
;;
esac
echo $value
}
handle_ebtables_rules() {
local sid="$1"
local is_l2_rule=0
local src_dhcp_options=""
local dst_dhcp_options=""
local protocol=""
local ip_version=""
init_broute_rule
config_get src_if "$sid" "ifname"
config_get src_mac "$sid" "src_mac"
config_get dst_mac "$sid" "dst_mac"
config_get dscp_filter "$sid" "dscp_filter"
config_get pcp_check "$sid" "pcp_check"
config_get eth_type "$sid" "ethertype"
config_get vid "$sid" "vid_check"
config_get dhcp_type "$sid" "dhcp_type" # dhcpv4 or v6
config_get src_vcid "$sid" "src_vendor_class_id" # dhcp option 60
config_get dst_vcid "$sid" "dst_vendor_class_id" # dhcp option 60
config_get src_clid "$sid" "src_client_id" # dhcp option 61
config_get dst_clid "$sid" "dst_client_id" # dhcp option 61
config_get src_ucid "$sid" "src_user_class_id" # dhcp option 77
config_get dst_ucid "$sid" "dst_user_class_id" # dhcp option 77
config_get traffic_class "$sid" "traffic_class"
config_get protocol "$sid" "proto"
if [ -n "$src_if" ]; then
for interf in $(db -q get hw.board.ethernetPortOrder); do
if [ "$src_if" == "$interf" ]; then
src_if="$src_if+"
broute_filter_on_src_if "$src_if"
is_l2_rule=1
fi
done
fi
if [ -n "$src_mac" ]; then
broute_filter_on_src_mac "$src_mac"
is_l2_rule=1
fi
if [ -n "$dst_mac" ]; then
broute_filter_on_dst_mac "$dst_mac"
is_l2_rule=1
fi
if [ -n "$pcp_check" ]; then
broute_filter_on_pcp "$pcp_check"
is_l2_rule=1
fi
if [ -n "$eth_type" ]; then
broute_filter_on_ether_type "$eth_type"
is_l2_rule=1
fi
if [ -n "$vid" ]; then
broute_filter_on_vid "$vid"
is_l2_rule=1
fi
case $eth_type in
IPv4|IPV4|0800)
ip_version=4
;;
IPv6|IPV6|86DD)
ip_version=6
;;
*)
if [ -z "$eth_type" ]; then
case "$src_ip$dst_ip" in
*.*)
ip_version=4
broute_filter_on_ether_type "IPv4"
;;
*:*)
ip_version=6
broute_filter_on_ether_type "IPv6"
;;
*)
if [ -n "$protocol" ] || [ -n "$dscp_filter" ]; then
# Neither ether_type nor ip address used,
# ethertype is not configured by user, so install
# both proto IPv4 and IPv6 rule (version 1)
ip_version=1
BR6_RULE="$BR_RULE"
broute_filter_on_ether_type "IPv4"
broute_filter_on_ether_type6 "IPv6"
fi
esac
fi
esac
if [ "$ip_version" == "4" ] || [ "$ip_version" == "1" ]; then
broute_ipv4_rule_options "$sid"
is_l2_rule=1
fi
if [ "$ip_version" == "6" ] || [ "$ip_version" == "1" ]; then
broute_ipv6_rule_options "$sid"
is_l2_rule=1
fi
# first process options that will help figure our source mac address
# dhcp option for "vendor class id"
if [ -n "$src_vcid" ]; then
src_dhcp_options="$src_dhcp_options vcid=$src_vcid"
is_l2_rule=1
fi
# dhcp option for "client id"
if [ -n "$src_clid" ]; then
src_dhcp_options="$src_dhcp_options clid=$src_clid"
is_l2_rule=1
fi
# dhcp option for "user class id"
if [ -n "$src_ucid" ]; then
src_dhcp_options="$src_dhcp_options ucid=$src_ucid"
is_l2_rule=1
fi
# if src mac is already a classification criteria, then it
# does not really make sense to add it as a criteria to
# filter packets again based on source mac
if [ -n "$src_dhcp_options" ] && [ -z "$src_mac" ]; then
comp="$(grep -i "$src_dhcp_options" /tmp/dhcp.client.options)"
if [ -n "$comp" ]; then
s_mac_add="$(echo $comp | head -n1 | awk '{print $1;}')"
if [ -n "$s_mac_add" ]; then
broute_filter_on_src_mac "$s_mac_add"
fi
fi
fi
# Now process options that will help figure our destination mac address
# dhcp option for "vendor class id"
if [ -n "$dst_vcid" ]; then
dst_dhcp_options="$dst_dhcp_options vcid=$dst_vcid"
is_l2_rule=1
fi
# dhcp option for "client id"
if [ -n "$dst_clid" ]; then
dst_dhcp_options="$dst_dhcp_options clid=$dst_clid"
is_l2_rule=1
fi
# dhcp option for "user class id"
if [ -n "$dst_ucid" ]; then
dst_dhcp_options="$dst_dhcp_options ucid=$dst_ucid"
is_l2_rule=1
fi
# if dst mac is already a classification criteria, then it
# does not really make sense to add it as a criteria to
# filter packets again based on destination mac
if [ -n "$dst_dhcp_options" ] && [ -z "$dst_mac" ] ; then
comp="$(grep -i "$dst_dhcp_options" /tmp/dhcp.client.options)"
if [ -n "$comp" ]; then
d_mac_add="$(echo $comp | head -n1 | awk '{print $1;}')"
if [ -n "$d_mac_add" ]; then
broute_filter_on_dst_mac "$d_mac_add"
fi
fi
fi
if [ $is_l2_rule -eq 0 ]; then
return
fi
[ -n "$traffic_class" ] && broute_rule_set_traffic_class "$traffic_class"
[ -n "$BR_RULE" ] && broute_append_rule
}
create_ebtables_chains() {
ebtables -t broute -N qos 2> /dev/null
ret=$?
if [ $ret -eq 0 ]; then
ebtables -t broute -I BROUTING -j qos
else
ebtables -t broute -D BROUTING -j qos
ebtables -t broute -I BROUTING -j qos
fi
}
flush_ebtables_chains() {
echo "ebtables -t broute -F qos" > /tmp/qos/classify.ebtables
}