mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			655 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/perl
 | 
						|
package xCAT_plugin::vlan::BNTSwitch;
 | 
						|
 | 
						|
BEGIN
 | 
						|
{
 | 
						|
    $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
 | 
						|
}
 | 
						|
use lib "$::XCATROOT/lib/perl";
 | 
						|
use strict;
 | 
						|
use xCAT::MacMap;
 | 
						|
use xCAT::Table;
 | 
						|
use Data::Dumper;
 | 
						|
use xCAT::SwitchHandler;
 | 
						|
use SNMP;
 | 
						|
 | 
						|
my $sysDescr = '.1.3.6.1.2.1.1.1';
 | 
						|
 | 
						|
#BNT uses different OIDs for different switch module and versions. The following
 | 
						|
#assumes that the FW versions are v6.x.
 | 
						|
#G8100 is not supported yet because it uses different method. No hw to test.
 | 
						|
my $BNTOID = {
 | 
						|
    'EN4093' => {
 | 
						|
        'vlanInfoId'         => '.1.3.6.1.4.1.20301.2.5.2.3.5.1.1.1',
 | 
						|
        'vlanInfoPorts'      => '.1.3.6.1.4.1.20301.2.5.2.3.5.1.1.7',
 | 
						|
        'portInfoPhyIfDescr' => '.1.3.6.1.4.1.20301.2.5.1.3.2.1.1.6',
 | 
						|
        'vlanNewCfgVlanName' => '.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.2',
 | 
						|
        'vlanNewCfgState' => '.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.4', #2:enable 3:disable
 | 
						|
        'vlanNewCfgAddPort'    => '.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.5',
 | 
						|
        'vlanNewCfgRemovePort' => '.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.6',
 | 
						|
        'vlanNewCfgDelete' => '.1.3.6.1.4.1.20301.2.5.2.1.1.3.1.7', #1:other 2:delete
 | 
						|
        'agPortNewCfgVlanTag' => '.1.3.6.1.4.1.20301.2.5.1.1.2.3.1.3', #2:tagged 3:untagged
 | 
						|
        'agPortNewCfgBpduGuard' => '.1.3.6.1.4.1.20301.2.5.1.1.2.3.1.41', #1:enable 2:disable
 | 
						|
        'agPortNewCfgStpExtGuard' => '.1.3.6.1.4.1.20301.2.5.1.1.2.3.1.52', #1:loop, 2:root, 3:none, 0:default
 | 
						|
        'agApplyConfig'           => '.1.3.6.1.4.1.20301.2.5.1.1.8.2',
 | 
						|
        'agSaveConfiguration'     => '.1.3.6.1.4.1.20301.2.5.1.1.1.4',      #saveActive(2), notSaveActive(3)
 | 
						|
        'arpInfoDestIp'           => '.1.3.6.1.4.1.20301.2.5.3.3.2.1.1.1',
 | 
						|
        'arpInfoSrcPort'          => '.1.3.6.1.4.1.20301.2.5.3.3.2.1.1.4',
 | 
						|
    },
 | 
						|
 | 
						|
    'G8000' => {
 | 
						|
        'vlanInfoId'         => '.1.3.6.1.4.1.26543.2.7.1.2.3.5.1.1.1',
 | 
						|
        'vlanInfoPorts'      => '.1.3.6.1.4.1.26543.2.7.1.2.3.5.1.1.7',
 | 
						|
        'portInfoPhyIfDescr' => '.1.3.6.1.4.1.26543.2.7.1.1.3.2.1.1.6',
 | 
						|
        'vlanNewCfgVlanName' => '.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.2',
 | 
						|
        'vlanNewCfgState' => '.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.4', #2:enable 3:disable
 | 
						|
        'vlanNewCfgAddPort'    => '.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.5',
 | 
						|
        'vlanNewCfgRemovePort' => '.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.6',
 | 
						|
        'vlanNewCfgDelete' => '.1.3.6.1.4.1.26543.2.7.1.2.1.1.3.1.7', #1:other 2:delete
 | 
						|
        'agPortNewCfgVlanTag' => '.1.3.6.1.4.1.26543.2.7.1.1.1.2.3.1.3', #2:tagged 3:untagged
 | 
						|
        'agPortNewCfgBpduGuard' => '.1.3.6.1.4.1.26543.2.7.1.1.1.2.3.1.41', #1:enable 2:disable
 | 
						|
        'agPortNewCfgStpExtGuard' => '.1.3.6.1.4.1.26543.2.7.1.1.1.2.3.1.52', #1:loop, 2:root, 3:none, 0:default
 | 
						|
        'agApplyConfig'           => '.1.3.6.1.4.1.26543.2.7.1.1.1.8.2',
 | 
						|
        'agSaveConfiguration'     => '.1.3.6.1.4.1.26543.2.7.1.1.1.1.4',      #saveActive(2), notSaveActive(3)
 | 
						|
        'arpInfoDestIp'           => '.1.3.6.1.4.1.26543.2.7.1.3.3.2.1.1.1',
 | 
						|
        'arpInfoSrcPort'          => '.1.3.6.1.4.1.26543.2.7.1.3.3.2.1.1.4',
 | 
						|
    },
 | 
						|
 | 
						|
    'G8052' => {
 | 
						|
        'vlanInfoId'              => '.1.3.6.1.4.1.26543.2.7.7.2.3.5.1.1.1',
 | 
						|
        'vlanInfoPorts'           => '.1.3.6.1.4.1.26543.2.7.7.2.3.5.1.1.7',
 | 
						|
        'portInfoPhyIfDescr'      => '.1.3.6.1.4.1.26543.2.7.7.1.3.2.1.1.6',
 | 
						|
        'vlanNewCfgVlanName'      => '.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.2',
 | 
						|
        'vlanNewCfgState'         => '.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.4',
 | 
						|
        'vlanNewCfgAddPort'       => '.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.5',
 | 
						|
        'vlanNewCfgRemovePort'    => '.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.6',
 | 
						|
        'vlanNewCfgDelete'        => '.1.3.6.1.4.1.26543.2.7.7.2.1.1.3.1.7',
 | 
						|
        'agPortNewCfgVlanTag'     => '.1.3.6.1.4.1.26543.2.7.7.1.1.2.3.1.3',
 | 
						|
        'agPortNewCfgBpduGuard'   => '.1.3.6.1.4.1.26543.2.7.7.1.1.2.3.1.41',
 | 
						|
        'agPortNewCfgStpExtGuard' => '.1.3.6.1.4.1.26543.2.7.7.1.1.2.3.1.52',
 | 
						|
        'agApplyConfig'           => '.1.3.6.1.4.1.26543.2.7.7.1.1.8.2',
 | 
						|
        'agSaveConfiguration' => '.1.3.6.1.4.1.26543.2.7.7.1.1.1.4', #saveActive(2), notSaveActive(3)
 | 
						|
        'arpInfoDestIp'  => '.1.3.6.1.4.1.26543.2.7.7.3.3.2.1.1.1',
 | 
						|
        'arpInfoSrcPort' => '.1.3.6.1.4.1.26543.2.7.7.3.3.2.1.1.4',
 | 
						|
    },
 | 
						|
 | 
						|
    'G8124' => {
 | 
						|
        'vlanInfoId'              => '.1.3.6.1.4.1.26543.2.7.4.2.3.5.1.1.1',
 | 
						|
        'vlanInfoPorts'           => '.1.3.6.1.4.1.26543.2.7.4.2.3.5.1.1.7',
 | 
						|
        'portInfoPhyIfDescr'      => '.1.3.6.1.4.1.26543.2.7.4.1.3.2.1.1.6',
 | 
						|
        'vlanNewCfgVlanName'      => '.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.2',
 | 
						|
        'vlanNewCfgState'         => '.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.4',
 | 
						|
        'vlanNewCfgAddPort'       => '.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.5',
 | 
						|
        'vlanNewCfgRemovePort'    => '.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.6',
 | 
						|
        'vlanNewCfgDelete'        => '.1.3.6.1.4.1.26543.2.7.4.2.1.1.3.1.7',
 | 
						|
        'agPortNewCfgVlanTag'     => '.1.3.6.1.4.1.26543.2.7.4.1.1.2.3.1.3',
 | 
						|
        'agPortNewCfgBpduGuard'   => '.1.3.6.1.4.1.26543.2.7.4.1.1.2.3.1.41',
 | 
						|
        'agPortNewCfgStpExtGuard' => '.1.3.6.1.4.1.26543.2.7.4.1.1.2.3.1.52',
 | 
						|
        'agApplyConfig'           => '.1.3.6.1.4.1.26543.2.7.4.1.1.8.2',
 | 
						|
        'agSaveConfiguration' => '.1.3.6.1.4.1.26543.2.7.4.1.1.1.4', #saveActive(2), notSaveActive(3)
 | 
						|
        'arpInfoDestIp'  => '.1.3.6.1.4.1.26543.2.7.4.3.3.2.1.1.1',
 | 
						|
        'arpInfoSrcPort' => '.1.3.6.1.4.1.26543.2.7.4.3.3.2.1.1.4',
 | 
						|
    },
 | 
						|
 | 
						|
    #this is for G8264 and 8264E
 | 
						|
    'G8264' => {
 | 
						|
        'vlanInfoId'              => '.1.3.6.1.4.1.26543.2.7.6.2.3.5.1.1.1',
 | 
						|
        'vlanInfoPorts'           => '.1.3.6.1.4.1.26543.2.7.6.2.3.5.1.1.7',
 | 
						|
        'portInfoPhyIfDescr'      => '.1.3.6.1.4.1.26543.2.7.6.1.3.2.1.1.6',
 | 
						|
        'vlanNewCfgVlanName'      => '.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.2',
 | 
						|
        'vlanNewCfgState'         => '.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.4',
 | 
						|
        'vlanNewCfgAddPort'       => '.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.5',
 | 
						|
        'vlanNewCfgRemovePort'    => '.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.6',
 | 
						|
        'vlanNewCfgDelete'        => '.1.3.6.1.4.1.26543.2.7.6.2.1.1.3.1.7',
 | 
						|
        'agPortNewCfgVlanTag'     => '.1.3.6.1.4.1.26543.2.7.6.1.1.2.3.1.3',
 | 
						|
        'agPortNewCfgBpduGuard'   => '.1.3.6.1.4.1.26543.2.7.6.1.1.2.3.1.41',
 | 
						|
        'agPortNewCfgStpExtGuard' => '.1.3.6.1.4.1.26543.2.7.6.1.1.2.3.1.52',
 | 
						|
        'agApplyConfig'           => '.1.3.6.1.4.1.26543.2.7.6.1.1.8.2',
 | 
						|
        'agSaveConfiguration' => '.1.3.6.1.4.1.26543.2.7.6.1.1.1.4', #saveActive(2), notSaveActive(3)
 | 
						|
        'arpInfoDestIp'  => '.1.3.6.1.4.1.26543.2.7.6.3.3.2.1.1.1',
 | 
						|
        'arpInfoSrcPort' => '.1.3.6.1.4.1.26543.2.7.6.3.3.2.1.1.4',
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
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 "BNT |Blade Network Technologies|IBM Networking Operating System|EN4093";
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=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 $swmod = getSwitchModule($session);
 | 
						|
    if (!$swmod) { return (); }
 | 
						|
 | 
						|
    my $vlanmap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{vlanInfoId}, 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 id 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 $swmod = getSwitchModule($session);
 | 
						|
    if (!$swmod) { return; }
 | 
						|
 | 
						|
 | 
						|
    my $namemap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{portInfoPhyIfDescr});
 | 
						|
    if ($namemap) {
 | 
						|
        my $ifnamesupport = 0;
 | 
						|
        foreach (keys %{$namemap}) {
 | 
						|
            if ($namemap->{$_}) {
 | 
						|
                $ifnamesupport = 1;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($ifnamesupport) {
 | 
						|
            $namemap = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    unless ($namemap) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    #print "namemap=" . Dumper($namemap) . "\n";
 | 
						|
 | 
						|
    my $portsvlanmap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{vlanInfoPorts}, silentfail => 1);
 | 
						|
 | 
						|
    #print "portsvlanmap=" . Dumper($portsvlanmap) . "\n";
 | 
						|
    foreach my $vid (keys(%$portsvlanmap)) {
 | 
						|
        my $data = $portsvlanmap->{$vid};
 | 
						|
        my @a = split(//, $data);
 | 
						|
        foreach (@a) {
 | 
						|
            my $num = unpack("C*", $_);
 | 
						|
            $_ = sprintf("%02x", $num);
 | 
						|
        }
 | 
						|
        $portsvlanmap->{$vid} = \@a;
 | 
						|
    }
 | 
						|
 | 
						|
    my %ret = ();
 | 
						|
    if (defined($portsvlanmap)) {
 | 
						|
        foreach my $portid (keys %{$namemap}) {
 | 
						|
            my $switchport = $namemap->{$portid};
 | 
						|
            foreach my $portname (@ports) {
 | 
						|
                unless (xCAT::MacMap::namesmatch($portname, $switchport)) {
 | 
						|
                    next;
 | 
						|
                }
 | 
						|
 | 
						|
                foreach my $vid (keys(%$portsvlanmap)) {
 | 
						|
                    my $data   = $portsvlanmap->{$vid};
 | 
						|
                    my $index  = int($portid / 8);
 | 
						|
                    my $offset = $portid % 8;
 | 
						|
                    my $num    = hex($data->[$index]) & ($HexConv{$offset});
 | 
						|
                    if ($num != 0) {
 | 
						|
                        if (exists($ret{$portname})) {
 | 
						|
                            my $pa = $ret{$portname};
 | 
						|
                            push(@$pa, $vid);
 | 
						|
                        } else {
 | 
						|
                            $ret{$portname} = [$vid];
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    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;
 | 
						|
 | 
						|
    my $swmod = getSwitchModule($session);
 | 
						|
    if (!$swmod) { return (1, "This BNT switch modeule is not supported."); }
 | 
						|
 | 
						|
    print "BNT $swmod\n";
 | 
						|
 | 
						|
    #name
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgVlanName}, $vlan_id, $vlan_name, 'OCTET');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vlanNewCfgVlanName " . $BNTOID->{$swmod}->{vlanNewCfgVlanName} . ".$vlan_id to $vlan_name.\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    my $tmp = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{vlanNewCfgVlanName});
 | 
						|
 | 
						|
    #print "tmp=" . Dumper($tmp) . "\n";
 | 
						|
 | 
						|
    #change to enable state
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgState}, $vlan_id, 2, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vlanNewCfgState " . $BNTOID->{$swmod}->{vlanNewCfgState} . ".$vlan_id to 2(enable).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    @ret = apply_changes($session, $swmod);
 | 
						|
 | 
						|
 | 
						|
    return @ret;
 | 
						|
}
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=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 @ports1   = @_;
 | 
						|
 | 
						|
    my $swmod = getSwitchModule($session);
 | 
						|
    if (!$swmod) { return (1, "This BNT switch modeule is not supported."); }
 | 
						|
 | 
						|
    my $port_vlan_hash = get_vlanids_for_ports($session, @ports1);
 | 
						|
 | 
						|
    #print "port_vlan_hash=" . Dumper($port_vlan_hash) . "\n";
 | 
						|
    my @ports = ();
 | 
						|
    foreach my $port (keys(%$port_vlan_hash)) {
 | 
						|
        my $val   = $port_vlan_hash->{$port};
 | 
						|
        my $found = 0;
 | 
						|
        foreach my $tmp_vid (@$val) {
 | 
						|
            if ($tmp_vid == $vlan_id) {
 | 
						|
                $found = 1;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if (!$found) {
 | 
						|
            push(@ports, $port);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (@ports == 0) { return (0, ""); }
 | 
						|
 | 
						|
    #print "vlan=$vlan_id, ports=@ports\n";
 | 
						|
    my $namemap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{portInfoPhyIfDescr});
 | 
						|
    if ($namemap) {
 | 
						|
        my $ifnamesupport = 0;
 | 
						|
        foreach (keys %{$namemap}) {
 | 
						|
            if ($namemap->{$_}) {
 | 
						|
                $ifnamesupport = 1;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($ifnamesupport) {
 | 
						|
            $namemap = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    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;
 | 
						|
            }
 | 
						|
 | 
						|
            print "portid=$portid, vlan_id=$vlan_id\n";
 | 
						|
            if ($portmode) {
 | 
						|
 | 
						|
                #change this port to untagged
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgVlanTag}, $portid, 3, 'INTEGER');
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Set agPortNewCfgVlanTag " . $BNTOID->{$swmod}->{agPortNewCfgVlanTag} . ".$portid to 3(untagged).\n" . $ret[1];
 | 
						|
                    return @ret;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
 | 
						|
                #change this port to tagged
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgVlanTag}, $portid, 2, 'INTEGER');
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Set agPortNewCfgVlanTag " . $BNTOID->{$swmod}->{agPortNewCfgVlanTag} . ".$portid to 2(tagged).\n" . $ret[1];
 | 
						|
                    return @ret;
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            #security feature:
 | 
						|
            if ($::XCATSITEVALS{vlansecurity} eq '1') {
 | 
						|
 | 
						|
                #enable bpdu guard on this port
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgBpduGuard}, $portid, 1, 'INTEGER');
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Enable bpdu guard for port $portid. (Set " . $BNTOID->{$swmod}->{agPortNewCfgBpduGuard} . ".$portid to 1.)\n" . $ret[1];
 | 
						|
                    return @ret;
 | 
						|
                }
 | 
						|
 | 
						|
                #enable root guard on this port
 | 
						|
                my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agPortNewCfgStpExtGuard}, $portid, 2, 'INTEGER');
 | 
						|
                if ($ret[0] != 0) {
 | 
						|
                    $ret[1] = "Enable root guard for port $portid. (Set  " . $BNTOID->{$swmod}->{agPortNewCfgStpExtGuard} . ".$portid to 2.\n" . $ret[1];
 | 
						|
 | 
						|
                    #	return @ret; #do not return because it is not supported for some switches yet. A defect will be fixed in BNT.
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            #add port in one by one
 | 
						|
            my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgAddPort}, $vlan_id, $portid, 'GAUGE');
 | 
						|
            if ($ret[0] != 0) {
 | 
						|
                $ret[1] = "Set vlanNewCfgAddPort" . $BNTOID->{$swmod}->{vlanNewCfgAddPort} . ".$vlan_id to $portid.\n" . $ret[1];
 | 
						|
                return @ret;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my @ret = apply_changes($session, $swmod);
 | 
						|
 | 
						|
    return @ret;
 | 
						|
}
 | 
						|
 | 
						|
#-------------------------------------------------------
 | 
						|
 | 
						|
=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, ""); }
 | 
						|
 | 
						|
    #    my $swmod=getSwitchModule($session);
 | 
						|
    #    if (!$swmod) { return (1, "This BNT switch modeule is not supported.");}
 | 
						|
 | 
						|
    #figure out the port numbers that are connecting to the given switches
 | 
						|
    #    my @ips=();
 | 
						|
    #get the ip address for each switch
 | 
						|
    #    foreach my $switch (@switches) {
 | 
						|
    #	my $ip=xCAT::NetworkUtils->getipaddr($switch);
 | 
						|
    #	if (!$ip) {
 | 
						|
    #	    $msg .= "Cannot resolve ip address for switch $switch\n";
 | 
						|
    #	} else {
 | 
						|
    #	   push(@ips, $ip);
 | 
						|
    #	}
 | 
						|
    #    }
 | 
						|
 | 
						|
    #    my @ports=();
 | 
						|
    #    my $tmp = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{arpInfoDestIp});
 | 
						|
    #    my $tmp1 = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{arpInfoSrcPort});
 | 
						|
    #    print Dumper($tmp);
 | 
						|
    #    print Dumper($tmp1);
 | 
						|
    #    foreach my $tmp_id (keys %{$tmp}) {
 | 
						|
    #	my $tmp_ip=$tmp->{$tmp_id};
 | 
						|
    #	if (grep /^$tmp_ip$/, @ips) {
 | 
						|
    #	    my $port=$tmp1->{$tmp_id};
 | 
						|
    #	    if ($port) { push(@ports, $port); }
 | 
						|
    #	}
 | 
						|
    #    }
 | 
						|
 | 
						|
    #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;
 | 
						|
 | 
						|
    my $swmod = getSwitchModule($session);
 | 
						|
    if (!$swmod) { return (1, "This BNT switch modeule is not supported."); }
 | 
						|
 | 
						|
    #set to delete state
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgDelete}, $vlan_id, 2, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set vlanNewCfgDelete " . $BNTOID->{$swmod}->{vlanNewCfgDelete} . ".$vlan_id to 2(delete).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    @ret = apply_changes($session, $swmod);
 | 
						|
 | 
						|
    return @ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#--------------------------------------------------------------
 | 
						|
 | 
						|
=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   = @_;
 | 
						|
 | 
						|
    my $swmod = getSwitchModule($session);
 | 
						|
    if (!$swmod) { return (1, "This BNT switch modeule is not supported."); }
 | 
						|
 | 
						|
    #print "vlan=$vlan_id, ports=@ports\n";
 | 
						|
    my $namemap = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{portInfoPhyIfDescr});
 | 
						|
    if ($namemap) {
 | 
						|
        my $ifnamesupport = 0;
 | 
						|
        foreach (keys %{$namemap}) {
 | 
						|
            if ($namemap->{$_}) {
 | 
						|
                $ifnamesupport = 1;
 | 
						|
                last;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        unless ($ifnamesupport) {
 | 
						|
            $namemap = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    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;
 | 
						|
            }
 | 
						|
 | 
						|
            print "portid=$portid, vlan_id=$vlan_id\n";
 | 
						|
 | 
						|
            #remove port in one by one
 | 
						|
            my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{vlanNewCfgRemovePort}, $vlan_id, $portid, 'GAUGE');
 | 
						|
            if ($ret[0] != 0) {
 | 
						|
                $ret[1] = "Set vlanNewCfgRemovePort " . $BNTOID->{$swmod}->{vlanNewCfgRemovePort} . ".$vlan_id to $portid.\n" . $ret[1];
 | 
						|
                return @ret;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    my @ret = apply_changes($session, $swmod);
 | 
						|
 | 
						|
    return @ret;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
sub apply_changes {
 | 
						|
    my $session = shift;
 | 
						|
    my $swmod   = shift;
 | 
						|
 | 
						|
    #apply
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agApplyConfig}, 0, 1, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set agApplyConfig " . $BNTOID->{$swmod}->{agApplyConfig} . ".0 to 1(apply).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    my $state = 3;
 | 
						|
    while ($state == 3) {
 | 
						|
        my $tmp = xCAT::MacMap::walkoid($session, $BNTOID->{$swmod}->{agApplyConfig});
 | 
						|
 | 
						|
        #print "tmp=" . Dumper($tmp) . "\n";
 | 
						|
        if ($tmp) {
 | 
						|
            $state = $tmp->{0};
 | 
						|
        }
 | 
						|
        sleep(3);
 | 
						|
    }
 | 
						|
 | 
						|
    #set apply to idle state
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agApplyConfig}, 0, 2, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set agApplyConfig " . $BNTOID->{$swmod}->{agApplyConfig} . ".0 to 2(idle).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ($state == 5) {
 | 
						|
        return (1, "Apply configuration failed.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    #save configurations.
 | 
						|
    my @ret = xCAT::SwitchHandler::setoid($session, $BNTOID->{$swmod}->{agSaveConfiguration}, 0, 2, 'INTEGER');
 | 
						|
    if ($ret[0] != 0) {
 | 
						|
        $ret[1] = "Set agSaveConfiguration " . $BNTOID->{$swmod}->{agSaveConfiguration} . ".0 to 2(saveActive).\n" . $ret[1];
 | 
						|
        return @ret;
 | 
						|
    }
 | 
						|
    return @ret;
 | 
						|
}
 | 
						|
 | 
						|
sub getSwitchModule {
 | 
						|
    my $session = shift;
 | 
						|
 | 
						|
    #get the the switch brand name
 | 
						|
    my $tmp = xCAT::MacMap::walkoid($session, "$sysDescr", silentfail => 1);
 | 
						|
    my $swmod;
 | 
						|
    my $descr = $tmp->{0};
 | 
						|
    if ($descr) {
 | 
						|
        if ($descr =~ /G8000/)  { return "G8000"; }
 | 
						|
        if ($descr =~ /G8052/)  { return "G8052"; }
 | 
						|
        if ($descr =~ /G8124/)  { return "G8124"; }
 | 
						|
        if ($descr =~ /G8264/)  { return "G8264"; }
 | 
						|
        if ($descr =~ /EN4093/) { return "EN4093"; }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
1;
 |