Class: Arp

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

Overview

Note:

the system arp table was a bit small for our cluster, so I increased the table size.

Bit of a hack :) We need to be able to translate for MAC addresses to IP addresses, The quick and dirty way to do this is to first ping every host, to ensure the OS arp table is full, Then we run /sbin/arp to read the system table, And translate this into a file we can use later.

  • In /etc/sysctl.conf

  • net.ipv4.neigh.default.gc_thresh3 = 4096

  • net.ipv4.neigh.default.gc_thresh2 = 2048

  • net.ipv4.neigh.default.gc_thresh1 = 1024

See Also:

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Arp) initialize(filename = nil)

Create an instance of Arp

Parameters:

  • filename (String) (defaults to: nil)

    Override the default arp.out file ('../conf/arp.out')



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'rlib/arp.rb', line 24

def initialize(filename = nil)
  @hosts = []
  #Default ARP table filename is in the conf directory, relative to this script
  default_directory = File.expand_path(File.dirname(__FILE__)) + '/../conf/'
  default_filename = 'arp.out'
  #ARP table file can be overridden if filename is specified.
  filename = File.join(default_directory, 'arp.out') if filename == nil
  load_arp(filename)
  @mac_index = {}
  @hosts.each do |h| 
     @mac_index[expand(h[1])] = h
  end
end

Instance Attribute Details

- (Object) hosts

Array of the hosts loaded from the arp.out file.



19
20
21
# File 'rlib/arp.rb', line 19

def hosts
  @hosts
end

Class Method Details

+ (String?) host(mac_address)

Class Level. Find the hostname from the MAC address.

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (String, nil)

    Hostname associated with the MAC address, or nil if it isn't known.



110
111
112
113
# File 'rlib/arp.rb', line 110

def self.host(mac_address)
   a = Arp.new
   a.host(mac_address)
end

+ (Object) test

Class method to run self test, by reading the arp.out file and dumping the Arp DB.



143
144
145
146
147
148
149
150
151
# File 'rlib/arp.rb', line 143

def self.test
  arp = Arp.new
  #Test for a know host, indexed by the MAC address.
  puts "arp.mac_index('34:40:B5:B9:D4:3F') => #{arp.mac_index("34:40:B5:B9:D4:3F")}"
  puts
  #Dump the whole ARP @hosts array.
  puts "Dump of entire Arp hosts Array, as loaded from conf/arp.out"
  pp arp.hosts
end

Instance Method Details

- (String) expand(mac_address)

Standardise the MAC address string format.

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (String)

    MAC address of the target with Uppercase, two digit Hexadecimal numbers, separated with ':'s.



129
130
131
132
133
134
# File 'rlib/arp.rb', line 129

def expand(mac_address) #want leading 0's, which sometimes we don't always get. Want uppercase, some compare is simpler.
  return nil if mac_address == nil
  as = mac_address.split(':')
  as.collect! { |x| "%02X" % (x.to_i(16)) }
  as.join(':')
end

- (String) host(mac_address)

Find the hostname from the MAC address.

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (String)

    Hostname associated with the MAC address, or the MAC address if it isn't known.



118
119
120
121
122
123
124
# File 'rlib/arp.rb', line 118

def host(mac_address)
   if mac_address != nil && (n = hostname(mac_address)) != nil && n != ''
     n
   else
     expand(mac_address)
   end
end

- (String?) hostname(mac_address)

Find the hostname from the MAC address.

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (String, nil)

    Hostname associated with the MAC address, or nil if it isn't known.



70
71
72
73
74
75
76
# File 'rlib/arp.rb', line 70

def hostname(mac_address)
  if(host = mac_index(mac_address)) != nil
    return host[0]
  else
    return nil
  end
end

- (String?) ip_address(mac_address)

Find the ip address from the MAC address.

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (String, nil)

    IP address associated with the MAC address, or nil if it isn't known.



92
93
94
95
96
97
98
# File 'rlib/arp.rb', line 92

def ip_address(mac_address)
  if(host = mac_index(mac_address)) != nil
    return host[2]
  else
    return nil
  end
end

- (Object) load_arp(filename)

was generating arp.out file with arp > arp.out, but IB interfaces cause fields to overrun each other Switched to arp -a > arp.out

See Also:

  • Arp.gen_arp_outgen_arp_out.sh


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'rlib/arp.rb', line 41

def load_arp(filename)
  line = 0
  File.open(filename,'r') do |fd|
    fd.each_line do |l|
      #Firstline of /sbin/arp -a output is a header.
      if line != 0 
        # @example lines in arp -a output 
        #    pdu-a2-c-u1 (10.0.116.180) at <incomplete> on eth2
        #    ? (10.0.111.183) at 6C:AE:8B:E4:CB:00 [ether] on eth2
        #    compute-a1-030-ib (10.0.133.30) at A0:00:01:00:FE:80:00:00:00 [infiniband] on ib0
        #    compute-a1-045-p (10.0.102.45) at 5C:F3:FC:A8:3E:76 [ether] on eth2
        tokens = l.chomp.strip.split(/\s\s*/)
        if tokens != nil && tokens.length == 7 && tokens[3] != "<incomplete>"
          if tokens[0] == '?'
            @hosts << [tokens[1], tokens[3], tokens[1]] #by IP address
          else
            @hosts << [tokens[0], tokens[3], tokens[1]] #by hostname
          end
        end
      else
        line = 1
      end
    end
  end
end

- (Boolean) mac_address?(mac_address)

Test to see if MAC address exists in our DB

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (Boolean)

    True if MAC address is known to us.



81
82
83
84
85
86
87
# File 'rlib/arp.rb', line 81

def mac_address?(mac_address) 
  if(host = mac_index(mac_address)) != nil
    return true
  else
    return false
  end
end

- (String?) mac_index(mac_address)

Find the DB entry from the MAC address.

Parameters:

  • mac_address (String)

    MAC address of the target.

Returns:

  • (String, nil)

    DB entry associated with the MAC address, or nil if it isn't known.



103
104
105
# File 'rlib/arp.rb', line 103

def mac_index(mac_address)
  @mac_index[expand(mac_address)]  
end

- (String) to_s

Return the ARP DB as a string.

Returns:

  • (String)

    Arp DB.



138
139
140
# File 'rlib/arp.rb', line 138

def to_s
  @hosts.to_s
end