]> git.ipfire.org Git - network.git/commitdiff
network: Updated stp framework.
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 29 Jul 2010 12:43:26 +0000 (14:43 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 29 Jul 2010 12:43:26 +0000 (14:43 +0200)
Add support for 802.1d.

functions.constants
functions.stp
functions.util
hooks/zones/bridge
hooks/zones/bridge.ports/ethernet

index 4dd919831a3eaaf5be6d3f295cfb6d6398ef027b..efca1467216c7a5528c9227f6e0bf33743183894 100644 (file)
@@ -69,4 +69,4 @@ SYS_CLASS_NET="/sys/class/net"
 # Timeout values
 TIMEOUT_RESTART=2
 
-DEVICE_PRINT_LINE1="    %-20s %s\n"
+DEVICE_PRINT_LINE1="    %-24s %s\n"
index a85138f75c8ec67e9943acd38c67f17def5b12db..ba906baca98ac008dac5f67f8aaf55fddf9cda91 100644 (file)
@@ -28,40 +28,19 @@ function stp_init() {
 
 init_register stp_init
 
-# XXX Very slow thing, caching?
-function __rstpctl_cmd() {
-       local command=$@
+function __rstpctl_bridge_get() {
+       local bridge=${1}
+       local param=${2}
+
+       assert isset bridge
+       assert isset param
 
-       local line
        local key
        local val
-
-       rstpctl ${command} | \
-               sed -e "s/\t\t\t/\n/g" \
-                       -e "s/^ //g" \
-                       -e "s/\t\s*/___/g" | \
-       while read line; do
-               [ "${line}" = "${line/___/_}" ] && continue
-
-               key=${line%%___*}
-               key=${key// /_}
-               key=${key^^}
-
-               val=${line#*___}
-
-               echo "${key}=\"${val}\""
-       done
-}
-
-function __rstpctl_showbridge_get() {
-       local bridge=${1}
-       local param=${2^^}
-
-       local line
-       for line in $(__rstpctl_cmd showbridge ${bridge}); do
-               if [ "${line%%=*}" = "${param}" ]; then
-                       line="${line##*=}"
-                       echo "${line//\"/}"
+       rstpctl dumpbridge ${bridge} | \
+               while read bridge key val; do
+               if [ "${key}" = "${param}" ]; then
+                       echo "${val}"
                        return ${EXIT_OK}
                fi
        done
@@ -69,16 +48,21 @@ function __rstpctl_showbridge_get() {
        return ${EXIT_ERROR}
 }
 
-function __rstpctl_showportdetail_get() {
+function __rstpctl_port_get() {
        local bridge=${1}
        local port=${2}
-       local param=${3^^}
+       local param=${3}
 
-       local line
-       for line in $(__rstpctl_cmd showportdetail ${bridge} ${port}); do
-               if [ "${line%%=*}" = "${param}" ]; then
-                       line="${line##*=}"
-                       echo "${line//\"/}"
+       assert isset bridge
+       assert isset port
+       assert isset param
+
+       local key
+       local val
+       rstpctl dumpports ${bridge} | \
+               while read por key val; do
+               if [ "${port}" = "${por}" -a "${key}" = "${param}" ]; then
+                       echo "${val}"
                        return ${EXIT_OK}
                fi
        done
@@ -86,213 +70,399 @@ function __rstpctl_showportdetail_get() {
        return ${EXIT_ERROR}
 }
 
-function __rstp_port_enabled() {
+function stp_enable() {
        local bridge=${1}
-       local port=${2}
 
-       local status=$(__rstpctl_showportdetail_get ${bridge} ${port} enabled)
+       assert isset bridge
+       assert zone_exists ${bridge}
 
-       if [ "${status}" = "yes" ]; then
-               return ${EXIT_OK}
-       fi
+       brctl stp ${bridge} on
 
-       return ${EXIT_ERROR}
+       local mode=$(zone_config_get ${bridge} STP_MODE)
+
+       case "${mode}" in
+               stp)
+                       rstpctl setforcevers ${bridge} slow
+                       ;;
+               rstp)
+                       rstpctl setforcevers ${bridge} normal
+                       ;;
+               *)
+                       error_log "Unknown protocol version: ${mode}."
+                       ;;
+       esac
 }
 
-function __rstp_port_state() {
+function stp_disable() {
        local bridge=${1}
-       local port=${2}
 
-       local output=$(__rstpctl_showportdetail_get ${bridge} ${port} state)
-       echo "${output^^}"
+       assert isset bridge
+       assert zone_exists ${bridge}
+
+       brctl stp ${bridge} off
 }
 
-function __rstp_port_pathcost() {
+function stp_bridge_get_protocol() {
        local bridge=${1}
-       local port=${2}
 
-       __rstpctl_showportdetail_get ${bridge} ${port} path_cost
+       assert isset bridge
+
+       local mode=$(__rstpctl_bridge_get ${bridge} protocol_version)
+
+       case "${mode}" in
+               0)
+                       echo "stp"
+                       ;;
+               2)
+                       echo "rstp"
+                       ;;              
+       esac
 }
 
-function __rstp_port_designated_root() {
+function stp_bridge_set_protocol() {
+       : XXX WANTED
+}
+
+function stp_bridge_get_id() {
        local bridge=${1}
-       local port=${2}
 
-       __rstpctl_showportdetail_get ${bridge} ${port} designated_root
+       assert isset bridge
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "id"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/bridge_id"
+                       return ${EXIT_OK}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
 }
 
-function __rstp_port_designated_bridge() {
+function stp_bridge_get_forward_delay() {
        local bridge=${1}
-       local port=${2}
 
-       __rstpctl_showportdetail_get ${bridge} ${port} designated_bridge
+       assert isset bridge
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "bridge_forward_delay"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/forward_delay"
+                       return ${EXIT_OK}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
 }
 
-function __rstp_topology_change() {
+function stp_bridge_get_hello_time() {
        local bridge=${1}
 
-       local state=$(__rstpctl_showbridge_get ${bridge} topology_change)
+       assert isset bridge
 
-       case "${state}" in
-               yes)
-                       echo "${state}"
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "bridge_hello_time"
                        return ${EXIT_OK}
                        ;;
-               no)
-                       echo "${state}"
-                       return ${EXIT_ERROR}
+               stp)
+                       __device_get_file ${bridge} "bridge/hello_time"
+                       return ${EXIT_OK}
                        ;;
        esac
+
+       return ${EXIT_ERROR}
 }
 
-function __rstp_topology_change_count() {
+function stp_bridge_get_max_age() {
        local bridge=${1}
 
-       # XXX typo in rstpctl -> toplogy
-       __rstpctl_showbridge_get ${bridge} toplogy_change_count
+       assert isset bridge
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "bridge_max_age"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/max_age"
+                       return ${EXIT_OK}
+                       ;;
+       esac
+
+       return ${EXIT_ERROR}
 }
 
-function __rstp_topology_change_time() {
+function stp_bridge_get_designated_root() {
        local bridge=${1}
+       local output
+
+       assert isset bridge
 
-       __rstpctl_showbridge_get ${bridge} time_since_topology_change
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       output=$(__rstpctl_bridge_get ${bridge} "designated_root")
+                       ;;
+               stp)
+                       output=$(__device_get_file ${bridge} "bridge/root_id")
+                       ;;
+       esac
+
+       if ! isset output; then
+               return ${EXIT_ERROR}
+       fi
+
+       mac_format "${output:5:12}"
+
+       return ${EXIT_OK}
 }
 
-function __rstp_bridge_id() {
+function stp_bridge_get_root_path_cost() {
        local bridge=${1}
 
-       local id=$(__rstpctl_showbridge_get ${bridge} bridge_id)
-       id=${id:5:12}
+       assert isset bridge
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "root_path_cost"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/root_path_cost"
+                       return ${EXIT_OK}
+                       ;;
+       esac
 
-       mac_format "${id}"
+       return ${EXIT_ERROR}
 }
 
-function __rstp_designated_root() {
+function stp_bridge_get_root_port_id() {
        local bridge=${1}
 
-       local root=$(__rstpctl_showbridge_get ${bridge} designated_root)
-       root=${root:5:12}
+       assert isset bridge
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "root_port"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/root_port"
+                       return ${EXIT_OK}
+                       ;;
+       esac
 
-       mac_format "${root}"
+       return ${EXIT_ERROR}
 }
 
-function __rstp_pathcost() {
+function stp_bridge_get_root_port() {
        local bridge=${1}
 
-       __rstpctl_showbridge_get ${bridge} path_cost
-}
+       assert isset bridge
 
-function __stp_port_enabled() {
-       : # XXX TBD
-}
+       local id=$(stp_bridge_get_root_port_id ${bridge})
 
-function __stp_port_state() {
-       : # XXX TBD
-}
+       local member
+       local member_id
+       for member in $(bridge_get_members ${bridge}); do
+               member_id=$(stp_port_get_id ${bridge} ${member})
 
-function __stp_port_pathcost() {
-       : # XXX TBD
-}
+               if [ "${id}" = "${member_id}" ]; then
+                       echo "${member}"
+                       return ${EXIT_OK}
+               fi
+       done
 
-function __stp_port_designated_root() {
-       : # XXX TBD
+       return ${EXIT_ERROR}
 }
 
-function __stp_port_designated_bridge() {
-       : # XXX TBD
-}
+function stp_bridge_is_root() {
+       local bridge=${1}
 
-function stp_port_enabled() {
-       __stp_wrapper port_enabled $@
-}
+       assert isset bridge
 
-function stp_port_state() {
-       __stp_wrapper port_state $@
+       [ -n "$(stp_bridge_get_root_port ${bridge})" ]
 }
 
-function stp_port_pathcost() {
-       __stp_wrapper port_pathcost $@
-}
+function stp_bridge_get_priority() {
+       local bridge=${1}
 
-function stp_port_designated_root() {
-       local root=$(__stp_wrapper port_designated_root $@)
+       assert isset bridge
 
-       # Cut prefix 8000. and format mac
-       root="${root:5:12}"
-       mac_format "${root}"
-}
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       local output=$(__rstpctl_bridge_get ${bridge} "root_path_cost")
+                       dec "${output:0:4}"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/priority"
+                       return ${EXIT_OK}
+                       ;;
+       esac
 
-function stp_port_designated_bridge() {
-       __stp_wrapper port_designated_bridge $@
+       return ${EXIT_ERROR}
 }
 
-function stp_topology_change() {
-       __stp_wrapper topology_change $@
-}
+function stp_bridge_get_topology_change_count() {
+       local bridge=${1}
 
-function stp_topology_change_count() {
-       __stp_wrapper topology_change_count $@
-}
+       assert isset bridge
 
-function stp_topology_change_time() {
-       __stp_wrapper topology_change_time $@
-}
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "topology_change_count"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/topology_change"
+                       return ${EXIT_OK}
+                       ;;
+       esac
 
-function stp_bridge_id() {
-       __stp_wrapper bridge_id $@
+       return ${EXIT_ERROR}
 }
 
-function stp_designated_root() {
-       __stp_wrapper designated_root $@
-}
+function stp_bridge_get_topology_change_timer() {
+       local bridge=${1}
+
+       assert isset bridge
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "time_since_topology_change"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/topology_change_timer"
+                       return ${EXIT_OK}
+                       ;;
+       esac
 
-function stp_pathcost() {
-       __stp_wrapper pathcost $@
+       return ${EXIT_ERROR}
 }
 
-function __stp_wrapper() {
-       local func=${1}
-       shift
+function stp_bridge_get_topology_change_detected() {
+       local bridge=${1}
 
-       # XXX we will detect what kind of protocol the
-       # bridge is running and process the correct funtions
-       local proto_version="rstp"
+       assert isset bridge
 
-       __${proto_version}_${func} $@
-}
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_bridge_get ${bridge} "topology_change"
+                       return ${EXIT_OK}
+                       ;;
+               stp)
+                       __device_get_file ${bridge} "bridge/topology_change_detected"
+                       return ${EXIT_OK}
+                       ;;
+       esac
 
-function stp_mode() {
-       : # XXX wanted
+       return ${EXIT_ERROR}
 }
 
-function stp_enable() {
+# STP states
+STP_STATE[0]="disabled"
+STP_STATE[1]="listening"
+STP_STATE[2]="learning"
+STP_STATE[3]="forwarding"
+STP_STATE[4]="blocking"
+
+function stp_port_get_state() {
        local bridge=${1}
+       local port=${2}
+       local output
 
        assert isset bridge
-       assert zone_exists ${bridge}
+       assert isset port
 
-       brctl stp ${bridge} on
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       output=$(__rstpctl_port_get ${bridge} ${port} "state")
+                       ;;
+               stp)
+                       output=$(__device_get_file ${bridge} "brif/${port}/state")
 
-       local mode=$(zone_config_get ${bridge} STP_MODE)
+                       # Translate int to name
+                       output="${STP_STATE[${output}]}"
+                       ;;
+       esac
 
-       case "${mode}" in
+       if ! isset output; then
+               return ${EXIT_ERROR}
+       fi
+
+       echo "${output^^}"
+
+       return ${EXIT_OK}
+}
+
+function stp_port_get_id() {
+       local bridge=${1}
+       local port=${2}
+
+       assert isset bridge
+       assert isset port
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       __rstpctl_port_get ${bridge} ${port} "id"
+                       return ${EXIT_OK}
+                       ;;
                stp)
-                       rstpctl setforcevers ${bridge} slow
+                       dec $(__device_get_file ${bridge} "brif/${port}/port_no")
+                       return ${EXIT_OK}
                        ;;
+       esac
+
+       return ${EXIT_ERROR}
+}
+
+function stp_port_get_cost() {
+       local bridge=${1}
+       local port=${2}
+
+       assert isset bridge
+       assert isset port
+
+       case "$(stp_bridge_get_protocol ${bridge})" in
                rstp)
-                       rstpctl setforcevers ${bridge} normal
+                       __rstpctl_port_get ${bridge} ${port} "path_cost"
+                       return ${EXIT_OK}
                        ;;
-               *)
-                       error_log "Unknown protocol version: ${mode}."
+               stp)
+                       __device_get_file ${bridge} "brif/${port}/path_cost"
+                       return ${EXIT_OK}
                        ;;
        esac
+
+       return ${EXIT_ERROR}
 }
 
-function stp_disable() {
+function stp_port_get_designated_root() {
        local bridge=${1}
+       local port=${2}
+       local output
 
        assert isset bridge
-       assert zone_exists ${bridge}
+       assert isset port
 
-       brctl stp ${bridge} off
+       case "$(stp_bridge_get_protocol ${bridge})" in
+               rstp)
+                       output=$(__rstpctl_port_get ${bridge} ${port} "designated_root")
+                       ;;
+               stp)
+                       output=$(__device_get_file ${bridge} "brif/${port}/designated_root")
+                       ;;
+       esac
+
+       mac_format ${output:5:12}
+
+       return ${EXIT_ERROR}
 }
index 104316ff744a165f8d83273bf73ebabfe34ec36f..8b207870c8b5f4786800063bec578555eb1ce3b5 100644 (file)
@@ -405,3 +405,13 @@ function process_kill() {
                done
        done
 }
+
+function dec() {
+       local hex=${1}
+
+       if [ "${hex:0:2}" != "0x" ]; then
+               hex="0x${hex}"
+       fi
+
+       printf "%d\n" "${hex}"
+}
index 701d3abd15e6044b4bbd70f1f676e5f7a1029c16..022ca65486bf63e17ad3f60352a3d8022b687755 100755 (executable)
@@ -157,21 +157,27 @@ function _status() {
        # XXX Add bridge stp priority here
        # brctl does not give any information about that
 
-       cli_headline "    Spanning Tree Protocol information:"
-       echo   "        Bridge ID             : $(stp_bridge_id ${zone})"
-       echo   "        Designated root       : $(stp_designated_root ${zone})"
-       echo   "        Path cost             : $(stp_pathcost ${zone})"
+       cli_headline "  Spanning Tree Protocol information:"
+       printf "${DEVICE_PRINT_LINE1}" "ID:" $(stp_bridge_get_id ${zone})
+       printf "${DEVICE_PRINT_LINE1}" "Priority:" $(stp_bridge_get_priority ${zone})
+
+       if stp_bridge_is_root ${zone}; then
+               echo -e "    ${COLOUR_BOLD}This bridge is root.${COLOUR_NORMAL}"
+       else
+               printf "${DEVICE_PRINT_LINE1}" "Designated root:" $(stp_bridge_get_designated_root ${zone})
+               printf "${DEVICE_PRINT_LINE1}" "Root path cost:" $(stp_bridge_get_root_path_cost ${zone})
+       fi
        echo # Empty line
 
        # Topology information
-       printf "        Topology changing     : %6s\n" $(stp_topology_change ${zone})
-       printf "        Topology change time  : %6s\n" $(beautify_time $(stp_topology_change_time ${zone}))
-       printf "        Topology change count : %6s\n" $(stp_topology_change_count ${zone})
+       printf "${DEVICE_PRINT_LINE1}" "Topology changing:" $(stp_bridge_get_topology_change_detected ${zone})
+       printf "${DEVICE_PRINT_LINE1}" "Topology change time:" $(beautify_time $(stp_bridge_get_topology_change_timer ${zone}))
+       printf "${DEVICE_PRINT_LINE1}" "Topology change count:" $(stp_bridge_get_topology_change_count ${zone})
 
-       cli_headline "    Ports:"
+       cli_headline "  Ports:"
        zone_ports_status ${zone}
 
-       cli_headline "    Configurations:"
+       cli_headline "  Configurations:"
        zone_configs_cmd status ${zone}
 
        echo # Empty line
index f7dd5064a9c78385af4cfbecd563a83d95b9e718..c249e1787ca90e09ab62c93d368cb516c5731e62 100755 (executable)
@@ -139,12 +139,12 @@ function _status() {
        if ! device_is_up ${port}; then
                echo -ne "${COLOUR_DOWN}   DOWN   ${COLOUR_NORMAL}"
        else
-               local state=$(stp_port_state ${zone} ${port})
+               local state=$(stp_port_get_state ${zone} ${port})
                local colour="COLOUR_STP_${state}"
                printf "${!colour}%10s${COLOUR_NORMAL}" ${state}
 
-               echo -n " - DSR: $(stp_port_designated_root ${zone} ${port})"
-               echo -n " - Cost: $(stp_port_pathcost ${zone} ${port})"
+               echo -n " - DSR: $(stp_port_get_designated_root ${zone} ${port})"
+               echo -n " - Cost: $(stp_port_get_cost ${zone} ${port})"
        fi
 
        echo