Forráskód Böngészése

Merge branch 'develop' of github.com:opensolutions/OSS_SNMP into develop

Barry O'Donovan 13 éve
szülő
commit
842ab69663
2 módosított fájl, 224 hozzáadás és 109 törlés
  1. 216 109
      OSS/SNMP/MIBS/Cisco/CDP.php
  2. 8 0
      OSS/SNMP/MIBS/Cisco/RSTP.php

+ 216 - 109
OSS/SNMP/MIBS/Cisco/CDP.php

@@ -541,39 +541,64 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
     /**
      * CDP utility function to get all CDP neighbours and their connected ports.
      *
-     * Returns an array of neighbours indexed by the neighbour CDP ID. For example:
-     *
-     *
-     * Array
-     * (
-     *     [cr-sw03.ixdub1.opensolutions.ie] => Array
-     *         (
-     *            [0] => Array
-     *                (
-     *                     [localPortId] => 10101
-     *                     [localPort] => GigabitEthernet1/0/1
-     *                     [remotePort] => GigabitEthernet0/1
-     *                 )
-     *
-     *             [1] => Array
-     *                 (
-     *                     [localPortId] => 10102
-     *                     [localPort] => GigabitEthernet1/0/2
-     *                     [remotePort] => FastEthernet0/2
-     *                 )
-     *
-     *         )
-     *     [ ... ]
-     * )
+     * Returns an array of neighbours indexed by the neighbour CDP ID with a lot of details.
+     *
+     * For example, here's a sample return for a switch with two neighbours where one neighbour
+     * is connected with a LAG / PortChannel and $inverse was set to true.
+     *
+     *
+     * array(2) {
+     *     ["cr-sw07.example.ie"] => array(1) {
+     *         [0] => array(7) {
+     *             ["localPortId"] => int(10103)
+     *             ["localPortName"] => string(7) "Gi1/0/3"
+     *             ["localPort"] => string(20) "GigabitEthernet1/0/3"
+     *             ["isLAG"] => bool(false)
+     *             ["remotePort"] => string(21) "GigabitEthernet1/0/24"
+     *             ["remotePortId"] => int(10124)
+     *             ["remotePortName"] => string(8) "Gi1/0/24"
+     *         }
+     *     }
+     *     ["cr-sw01.example.ie"] => array(2) {
+     *         [0] => array(11) {
+     *             ["localPortId"] => int(10111)
+     *             ["localPortName"] => string(8) "Gi1/0/11"
+     *             ["localPort"] => string(21) "GigabitEthernet1/0/11"
+     *             ["isLAG"] => bool(true)
+     *             ["lagPortId"] => int(5048)
+     *             ["lagPortName"] => string(4) "Po48"
+     *             ["remotePort"] => string(21) "GigabitEthernet1/0/11"
+     *             ["remotePortId"] => int(10111)
+     *             ["remotePortName"] => string(8) "Gi1/0/11"
+     *             ["remoteLagPortId"] => int(5048)
+     *             ["remoteLagPortName"] => string(4) "Po48"
+     *         }
+     *         [1] => array(11) {
+     *             ["localPortId"] => int(10112)
+     *             ["localPortName"] => string(8) "Gi1/0/12"
+     *             ["localPort"] => string(21) "GigabitEthernet1/0/12"
+     *             ["isLAG"] => bool(true)
+     *             ["lagPortId"] => int(5048)
+     *             ["lagPortName"] => string(4) "Po48"
+     *             ["remotePort"] => string(21) "GigabitEthernet1/0/12"
+     *             ["remotePortId"] => int(10112)
+     *             ["remotePortName"] => string(8) "Gi1/0/12"
+     *             ["remoteLagPortId"] => int(5048)
+     *             ["remoteLagPortName"] => string(4) "Po48"
+     *         }
+     *     }
      *
      * @see neighbourId()
      * @see \OSS\SNMP\MIBS\Interface::descriptions()
      * @see neighbourPort()
+     * @param boolean $inverse If true, all remoteXXX params will be discovered (only remotePort is returned otherwise)
+     * @param array $skipHostIds If using $inverse, pass an array of CDP IDs of neighbours that should not be 'inverse' discovered.
      * @return array CDP neighbours and their connected ports
      */
-    public function neighbours()
+    public function neighbours( $inverse = false, $skipHostIds = null )
     {
         $neighbours = array();
+        $remotes = array();
 
         foreach( $this->neighbourId() as $localPortId => $neighbourCdpId )
         {
@@ -588,6 +613,7 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
             $neighbours[ $neighbourCdpId ][$count]['localPortId']   = $localPortId;
             $neighbours[ $neighbourCdpId ][$count]['localPortName'] = $this->getSNMP()->useIface()->names()[$localPortId];
             $neighbours[ $neighbourCdpId ][$count]['localPort']     = $this->getSNMP()->useIface()->descriptions()[$localPortId];
+
             try
             {
                 if( $this->getSNMP()->useLAG()->isAggregatePorts()[$localPortId] )
@@ -607,6 +633,46 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
             }
 
             $neighbours[ $neighbourCdpId ][$count]['remotePort']    = $this->neighbourPort()[$localPortId];
+
+            if( $inverse )
+            {
+                if( !is_array( $skipHostIds ) || !in_array( $neighbourCdpId, $skipHostIds ) )
+                {
+                    try
+                    {
+                        if( !isset( $remotes[ $neighbourCdpId ] ) )
+                            $remotes[ $neighbourCdpId ] = new \OSS\SNMP( $neighbourCdpId, $this->getSNMP()->getCommunity() );
+
+                        $remote = $remotes[ $neighbourCdpId ];
+                        $rneighbours = $remote->useCisco_CDP()->neighbours( false );
+
+                        foreach( $rneighbours as $rNeighbourCdpId => $rLinks )
+                        {
+                            foreach( $rLinks as $rIndex => $rPortDetails )
+                            {
+                                $rLocalPortId = $rPortDetails[ 'localPortId' ];
+                                if( $rNeighbourCdpId == $this->id()
+                                        && $remote->useIface()->descriptions()[ $rLocalPortId ] == $neighbours[ $neighbourCdpId ][$count]['remotePort'] )
+                                {
+                                    $neighbours[ $neighbourCdpId ][$count]['remotePortId']   = $rLocalPortId;
+                                    $neighbours[ $neighbourCdpId ][$count]['remotePortName'] = $remote->useIface()->names()[ $rLocalPortId ];
+
+                                    if( $neighbours[ $neighbourCdpId ][$count]['isLAG'] )
+                                    {
+                                        $neighbours[ $neighbourCdpId ][$count]['remoteLagPortId']   = $remote->useLAG()->portAttachedIds()[$rLocalPortId];
+                                        $neighbours[ $neighbourCdpId ][$count]['remoteLagPortName'] = $remote->useIface()->names()[ $neighbours[ $neighbourCdpId ][$count]['remoteLagPortId'] ];
+                                    }
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    catch( \OSS\Exception $e )
+                    {
+                    }
+                }
+            }
+
         }
 
         return $neighbours;
@@ -629,7 +695,7 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
         if( !count( $devices ) )
         {
             $device = $this->id();
-            $devices[ $device ] = $this->neighbours();
+            $devices[ $device ] = $this->neighbours( true, $ignore );
         }
 
         foreach( $devices[ $device ] as $feNeighbour => $feConnections )
@@ -644,13 +710,11 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
 
             if( !isset( $devices[ $feNeighbour ] ) )
             {
-                #echo "Crawling $feNeighbour<br>\n";
-                #flush();ob_end_flush();
                 $snmp = new \OSS\SNMP( $feNeighbour, $this->getSNMP()->getCommunity() );
 
                 try
                 {
-                    $devices[ $feNeighbour ] = $snmp->useCisco_CDP()->neighbours();
+                    $devices[ $feNeighbour ] = $snmp->useCisco_CDP()->neighbours( true, $ignore );
                     unset( $snmp );
                     $this->crawl( $devices, $feNeighbour, $ignore );
                 }
@@ -662,52 +726,6 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
             }
         }
 
-        // find LAGs and more
-        foreach( $devices as $parent => $neighbours )
-        {
-            foreach( $neighbours as $neighbour => $links )
-            {
-                foreach( $links as $idx => $link )
-                {
-                    if( $link['isLAG'] and !isset( $link['remoteLagPortId'] ) )
-                    {
-                        if( isset( $devices[ $neighbour ][ $parent ] ) )
-                        {
-                            foreach( $devices[ $neighbour ][ $parent ] as $_idx => $_link )
-                            {
-                                if( $_link['localPort'] == $link['remotePort'] )
-                                {
-                                    $devices[ $parent ][ $neighbour ][ $idx ][ 'remoteLagPortId' ]   = $_link['lagPortId'];
-                                    $devices[ $parent ][ $neighbour ][ $idx ][ 'remoteLagPortName' ] = $_link['lagPortName'];
-
-                                    $devices[ $neighbour ][ $parent ][ $_idx ][ 'remoteLagPortId' ]   = $link['lagPortId'];
-                                    $devices[ $neighbour ][ $parent ][ $_idx ][ 'remoteLagPortName' ] = $link['lagPortName'];
-
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    if( !isset( $link['remotePortId'] ) )
-                    {
-                        if( isset( $devices[ $neighbour ][ $parent ] ) )
-                        {
-                            foreach( $devices[ $neighbour ][ $parent ] as $_idx => $_link )
-                            {
-                                if( $_link['localPort'] == $link['remotePort'] )
-                                {
-                                    $devices[ $parent ][ $neighbour ][ $idx ][ 'remotePortId' ]   = $_link['localPortId'];
-                                    $devices[ $parent ][ $neighbour ][ $idx ][ 'remotePortName' ] = $_link['localPortName'];
-
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
         return $devices;
     }
 
@@ -717,13 +735,16 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
      *
      * Huh? This function:
      *
-     * * takes the result of crawl() (or calls crawl()) to get the CDP topology
-     * * foreach device, builds an array of device to device links
+     * * takes the result of crawl() (or calls crawl()) to get the CDP topology;
+     * * foreach device, builds an array of device to device links;
      * * SO LONG as that link has already not been accounted for in the other direction.
      *
-     * I.e. if a link is found A -> B, then the same B -> A link will not be included
+     * I.e. if a link is found A -> B, then the same B -> A link will not be included.
+     *
+     * The primary differences to the return value of this and crawl() are:
      *
-     * The array returned is, for example:
+     * * links only appear once (unidirectional) rather than twice (bidirectional)
+     * * the links are indexed by the localPortName rather than an integer index:
      *
      * [cr-sw04.degkcp.example.ie] => Array
      * (
@@ -733,28 +754,11 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
      *          (
      *              [remotePort] => FastEthernet0/1
      *              [isLAG]      => false
+     *              ........
      *      )
      *
-     *      [cr-sw03.degkcp.example.ie] => Array
-     *      (
-     *          [GigabitEthernet1/0/23] => Array
-     *          (
-     *              [remotePort] => GigabitEthernet1/0/23
-     *              [isLAG]      => false
-     *          )
-     *          [GigabitEthernet1/0/24] => Array
-     *          (
-     *              [remotePort] => GigabitEthernet1/0/24
-     *              [isLAG]      => false
-     *          )
-     *      )
-     * )
-     *
-     * This tells us that cr-sw04(GigabitEthernet1/0/3) is connected to cd-sw02(FastEthernet0/1).
-     *
-     * It also tells us that cr-sw04 has two connections to cr-sw03.
      *
-     * You'll notice it also tells us if it's a LAG or not. More information can be added as needed.
+     * All port information is copied over from the supplied / called crawl() array
      *
      * @see crawl()
      * @param array $devices The result of crawl() (if null, this function performs a crawl())
@@ -783,25 +787,128 @@ class CDP extends \OSS\SNMP\MIBS\Cisco
                         $links[ $feDevice ][ $fe2Device ] = array();
 
                     $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ] = array();
-                    $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'remotePort' ]   = $fe2Link['remotePort'];
-                    $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'isLAG' ]        = $fe2Link['isLAG'];
-                    $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'localPortId' ]  = $fe2Link['localPortId'];
-                    $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'remotePortId' ] = $fe2Link['remotePortId'];
 
-                    if( $fe2Link['isLAG'] )
+                    foreach( $fe2Link as $k => $v )
+                        $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ $k ]   = $v;
+                }
+            }
+        }
+
+        return $links;
+    }
+
+
+    /**
+     * Utility function to process the output from neighbours() and remove individual trunk ports leaving only
+     * single LAG links.
+     *
+     * For example, here's a sample return for a switch with a neighbour
+     * connected with a LAG / PortChannel:
+     *
+     * array(2) {
+     *     ["cr-sw01.example.ie"] => array(2) {
+     *         [0] => array(11) {
+     *             ["localPortId"] => int(10111)
+     *             ["localPortName"] => string(8) "Gi1/0/11"
+     *             ["localPort"] => string(21) "GigabitEthernet1/0/11"
+     *             ["isLAG"] => bool(true)
+     *             ["lagPortId"] => int(5048)
+     *             ["lagPortName"] => string(4) "Po48"
+     *             ["remotePort"] => string(21) "GigabitEthernet1/0/11"
+     *             ["remotePortId"] => int(10111)
+     *             ["remotePortName"] => string(8) "Gi1/0/11"
+     *             ["remoteLagPortId"] => int(5048)
+     *             ["remoteLagPortName"] => string(4) "Po48"
+     *         }
+     *         [1] => array(11) {
+     *             ["localPortId"] => int(10112)
+     *             ["localPortName"] => string(8) "Gi1/0/12"
+     *             ["localPort"] => string(21) "GigabitEthernet1/0/12"
+     *             ["isLAG"] => bool(true)
+     *             ["lagPortId"] => int(5048)
+     *             ["lagPortName"] => string(4) "Po48"
+     *             ["remotePort"] => string(21) "GigabitEthernet1/0/12"
+     *             ["remotePortId"] => int(10112)
+     *             ["remotePortName"] => string(8) "Gi1/0/12"
+     *             ["remoteLagPortId"] => int(5048)
+     *             ["remoteLagPortName"] => string(4) "Po48"
+     *         }
+     *     }
+     *     ...
+     * }
+     *
+     * The result of this function would be:
+     *
+     * array(2) {
+     *     ["cr-sw01.example.ie"] => array(1) {
+     *         [0] => array(11) {
+     *             ["localPortId"] => int(5048)
+     *             ["localPortName"] => string(8) "Po48"
+     *             ["localPort"] => string(21) "Po48"
+     *             ["isLAG"] => bool(true)
+     *             ["lagPortId"] => int(5048)
+     *             ["lagPortName"] => string(4) "Po48"
+     *             ["remotePort"] => string(21) "Po48"
+     *             ["remotePortId"] => int(5048)
+     *             ["remotePortName"] => string(8) "Po48"
+     *             ["remoteLagPortId"] => int(5048)
+     *             ["remoteLagPortName"] => string(4) "Po48"
+     *         }
+     *     }
+     *     ...
+     * }
+     *
+     * @see neighbours()
+     * @param array $neighbours The result of a call to neighbours()
+     * @return array Processed CDP neighbours with LAG ports collapsed
+     */
+    public function collapseLAGs( $neighbours )
+    {
+        foreach( $neighbours as $neighbour => $links )
+        {
+            $removed = array();
+            foreach( $links as $idx => $linkDetails )
+            {
+                if( $linkDetails['isLAG'] )
+                {
+                    if( isset( $removed[ $linkDetails['localLagPortId'] ] ) )
+                        unset( $neighbours[ $neighbour ][ $idx ] );
+                    else
                     {
-                        $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'localLagPortId' ]    = $fe2Link['lagPortId'];
-                        $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'localLagPortName' ]  = $fe2Link['lagPortName'];
-                        $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'remoteLagPortId' ]   = $fe2Link['remoteLagPortId'];
-                        $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'remoteLagPortName' ] = $fe2Link['remoteLagPortName'];
-                        $links[ $feDevice ][ $fe2Device ][ $fe2Link['localPort'] ][ 'remotePortId' ]      = $fe2Link['remoteLagPortId'];
+                        $removed[ $linkDetails['localLagPortId'] ] = true;
+                        $neighbours[ $neighbour ][ $idx ]['localPortId']    = $neighbours[ $neighbour ][ $idx ]['lagPortId'];
+                        $neighbours[ $neighbour ][ $idx ]['localPortName']  = $neighbours[ $neighbour ][ $idx ]['lagPortName'];
+                        $neighbours[ $neighbour ][ $idx ]['localPort']      = $neighbours[ $neighbour ][ $idx ]['lagPortName'];
+                        $neighbours[ $neighbour ][ $idx ]['remotePortId']   = $neighbours[ $neighbour ][ $idx ]['remoteLagPortId'];
+                        $neighbours[ $neighbour ][ $idx ]['remotePortName'] = $neighbours[ $neighbour ][ $idx ]['remoteLagPortName'];
+                        $neighbours[ $neighbour ][ $idx ]['remotePort']     = $neighbours[ $neighbour ][ $idx ]['remoteLagPortName'];
                     }
                 }
             }
         }
 
-        return $links;
+        return $neighbours;
     }
+
+    /**
+     * An extension of collapseLAGs() to work with crawl() and linkTopology().
+     *
+     * Rather than taking the input from neighbours(), it takes input from crawl() or linkTopology()
+     * and processes all neighbours.
+     *
+     * @see collapseLAGs()
+     * @param array $devices The result of a call to crawl() or linkTopology()
+     * @return array Processed CDP neighbours with LAG ports collapsed
+     */
+    public function collapseDevicesLAGs( $devices )
+    {
+        foreach( $devices as $parent => $neighbours )
+            $devices[ $parent ] = $this->collapseLAGs( $neighbours );
+
+        return $devices;
+    }
+
+
 }
 
 

+ 8 - 0
OSS/SNMP/MIBS/Cisco/RSTP.php

@@ -106,6 +106,14 @@ class RSTP extends \OSS\SNMP\MIBS\Cisco
         self::STP_X_RSTP_PORT_ROLE_MASTER      => 'master'
     );
 
+    /**
+     * Array of port states that indicate traffic is/can pass
+     * @var Array of port states that indicate traffic is/can pass
+     */
+    public static $STP_X_RSTP_PASSING_PORT_ROLES = array(
+        self::STP_X_RSTP_PORT_ROLE_ROOT        => 'root',
+        self::STP_X_RSTP_PORT_ROLE_DESIGNATED  => 'designated'
+    );
 
     /**
      * Get the device's RSTP port roles (by given vlan id)