Class: Switch

Inherits:
Object
  • Object
show all
Defined in:
rlib/switch.rb

Overview

Holds a record for a Switch.

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Switch) initialize(name, ip, mac, switch_make, switch_model, category, community, do_snmpwalk = false)

Create an instance of Switch

Parameters:

  • name (String)

    Switch name

  • ip (String, Array<String>)

    IP address of the switch itself. If more than on IP address, then this is an Array.

  • mac (String, Array<String>)

    MAC address of the switch itself. If more than one, then this is an Array.

  • switch_make (String)

    Manufacturers make

  • switch_model (String)

    Manufacturers model

  • category (String)

    Designates position in the network, which helps in making pretty pictures [“external” | “private_core”, | “private_leaf” | …]

  • community (String)

    This switches SNMP read community string

  • do_snmpwalk (Boolean) (defaults to: false)

    True, if we want to query the switch. False, if we want to skip this switch.



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'rlib/switch.rb', line 21

def initialize(name, ip, mac, switch_make, switch_model, category, community, do_snmpwalk=false)
  @name, @ip, @switch_make, @switch_model, @category = name, ip,  switch_make, switch_model, category
  @community = community
  if mac.class == Array
    @mac = mac.collect {|x| x.upcase }
  else
    @mac = mac.upcase
  end
  @ports = {}
  @physical_port_map = {} #Port numbers in some parts of the MIB don't match the physical port numbers. Map from virtual -> physical.
  @trunk_port_map = {}
  snmpwalk if do_snmpwalk
end

Instance Attribute Details

- (Object) category

Returns the value of attribute category



9
10
11
# File 'rlib/switch.rb', line 9

def category
  @category
end

- (Object) ip

Returns the value of attribute ip



9
10
11
# File 'rlib/switch.rb', line 9

def ip
  @ip
end

- (Object) mac

Returns the value of attribute mac



9
10
11
# File 'rlib/switch.rb', line 9

def mac
  @mac
end

- (Object) name

Returns the value of attribute name



9
10
11
# File 'rlib/switch.rb', line 9

def name
  @name
end

- (Object) ports

Returns the value of attribute ports



9
10
11
# File 'rlib/switch.rb', line 9

def ports
  @ports
end

- (Object) switch_make

Returns the value of attribute switch_make



9
10
11
# File 'rlib/switch.rb', line 9

def switch_make
  @switch_make
end

- (Object) switch_model

Returns the value of attribute switch_model



9
10
11
# File 'rlib/switch.rb', line 9

def switch_model
  @switch_model
end

Instance Method Details

- (Object) process_switch(ifTable_columns)

Process switch is called by snmpwalk to run a single SNMP query to retrieve the OID or OIDS passed in.

Parameters:

  • ifTable_columns (String, Array<String>)

    The OIDS we want to retrieve from this switch.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'rlib/switch.rb', line 148

def process_switch(ifTable_columns)
  begin
    SNMP::Manager.open(:Host => @ip, :Community => "#{@community}", :Version => :SNMPv2c) do |manager|
      manager.walk(ifTable_columns) do |row|
        row.each do |vb| 
            oid = vb.name.to_s.split('.')
            yield [oid, vb.value.to_s]
        end
      end
    end
  rescue Exception => message
    print "#{@name}: #{message}\n"
  end
end

- (Boolean) remote_switch?(pport, switches)

Is a remote switch on this port, or just a host or hosts. Check is made using the results of querying the bridge MIB.

Parameters:

  • pport (Port)

    Port record we want to test.

  • switches (Hash)

    Hash by switch name, of all Switch records.

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'rlib/switch.rb', line 40

def remote_switch?(pport, switches)
  switches.each do |sk,sv| #Look on all the switches we have to see if the switch Mac and port Mac match
    if sv.mac.class == Array
      sv.mac.each do |mac|
        if mac == pport.remote_mac #We found a match
           return true #Mark it as a bridge port.
        end
      end
    else
      if sv.mac == pport.remote_mac #We found a match
        return true #Mark it as a bridge port.
      end
    end
  end
  return false
end

- (Object) set_is_our_switch(switches)

Process all switches, and tag switch ports, that are connected to another of our switches.

Parameters:

  • switches (Hash)

    Hash by switch name, of all Switch records.



59
60
61
62
63
64
65
66
67
# File 'rlib/switch.rb', line 59

def set_is_our_switch(switches)
  @ports.each do |pkey, pport|#for each port on this switch
    if(pport.remote_mac != nil && pport.remote_mac != '') #if we have a remote port recorded.
      #puts "#{@name} #{pport.port_number} #{pport.remote_mac} #{pport.remote_switch_name} #{pport.remote_port_number}"
      pport.bridge_port = remote_switch?(pport, switches)
      #puts "  Bridge" if pport.bridge_port
    end
  end
end

- (Object) snmpwalk

Snmpwalk is run to retrieve multiple OIDs from ths switch, and set switch and port attributes.



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'rlib/switch.rb', line 75

def snmpwalk
  process_switch(["1.0.8802.1.1.2.1.3.7.1.3"]) do |k,v| #Port numbers
    v = k[-1] if v == "" #Pronto8 switch sets v to ''
    @ports[k[-1]] = Port.new(v)
    @trunk_port_map[k[-1]] = k[-1] #Prime the trunk to port mapping to be 1:1
    @physical_port_map[k[-1]] = k[-1]
  end
  process_switch(["1.0.8802.1.1.2.1.3.7.1.4"]) do |k,v| #Port names
    v = k[-1] if v == "" #Pronto8 switch sets v to ''
    @ports[k[-1]].port_name = v
  end
=begin
 #BAD TEST for switch: remote nodes type (7 seems to be a switch. 5 is used by the pronto switch. 3 seems to be a host. Except fmhs-003 uses 5 :( ))
  process_switch(["1.0.8802.1.1.2.1.4.1.1.6"]) do |k,v| 
    if v != "3" && v != "0"
      @ports[k[-2]].bridge_port = true
    end
  end
=end
  process_switch(["1.0.8802.1.1.2.1.4.1.1.5"]) do |k,v| #remote switch Mac address. Might also be a host running LLDP.
    #Pronto8 switch sets v to '' if there is no remote switch. Other switches leave the OID out completely.
    @ports[k[-2]].remote_switch_name = v # Fill this in now, in case the switch name is blank in the next step.
    @ports[k[-2]].remote_mac = v.upcase
  end
  process_switch(["1.0.8802.1.1.2.1.4.1.1.9"]) do |k,v| #Names of connected switches
    @ports[k[-2]].remote_switch_name = v #Might actually be a node name.
  end
  process_switch(["1.0.8802.1.1.2.1.4.1.1.8"]) do |k,v|  #Names of remote port name
    @ports[k[-2]].remote_port_name = v
  end
  process_switch(["1.0.8802.1.1.2.1.4.1.1.7"]) do |k,v|  #Names of remote port number
    @ports[k[-2]].remote_port_number = v
  end
  
  #See if any of the LLDP entries we found are switches we know of. 
  #If they are, mark entry as a switch
  #If not, they may be hosts running LLDP, or switches we don't know about.
  #In either case, treat them as a host for display purposes (will just get lots of ARP entries for switches and virtual switches)
  
  #SNMPv2-SMI::mib-2.17.1.4.1.2.port => interface number
  process_switch(["SNMPv2-SMI::mib-2.17.1.4.1.2"]) do |k,v| 
    if @switch_make != "juniper"
      @physical_port_map[v] = k[-1] #Physical port number is derived from using virtual port number as a hash index
    end
  end
  
  #SNMPv2-SMI::enterprises.26543.2.7.4.2.3.9.2.1.1.<trunk>.<port> => <trunk>
  process_switch(["SNMPv2-SMI::enterprises.26543.2.7.4.2.3.9.2.1.1"]) do |k,v| 
    #Most switches, this will be a null mapping, but for BNT wit LACP links, the trunk numbers are returned where we would expect port numbers on other switches.
    @trunk_port_map[v] = k[-1] #Physical port number is derived from using trunk number as a hash index
  end
 
  process_switch(["IF-MIB::ifOperStatus"]) do |k,v| 
    port_index = @physical_port_map[k[-1]]
    if port_index != nil && @ports[port_index] != nil
      @ports[port_index].up = (v == "1") 
    end
  end
  
  process_switch(["SNMPv2-SMI::mib-2.17.4.3.1.2"]) do |k,v| #switch port mac address
  #process_switch(["SNMPv2-SMI::mib-2.17.7.1.2.2.1.2.1"]) do |k,v| #switch port mac address
    port_index = @trunk_port_map[v]
    if port_index != nil && @ports[port_index] != nil # && @ports[port_index].bridge_port == false
      s = ""
      k[-6,6].each { |x| s << sprintf("%02X:", x.to_i) }
      s[-1] = ""
      @ports[port_index].port_arp << s
    end
  end
end

- (Object) to_s

To_s for this class for diagnositic purposes.



70
71
72
# File 'rlib/switch.rb', line 70

def to_s
  "name=>#{@name}, ip=>#{@ip} mac=>#{@mac} @switch_make=>#{@switch_make} @switch_model=>#{@switch_model} category=>#{@category} community=>#{@communtiy}\nports=>#{@ports}"
end