mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 19:32:31 +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;
 |