From d7ca8e25c239adadb43ab46a196d798c39e00d1e Mon Sep 17 00:00:00 2001 From: syrinx Date: Thu, 7 Dec 2006 22:36:17 +0000 Subject: Add support for RSTP (RFC4318) to the SNMP bridge monitoring module. Approved by: bz (mentor) --- .../modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt | 191 +++++++++++- usr.sbin/bsnmpd/modules/snmp_bridge/Makefile | 2 +- usr.sbin/bsnmpd/modules/snmp_bridge/RSTP-MIB.txt | 325 +++++++++++++++++++++ usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c | 77 ++++- usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c | 255 +++++++++++++++- usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c | 10 +- usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h | 45 +++ usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c | 263 +++++++++++++++-- .../bsnmpd/modules/snmp_bridge/bridge_tree.def | 40 +++ usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 | 9 +- 10 files changed, 1170 insertions(+), 47 deletions(-) create mode 100644 usr.sbin/bsnmpd/modules/snmp_bridge/RSTP-MIB.txt (limited to 'usr.sbin/bsnmpd') diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt b/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt index fdba57b..4de407c 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/BEGEMOT-BRIDGE-MIB.txt @@ -41,7 +41,7 @@ IMPORTS FROM BEGEMOT-MIB; begemotBridge MODULE-IDENTITY - LAST-UPDATED "200608100000Z" + LAST-UPDATED "200611210000Z" ORGANIZATION "Sofia University St. Kliment Ohridski" CONTACT-INFO " Shteryana Shopova @@ -56,7 +56,13 @@ begemotBridge MODULE-IDENTITY E-Mail: syrinx@FreeBSD.org" DESCRIPTION "The Begemot MIB for managing bridge interfaces." - + REVISION "200611210000Z" + DESCRIPTION + "Second revision adds support for monitoring RSTP + specific variables." + REVISION "200607270000Z" + DESCRIPTION + "Initial revision." ::= { begemot 205 } -- ---------------------------------------------------------- -- @@ -303,7 +309,9 @@ BegemotBridgeStpEntry ::= SEQUENCE { begemotBridgeStpForwardDelay Timeout, begemotBridgeStpBridgeMaxAge Timeout, begemotBridgeStpBridgeHelloTime Timeout, - begemotBridgeStpBridgeForwardDelay Timeout + begemotBridgeStpBridgeForwardDelay Timeout, + begemotBridgeStpVersion INTEGER, + begemotBridgeStpTxHoldCount Integer32 } begemotBridgeStpProtocolSpecification OBJECT-TYPE @@ -466,6 +474,41 @@ begemotBridgeStpBridgeForwardDelay OBJECT-TYPE bridge was the root of the spanning tree." ::= { begemotBridgeStpEntry 14 } +begemotBridgeStpVersion OBJECT-TYPE + SYNTAX INTEGER { + stpCompatible(0), + rstp(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The version of Spanning Tree Protocol the bridge is + currently running. The value 'stpCompatible(0)' + indicates the Spanning Tree Protocol specified in + IEEE 802.1D-1998 and 'rstp(2)' indicates the Rapid + Spanning Tree Protocol specified in IEEE 802.1w and + clause 17 of 802.1D-2004. The values are directly from + the IEEE standard. New values may be defined as future + versions of the protocol become available. + + The value of this object MUST be retained across + reinitializations of the management system." + DEFVAL { rstp } + ::= { begemotBridgeStpEntry 15 } + +begemotBridgeStpTxHoldCount OBJECT-TYPE + SYNTAX Integer32 (1..10) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value used by the Port Transmit state machine to limit + the maximum transmission rate of BPDUs on the bridge interface. + + The value of this object MUST be retained across + reinitializations of the management system." + DEFVAL { 3 } + ::= { begemotBridgeStpEntry 16 } + -- ---------------------------------------------------------- -- -- the Bridge STP ports table -- ---------------------------------------------------------- -- @@ -620,6 +663,148 @@ begemotBridgeStpPortForwardTransitions OBJECT-TYPE ::= { begemotBridgeStpPortEntry 10 } -- ---------------------------------------------------------- -- +-- the Bridge STP extended ports table +-- ---------------------------------------------------------- -- + +begemotBridgeStpExtPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotBridgeStpExtPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains port-specific Rapid Spanning Tree + information for the bridge interface members." + ::= { begemotBridgeStp 3 } + +begemotBridgeStpExtPortEntry OBJECT-TYPE + SYNTAX BegemotBridgeStpExtPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of Rapid Spanning Tree information maintained by + each bridge interface member." + AUGMENTS { begemotBridgeStpPortEntry } + ::= { begemotBridgeStpExtPortTable 1 } + +BegemotBridgeStpExtPortEntry ::= SEQUENCE { + begemotBridgeStpPortProtocolMigration TruthValue, + begemotBridgeStpPortAdminEdgePort TruthValue, + begemotBridgeStpPortOperEdgePort TruthValue, + begemotBridgeStpPortAdminPointToPoint INTEGER, + begemotBridgeStpPortOperPointToPoint TruthValue, + begemotBridgeStpPortAdminPathCost Integer32 +} + +begemotBridgeStpPortProtocolMigration OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "When operating in RSTP (version 2) mode, writing true(1) + to this object forces this port to transmit RSTP BPDUs. + Any other operation on this object has no effect and + it always returns false(2) when read." + ::= { begemotBridgeStpExtPortEntry 1 } + +begemotBridgeStpPortAdminEdgePort OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administrative value of the Edge Port parameter. A + value of true(1) indicates that this port should be + assumed as an edge-port, and a value of false(2) indicates + that this port should be assumed as a non-edge-port. + Setting this object will also cause the corresponding + instance of begemotBridgeStpPortOperEdgePort to change to + the same value. Note that even when this object's value + is true, the value of the corresponding instance of + begemotBridgeStpPortOperEdgePort can be false if a BPDU + has been received. + + The value of this object MUST be retained across + reinitializations of the management system." + ::= { begemotBridgeStpExtPortEntry 2 } + +begemotBridgeStpPortOperEdgePort OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The operational value of the Edge Port parameter. The + object is initialized to the value of the corresponding + instance of begemotBridgeStpPortAdminEdgePort. When the + corresponding instance of begemotBridgeStpPortAdminEdgePort + is set, this object will be changed as well. This object + will also be changed to false on reception of a BPDU." + ::= { begemotBridgeStpExtPortEntry 3 } + +begemotBridgeStpPortAdminPointToPoint OBJECT-TYPE + SYNTAX INTEGER { + forceTrue(0), + forceFalse(1), + auto(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administrative point-to-point status of the LAN segment + attached to this port, using the enumeration values of the + IEEE 802.1w clause. A value of forceTrue(0) indicates + that this port should always be treated as if it is + connected to a point-to-point link. A value of + forceFalse(1) indicates that this port should be treated as + having a shared media connection. A value of auto(2) + indicates that this port is considered to have a + point-to-point link if it is an Aggregator and all of its + members are aggregatable, or if the MAC entity + is configured for full duplex operation, either through + auto-negotiation or by management means. Manipulating this + object changes the underlying adminPortToPortMAC. + + The value of this object MUST be retained across + reinitializations of the management system." + ::= { begemotBridgeStpExtPortEntry 4 } + +begemotBridgeStpPortOperPointToPoint OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The operational point-to-point status of the LAN segment + attached to this port. It indicates whether a port is + considered to have a point-to-point connection. + If adminPointToPointMAC is set to auto(2), then the value + of operPointToPointMAC is determined in accordance with the + specific procedures defined for the MAC entity concerned, + as defined in IEEE 802.1w, clause 6.5. The value is + determined dynamically; that is, it is re-evaluated whenever + the value of adminPointToPointMAC changes, and whenever + the specific procedures defined for the MAC entity evaluates + a change in its point-to-point status." + ::= { begemotBridgeStpExtPortEntry 5 } + +begemotBridgeStpPortAdminPathCost OBJECT-TYPE + SYNTAX Integer32 (0..200000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administratively assigned value for the contribution + of this port to the path cost of paths toward the spanning + tree root. + + Writing a value of '0' assigns the automatically calculated + default Path Cost value to the port. If the default Path + Cost is being used, this object returns '0' when read. + + This complements the object begemotBridgeStpPortPathCost or + begemotBridgeStpPortPathCost32, which returns the operational + value of the path cost. + + The value of this object MUST be retained across + reinitializations of the management system." + ::= { begemotBridgeStpExtPortEntry 6 } + +-- ---------------------------------------------------------- -- -- the Bridge interface Transparent bridging table -- ---------------------------------------------------------- -- diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile b/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile index 873151c..5d0afec 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/Makefile @@ -12,7 +12,7 @@ XSYM= dot1dBridge newRoot topologyChange begemotBridgeNewRoot \ MAN= snmp_bridge.3 -BMIBS= BRIDGE-MIB.txt BEGEMOT-BRIDGE-MIB.txt +BMIBS= BRIDGE-MIB.txt BEGEMOT-BRIDGE-MIB.txt RSTP-MIB.txt DEFS= ${MOD}_tree.def INCS= ${MOD}_snmp.h diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/RSTP-MIB.txt b/usr.sbin/bsnmpd/modules/snmp_bridge/RSTP-MIB.txt new file mode 100644 index 0000000..ea6648e --- /dev/null +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/RSTP-MIB.txt @@ -0,0 +1,325 @@ +-- +-- Copyright (C) The Internet Society (2005). +-- +-- This document is subject to the rights, licenses and restrictions +-- contained in BCP 78, and except as set forth therein, the authors +-- retain all their rights. +-- +-- This document and the information contained herein are provided on an +-- "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS +-- OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET +-- ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, +-- INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE +-- INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED +-- WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +-- +-- $FreeBSD$ +-- + +RSTP-MIB DEFINITIONS ::= BEGIN + +-- ------------------------------------------------------------- +-- MIB for IEEE 802.1w Rapid Spanning Tree Protocol +-- ------------------------------------------------------------- + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Integer32, mib-2 + FROM SNMPv2-SMI + TruthValue + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF + dot1dStp, dot1dStpPortEntry + FROM BRIDGE-MIB; + +rstpMIB MODULE-IDENTITY + LAST-UPDATED "200512070000Z" + ORGANIZATION "IETF Bridge MIB Working Group" + CONTACT-INFO + "Email: Bridge-mib@ietf.org" + DESCRIPTION + "The Bridge MIB Extension module for managing devices + that support the Rapid Spanning Tree Protocol defined + by IEEE 802.1w. + + Copyright (C) The Internet Society (2005). This version of + this MIB module is part of RFC 4318; See the RFC itself for + full legal notices." + + REVISION "200512070000Z" + DESCRIPTION + "The initial version of this MIB module as published in + RFC 4318." + ::= { mib-2 134 } + +-- ---------------------------------------------------------- -- +-- subtrees in the RSTP-MIB +-- ---------------------------------------------------------- -- + +rstpNotifications OBJECT IDENTIFIER ::= { rstpMIB 0 } +rstpObjects OBJECT IDENTIFIER ::= { rstpMIB 1 } +rstpConformance OBJECT IDENTIFIER ::= { rstpMIB 2 } + +-- ------------------------------------------------------------- +-- Addition to the dot1dStp group +-- ------------------------------------------------------------- + +dot1dStpVersion OBJECT-TYPE + SYNTAX INTEGER { + stpCompatible(0), + rstp(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The version of Spanning Tree Protocol the bridge is + currently running. The value 'stpCompatible(0)' + indicates the Spanning Tree Protocol specified in + IEEE 802.1D-1998 and 'rstp(2)' indicates the Rapid + Spanning Tree Protocol specified in IEEE 802.1w and + clause 17 of 802.1D-2004. The values are directly from + the IEEE standard. New values may be defined as future + versions of the protocol become available. + + The value of this object MUST be retained across + reinitializations of the management system." + REFERENCE + "IEEE 802.1w clause 14.8.1, 17.12, 17.16.1" + DEFVAL { rstp } + ::= { dot1dStp 16 } + +dot1dStpTxHoldCount OBJECT-TYPE + SYNTAX Integer32 (1..10) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The value used by the Port Transmit state machine to limit + the maximum transmission rate. + + The value of this object MUST be retained across + reinitializations of the management system." + + REFERENCE + "IEEE 802.1w clause 17.16.6" + DEFVAL { 3 } + ::= { dot1dStp 17 } + +-- +-- { dot1dStp 18 } was used to represent dot1dStpPathCostDefault +-- in an earlier version of this MIB. It has since been +-- obsoleted, and should not be used. +-- + +dot1dStpExtPortTable OBJECT-TYPE + SYNTAX SEQUENCE OF Dot1dStpExtPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table that contains port-specific Rapid Spanning Tree + information." + ::= { dot1dStp 19 } + +dot1dStpExtPortEntry OBJECT-TYPE + SYNTAX Dot1dStpExtPortEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of Rapid Spanning Tree information maintained by + each port." + AUGMENTS { dot1dStpPortEntry } + ::= { dot1dStpExtPortTable 1 } + +Dot1dStpExtPortEntry ::= + SEQUENCE { + dot1dStpPortProtocolMigration + TruthValue, + dot1dStpPortAdminEdgePort + TruthValue, + dot1dStpPortOperEdgePort + TruthValue, + dot1dStpPortAdminPointToPoint + INTEGER, + dot1dStpPortOperPointToPoint + TruthValue, + dot1dStpPortAdminPathCost + Integer32 + } + +dot1dStpPortProtocolMigration OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "When operating in RSTP (version 2) mode, writing true(1) + to this object forces this port to transmit RSTP BPDUs. + Any other operation on this object has no effect and + it always returns false(2) when read." + REFERENCE + "IEEE 802.1w clause 14.8.2.4, 17.18.10, 17.26" + ::= { dot1dStpExtPortEntry 1 } + +dot1dStpPortAdminEdgePort OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administrative value of the Edge Port parameter. A + value of true(1) indicates that this port should be + assumed as an edge-port, and a value of false(2) indicates + that this port should be assumed as a non-edge-port. + Setting this object will also cause the corresponding + instance of dot1dStpPortOperEdgePort to change to the + same value. Note that even when this object's value + is true, the value of the corresponding instance of + dot1dStpPortOperEdgePort can be false if a BPDU has + been received. + + The value of this object MUST be retained across + reinitializations of the management system." + + REFERENCE + "IEEE 802.1t clause 14.8.2, 18.3.3" + ::= { dot1dStpExtPortEntry 2 } + +dot1dStpPortOperEdgePort OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The operational value of the Edge Port parameter. The + object is initialized to the value of the corresponding + instance of dot1dStpPortAdminEdgePort. When the + corresponding instance of dot1dStpPortAdminEdgePort is + set, this object will be changed as well. This object + will also be changed to false on reception of a BPDU." + + REFERENCE + "IEEE 802.1t clause 14.8.2, 18.3.4" + ::= { dot1dStpExtPortEntry 3 } + +dot1dStpPortAdminPointToPoint OBJECT-TYPE + SYNTAX INTEGER { + forceTrue(0), + forceFalse(1), + auto(2) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administrative point-to-point status of the LAN segment + attached to this port, using the enumeration values of the + IEEE 802.1w clause. A value of forceTrue(0) indicates + that this port should always be treated as if it is + connected to a point-to-point link. A value of + forceFalse(1) indicates that this port should be treated as + having a shared media connection. A value of auto(2) + indicates that this port is considered to have a + point-to-point link if it is an Aggregator and all of its + members are aggregatable, or if the MAC entity + is configured for full duplex operation, either through + auto-negotiation or by management means. Manipulating this + object changes the underlying adminPortToPortMAC. + + The value of this object MUST be retained across + reinitializations of the management system." + + REFERENCE + "IEEE 802.1w clause 6.4.3, 6.5, 14.8.2" + ::= { dot1dStpExtPortEntry 4 } + +dot1dStpPortOperPointToPoint OBJECT-TYPE + SYNTAX TruthValue + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The operational point-to-point status of the LAN segment + attached to this port. It indicates whether a port is + considered to have a point-to-point connection. + If adminPointToPointMAC is set to auto(2), then the value + of operPointToPointMAC is determined in accordance with the + specific procedures defined for the MAC entity concerned, + as defined in IEEE 802.1w, clause 6.5. The value is + determined dynamically; that is, it is re-evaluated whenever + the value of adminPointToPointMAC changes, and whenever + the specific procedures defined for the MAC entity evaluate + a change in its point-to-point status." + REFERENCE + "IEEE 802.1w clause 6.4.3, 6.5, 14.8.2" + ::= { dot1dStpExtPortEntry 5 } + +dot1dStpPortAdminPathCost OBJECT-TYPE + SYNTAX Integer32 (0..200000000) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The administratively assigned value for the contribution + of this port to the path cost of paths toward the spanning + tree root. + + Writing a value of '0' assigns the automatically calculated + default Path Cost value to the port. If the default Path + Cost is being used, this object returns '0' when read. + + This complements the object dot1dStpPortPathCost or + dot1dStpPortPathCost32, which returns the operational value + of the path cost. + + The value of this object MUST be retained across + reinitializations of the management system." + REFERENCE + "IEEE 802.1D-1998: Section 8.5.5.3" + ::= { dot1dStpExtPortEntry 6 } + +-- ------------------------------------------------------------- +-- rstpMIB - Conformance Information +-- ------------------------------------------------------------- + +rstpGroups OBJECT IDENTIFIER ::= { rstpConformance 1 } + +rstpCompliances OBJECT IDENTIFIER ::= { rstpConformance 2 } + +-- ------------------------------------------------------------- +-- Units of conformance +-- ------------------------------------------------------------- + +rstpBridgeGroup OBJECT-GROUP + OBJECTS { + dot1dStpVersion, + dot1dStpTxHoldCount + } + STATUS current + DESCRIPTION + "Rapid Spanning Tree information for the bridge." + ::= { rstpGroups 1 } + +rstpPortGroup OBJECT-GROUP + OBJECTS { + dot1dStpPortProtocolMigration, + dot1dStpPortAdminEdgePort, + dot1dStpPortOperEdgePort, + dot1dStpPortAdminPointToPoint, + dot1dStpPortOperPointToPoint, + dot1dStpPortAdminPathCost + } + STATUS current + DESCRIPTION + "Rapid Spanning Tree information for individual ports." + ::= { rstpGroups 2 } + +-- ------------------------------------------------------------- +-- Compliance statements +-- ------------------------------------------------------------- + +rstpCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for device support of Rapid + Spanning Tree Protocol (RSTP) bridging services." + MODULE + MANDATORY-GROUPS { + rstpBridgeGroup, + rstpPortGroup + } + ::= { rstpCompliances 1 } + +END diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c index d188ab5..2805d85 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_if.c @@ -674,6 +674,7 @@ int op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, uint sub, uint iidx __unused, enum snmp_op op) { + int ret; struct bridge_if *bif; if ((bif = bridge_get_default()) == NULL) @@ -743,6 +744,11 @@ op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, case LEAF_dot1dStpBridgeForwardDelay: value->v.integer = bif->bridge_fwd_delay; break; + case LEAF_dot1dStpVersion: + value->v.integer = bif->stp_version; + break; + case LEAF_dot1dStpTxHoldCount: + value->v.integer = bif->tx_hold_count; } return (SNMP_ERR_NOERROR); @@ -754,26 +760,32 @@ op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, switch (value->var.subs[sub - 1]) { case LEAF_dot1dStpPriority: ctx->scratch->int1 = bif->priority; - if (bridge_set_priority(bif, value->v.integer) < 0) - return (SNMP_ERR_GENERR); + ret = bridge_set_priority(bif, value->v.integer); break; case LEAF_dot1dStpBridgeMaxAge: ctx->scratch->int1 = bif->bridge_max_age; - if (bridge_set_maxage(bif, value->v.integer) < 0) - return (SNMP_ERR_GENERR); + ret = bridge_set_maxage(bif, value->v.integer); break; case LEAF_dot1dStpBridgeHelloTime: ctx->scratch->int1 = bif->bridge_hello_time; - if (bridge_set_hello_time(bif, value->v.integer) < 0) - return (SNMP_ERR_GENERR); + ret = bridge_set_hello_time(bif, value->v.integer); break; case LEAF_dot1dStpBridgeForwardDelay: ctx->scratch->int1 = bif->bridge_fwd_delay; - if (bridge_set_forward_delay(bif, value->v.integer) < 0) - return (SNMP_ERR_GENERR); + ret = bridge_set_forward_delay(bif, value->v.integer); + break; + + case LEAF_dot1dStpVersion: + ctx->scratch->int1 = bif->stp_version; + ret = bridge_set_stp_version(bif, value->v.integer); + break; + + case LEAF_dot1dStpTxHoldCount: + ctx->scratch->int1 = bif->tx_hold_count; + ret = bridge_set_tx_hold_count(bif, value->v.integer); break; case LEAF_dot1dStpProtocolSpecification: @@ -787,24 +799,35 @@ op_dot1d_stp(struct snmp_context *ctx, struct snmp_value *value, case LEAF_dot1dStpHoldTime: case LEAF_dot1dStpForwardDelay: return (SNMP_ERR_NOT_WRITEABLE); + default: + return (SNMP_ERR_NOSUCHNAME); } + if (ret == -2) + return (SNMP_ERR_WRONG_VALUE); + else if (ret < 0) + return (SNMP_ERR_GENERR); return (SNMP_ERR_NOERROR); case SNMP_OP_ROLLBACK: switch (value->var.subs[sub - 1]) { case LEAF_dot1dStpPriority: - (void) bridge_set_priority(bif, ctx->scratch->int1); + bridge_set_priority(bif, ctx->scratch->int1); break; case LEAF_dot1dStpBridgeMaxAge: - (void) bridge_set_maxage(bif, ctx->scratch->int1); + bridge_set_maxage(bif, ctx->scratch->int1); break; case LEAF_dot1dStpBridgeHelloTime: - (void) bridge_set_hello_time(bif, ctx->scratch->int1); + bridge_set_hello_time(bif, ctx->scratch->int1); break; case LEAF_dot1dStpBridgeForwardDelay: - (void) bridge_set_forward_delay(bif, - ctx->scratch->int1); + bridge_set_forward_delay(bif, ctx->scratch->int1); + break; + case LEAF_dot1dStpVersion: + bridge_set_stp_version(bif, ctx->scratch->int1); + break; + case LEAF_dot1dStpTxHoldCount: + bridge_set_tx_hold_count(bif, ctx->scratch->int1); break; } return (SNMP_ERR_NOERROR); @@ -854,7 +877,7 @@ op_dot1d_tp(struct snmp_context *ctx, struct snmp_value *value, case SNMP_OP_ROLLBACK: if (value->var.subs[sub - 1] == LEAF_dot1dTpAgingTime) - (void) bridge_set_aging_time(bif, ctx->scratch->int1); + bridge_set_aging_time(bif, ctx->scratch->int1); return (SNMP_ERR_NOERROR); case SNMP_OP_COMMIT: @@ -1181,6 +1204,16 @@ op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, ret = bridge_set_forward_delay(bif, val->v.integer); break; + case LEAF_begemotBridgeStpVersion: + ctx->scratch->int1 = bif->stp_version; + ret = bridge_set_stp_version(bif, val->v.integer); + break; + + case LEAF_begemotBridgeStpTxHoldCount: + ctx->scratch->int1 = bif->tx_hold_count; + ret = bridge_set_tx_hold_count(bif, val->v.integer); + break; + case LEAF_begemotBridgeStpProtocolSpecification: case LEAF_begemotBridgeStpTimeSinceTopologyChange: case LEAF_begemotBridgeStpTopChanges: @@ -1220,6 +1253,14 @@ op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, case LEAF_begemotBridgeStpBridgeForwardDelay: bridge_set_forward_delay(bif, ctx->scratch->int1); break; + + case LEAF_begemotBridgeStpVersion: + bridge_set_stp_version(bif, ctx->scratch->int1); + break; + + case LEAF_begemotBridgeStpTxHoldCount: + bridge_set_tx_hold_count(bif, ctx->scratch->int1); + break; } return (SNMP_ERR_NOERROR); @@ -1284,6 +1325,14 @@ op_begemot_stp(struct snmp_context *ctx, struct snmp_value *val, case LEAF_begemotBridgeStpBridgeForwardDelay: val->v.integer = bif->bridge_fwd_delay; break; + + case LEAF_begemotBridgeStpVersion: + val->v.integer = bif->stp_version; + break; + + case LEAF_begemotBridgeStpTxHoldCount: + val->v.integer = bif->tx_hold_count; + break; } return (ret); diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c index 35b2100..44ea959 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_port.c @@ -274,6 +274,17 @@ bridge_new_port(struct mibif *mif, struct bridge_if *bif) strlcpy(bp->p_name, mif->name, IFNAMSIZ); bp->circuit = oid_zeroDotZero; + /* + * Initialize all rstpMib specific values to false/default. + * These will be set to their true values later if the bridge + * supports RSTP. + */ + bp->proto_migr = TruthValue_false; + bp->admin_edge = TruthValue_false; + bp->oper_edge = TruthValue_false; + bp->oper_p2p = TruthValue_false; + bp->admin_p2p = StpPortAdminPointToPointType_auto; + bridge_port_memif_insert(&bridge_ports, bp, &(bif->f_bp)); return (bp); @@ -411,7 +422,6 @@ op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, return (SNMP_ERR_NOSUCHNAME); bp = NULL; /* Make the compiler happy. */ - ret = SNMP_ERR_NOERROR; switch (op) { case SNMP_OP_GET: @@ -437,6 +447,8 @@ op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, break; case SNMP_OP_SET: + if (val->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); if ((bp = bridge_port_find(val->var.subs[sub], bif)) == NULL) return (SNMP_ERR_NOSUCHNAME); @@ -465,6 +477,8 @@ op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, case LEAF_dot1dStpPortDesignatedPort: case LEAF_dot1dStpPortForwardTransitions: return (SNMP_ERR_NOT_WRITEABLE); + default: + return (SNMP_ERR_NOSUCHNAME); } if (ret == 0) return (SNMP_ERR_NOERROR); @@ -495,7 +509,8 @@ op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, case SNMP_OP_COMMIT: return (SNMP_ERR_NOERROR); } - + + ret = SNMP_ERR_NOERROR; switch (val->var.subs[sub - 1]) { case LEAF_dot1dStpPort: val->v.integer = bp->port_no; @@ -535,8 +550,133 @@ op_dot1d_stp_port(struct snmp_context *ctx, struct snmp_value *val, } int +op_dot1d_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_if *bif; + struct bridge_port *bp; + + if ((bif = bridge_get_default()) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + if (time(NULL) - bif->ports_age > bridge_get_data_maxage() && + bridge_update_memif(bif) <= 0) + return (SNMP_ERR_NOSUCHNAME); + + bp = NULL; /* Make the compiler happy. */ + switch (op) { + case SNMP_OP_GET: + if (val->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if (val->var.len - sub == 0) { + if ((bp = bridge_port_bif_first(bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } else { + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL || + (bp = bridge_port_bif_next(bp)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + } + val->var.len = sub + 1; + val->var.subs[sub] = bp->port_no; + break; + + case SNMP_OP_SET: + if (val->var.len - sub != 1) + return (SNMP_ERR_NOSUCHNAME); + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dStpPortAdminEdgePort: + ctx->scratch->int1 = bp->admin_edge; + ret = bridge_port_set_admin_edge(bif->bif_name, bp, + val->v.integer); + break; + case LEAF_dot1dStpPortAdminPointToPoint: + ctx->scratch->int1 = bp->admin_p2p; + ret = bridge_port_set_admin_p2p(bif->bif_name, bp, + val->v.integer); + break; + case LEAF_dot1dStpPortAdminPathCost: + ctx->scratch->int1 = bp->admin_path_cost; + ret = bridge_port_set_path_cost(bif->bif_name, bp, + val->v.integer); + break; + case LEAF_dot1dStpPortProtocolMigration: + case LEAF_dot1dStpPortOperEdgePort: + case LEAF_dot1dStpPortOperPointToPoint: + return (SNMP_ERR_NOT_WRITEABLE); + default: + return (SNMP_ERR_NOSUCHNAME); + } + + if (ret == 0) + return (SNMP_ERR_NOERROR); + else if (ret == -2) + return (SNMP_ERR_WRONG_VALUE); + return (SNMP_ERR_GENERR); + + case SNMP_OP_ROLLBACK: + if ((bp = bridge_port_find(val->var.subs[sub], + bif)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dStpPortAdminEdgePort: + bridge_port_set_admin_edge(bif->bif_name, bp, + ctx->scratch->int1); + break; + case LEAF_dot1dStpPortAdminPointToPoint: + bridge_port_set_admin_p2p(bif->bif_name, bp, + ctx->scratch->int1); + break; + case LEAF_dot1dStpPortAdminPathCost: + bridge_port_set_path_cost(bif->bif_name, bp, + ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_dot1dStpPortProtocolMigration: + val->v.integer = bp->proto_migr; + break; + case LEAF_dot1dStpPortAdminEdgePort: + val->v.integer = bp->admin_edge; + break; + case LEAF_dot1dStpPortOperEdgePort: + val->v.integer = bp->oper_edge; + break; + case LEAF_dot1dStpPortAdminPointToPoint: + val->v.integer = bp->admin_p2p; + break; + case LEAF_dot1dStpPortOperPointToPoint: + val->v.integer = bp->oper_p2p; + break; + case LEAF_dot1dStpPortAdminPathCost: + val->v.integer = bp->admin_path_cost; + break; + } + + return (SNMP_ERR_NOERROR); +} + +int op_dot1d_tp_port(struct snmp_context *c __unused, struct snmp_value *val, - uint sub, uint iidx __unused, enum snmp_op op) + uint sub, uint iidx __unused, enum snmp_op op) { struct bridge_if *bif; struct bridge_port *bp; @@ -1064,7 +1204,6 @@ op_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val, } ret = SNMP_ERR_NOERROR; - switch (val->var.subs[sub - 1]) { case LEAF_begemotBridgeStpPort: val->v.integer = bp->port_no; @@ -1102,6 +1241,114 @@ op_begemot_stp_port(struct snmp_context *ctx, struct snmp_value *val, } int +op_begemot_stp_ext_port(struct snmp_context *ctx, struct snmp_value *val, + uint sub, uint iidx __unused, enum snmp_op op) +{ + int ret; + struct bridge_port *bp = NULL; + const char *b_name; + + if (time(NULL) - ports_list_age > bridge_get_data_maxage()) + bridge_update_all_ports(); + + switch (op) { + case SNMP_OP_GET: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_GETNEXT: + if ((bp = bridge_port_index_getnext(&val->var, sub, 0)) == + NULL || bridge_port_index_append(&val->var, sub, bp) < 0) + return (SNMP_ERR_NOSUCHNAME); + break; + + case SNMP_OP_SET: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL) + return (SNMP_ERR_NOSUCHNAME); + if ((b_name = bridge_if_find_name(bp->sysindex)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPortAdminEdgePort: + ctx->scratch->int1 = bp->admin_edge; + ret = bridge_port_set_admin_edge(b_name, bp, + val->v.integer); + break; + case LEAF_begemotBridgeStpPortAdminPointToPoint: + ctx->scratch->int1 = bp->admin_p2p; + ret = bridge_port_set_admin_p2p(b_name, bp, + val->v.integer); + break; + case LEAF_begemotBridgeStpPortAdminPathCost: + ctx->scratch->int1 = bp->admin_path_cost; + ret = bridge_port_set_path_cost(b_name, bp, + val->v.integer); + break; + case LEAF_begemotBridgeStpPortProtocolMigration: + case LEAF_begemotBridgeStpPortOperEdgePort: + case LEAF_begemotBridgeStpPortOperPointToPoint: + return (SNMP_ERR_NOT_WRITEABLE); + default: + return (SNMP_ERR_NOSUCHNAME); + } + + if (ret == 0) + return (SNMP_ERR_NOERROR); + else if (ret == -2) + return (SNMP_ERR_WRONG_VALUE); + return (SNMP_ERR_GENERR); + + case SNMP_OP_ROLLBACK: + if ((bp = bridge_port_index_get(&val->var, sub, 0)) == NULL || + (b_name = bridge_if_find_name(bp->sysindex)) == NULL) + return (SNMP_ERR_GENERR); + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPortAdminEdgePort: + bridge_port_set_admin_edge(b_name, bp, + ctx->scratch->int1); + break; + case LEAF_begemotBridgeStpPortAdminPointToPoint: + bridge_port_set_admin_p2p(b_name, bp, + ctx->scratch->int1); + break; + case LEAF_begemotBridgeStpPortAdminPathCost: + bridge_port_set_path_cost(b_name, bp, + ctx->scratch->int1); + break; + } + return (SNMP_ERR_NOERROR); + + case SNMP_OP_COMMIT: + return (SNMP_ERR_NOERROR); + } + + switch (val->var.subs[sub - 1]) { + case LEAF_begemotBridgeStpPortProtocolMigration: + val->v.integer = bp->proto_migr; + break; + case LEAF_begemotBridgeStpPortAdminEdgePort: + val->v.integer = bp->admin_edge; + break; + case LEAF_begemotBridgeStpPortOperEdgePort: + val->v.integer = bp->oper_edge; + break; + case LEAF_begemotBridgeStpPortAdminPointToPoint: + val->v.integer = bp->admin_p2p; + break; + case LEAF_begemotBridgeStpPortOperPointToPoint: + val->v.integer = bp->oper_p2p; + break; + case LEAF_begemotBridgeStpPortAdminPathCost: + val->v.integer = bp->admin_path_cost; + break; + } + + return (SNMP_ERR_NOERROR); +} + +int op_begemot_tp_port(struct snmp_context *c __unused, struct snmp_value *val, uint sub, uint iidx __unused, enum snmp_op op) { diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c index dfcd1f9..6a13bca 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.c @@ -119,8 +119,10 @@ bridge_set_default_name(const char *bif_name, uint len) bcopy(bif_name, bif_default_name, len); bif_default_name[len] = '\0'; - if ((bif = bridge_if_find_ifname(bif_default_name)) == NULL) + if ((bif = bridge_if_find_ifname(bif_default_name)) == NULL) { + bif_default = NULL; return (0); + } bif_default = bif; return (1); @@ -197,10 +199,16 @@ op_begemot_bridge_config(struct snmp_context *ctx, struct snmp_value *val, return (SNMP_ERR_BADVALUE); break; case LEAF_begemotBridgeDataUpdate: + if (val->v.integer < SNMP_BRIDGE_DATA_MAXAGE_MIN || + val->v.integer > SNMP_BRIDGE_DATA_MAXAGE_MAX) + return (SNMP_ERR_WRONG_VALUE); ctx->scratch->int1 = bridge_data_maxage; bridge_data_maxage = val->v.integer; break; case LEAF_begemotBridgeDataPoll: + if (val->v.integer < SNMP_BRIDGE_POLL_INTERVAL_MIN || + val->v.integer > SNMP_BRIDGE_POLL_INTERVAL_MAX) + return (SNMP_ERR_WRONG_VALUE); ctx->scratch->int1 = val->v.integer; break; } diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h index 75d4096..6d77420 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_snmp.h @@ -41,11 +41,32 @@ typedef u_char bridge_id[SNMP_BRIDGE_ID_LEN]; #define SNMP_BRIDGE_MIN_AGE_TIME 10 #define SNMP_BRIDGE_MAX_AGE_TIME 1000000 +#define SNMP_BRIDGE_MIN_TXHC 1 +#define SNMP_BRIDGE_MAX_TXHC 10 + +#define SNMP_BRIDGE_MIN_MAGE 600 +#define SNMP_BRIDGE_MAX_MAGE 4000 + +#define SNMP_BRIDGE_MIN_HTIME 100 +#define SNMP_BRIDGE_MAX_HTIME 1000 + +#define SNMP_BRIDGE_MIN_FDELAY 400 +#define SNMP_BRIDGE_MAX_FDELAY 3000 + #define SNMP_PORT_PATHCOST_OBSOLETE 65535 +#define SNMP_PORT_MIN_PATHCOST 0 +#define SNMP_PORT_MAX_PATHCOST 200000000 +#define SNMP_PORT_PATHCOST_AUTO 0 #define SNMP_BRIDGE_DATA_MAXAGE 10 +#define SNMP_BRIDGE_DATA_MAXAGE_MIN 1 +#define SNMP_BRIDGE_DATA_MAXAGE_MAX 300 + /* By default poll kernel data every 5 minutes. */ #define SNMP_BRIDGE_POLL_INTERVAL (5 * 60) +#define SNMP_BRIDGE_POLL_INTERVAL_MIN 1 +#define SNMP_BRIDGE_POLL_INTERVAL_MAX 3600 + /* Poll for a topology change once every 30 seconds. */ #define SNMP_BRIDGE_TC_POLL_INTERVAL 30 @@ -98,6 +119,14 @@ struct bridge_port { bridge_id design_root; bridge_id design_bridge; + /* rstpMib extensions. */ + int32_t admin_path_cost; + enum TruthValue proto_migr; + enum TruthValue admin_edge; + enum TruthValue oper_edge; + enum TruthValue oper_p2p; + enum StpPortAdminPointToPointType admin_p2p; + /* dot1dTp subtree objects. */ int32_t max_info; int32_t in_frames; @@ -135,7 +164,9 @@ struct bridge_if { int32_t bridge_max_age; /* Configured max age. */ int32_t bridge_hello_time; /* Configured hello time. */ int32_t bridge_fwd_delay; /* Configured forward delay. */ + int32_t tx_hold_count; uint32_t top_changes; + enum dot1dStpVersion stp_version; enum dot1dStpProtocolSpecification prot_spec; struct timeval last_tc_time; bridge_id design_root; @@ -268,6 +299,12 @@ int bridge_set_aging_time(struct bridge_if *bif, int32_t age_time); /* Set the max number of entries in the bridge address cache. */ int bridge_set_max_cache(struct bridge_if *bif, int32_t max_cache); +/* Set the bridge TX hold count. */ +int bridge_set_tx_hold_count(struct bridge_if *bif, int32_t tx_hc); + +/* Set the bridge STP protocol version. */ +int bridge_set_stp_version(struct bridge_if *bif, int32_t stp_proto); + /* Set the bridge interface status to up/down. */ int bridge_set_if_up(const char* b_name, int8_t up); @@ -292,6 +329,14 @@ int bridge_port_set_stp_enable(const char *bif_name, struct bridge_port *bp, int bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, int32_t path_cost); +/* Set admin point-to-point link. */ +int bridge_port_set_admin_p2p(const char *bif_name, struct bridge_port *bp, + uint32_t admin_p2p); + +/* Set admin edge. */ +int bridge_port_set_admin_edge(const char *bif_name, struct bridge_port *bp, + uint32_t enable); + /* Add a bridge member port. */ int bridge_port_addm(struct bridge_port *bp, const char *b_name); diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c index 13b3007..585a4e2 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_sys.c @@ -238,6 +238,10 @@ bridge_get_op_param(struct bridge_if *bif) bif->max_age = 100 * b_req.ifbop_maxage; bif->hello_time = 100 * b_req.ifbop_hellotime; bif->fwd_delay = 100 * b_req.ifbop_fwddelay; +#if __FreeBSD_version > 700024 + bif->stp_version = b_req.ifbop_protocol; + bif->tx_hold_count = b_req.ifbop_holdcount; +#endif if (b_req.ifbop_root_port == 0 && bif->root_port != b_req.ifbop_root_port) @@ -312,11 +316,14 @@ bridge_set_priority(struct bridge_if *bif, int32_t priority) * To convert a Timeout value into a value in units of * 1/256 seconds, the following algorithm should be used: * b = floor( (n * 256) / 100) + * The conversion to 1/256 of a second happens in the kernel - + * just make sure we correctly convert the seconds to Timout + * and vice versa. */ static uint32_t -snmp_hundred_secs2_256(int32_t h_secs) +snmp_timeout2_sec(int32_t secs) { - return ((h_secs * 256) / 100); + return (secs / 100); } int @@ -325,10 +332,14 @@ bridge_set_maxage(struct bridge_if *bif, int32_t max_age) struct ifdrv ifd; struct ifbrparam b_param; + if (max_age < SNMP_BRIDGE_MIN_MAGE || + max_age > SNMP_BRIDGE_MAX_MAGE) + return (-2); + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); ifd.ifd_len = sizeof(b_param); ifd.ifd_data = &b_param; - b_param.ifbrp_maxage = (uint32_t) max_age; + b_param.ifbrp_maxage = snmp_timeout2_sec(max_age); ifd.ifd_cmd = BRDGSMA; if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { @@ -347,10 +358,14 @@ bridge_set_hello_time(struct bridge_if *bif, int32_t hello_time) struct ifdrv ifd; struct ifbrparam b_param; + if (hello_time < SNMP_BRIDGE_MIN_HTIME || + hello_time > SNMP_BRIDGE_MAX_HTIME) + return (-2); + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); ifd.ifd_len = sizeof(b_param); ifd.ifd_data = &b_param; - b_param.ifbrp_hellotime = snmp_hundred_secs2_256(hello_time); + b_param.ifbrp_hellotime = snmp_timeout2_sec(hello_time); ifd.ifd_cmd = BRDGSHT; if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { @@ -369,10 +384,14 @@ bridge_set_forward_delay(struct bridge_if *bif, int32_t fwd_delay) struct ifdrv ifd; struct ifbrparam b_param; + if (fwd_delay < SNMP_BRIDGE_MIN_FDELAY || + fwd_delay > SNMP_BRIDGE_MAX_FDELAY) + return (-2); + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); ifd.ifd_len = sizeof(b_param); ifd.ifd_data = &b_param; - b_param.ifbrp_fwddelay = snmp_hundred_secs2_256(fwd_delay); + b_param.ifbrp_fwddelay = snmp_timeout2_sec(fwd_delay); ifd.ifd_cmd = BRDGSFD; if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { @@ -434,6 +453,67 @@ bridge_set_max_cache(struct bridge_if *bif, int32_t max_cache) return (0); } +int +bridge_set_tx_hold_count(struct bridge_if *bif __unused, + int32_t tx_hc __unused) +{ +#if __FreeBSD_version > 700024 + struct ifdrv ifd; + struct ifbrparam b_param; + + if (tx_hc < SNMP_BRIDGE_MIN_TXHC || tx_hc > SNMP_BRIDGE_MAX_TXHC) + return (-1); + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_txhc = tx_hc; + ifd.ifd_cmd = BRDGSTXHC; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSTXHC) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->tx_hold_count = b_param.ifbrp_txhc; + return (0); +#else + return (-1); +#endif +} + +int +bridge_set_stp_version(struct bridge_if *bif __unused, + int32_t stp_proto __unused) +{ +#if __FreeBSD_version > 700024 + struct ifdrv ifd; + struct ifbrparam b_param; + + if (stp_proto != dot1dStpVersion_stpCompatible && + stp_proto != dot1dStpVersion_rstp) + return (-2); + + strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); + ifd.ifd_len = sizeof(b_param); + ifd.ifd_data = &b_param; + b_param.ifbrp_proto = stp_proto; + ifd.ifd_cmd = BRDGSPROTO; + + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set bridge param: ioctl(BRDGSPROTO) " + "failed: %s", strerror(errno)); + return (-1); + } + + bif->stp_version = b_param.ifbrp_proto; + return (0); +#else + return (-1); +#endif +} + /* * Set the bridge interface status to up/down. */ @@ -580,6 +660,9 @@ state2snmp_st(uint8_t ifbr_state) case BSTP_IFSTATE_FORWARDING: return (StpPortState_forwarding); case BSTP_IFSTATE_BLOCKING: +#if __FreeBSD_version > 700024 + case BSTP_IFSTATE_DISCARDING: +#endif return (StpPortState_blocking); } @@ -605,20 +688,12 @@ bridge_port_getinfo_conf(struct ifbreq *k_info, struct bridge_port *bp) * the maximum value." */ -#if 0 - /* - * Kernel variable is a 32-bit integer but the ioctl supports - * only getting/setting a 8-bit value. - */ - - if (k_info->ifbr_path_cost > SNMP_PORT_PATHCOST_OBSOLETE) { - bp->path_cost = SNMP_PORT_PATHCOST_OBSOLETE; - bp->path_cost32 = k_info->ifbr_path_cost; - } else - - bp->path_cost = bp->path_cost32 = k_info->ifbr_path_cost; +#if __FreeBSD_version > 700024 + if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMCOST) + bp->admin_path_cost = k_info->ifbr_path_cost; + else + bp->admin_path_cost = 0; #endif - bp->path_cost = k_info->ifbr_path_cost; if (k_info->ifbr_ifsflags & IFBIF_STP) @@ -631,6 +706,32 @@ bridge_port_getinfo_conf(struct ifbreq *k_info, struct bridge_port *bp) bp->span_enable = begemotBridgeBaseSpanEnabled_enabled; else bp->span_enable = begemotBridgeBaseSpanEnabled_disabled; + +#if __FreeBSD_version > 700024 + if (k_info->ifbr_ifsflags & IFBIF_BSTP_ADMEDGE) + bp->admin_edge = TruthValue_true; + else + bp->admin_edge = TruthValue_false; + + if (k_info->ifbr_ifsflags & IFBIF_BSTP_EDGE) + bp->oper_edge = TruthValue_true; + else + bp->oper_edge = TruthValue_false; + + if (k_info->ifbr_ifsflags & IFBIF_BSTP_AUTOP2P) { + bp->admin_p2p = StpPortAdminPointToPointType_auto; + if (k_info->ifbr_ifsflags & IFBIF_BSTP_P2P) + bp->oper_p2p = TruthValue_true; + else + bp->oper_p2p = TruthValue_false; + } else if (k_info->ifbr_ifsflags & IFBIF_BSTP_P2P) { + bp->admin_p2p = StpPortAdminPointToPointType_forceTrue; + bp->oper_p2p = TruthValue_true; + } else { + bp->admin_p2p = StpPortAdminPointToPointType_forceFalse; + bp->oper_p2p = TruthValue_false; + } +#endif } /* @@ -753,15 +854,22 @@ bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, struct ifdrv ifd; struct ifbreq b_req; - if (path_cost > SNMP_PORT_PATHCOST_OBSOLETE) +#if __FreeBSD_version > 700024 + if (path_cost < SNMP_PORT_MIN_PATHCOST || + path_cost > SNMP_PORT_MAX_PATHCOST) + return (-2); +#else + if (path_cost < SNMP_PORT_MIN_PATHCOST || + path_cost > SNMP_PORT_PATHCOST_OBSOLETE) return (-2); +#endif strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); ifd.ifd_len = sizeof(b_req); ifd.ifd_data = &b_req; strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); - b_req.ifbr_path_cost = (uint16_t) path_cost; + b_req.ifbr_path_cost = path_cost; ifd.ifd_cmd = BRDGSIFCOST; if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { @@ -770,8 +878,121 @@ bridge_port_set_path_cost(const char *bif_name, struct bridge_port *bp, return (-1); } +#if __FreeBSD_version > 700024 + bp->admin_path_cost = path_cost; +#else bp->path_cost = path_cost; +#endif + + return (0); +} + +/* + * Set the PonitToPoint status of the link administratively. + */ +int +bridge_port_set_admin_p2p(const char *bif_name __unused, + struct bridge_port *bp __unused, uint32_t admin_p2p __unused) +{ +#if __FreeBSD_version > 700024 + struct ifdrv ifd; + struct ifbreq b_req; + + if (bp->admin_p2p == admin_p2p) + return (0); + + if (admin_p2p > StpPortAdminPointToPointType_auto) + return (-2); + + bzero(&b_req, sizeof(b_req)); + strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + ifd.ifd_cmd = BRDGGIFFLGS; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + switch (admin_p2p) { + case StpPortAdminPointToPointType_forceTrue: + b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOP2P; + b_req.ifbr_ifsflags |= IFBIF_BSTP_P2P; + break; + case StpPortAdminPointToPointType_forceFalse: + b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOP2P; + b_req.ifbr_ifsflags &= ~IFBIF_BSTP_P2P; + break; + case StpPortAdminPointToPointType_auto: + b_req.ifbr_ifsflags |= IFBIF_BSTP_AUTOP2P; + break; + } + + ifd.ifd_cmd = BRDGSIFFLGS; + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + bp->admin_p2p = admin_p2p; return (0); +#else + return (-1); +#endif +} + +/* + * Set admin edge. + */ +int +bridge_port_set_admin_edge(const char *bif_name __unused, + struct bridge_port *bp __unused, uint32_t enable __unused) +{ +#if __FreeBSD_version > 700024 + struct ifdrv ifd; + struct ifbreq b_req; + + if (bp->admin_edge == enable) + return (0); + + if (enable != TruthValue_true && enable != TruthValue_false) + return (-2); + + bzero(&b_req, sizeof(b_req)); + strlcpy(ifd.ifd_name, bif_name, sizeof(ifd.ifd_name)); + ifd.ifd_len = sizeof(b_req); + ifd.ifd_data = &b_req; + strlcpy(b_req.ifbr_ifsname, bp->p_name, sizeof(b_req.ifbr_ifsname)); + ifd.ifd_cmd = BRDGGIFFLGS; + + if (ioctl(sock, SIOCGDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "get member %s param: ioctl(BRDGGIFFLGS) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + if (enable == TruthValue_true) { + b_req.ifbr_ifsflags &= ~IFBIF_BSTP_AUTOEDGE; + b_req.ifbr_ifsflags |= IFBIF_BSTP_EDGE; + } else + b_req.ifbr_ifsflags &= ~IFBIF_BSTP_EDGE; + + ifd.ifd_cmd = BRDGSIFFLGS; + if (ioctl(sock, SIOCSDRVSPEC, &ifd) < 0) { + syslog(LOG_ERR, "set member %s param: ioctl(BRDGSIFFLGS) " + "failed: %s", bp->p_name, strerror(errno)); + return (-1); + } + + bp->admin_edge = enable; + return (0); +#else + return (-1); +#endif } /* @@ -899,7 +1120,7 @@ bridge_port_get_ifstplist(struct bridge_if *bif, char **buf) struct ifbpstpconf ifbstp; struct ifdrv ifd; - *buf = NULL; + *buf = NULL; strlcpy(ifd.ifd_name, bif->bif_name, IFNAMSIZ); ifd.ifd_cmd = BRDGGIFSSTP; ifd.ifd_len = sizeof(ifbstp); diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def index 892615b..5a161af 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/bridge_tree.def @@ -51,6 +51,12 @@ typedef StpPortState ENUM ( 6 broken ) +typedef StpPortAdminPointToPointType ENUM ( + 0 forceTrue + 1 forceFalse + 2 auto +) + typedef BaseType ENUM ( 1 unknown 2 transparent-only @@ -115,6 +121,17 @@ typedef TpFdbStatus ENUM ( (9 dot1dStpPortDesignatedPort OCTETSTRING | BridgePortId GET) (10 dot1dStpPortForwardTransitions COUNTER GET) )) + (16 dot1dStpVersion ENUM ( 0 stpCompatible 2 rstp ) op_dot1d_stp GET SET) + (17 dot1dStpTxHoldCount INTEGER op_dot1d_stp GET SET) + (19 dot1dStpExtPortTable + (1 dot1dStpExtPortEntry : INTEGER op_dot1d_stp_ext_port + (1 dot1dStpPortProtocolMigration TruthValue GET) # SET + (2 dot1dStpPortAdminEdgePort TruthValue GET SET) + (3 dot1dStpPortOperEdgePort TruthValue GET) + (4 dot1dStpPortAdminPointToPoint StpPortAdminPointToPointType GET SET) + (5 dot1dStpPortOperPointToPoint TruthValue GET) + (6 dot1dStpPortAdminPathCost INTEGER GET SET) + )) ) (3 dot1dSr ) @@ -144,6 +161,18 @@ typedef TpFdbStatus ENUM ( (2 dot1dCompliances ) ) + ) + (134 rstpMIB + (0 rstpNotifications + ) + (1 rstpObjects + ) + (2 rstpConformance + (1 rstpGroups + ) + (2 rstpCompliances + ) + ) ))) (4 private (1 enterprises @@ -190,6 +219,8 @@ typedef TpFdbStatus ENUM ( (12 begemotBridgeStpBridgeMaxAge INTEGER GET SET) (13 begemotBridgeStpBridgeHelloTime INTEGER GET SET) (14 begemotBridgeStpBridgeForwardDelay INTEGER GET SET) + (15 begemotBridgeStpVersion ENUM ( 0 stpCompatible 2 rstp ) GET SET) + (16 begemotBridgeStpTxHoldCount INTEGER GET SET) )) (2 begemotBridgeStpPortTable (1 begemotBridgeStpPortEntry : OCTETSTRING | BridgeIfName INTEGER op_begemot_stp_port @@ -204,6 +235,15 @@ typedef TpFdbStatus ENUM ( (9 begemotBridgeStpPortDesignatedPort OCTETSTRING | BridgePortId GET) (10 begemotBridgeStpPortForwardTransitions COUNTER GET) )) + (3 begemotBridgeStpExtPortTable + (1 begemotBridgeStpExtPortEntry : OCTETSTRING | BridgeIfName INTEGER op_begemot_stp_ext_port + (1 begemotBridgeStpPortProtocolMigration TruthValue GET) # SET + (2 begemotBridgeStpPortAdminEdgePort TruthValue GET SET) + (3 begemotBridgeStpPortOperEdgePort TruthValue GET) + (4 begemotBridgeStpPortAdminPointToPoint StpPortAdminPointToPointType GET SET) + (5 begemotBridgeStpPortOperPointToPoint TruthValue GET) + (6 begemotBridgeStpPortAdminPathCost INTEGER GET SET) + )) ) (3 begemotBridgeTp (1 begemotBridgeTpTable diff --git a/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 b/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 index cc942b4..204912a 100644 --- a/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 +++ b/usr.sbin/bsnmpd/modules/snmp_bridge/snmp_bridge.3 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 18, 2006 +.Dd December 8, 2006 .Dt snmp_bridge 3 .Os .Sh NAME @@ -36,8 +36,9 @@ .Sh DESCRIPTION The .Nm snmp_bridge -module implements the BRIDGE-MIB as standardized in RFC 4188 and a private -BEGEMOT-BRIDGE-MIB, which allows management of multiple bridge interfaces. +module implements the BRIDGE-MIB as standardized in RFC 4188, the RSTP-MIB +standardized in RFC4318 and a private BEGEMOT-BRIDGE-MIB, which allows +management of multiple bridge interfaces. Most of the objects defined in the private BEGEMOT-BRIDGE-MIB are duplicates of the original objects defined by the standard BRIDGE-MIB, but the private MIB also defines additional objects which make the functionality of @@ -100,6 +101,8 @@ The description of the MIB tree implemented by .Nm . .It Pa /usr/share/snmp/mibs/BRIDGE-MIB.txt This is the BRIDGE-MIB that is implemented by this module. +.It Pa /usr/share/snmp/mibs/RSTP-MIB.txt +This is the RSTP-MIB implemented by this module. .It Pa /usr/share/snmp/mibs/BEGEMOT-BRIDGE-MIB.txt This is the private BEGEMOT-BRIDGE-MIB that is implemented by this module. .El -- cgit v1.1