View Issue Details

IDProjectCategoryView StatusLast Update
533RackTables802.1Q VLANspublic2012-03-01 13:37
Reporteruser287Assigned Toinfrastation  
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Product Version0.19.11 
Target Version0.19.12Fixed in Version0.19.12 
Summary533: Adding support for D-Link L2 switches
DescriptionInitial support for communicating with D-Link hardware:
get VLAN list, get port status list, get MAC list.

Tested on DES-3xxx with fresh firmware.

Side effect: disables CLI paging.
TagsNo tags attached.

Relationships

parent of 537 closedinfrastation Bugfix D-Link support 

Activities

2012-02-28 21:29

 

racktables-0.19.11-dlink.diff (11,927 bytes)   
Index: gateways/deviceconfig/dlink.connector
===================================================================
--- gateways/deviceconfig/dlink.connector       (revision 0)
+++ gateways/deviceconfig/dlink.connector       (revision 0)
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+#  ./racktables/gateways/deviceconfig/dlink.connector
+#
+#  Written by evseev@fastvps.ru at Feb-2011
+#  Based on ios12.connector
+#
+
+[ $# = 3 ] || exit 1
+
+ENDPOINT=$1
+COMMAND=$2
+WORKFILE=$3
+
+prepare_connect_commands()
+{
+       [ $# = 1 ] || exit 2
+       local skip=yes cval found=no MYDIR=`dirname $0`
+       while read line; do
+               if [ "$skip" = "yes" -a "$line" = "# S-T-A-R-T" ]; then
+                       skip=no
+                       continue
+               fi
+               if [ "$skip" = "no" -a "$line" = "# S-T-O-P" ]; then
+                       skip=yes
+                       continue
+               fi
+               [ "$skip" = "yes" ] && continue
+               # ignore comments
+               [ -z "${line###*}" ] && continue
+
+               # First endpoint string/regexp match is sufficient for us.
+               cval=`echo $line | cut -s -d' ' -f1`
+               if [ -z "${1##$cval}" ]; then
+                       found=yes
+                       username=`echo $line | cut -s -d' ' -f5`
+                       [ "$username" != "-" ] && echo $username > $SESSION
+                       # access password
+                       echo $line | cut -s -d' ' -f6 >> $SESSION
+                       enable_password=`echo $line | cut -s -d' ' -f7`
+                       [ "$enable_password" != "-" ] && {
+                               echo 'enable admin' >> $SESSION
+                               echo $enable_password >> $SESSION
+                       }
+                       break
+               fi
+               echo 'disable clipaging' >> "$SESSION"  # ..requires admin!
+       done < "$MYDIR/switch.secrets.php"
+       [ "$found" = "yes" ] && return
+       exit 3
+}
+
+MYNAME=`basename $0`
+SESSION=`mktemp /tmp/$MYNAME.XXXXXX`
+[ -f "$SESSION" ] || exit 5
+prepare_connect_commands $ENDPOINT
+case $COMMAND in
+get8021q)
+       echo 'show vlan' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
+getportstatus)
+       echo 'show ports' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
+getmaclist)
+       echo 'show fdb' >> "$SESSION"
+       outfile="$WORKFILE"
+       ;;
+deploy)
+       cat "$WORKFILE" >> "$SESSION"
+       outfile=/dev/null
+       ;;
+*)
+       rm -f "$SESSION"
+       exit 6
+       ;;
+esac
+echo 'logout' >> "$SESSION"
+#echo "[ $(date +'%Y.%m.%d %H:%M:%S') ]  cmd=$COMMAND, ep=$ENDPOINT, wf=$WORKFILE, sess=$SESSION, of=$outfile" >> /tmp/dlink.connector.debug
+rc=0
+nc -w 30 $ENDPOINT 23 < "$SESSION" > "$outfile" || rc=4
+#cp -p "$outfile" "$outfile.copy"
+rm -f "$SESSION"
+exit $rc

Property changes on: gateways/deviceconfig/dlink.connector
___________________________________________________________________
Added: svn:executable
   + *

Index: wwwroot/inc/gateways.php
===================================================================
--- wwwroot/inc/gateways.php    (revision 4865)
+++ wwwroot/inc/gateways.php    (working copy)
@@ -30,6 +30,7 @@
 );
 $gwrxlator['get8021q'] = array
 (
+       'dlink' => 'dlinkReadVLANConfig',
        'ios12' => 'ios12ReadVLANConfig',
        'fdry5' => 'fdry5ReadVLANConfig',
        'vrp53' => 'vrp53ReadVLANConfig',
@@ -40,6 +41,7 @@
 );
 $gwrxlator['getportstatus'] = array
 (
+       'dlink' => 'dlinkReadInterfaceStatus',
        'ios12' => 'ciscoReadInterfaceStatus',
        'vrp53' => 'vrpReadInterfaceStatus',
        'vrp55' => 'vrpReadInterfaceStatus',
@@ -47,6 +49,7 @@
 );
 $gwrxlator['getmaclist'] = array
 (
+       'dlink' => 'dlinkReadMacList',
        'ios12' => 'ios12ReadMacList',
        'vrp53' => 'vrp53ReadMacList',
        'vrp55' => 'vrp55ReadMacList',
@@ -334,8 +337,14 @@
                1367 => 'jun10',
        );
        foreach (getAttrValues ($object_id) as $record)
+       {
+               // See Attribute table: ID = 4, Type = 'dict', Name = 'SW Type'
                if ($record['id'] == 4 and array_key_exists ($record['key'], $breed_by_swcode))
                        return $breed_by_swcode[$record['key']];
+               // See Attribute table: ID = 2, Type = 'dict', Name = 'HW Type'
+               if ($record['id'] == 2 and $record['key'] >= 589 and $record['key'] <= 637)
+                       return 'dlink';
+       }
        return '';
 }

Index: wwwroot/inc/deviceconfig.php
===================================================================
--- wwwroot/inc/deviceconfig.php        (revision 4865)
+++ wwwroot/inc/deviceconfig.php        (working copy)
@@ -183,6 +183,119 @@
        return $ret;
 }

+/*
+D-Link VLAN info sample:
+========================
+VID             : 72          VLAN Name       : v72
+VLAN Type       : Static      Advertisement   : Disabled
+Member Ports    : 1-16,25-28
+Static Ports    : 1-16,25-28
+Current Tagged Ports   : 25-28
+Current Untagged Ports : 1-16
+Static Tagged Ports    : 25-28
+Static Untagged Ports  : 1-16
+Forbidden Ports        :
+*/
+function dlinkReadVLANConfig ($input)
+{
+       $ret = array
+       (
+               'vlanlist' => array(),
+               'portdata' => array(),
+       );
+       $procfunc = 'dlinkScanTopLevel';
+       foreach (preg_split("/\n\r?/", $input) as $line)
+               $procfunc = $procfunc ($ret, $line);
+       return $ret;
+}
+
+function dlinkScanTopLevel(&$work, $line)
+{
+       $matches = array();
+       switch(TRUE)
+       {
+       case (preg_match('@^\s*VID\s*:\s*(\d+)\s+.*name\s*:\s*(.+)$@i', $line, $matches)):
+               $work['current'] = array
+               (
+                              'vlan_id' => $matches[1],
+                            'vlan_name' => $matches[2],
+                         'tagged_ports' => '',
+                       'untagged_ports' => '',
+               );
+               return 'dlinkPickVLANCommand';
+       default:
+               return __FUNCTION__;
+       }
+}
+
+function dlinkPickVLANCommand(&$work, $line)
+{
+       switch(TRUE)
+       {
+       case (preg_match ('@END OF VLAN LIST@', $line)):
+       case (trim($line) === ''):
+               if (!isset($work['current']))
+                       break;
+               $work['vlanlist'][] = $work['current']['vlan_id'];
+               foreach (dlinkParsePortList ($work['current']['tagged_ports']) as $port_name)
+                       dlinkStorePortInfo ($work, $port_name, 'trunk', 'trunk');
+               foreach (dlinkParsePortList ($work['current']['untagged_ports']) as $port_name)
+                       dlinkStorePortInfo ($work, $port_name, 'access');
+               unset ($work['current']);
+               return 'dlinkScanTopLevel';
+       case (preg_match('@current tagged ports\s*:\s*([[:digit:]]+.*)$@i', $line, $matches)):
+               $work['current']['tagged_ports'] = $matches[1];
+               break;
+       case (preg_match('@current untagged ports\s*:\s*([[:digit:]]+.*)$@i', $line, $matches)):
+               $work['current']['untagged_ports'] = $matches[1];
+               break;
+//     default:
+//             error_log("dlinkPickVLANCommand: skip: \"$line\".");
+       }
+       return __FUNCTION__;
+}
+
+function dlinkStorePortInfo (&$work, $port_name, $new_mode, $overwrite_mode = '')
+{
+       if (!array_key_exists($port_name, $work['portdata']))
+       {
+               $work['portdata'][$port_name] = array
+               (
+                          'mode' => $new_mode,
+                       'allowed' => array($work['current']['vlan_id']),
+                        'native' => $work['current']['vlan_id']
+               );
+               return;
+       }
+       $work['portdata'][$port_name]['allowed'][] = $work['current']['vlan_id'];
+       if ($overwrite_mode !== '')
+               $work['portdata'][$port_name]['mode'] = $overwrite_mode;
+}
+
+// portlist = range[,range..]
+// range = N[-N]
+function dlinkParsePortList($portlist)
+{
+       $ret = array();
+       foreach(explode(',', $portlist) as $port_range)
+       {
+               $a = explode('-', $port_range);
+               switch (count($a))
+               {
+               case 1:
+                       $ret[] = $port_range;
+                       break;
+               case 2:
+                       for ($p = $a[0]; $p <= $a[1]; $p++)
+                               $ret[] = $p;
+                       break;
+               default:
+                       // ..impossible?
+               }
+       }
+       return $ret;
+}
+
 function ios12ReadVLANConfig ($input)
 {
        $ret = array
@@ -1416,6 +1529,43 @@
        return $ret;
 }

+/*
+ D-Link "show ports" output sample
+ =================================
+
+ Port   State/          Settings             Connection           Address
+        MDI       Speed/Duplex/FlowCtrl  Speed/Duplex/FlowCtrl    Learning
+ -----  --------  ---------------------  ---------------------    --------
+ 1      Enabled   Auto/Disabled          100M/Full/None           Enabled
+        Auto
+ ...
+ 26(C)  Enabled   Auto/Disabled          LinkDown                 Enabled
+        Auto
+ 26(F)  Enabled   Auto/Disabled          LinkDown                 Enabled
+*/
+function dlinkReadInterfaceStatus ($text)
+{
+       $result = array();
+       foreach (preg_split ("/\n\r?/", $text) as $line)
+       {
+               if (!preg_match ('/^\s*\d+/', $line))
+                       continue;
+               $w = preg_split ('/\s+/', strtolower($line));
+               if (count($w) != 5)
+                       continue;
+               $port_name = $w[0];
+               if ($w[1] != 'enabled') {
+                       $result[$portname] = array ('status'=>'disabled', 'speed'=>0, 'duplex'=>'');
+               } elseif ($w[3] == 'linkdown') {
+                       $result[$portname] = array ('status'=>'down', 'speed'=>0, 'duplex'=>'');
+               } else {
+                       $s = split('/', $w[3]);
+                       $result[$portname] = array ('status'=>'up', 'speed'=>$s[0], 'duplex'=>$s[1]);
+               }
+       }
+       return $result;
+}
+
 function ciscoReadInterfaceStatus ($text)
 {
        $result = array();
@@ -1501,6 +1651,37 @@
        return ($a['vid'] < $b['vid']) ? -1 : 1;
 }

+/*
+D-Link "show fdb" output sample
+===============================
+
+VID  VLAN Name                        MAC Address       Port Type
+---- -------------------------------- ----------------- ---- ---------------
+1    default                          00-1B-2C-5F-4E-AE 27   Dynamic
+99   switch                           00-00-3E-11-B7-52 27   Dynamic
+99   switch                           84-C9-B2-36-80-F2 27   Dynamic
+*/
+function dlinkReadMacList ($text)
+{
+       $result = array();
+       foreach (preg_split ("/\n\r?/", $text) as $line)
+       {
+               if (!preg_match ('/^\s*\d+\s+/', $line))
+                       continue;
+               $w = preg_split ('/\s+/', $line);
+               if (count($w) != 5)
+                       continue;
+               $result[$w[3]][] = array
+               (
+                       'mac' => $w[2],
+                       'vid' => $w[0],
+               );
+       }
+       foreach ($result as $portname => &$maclist)
+               usort ($maclist, 'maclist_sort');
+       return $result;
+}
+
 function ios12ReadMacList ($text)
 {
        $result = array();
racktables-0.19.11-dlink.diff (11,927 bytes)   
infrastation

infrastation

2012-03-01 13:37

administrator   ~0000621

(Note that I don't have the hardware to test this code against.) Merged into maintenance-0.19.x branch, the changes will be available in 0.19.12 release. Please consider sending next diffs without converting tabs into 8 spaces.

As soon as 0.20.x series comes with a refactored gateway code, someone will have to take the care of forward-porting the feature (this should not be hard).

Thank you.

Issue History

Date Modified Username Field Change
2012-02-28 21:29 user287 New Issue
2012-02-28 21:29 user287 Status new => assigned
2012-02-28 21:29 user287 Assigned To => infrastation
2012-02-28 21:29 user287 File Added: racktables-0.19.11-dlink.diff
2012-03-01 13:37 infrastation Note Added: 0000621
2012-03-01 13:37 infrastation Status assigned => closed
2012-03-01 13:37 infrastation Resolution open => fixed
2012-03-01 13:37 infrastation Fixed in Version => 0.19.12
2012-03-01 13:37 infrastation Target Version => 0.19.12
2012-03-02 09:50 infrastation Relationship added parent of 537