]> git.ipfire.org Git - people/stevee/network.git/commitdiff
batman-adv: Enhance functionality.
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 11 Mar 2013 13:34:49 +0000 (14:34 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 11 Mar 2013 13:34:49 +0000 (14:34 +0100)
* Created a -port hook, which enables us to bridge several
  wireless adapters.
* Make hotplugging work.

functions.batman-adv
functions.cli
functions.constants
functions.device
hooks/ports/batman-adv
hooks/ports/batman-adv-port [new file with mode: 0755]
hooks/zones/bridge.ports/batman-adv [new symlink]
udev/network-hotplug

index f4a19c55469aa66ed8710709d7c309a49712ae2e..77cf9bf9dd00dc50b3132d5f24168ab519f0df4f 100644 (file)
 #                                                                             #
 ###############################################################################
 
+function batman_adv_start() {
+       # Load the batman kernel module.
+       module_load "batman-adv"
+}
+
 function batman_adv_interface_add() {
        local device=${1}
        assert isset device
 
-       cmd_quiet batctl interface add ${device}
+       local port=${2}
+       assert isset port
+
+       # Make sure, batman is running.
+       batman_adv_start
+
+       assert device_is_batman_adv_port "${port}"
+
+       fwrite "${SYS_CLASS_NET}/${port}/batman_adv/mesh_iface" "${device}"
 }
 
 function batman_adv_interface_del() {
+       local port=${1}
+       assert isset port
+
+       fwrite "${SYS_CLASS_NET}/${port}/batman_adv/mesh_iface" "none"
+}
+
+function batman_adv_get_aggregated_ogms() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/aggregated_ogms)"
+       case "${value}" in
+               enabled)
+                       return ${EXIT_TRUE}
+                       ;;
+               disabled)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_ap_isolation() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/ap_isolation)"
+       case "${value}" in
+               enabled)
+                       return ${EXIT_TRUE}
+                       ;;
+               disabled)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_bonding_mode() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/bonding)"
+       case "${value}" in
+               enabled)
+                       return ${EXIT_TRUE}
+                       ;;
+               disabled)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_distributed_arp_table() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/distributed_arp_table)"
+       case "${value}" in
+               enabled)
+                       return ${EXIT_TRUE}
+                       ;;
+               disabled)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_bridge_loop_avoidance() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/bridge_loop_avoidance)"
+       case "${value}" in
+               enabled)
+                       return ${EXIT_TRUE}
+                       ;;
+               disabled)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_fragmentation() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/fragmentation)"
+       case "${value}" in
+               enabled)
+                       return ${EXIT_TRUE}
+                       ;;
+               disabled)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_gateway_mode() {
+       local device=${1}
+       assert isset device
+
+       local value="$(fread ${SYS_CLASS_NET}/${device}/mesh/gw_mode)"
+       case "${value}" in
+               on)
+                       return ${EXIT_TRUE}
+                       ;;
+               off)
+                       return ${EXIT_FALSE}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function batman_adv_get_gateway_bandwidth() {
+       local device=${1}
+       assert isset device
+
+       fread "${SYS_CLASS_NET}/${device}/mesh/gw_bandwidth"
+}
+
+function batman_adv_get_gateway_selection_class() {
+       local device=${1}
+       assert isset device
+
+       fread "${SYS_CLASS_NET}/${device}/mesh/gw_sel_class"
+}
+
+function batman_adv_get_hop_penalty() {
+       local device=${1}
+       assert isset device
+
+       fread "${SYS_CLASS_NET}/${device}/mesh/hop_penalty"
+}
+
+function batman_adv_get_originator_interval() {
+       local device=${1}
+       assert isset device
+
+       fread "${SYS_CLASS_NET}/${device}/mesh/orig_interval"
+}
+
+function batman_adv_get_routing_algorithm() {
        local device=${1}
        assert isset device
 
-       cmd_quiet batctl interface del ${device}
+       fread "${SYS_CLASS_NET}/${device}/mesh/routing_algo"
 }
index c24c9e948bbaa932f948de836724b6accacbd8d7..2d35e6420354108c82f203f31033940360cf3337 100644 (file)
@@ -268,7 +268,7 @@ function cli_print_fmt1() {
        local level=${1}
        shift
 
-       local space=$(( 30 - (${level} * ${#IDENT}) ))
+       local space=$(( 34 - (${level} * ${#IDENT}) ))
        local format="%-${space}s %s"
 
        cli_print ${level} "${format}" "$@"
index b7c4c52ebad5b52fa3bf26250e54780b24887c41..21b44fcad413fb47250bafc20e15f565fccda768 100644 (file)
@@ -80,5 +80,6 @@ DEVICE_PRINT_LINE1="    %-24s %s\n"
 
 PORT_PATTERN="pN"
 PORT_PATTERN_ACCESSPOINT="apN"
-PORT_PATTERN_BATMANADV="bN"
+PORT_PATTERN_BATMAN_ADV="batN"
+PORT_PATTERN_BATMAN_ADV_PORT="batpN"
 PORT_PATTERN_WIRELESS="wN"
index 6de949e02038b5d9e69454b6655d008d5ae841c3..b15e15ec96d190df16074a89393b0d146f07eb2b 100644 (file)
@@ -146,6 +146,16 @@ function device_get_ifindex() {
        print "$(<${path})"
 }
 
+# Check if the device is a batman-adv bridge
+function device_is_batman_adv() {
+       [ -d "${SYS_CLASS_NET}/${1}/mesh" ]
+}
+
+# Check if the device is a batman-adv bridge port
+function device_is_batman_adv_port() {
+       [ -d "${SYS_CLASS_NET}/${1}/batman_adv" ]
+}
+
 # Check if the device is a bonding device
 function device_is_bonding() {
        [ -d "/sys/class/net/${1}/bonding" ]
@@ -165,7 +175,6 @@ function device_is_bridge() {
 
 function device_is_bridge_attached() {
        local device=${1}
-
        [ -d "${SYS_CLASS_NET}/${device}/brport" ]
 }
 
@@ -297,6 +306,12 @@ function device_get_type() {
        elif device_is_ppp ${device}; then
                echo "ppp"
 
+       elif device_is_batman_adv ${device}; then
+               echo "batman-adv"
+
+       elif device_is_batman_adv_port ${device}; then
+               echo "batman-adv-port"
+
        elif device_is_loopback ${device}; then
                echo "loopback"
 
index cdbf73355ad1eb2a0c868823b15fdc226c1bac2d..a2cb151e0a055883a1519b5dd1e3c32dc28fdb7a 100755 (executable)
 
 . /usr/lib/network/header-port
 
-HOOK_SETTINGS="HOOK ADDRESS MESH_ID SSID CHANNEL COUNTRY_CODE PHY"
+HOOK_SETTINGS="HOOK ADDRESS SLAVES"
 
-ADDRESS=$(mac_generate)
-CHANNEL=1
-COUNTRY_CODE="US"
-MESH_ID=
-SSID=
+PORT_CHILDREN_VAR="SLAVES"
 
-# batman-adv inserts an additional header of 28 bytes, so we set the MTU
-# to 1528, that normal ethernet packets with 1500 bytes can pass the network.
-MTU=1528
-MTU=1500
+ADDRESS=$(mac_generate)
+SLAVES=
 
 function _check() {
        assert isset ADDRESS
        assert ismac ADDRESS
-       assert isset CHANNEL
-       assert isset COUNTRY_CODE
-       assert isset MESH_ID
-       assert ismac MESH_ID
-       assert isset PHY
-       assert ismac PHY
-       assert isset SSID
 }
 
 function _create() {
        while [ $# -gt 0 ]; do
                case "${1}" in
                        --address=*)
-                               ADDRESS=$(cli_get_val ${1})
-                               ;;
-                       --channel=*)
-                               CHANNEL=$(cli_get_val ${1})
-                               ;;
-                       --country-code=*)
-                               COUNTRY_CODE=$(cli_get_val ${1})
-                               ;;
-                       --phy=*)
-                               PHY=$(cli_get_val ${1})
+                               ADDRESS="$(cli_get_val ${1})"
                                ;;
-                       --ssid=*)
-                               SSID=$(cli_get_val ${1})
-                               ;;
-                       --mesh-id=*)
-                               MESH_ID=$(cli_get_val ${1})
+                       --slaves=*)
+                               SLAVES="$(cli_get_val ${1})"
                                ;;
                        *)
                                warning "Ignoring unknown argument '${1}'"
@@ -74,11 +49,7 @@ function _create() {
                shift
        done
 
-       # Save address of phy do identify it again
-       PHY=$(phy_get ${PHY})
-       PHY=$(phy_get_address ${PHY})
-
-       local port=$(port_find_free ${PORT_PATTERN_BATMANADV})
+       local port=$(port_find_free ${PORT_PATTERN_BATMAN_ADV})
        assert isset port
 
        config_write $(port_file ${port}) ${HOOK_SETTINGS}
@@ -95,17 +66,21 @@ function _edit() {
 
        while [ $# -gt 0 ]; do
                case "${1}" in
-                       --channel=*)
-                               CHANNEL=$(cli_get_val ${1})
-                               ;;
-                       --country-code=*)
-                               COUNTRY_CODE=$(cli_get_val ${1})
+                       --address=*)
+                               ADDRESS="$(cli_get_val ${1})"
                                ;;
-                       --mesh-id=*)
-                               MESH_ID=$(cli_get_val ${1})
+                       --add-slave=*)
+                               SLAVES="${SLAVES} $(cli_get_val ${1})"
                                ;;
-                       --ssid=*)
-                               SSID=$(cli_get_val ${1})
+                       --del-slave=*)
+                               local slave="$(cli_get_val ${1})"
+
+                               local s slaves
+                               for s in ${SLAVES}; do
+                                       [ "${slave}" = "${s}" ] && continue
+                                       slaves="${slaves} ${s}"
+                               done
+                               SLAVES="${slaves}"
                                ;;
                        *)
                                warning "Unknown argument '${1}'"
@@ -125,30 +100,22 @@ function _up() {
 
        config_read $(port_file ${port})
 
-       # Check if the PHY is present.
-       local phy=$(phy_get ${PHY})
-       if ! isset phy; then
-               log DEBUG "phy '${PHY}' is not present"
-               exit ${EXIT_ERROR}
-       fi
-
-       # Create the wireless device, if it does not exist, yet.
-       if ! device_exists ${port}; then
-               wireless_create ${port} \
-                       --address="${ADDRESS}" \
-                       --phy="${phy}" \
-                       --type="ibss"
-       fi
+       # This cannot be started manually, but is created automatically
+       # when a slave device is brought up and set up by _hotplug.
 
-       # Set the MTU.
-       device_set_mtu "${port}" "${MTU}"
+       local slave
+       for slave in ${SLAVES}; do
+               port_up "${slave}"
+       done
 
-       # Join the ad-hoc network.
-       wireless_ibss_join "${port}" --channel="${CHANNEL}" \
-               --bssid="${MESH_ID}" --essid="${SSID}"
+       # If the port has been created (does not happen, when there are
+       # no slaves), we bring it up.
+       if device_exists "${port}"; then
+               # Set the address.
+               device_set_address "${port}" "${ADDRESS}"
 
-       # Add the device as a batman-adv device.
-       batman_adv_interface_add "${port}"
+               device_set_up "${port}"
+       fi
 
        exit ${EXIT_OK}
 }
@@ -157,16 +124,12 @@ function _down() {
        local port=${1}
        assert isset port
 
-       # Remove the batman-adv device.
-       batman_adv_interface_del "${port}"
-
-       # Leave the ad-hoc network.
-       wireless_ibss_leave "${port}"
+       config_read $(port_file ${port})
 
-       # Remove the device if it is still present.
-       if device_exists ${port}; then
-               wireless_remove ${port}
-       fi
+       local slave
+       for slave in ${SLAVES}; do
+               port_down "${slave}"
+       done
 
        exit ${EXIT_OK}
 }
@@ -178,22 +141,77 @@ function _hotplug() {
        local phy=${2}
        assert isset phy
 
-       assert port_exists ${port}
+       # Bring up the device.
+       port_up "${port}"
 
-       # Read configuration of port.
-       config_read $(port_file ${port})
+       exit ${EXIT_OK}
+}
+
+function _status() {
+       local port=${1}
+       assert isset port
+
+       cli_device_headline "${port}" --long
+
+       cli_headline 2 "B.A.T.M.A.N."
+
+       # Routing algorithm
+       cli_print_fmt1 2 "Routing Algorithm" \
+               "$(batman_adv_get_routing_algorithm "${port}")"
+
+       # Space
+       cli_space
+
+       # Originator interval
+       cli_print_fmt1 2 "Originator Interval" \
+               "$(batman_adv_get_originator_interval "${port}") ms"
+
+       # Aggregated originator messages
+       batman_adv_get_aggregated_ogms "${port}"
+       cli_print_fmt1 2 "Aggregated Originator Messages" "$(cli_print_bool $?)"
 
-       # Get the address of the phy.
-       local phy_address=$(phy_get_address ${phy})
+       # AP isolation
+       batman_adv_get_ap_isolation "${port}"
+       cli_print_fmt1 2 "Access Point Isolation" "$(cli_print_bool $?)"
 
-       # Check if the phy is the same we have
-       # read from the configuration file.
-       if [ "${PHY}" = "${phy_address}" ]; then
-               wireless_create ${port} \
-                       --address="${ADDRESS}" \
-                       --phy="${phy_address}" \
-                       --type="ibss"
+       # Bonding mode
+       batman_adv_get_bonding_mode "${port}"
+       cli_print_fmt1 2 "Bonding Mode" "$(cli_print_bool $?)"
+
+       # Bridge loop avoidance
+       batman_adv_get_bridge_loop_avoidance "${port}"
+       cli_print_fmt1 2 "Bridge Loop Avoidance" "$(cli_print_bool $?)"
+
+       # Distributed ARP table
+       batman_adv_get_distributed_arp_table "${port}"
+       cli_print_fmt1 2 "Distributed ARP Table" "$(cli_print_bool $?)"
+
+       # Fragmentation
+       batman_adv_get_fragmentation "${port}"
+       cli_print_fmt1 2 "Fragmentation" "$(cli_print_bool $?)"
+
+       # Hop penalty
+       cli_print_fmt1 2 "Hop Penalty" \
+               "$(batman_adv_get_hop_penalty "${port}")"
+       cli_space
+
+       # Gateway
+       cli_headline 3 "Gateway"
+
+       # Gateway mode
+       batman_adv_get_gateway_mode "${port}"
+       local gw_enabled=$?
+
+       cli_print_fmt1 3 "Enabled" "$(cli_print_bool ${gw_enabled})"
+
+       if [ ${gw_enabled} -eq ${EXIT_TRUE} ]; then
+               cli_print_fmt1 3 "Bandwidth" \
+                       "$(batman_adv_get_gateway_bandwidth "${port}")"
+               cli_print_fmt1 3 "Selection Class" \
+                       "$(batman_adv_get_gateway_selection_class "${port}")"
        fi
 
+       cli_space
+
        exit ${EXIT_OK}
 }
diff --git a/hooks/ports/batman-adv-port b/hooks/ports/batman-adv-port
new file mode 100755 (executable)
index 0000000..0d44ba3
--- /dev/null
@@ -0,0 +1,221 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2013 Michael Tremer                                           #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+. /usr/lib/network/header-port
+
+HOOK_SETTINGS="HOOK ADDRESS MESH_ID SSID CHANNEL COUNTRY_CODE PHY"
+
+ADDRESS=$(mac_generate)
+CHANNEL=1
+COUNTRY_CODE="US"
+MESH_ID=
+SSID=
+
+# batman-adv inserts an additional header of 28 bytes, so we set the MTU
+# to 1528, that normal ethernet packets with 1500 bytes can pass the network.
+MTU=1528
+
+function _check() {
+       assert isset ADDRESS
+       assert ismac ADDRESS
+       assert isset CHANNEL
+       assert isset COUNTRY_CODE
+       assert isset MESH_ID
+       assert ismac MESH_ID
+       assert isset PHY
+       assert ismac PHY
+       assert isset SSID
+}
+
+function _create() {
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --address=*)
+                               ADDRESS=$(cli_get_val ${1})
+                               ;;
+                       --channel=*)
+                               CHANNEL=$(cli_get_val ${1})
+                               ;;
+                       --country-code=*)
+                               COUNTRY_CODE=$(cli_get_val ${1})
+                               ;;
+                       --phy=*)
+                               PHY=$(cli_get_val ${1})
+                               ;;
+                       --ssid=*)
+                               SSID=$(cli_get_val ${1})
+                               ;;
+                       --mesh-id=*)
+                               MESH_ID=$(cli_get_val ${1})
+                               ;;
+                       *)
+                               warning "Ignoring unknown argument '${1}'"
+                               ;;
+               esac
+               shift
+       done
+
+       # Save address of phy do identify it again
+       PHY=$(phy_get ${PHY})
+       PHY=$(phy_get_address ${PHY})
+
+       local port=$(port_find_free ${PORT_PATTERN_BATMAN_ADV_PORT})
+       assert isset port
+
+       config_write $(port_file ${port}) ${HOOK_SETTINGS}
+
+       exit ${EXIT_OK}
+}
+
+function _edit() {
+       local port=${1}
+       assert isset port
+       shift
+
+       config_read $(port_file ${port})
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --channel=*)
+                               CHANNEL=$(cli_get_val ${1})
+                               ;;
+                       --country-code=*)
+                               COUNTRY_CODE=$(cli_get_val ${1})
+                               ;;
+                       --mesh-id=*)
+                               MESH_ID=$(cli_get_val ${1})
+                               ;;
+                       --ssid=*)
+                               SSID=$(cli_get_val ${1})
+                               ;;
+                       *)
+                               warning "Unknown argument '${1}'"
+                               ;;
+               esac
+               shift
+       done
+
+       config_write $(port_file ${port}) ${HOOK_SETTINGS}
+
+       exit ${EXIT_OK}
+}
+
+function _up() {
+       local port=${1}
+       assert isset port
+
+       config_read $(port_file ${port})
+
+       # Check if the PHY is present.
+       local phy=$(phy_get ${PHY})
+       if ! isset phy; then
+               log DEBUG "phy '${PHY}' is not present"
+               exit ${EXIT_ERROR}
+       fi
+
+       # Create the wireless device, if it does not exist, yet.
+       if ! device_exists ${port}; then
+               wireless_create ${port} \
+                       --address="${ADDRESS}" \
+                       --phy="${phy}" \
+                       --type="ibss"
+       fi
+
+       # Set the MTU.
+       device_set_mtu "${port}" "${MTU}"
+
+       # Join the ad-hoc network.
+       wireless_ibss_join "${port}" --channel="${CHANNEL}" \
+               --bssid="${MESH_ID}" --essid="${SSID}"
+
+       # Add the device as a batman-adv device.
+       local parent="$(_find_parent ${port})"
+       if isset parent; then
+               batman_adv_interface_add "${parent}" "${port}"
+       fi
+
+       exit ${EXIT_OK}
+}
+
+function _down() {
+       local port=${1}
+       assert isset port
+
+       # Remove the batman-adv device.
+       batman_adv_interface_del "${port}"
+
+       # Leave the ad-hoc network.
+       wireless_ibss_leave "${port}"
+
+       # Remove the device if it is still present.
+       if device_exists ${port}; then
+               wireless_remove ${port}
+       fi
+
+       exit ${EXIT_OK}
+}
+
+function _hotplug() {
+       local port=${1}
+       assert isset port
+
+       local phy=${2}
+       assert isset phy
+
+       assert port_exists ${port}
+
+       # Read configuration of port.
+       config_read $(port_file ${port})
+
+       # Get the address of the phy.
+       local phy_address=$(phy_get_address ${phy})
+
+       # Check if the phy is the same we have
+       # read from the configuration file.
+       if [ "${PHY}" = "${phy_address}" ]; then
+               # Bring up the device.
+               port_up "${port}"
+       fi
+
+       exit ${EXIT_OK}
+}
+
+function _find_parent() {
+       local port=${1}
+       assert isset port
+
+       local p child hook
+       for p in $(ports_get); do
+               hook=$(port_get_hook "${p}")
+
+               if [ "${hook}" = "batman-adv" ]; then
+                       for child in $(port_get_children "${p}"); do
+                               log ERROR "child=${child}"
+                               [ "${child}" = "${port}" ] || continue
+
+                               print "${p}"
+                               return ${EXIT_OK}
+                       done
+               fi
+       done
+
+       return ${EXIT_ERROR}
+}
diff --git a/hooks/zones/bridge.ports/batman-adv b/hooks/zones/bridge.ports/batman-adv
new file mode 120000 (symlink)
index 0000000..3857774
--- /dev/null
@@ -0,0 +1 @@
+ethernet
\ No newline at end of file
index 063d33fb656379cbdca519f7cd16458f3857782e..f469e6ce5e6bb8dfd5a89430f83e5b1544e74a8e 100755 (executable)
@@ -55,8 +55,8 @@ case "${ACTION}" in
                                        port_create ethernet ${INTERFACE}
                                        ;;
 
-                               # Handle wireless devices.
-                               wireless)
+                               # Handle batman-adv and wireless devices.
+                               batman-adv|batman-adv-port|wireless)
                                        # Save the phy of this device for later.
                                        phy=$(phy_get ${INTERFACE})
                                        assert isset phy