mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 13:22:36 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			671 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			671 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/perl
 | 
						|
package xCAT_plugin::vlan::CiscoSwitch;
 | 
						|
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
}
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
use strict;
 | 
						|
use xCAT::MacMap;
 | 
						|
use Data::Dumper;
 | 
						|
use xCAT::SwitchHandler;
 | 
						|
use SNMP;
 | 
						|
 | 
						|
#IF-MIB
 | 
						|
my $ifName       = '.1.3.6.1.2.1.31.1.1.1.1';
 | 
						|
my $ifDescr      = '.1.3.6.1.2.1.2.2.1.2';
 | 
						|
my $ifOperStatus = '.1.3.6.1.2.1.2.2.1.8';
 | 
						|
 | 
						|
#CISCO-VTP-MIB
 | 
						|
my $vtpVlanEditTable               = '.1.3.6.1.4.1.9.9.46.1.4.2';
 | 
						|
my $vtpVlanEditOperation           = '.1.3.6.1.4.1.9.9.46.1.4.1.1.1';
 | 
						|
my $vtpVlanEditBufferOwner         = '.1.3.6.1.4.1.9.9.46.1.4.1.1.3';
 | 
						|
my $vtpVlanEditRowStatus           = '.1.3.6.1.4.1.9.9.46.1.4.2.1.11.1';
 | 
						|
my $vtpVlanEditType                = '.1.3.6.1.4.1.9.9.46.1.4.2.1.3.1';
 | 
						|
my $vtpVlanEditName                = '.1.3.6.1.4.1.9.9.46.1.4.2.1.4.1';
 | 
						|
my $vtpVlanEditDot10Said           = '.1.3.6.1.4.1.9.9.46.1.4.2.1.6.1';
 | 
						|
my $vtpVlanState                   = '.1.3.6.1.4.1.9.9.46.1.3.1.1.2';
 | 
						|
my $vlanTrunkPortDynamicStatus     = '.1.3.6.1.4.1.9.9.46.1.6.1.1.14';
 | 
						|
my $vlanTrunkPortDynamicState      = '.1.3.6.1.4.1.9.9.46.1.6.1.1.13';
 | 
						|
my $vlanTrunkPortNativeVlan        = '.1.3.6.1.4.1.9.9.46.1.6.1.1.5';
 | 
						|
my $vlanTrunkPortVlansEnabled      = '.1.3.6.1.4.1.9.9.46.1.6.1.1.4';
 | 
						|
my $vlanTrunkPortEncapsulationType = '.1.3.6.1.4.1.9.9.46.1.6.1.1.3';
 | 
						|
 | 
						|
#CISCO-VLAN-MEMBERSHIP-MIB
 | 
						|
my $vmVlan     = '.1.3.6.1.4.1.9.9.68.1.2.2.1.2';
 | 
						|
my $vmVlanType = '.1.3.6.1.4.1.9.9.68.1.2.2.1.1';    #1:static 2:dynamic 3:trunk
 | 
						|
 | 
						|
#CISCI-STP-EXTENSION-MIB
 | 
						|
my $stpxRootGuardConfigEnabled = '1.3.6.1.4.1.9.9.82.1.5.1.1.2'; #1:enable 2:disable
 | 
						|
my $stpxFastStartPortBpduGuardMode = '1.3.6.1.4.1.9.9.82.1.9.3.1.4'; #1:enable 2:disable 3:default
 | 
						|
 | 
						|
 | 
						|
my %HexConv = (0 => 0x80, 1 => 0x40, 2 => 0x20, 3 => 0x10,
 | 
						|
    4 => 0x08, 5 => 0x04, 6 => 0x02, 7 => 0x01);
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 filter_string 
 | 
						|
  
 | 
						|
    Every switch plugin must implement this subroutine.
 | 
						|
 | 
						|
    The return value will be used comare against the string 
 | 
						|
    from sysDescr value from snmpget. If the latter contains
 | 
						|
    this string, then this mudule will be used to handle the 
 | 
						|
    requests for vlan configuration.
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub filter_string {
 | 
						|
    return "Cisco ";
 | 
						|
}
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 get_vlan_ids  
 | 
						|
  
 | 
						|
  Every switch plugin must implement this subroutine.
 | 
						|
 | 
						|
  It gets the existing vlan IDs for the switch.
 | 
						|
  Returns:  an array containing all the vlan ids for the switch
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub get_vlan_ids {
 | 
						|
    my $session = shift;
 | 
						|
 | 
						|
    my $vlanmap = xCAT::MacMap::walkoid($session, "$vtpVlanState.1", silentfail => 1);
 | 
						|
    my %vlanids = ();
 | 
						|
    foreach (keys(%$vlanmap)) {
 | 
						|
        $vlanids{$_} = 1;
 | 
						|
    }
 | 
						|
 | 
						|
    my @ret = (sort keys(%vlanids));
 | 
						|
    print "ids=@ret\n";
 | 
						|
    return @ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 get_vlanids_for_ports 
 | 
						|
  
 | 
						|
    Every switch plugin must implement this subroutine.
 | 
						|
 | 
						|
    It returns a hash pointer that contains the vlan ids for each given port.
 | 
						|
    The kay is the port, the vlaue is a pointer to an array.
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub get_vlanids_for_ports {
 | 
						|
    my $session = shift;
 | 
						|
    my @ports   = @_;
 | 
						|
 | 
						|
    my $namemap = xCAT::MacMap::walkoid($session, $ifName);
 | 
						|
 | 
						|
    #namemap is the mapping of ifIndex->(human readable name)
 | 
						|
    if ($namemap) {
 | 
						|
        my $ifnamesupport = 0;
 | 
						|
        foreach (keys %{$namemap}) {
 | 
						|
            if ($namemap->{$_}) {
 | 
						|
                $ifnamesupport = 1;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($ifnamesupport) {
 | 
						|
            $namemap = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches
 | 
						|
        $namemap = xCAT::MacMap::walkoid($session, $ifDescr);
 | 
						|
    }
 | 
						|
    unless ($namemap) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    #print "namemap=" . Dumper($namemap) . "\n";
 | 
						|
 | 
						|
    my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail => 1);
 | 
						|
 | 
						|
    #print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
 | 
						|
 | 
						|
    my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail => 1); #for trunk ports, we are interested in the native vlan
 | 
						|
            #print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
 | 
						|
 | 
						|
    my %ret = ();
 | 
						|
    if (defined($iftovlanmap) or defined($trunktovlanmap)) {
 | 
						|
        foreach my $portid (keys %{$namemap}) {
 | 
						|
            my $switchport = $namemap->{$portid};
 | 
						|
            foreach my $portname (@ports) {
 | 
						|
                unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                if (defined $iftovlanmap->{$portid}) {
 | 
						|
                    $ret{$portname} = [ $iftovlanmap->{$portid} ];
 | 
						|
                } elsif (defined $trunktovlanmap->{$portid}) {
 | 
						|
                    $ret{$portname} = [ $trunktovlanmap->{$portid} ];
 | 
						|
                } else {
 | 
						|
                    $ret{$portname} = ['NA'];
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return \%ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 create_vlan
 | 
						|
  
 | 
						|
    Every switch plugin must implement this subroutine.
 | 
						|
 
 | 
						|
    Creates a new vlan on the switch
 | 
						|
    Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub create_vlan {
 | 
						|
    my $session   = shift;
 | 
						|
    my $vlan_id   = shift;
 | 
						|
    my $vlan_name = "xcat_vlan_" . $vlan_id;
 | 
						|
 | 
						|
    print "Cisco\n";
 | 
						|
 | 
						|
    #Verify if the edition is in use by another NMS station or device.
 | 
						|
    #The edition is not in use if you see this message: no MIB objects contained under subtree:
 | 
						|
    my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditTable);
 | 
						|
 | 
						|
    #print "tmp=" . Dumper($tmp) . "\n";
 | 
						|
 | 
						|
    #Set the vtpVlanEditOperation to the copy state(2). This allows to create the VLAN.
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 2, 'INTEGER');
 | 
						|
 | 
						|
    #if ($ret[0] != 0) { return @ret; }
 | 
						|
 | 
						|
    #set vtpVlanEditBufferOwner in order to makethe current owner of the edit permission visible
 | 
						|
    my $username = "xcat";
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditBufferOwner, 1, $username, 'OCTET');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditBufferOwner $vtpVlanEditBufferOwner.1 to $username.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditOperation);
 | 
						|
    #print "tmp=" . Dumper($tmp) . "\n";
 | 
						|
 | 
						|
    #my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditBufferOwner);
 | 
						|
    #print "tmp=" . Dumper($tmp) . "\n";
 | 
						|
 | 
						|
    #set vtpVlanEditRowStatus to createAndGo(4)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditRowStatus, $vlan_id, 4, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditRowStatus $vtpVlanEditRowStatus.$vlan_id to 4.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #set vtpVlanEditType to ethernet (1)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditType, $vlan_id, 1, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditType $vtpVlanEditType.$vlan_id to 1.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #set vtpVlanEditName to xcat_vlan_#
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditName, $vlan_id, $vlan_name, 'OCTET');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditName $vtpVlanEditName.$vlan_id to $vlan_name.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #Set the vtpVlanEditDot10Said. This is the VLAN number + 100000 translated to hexadecimal.
 | 
						|
    my $num = 100000 + $vlan_id;
 | 
						|
    my $hex_num = sprintf("%x", $num);
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditDot10Said, $vlan_id, $hex_num, 'OCTETHEX');
 | 
						|
 | 
						|
    #if ($ret[0] != 0) {
 | 
						|
    #	$ret[1]="Set vtpVlanEditDot10Said $vtpVlanEditDot10Said.$vlan_id to $hex_num.\n" . $ret[1];
 | 
						|
    #return @ret;
 | 
						|
    #}
 | 
						|
 | 
						|
    #apply the changes, set vtpVlanEditOperation.1 to apply (3)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 3, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 3.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #release the edition buffer, set vtpVlanEditOperation.1 to release (4)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 4, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 4.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    return (0, "");
 | 
						|
}
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 add_ports_to_vlan   
 | 
						|
 | 
						|
    Every switch plugin must implement this subroutine.
 | 
						|
 | 
						|
    Adds the given ports to the existing vlan
 | 
						|
    Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub add_ports_to_vlan {
 | 
						|
    my $session = shift;
 | 
						|
    my $vlan_id = shift;
 | 
						|
 | 
						|
    # If portmode is set, we'll set the switchport to untagged(access) mode.
 | 
						|
    my $portmode = shift;
 | 
						|
    my @ports    = @_;
 | 
						|
 | 
						|
    #print "Add ports @ports to vla $vlan_id.\n";
 | 
						|
 | 
						|
    #add ports to the vlan.
 | 
						|
    if (@ports > 0) {
 | 
						|
        my $namemap = xCAT::MacMap::walkoid($session, $ifName);
 | 
						|
 | 
						|
        #namemap is the mapping of ifIndex->(human readable name)
 | 
						|
        if ($namemap) {
 | 
						|
            my $ifnamesupport = 0; #Assume broken ifnamesupport until proven good... (Nortel switch)
 | 
						|
            foreach (keys %{$namemap}) {
 | 
						|
                if ($namemap->{$_}) {
 | 
						|
                    $ifnamesupport = 1;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            unless ($ifnamesupport) {
 | 
						|
                $namemap = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches
 | 
						|
            $namemap = xCAT::MacMap::walkoid($session, $ifDescr);
 | 
						|
        }
 | 
						|
        unless ($namemap) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        #print "namemap=" . Dumper($namemap) . "\n";
 | 
						|
 | 
						|
        my $trunkportstate = xCAT::MacMap::walkoid($session, $vlanTrunkPortDynamicState);
 | 
						|
 | 
						|
        #print "trunkportstate=" . Dumper($trunkportstate) . "\n";
 | 
						|
 | 
						|
        my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail => 1);
 | 
						|
 | 
						|
        #print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
 | 
						|
        my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail => 1);
 | 
						|
 | 
						|
        #print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
 | 
						|
 | 
						|
        #get current vlan type (static, dynamic or trunk)
 | 
						|
        my $vlantypemap = xCAT::MacMap::walkoid($session, $vmVlanType, silentfail => 1);
 | 
						|
 | 
						|
        #print "vlantypemap=" . Dumper($vlantypemap) . "\n";
 | 
						|
 | 
						|
 | 
						|
        foreach my $portid (keys %{$namemap}) {
 | 
						|
            my $switchport = $namemap->{$portid};
 | 
						|
            foreach my $portname (@ports) {
 | 
						|
                unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
 | 
						|
                ### set the port to trunk mode
 | 
						|
                print "portid=$portid\n";
 | 
						|
 | 
						|
                # TODO: need testing in cisco's env for how to set a port as access mode through snmpset?
 | 
						|
                # Can setting vlanTrunkPortDot1qTunnel or cltcDot1qTunnelMode helps?
 | 
						|
                if ($trunkportstate->{$portid} != 1) {
 | 
						|
                    my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortEncapsulationType, $portid, 4, 'INTEGER');
 | 
						|
                    if ($ret[0] != 0) {
 | 
						|
                        $ret[1] = "Set vlanTrunkPortEncapsulationType $vlanTrunkPortEncapsulationType.$portid to 4(dot1Q).\n" . $ret[1];
 | 
						|
                        return @ret;
 | 
						|
                    }
 | 
						|
                    my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortDynamicState, $portid, 1, 'INTEGER');
 | 
						|
                    if ($ret[0] != 0) {
 | 
						|
                        $ret[1] = "Set vlanTrunkPortDynamicState $vlanTrunkPortDynamicState.$portid to 1.\n" . $ret[1];
 | 
						|
                        return @ret;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
 | 
						|
                ### set trunk native vlan id
 | 
						|
                my $native_vlanid = 1;
 | 
						|
                if ((exists($vlantypemap->{$portid})) && ($vlantypemap->{$portid} < 3)) { #the port was set to access mode before
 | 
						|
                    if ((exists($iftovlanmap->{$portid})) && ($iftovlanmap->{$portid} > 0)) {
 | 
						|
                        $native_vlanid = $iftovlanmap->{$portid};
 | 
						|
                    }
 | 
						|
                } else {    #the port is originally set to trunk mode
 | 
						|
                    if ((exists($trunktovlanmap->{$portid})) && ($trunktovlanmap->{$portid} > 0)) {
 | 
						|
                        $native_vlanid = $trunktovlanmap->{$portid};
 | 
						|
                    } elsif ((exists($iftovlanmap->{$portid})) && ($iftovlanmap->{$portid} > 0)) {
 | 
						|
                        $native_vlanid = $iftovlanmap->{$portid};
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                print "*** native_vlanid=$native_vlanid\n";
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortNativeVlan, $portid, $native_vlanid, 'INTEGER');
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Set native vlan for port $portid to $native_vlanid ($vlanTrunkPortNativeVlan.$portid to $native_vlanid).\n" . $ret[1];
 | 
						|
                    return @ret;
 | 
						|
                }
 | 
						|
 | 
						|
 | 
						|
                ### allow this vlan on the port
 | 
						|
                my $data = $session->get([ $vlanTrunkPortVlansEnabled, $portid ]);
 | 
						|
                my @a = split(//, $data);
 | 
						|
                foreach (@a) {
 | 
						|
                    my $num = unpack("C*", $_);
 | 
						|
                    $_ = sprintf("%02x", $num);
 | 
						|
                }
 | 
						|
                if ((exists($vlantypemap->{$portid})) && ($vlantypemap->{$portid} < 3)) {
 | 
						|
 | 
						|
                    #if originally this port was in access or dynamic mode, only enable original vlan and this tagged vlan
 | 
						|
                    #reset the matrix
 | 
						|
                    #print "***was access mode\n";
 | 
						|
                    foreach (@a) {
 | 
						|
                        $_ = "00";
 | 
						|
                    }
 | 
						|
 | 
						|
                    #add native vlan id in the matrix
 | 
						|
                    my $index  = int($native_vlanid / 8);
 | 
						|
                    my $offset = $native_vlanid % 8;
 | 
						|
                    my $num    = hex($a[$index]) | $HexConv{$offset};
 | 
						|
                    $a[$index] = sprintf("%02x", $num);
 | 
						|
 | 
						|
                    #print "index=$index, offset=$offset\n";
 | 
						|
 | 
						|
                    #add current vlan id in the matrix
 | 
						|
                    $index  = int($vlan_id / 8);
 | 
						|
                    $offset = $vlan_id % 8;
 | 
						|
                    $num    = hex($a[$index]) | $HexConv{$offset};
 | 
						|
                    $a[$index] = sprintf("%02x", $num);
 | 
						|
                } else {
 | 
						|
 | 
						|
                    #if this port was trunk mode before, add this tagged vlan in the matrix
 | 
						|
                    # print "***was trunk mode\n";
 | 
						|
                    my $index  = int($vlan_id / 8);
 | 
						|
                    my $offset = $vlan_id % 8;
 | 
						|
                    my $num    = hex($a[$index]) | $HexConv{$offset};
 | 
						|
                    $a[$index] = sprintf("%02x", $num);
 | 
						|
                }
 | 
						|
 | 
						|
                #print "a=@a\n";
 | 
						|
                foreach (@a) {
 | 
						|
                    $_ = hex($_);
 | 
						|
                    $_ = pack("C*", $_);
 | 
						|
                }
 | 
						|
                my $s = join(//, @a);
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortVlansEnabled, $portid, $s, 'OCTET');
 | 
						|
 | 
						|
                #print "**** ret=@ret\n";
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Allow vlan on port $portid ($vlanTrunkPortVlansEnabled.$portid=$s).\n" . $ret[1];
 | 
						|
                    return @ret;
 | 
						|
                }
 | 
						|
 | 
						|
 | 
						|
                ### security feature
 | 
						|
                if ($::XCATSITEVALS{vlansecurity} eq '1') {
 | 
						|
 | 
						|
                    #set root guard on the port
 | 
						|
                    my @ret = xCAT::SwitchHandler::setoid($session, $stpxRootGuardConfigEnabled, $portname, 1, 'INTEGER');
 | 
						|
                    if ($ret[0] != 0) {
 | 
						|
                        $ret[1] = "Set root guard for port $portname to enable ($stpxRootGuardConfigEnabled.$portname=1).\n" . $ret[1];
 | 
						|
                        return @ret;
 | 
						|
                    }
 | 
						|
 | 
						|
                    #set bpdu guard on the port
 | 
						|
                    my @ret = xCAT::SwitchHandler::setoid($session, $stpxFastStartPortBpduGuardMode, $portname, 1, 'INTEGER');
 | 
						|
                    if ($ret[0] != 0) {
 | 
						|
                        $ret[1] = "Set bpdu guard for port $portname to enalbe ($stpxFastStartPortBpduGuardMode.$portname=1).\n" . $ret[1];
 | 
						|
                        return @ret;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return (0, "");
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=head3  add_crossover_ports_to_vlan
 | 
						|
  It enables the vlan on the cross-over links.
 | 
						|
    Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
sub add_crossover_ports_to_vlan {
 | 
						|
    my $session  = shift;
 | 
						|
    my $vlan_id  = shift;
 | 
						|
    my $switch   = shift;
 | 
						|
    my @switches = @_;
 | 
						|
    my @ret      = (0, "");
 | 
						|
    my $msg;
 | 
						|
 | 
						|
    if (@switches == 0) { return (0, ""); }
 | 
						|
 | 
						|
    #get the ports that are connects to the switches
 | 
						|
    my $switchestab = xCAT::Table->new('switches', -create => 0);
 | 
						|
    my $ent = $switchestab->getNodeAttribs($switch, [qw(switch linkports)]);
 | 
						|
    if ((!$ent) || (!$ent->{linkports})) { return (0, $msg); }
 | 
						|
 | 
						|
    my %linkports = ();
 | 
						|
    foreach my $item (split(',', $ent->{linkports})) {
 | 
						|
        my @a = split(':', $item);
 | 
						|
        if (@a > 1) {
 | 
						|
            $linkports{ $a[1] } = $a[0];
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #print Dumper(%linkports);
 | 
						|
 | 
						|
    my @ports = ();
 | 
						|
    foreach my $sw (@switches) {
 | 
						|
        if (exists($linkports{$sw})) {
 | 
						|
            push(@ports, $linkports{$sw});
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #print "ports=@ports\n";
 | 
						|
 | 
						|
    #now add the ports to the vlan
 | 
						|
    if (@ports > 0) {
 | 
						|
        my ($code, $msg1) = add_ports_to_vlan($session, $vlan_id, @ports);
 | 
						|
        if ($msg) {
 | 
						|
            $msg1 = $msg . $msg1;
 | 
						|
        }
 | 
						|
 | 
						|
        return ($code, $msg1);
 | 
						|
    }
 | 
						|
 | 
						|
    return (0, $msg);
 | 
						|
}
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 remove_vlan   
 | 
						|
 | 
						|
    Every switch plugin must implement this subroutine.
 | 
						|
 | 
						|
    Remove a vlan from the switch
 | 
						|
    Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub remove_vlan {
 | 
						|
    my $session = shift;
 | 
						|
    my $vlan_id = shift;
 | 
						|
 | 
						|
    #Verify if the edition is in use by another NMS station or device.
 | 
						|
    #The edition is not in use if you see this message: no MIB objects contained under subtree:
 | 
						|
    my $tmp = xCAT::MacMap::walkoid($session, $vtpVlanEditTable);
 | 
						|
 | 
						|
    #print "tmp=" . Dumper($tmp) . "\n";
 | 
						|
 | 
						|
    #Set the vtpVlanEditOperation to the copy state(2). This allows to delete the VLAN.
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 2, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 3 (copy state).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #set vtpVlanEditBufferOwner in order to makethe current owner of the edit permission visible
 | 
						|
    my $username = "xcat";
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditBufferOwner, 1, $username, 'OCTET');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditBufferOwner $vtpVlanEditBufferOwner.1 to $username.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #set vtpVlanEditRowStatus to destroy(6)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditRowStatus, $vlan_id, 6, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditRowStatus $vtpVlanEditRowStatus.$vlan_id to 6 (destroy).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #apply the changes, set vtpVlanEditOperation.1 to apply (3)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 3, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set $vtpVlanEditOperation.1 to 3 (apply).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #release the edition buffer, set vtpVlanEditOperation.1 to release (4)
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $vtpVlanEditOperation, 1, 4, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vtpVlanEditOperation $vtpVlanEditOperation.1 to 4 (release).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    #my $iftovlanmap = xCAT::MacMap::walkoid($session, $vmVlan, silentfail=>1);
 | 
						|
    #print "iftovlanmap=" . Dumper($iftovlanmap) . "\n";
 | 
						|
    #foreach (keys(%$iftovlanmap)) {
 | 
						|
    #	if($iftovlanmap->{$_} == $vlan_id) {
 | 
						|
    #my @ret= xCAT::SwitchHandler::setoid($session, $vmVlan, $_, 1, 'INTEGER');
 | 
						|
    #if ($ret[0] != 0) {
 | 
						|
    #	$ret[1]="Set $vmVlan.$_ to 1.\n" . $ret[1];
 | 
						|
    #   return @ret;
 | 
						|
    #}
 | 
						|
    #	}
 | 
						|
    #}
 | 
						|
    #my $trunktovlanmap = xCAT::MacMap::walkoid($session, $vlanTrunkPortNativeVlan, silentfail=>1); #for trunk ports, we are interested in the native vlan
 | 
						|
    #print "trunktovlanmap=" . Dumper($trunktovlanmap) . "\n";
 | 
						|
    #foreach (keys(%$trunktovlanmap)) {
 | 
						|
    #	if($trunktovlanmap->{$_} == $vlan_id) {
 | 
						|
    # my @ret= xCAT::SwitchHandler::setoid($session, $vlanTrunkPortNativeVlan, $_, 1, 'INTEGER');
 | 
						|
    # if ($ret[0] != 0) {
 | 
						|
    #	$ret[1]="Set $vlanTrunkPortNativeVlan.$_ to 1.\n" . $ret[1];
 | 
						|
    #	return @ret;
 | 
						|
    # }
 | 
						|
    #	}
 | 
						|
    #}
 | 
						|
 | 
						|
 | 
						|
    return (0, "");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=head3 remove_ports_from_vlan  
 | 
						|
 | 
						|
    Every switch plugin must implement this subroutine.
 | 
						|
 | 
						|
    Remove ports from a vlan
 | 
						|
    Returns an array. (erorcode, errormsg). When errorcode=0, means no error.
 | 
						|
=cut
 | 
						|
 | 
						|
#-------------------------------------------------------------
 | 
						|
sub remove_ports_from_vlan {
 | 
						|
    my $session = shift;
 | 
						|
    my $vlan_id = shift;
 | 
						|
    my @ports   = @_;
 | 
						|
 | 
						|
 | 
						|
    if (@ports > 0) {
 | 
						|
        my $namemap = xCAT::MacMap::walkoid($session, $ifName);
 | 
						|
 | 
						|
        #namemap is the mapping of ifIndex->(human readable name)
 | 
						|
        if ($namemap) {
 | 
						|
            my $ifnamesupport = 0;
 | 
						|
            foreach (keys %{$namemap}) {
 | 
						|
                if ($namemap->{$_}) {
 | 
						|
                    $ifnamesupport = 1;
 | 
						|
                    last;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            unless ($ifnamesupport) {
 | 
						|
                $namemap = 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($namemap) { #Failback to ifDescr.  ifDescr is close, but not perfect on some switches
 | 
						|
            $namemap = xCAT::MacMap::walkoid($session, $ifDescr);
 | 
						|
        }
 | 
						|
        unless ($namemap) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        #print "namemap=" . Dumper($namemap) . "\n";
 | 
						|
 | 
						|
        foreach my $portid (keys %{$namemap}) {
 | 
						|
            my $switchport = $namemap->{$portid};
 | 
						|
            foreach my $portname (@ports) {
 | 
						|
                unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                #remove the vlan id from the vlanTrunkPortVlansEnabled.port  matrix
 | 
						|
                my $data = $session->get([ $vlanTrunkPortVlansEnabled, $portid ]);
 | 
						|
                my @a = split(//, $data);
 | 
						|
                foreach (@a) {
 | 
						|
                    my $num = unpack("C*", $_);
 | 
						|
                    $_ = sprintf("%02x", $num);
 | 
						|
                }
 | 
						|
 | 
						|
                #print "a=@a\n";
 | 
						|
                my $index  = int($vlan_id / 8);
 | 
						|
                my $offset = $vlan_id % 8;
 | 
						|
                my $num    = hex($a[$index]) & (~$HexConv{$offset});
 | 
						|
                $a[$index] = sprintf("%02x", $num);
 | 
						|
 | 
						|
                #print "a=@a\n";
 | 
						|
 | 
						|
                foreach (@a) {
 | 
						|
                    $_ = hex($_);
 | 
						|
                    $_ = pack("C*", $_);
 | 
						|
                }
 | 
						|
 | 
						|
                my $s = join(//, @a);
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $vlanTrunkPortVlansEnabled, $portid, $s, 'OCTET');
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Set vlanTrunkPortVlansEnabled $vlanTrunkPortVlansEnabled.$portid to $s.\n" . $ret[1];
 | 
						|
                    return @ret;
 | 
						|
                }
 | 
						|
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return (0, "");
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
1;
 |