Class: Distem::Lib::NetTools

Inherits:
Object
  • Object
show all
Defined in:
lib/distem/distemlib/nettools.rb

Overview

Class that allow to perform physical operations on a physical network resource

Constant Summary

DEFAULT_BRIDGE =

Name used for the bridge set up on a physical machine

'br0'
VXLAN_BRIDGE_PREFIX =
'vxlanbr'
VXLAN_INTERFACE_PREFIX =
'vxlan'
LOCALHOST =

:nodoc:

'localhost'
IFNAMEMAXSIZE =

Maximal size for a network interface name (from GNU/Linux specifications)

15
@@nic_count =
1
@@addr_default =
nil
@@br_info =

Hash containing the (interface name, interface address, interface netmask) triplet for a root interface on which a bridge is plugged on

{}

Class Method Summary (collapse)

Instance Method Summary (collapse)

Class Method Details

+ (Object) create_vxlan_interface(id, mcast_id, address, netmask, root_interface)

Create a VXLAN interface to encapsulate inter-pnode traffic inside VXLAN tunnel

Attributes

  • id identifier of the VXLAN

  • mcast_id identifier used to generate the address of the multicast group

  • address address of the related virtual network

  • netmask netmask of the related virtual network

  • default_interface specify a default interface used to plug the VXLAN interface



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/distem/distemlib/nettools.rb', line 259

def self.create_vxlan_interface(id, mcast_id, address,netmask,root_interface)
  vxlan_iface = VXLAN_INTERFACE_PREFIX + id.to_s
  bridge = VXLAN_BRIDGE_PREFIX + id.to_s
  # First, we set up the VXLAN interface
  mcast_addr = IPAddress::IPv4::parse_u32(mcast_id + IPAddress("239.0.0.0").u32).address
  Shell.run("ip link add #{vxlan_iface} type vxlan id #{id} group #{mcast_addr} ttl 10 dev #{root_interface} dstport 4789")
  Shell.run("ip link set up dev #{vxlan_iface}")
  # Then, we create a bridge
  Shell.run("brctl addbr #{bridge}")
  Shell.run("brctl setfd #{bridge} 0")
  Shell.run("brctl setageing #{bridge} 3000000")
  Shell.run("/bin/ip link set dev #{bridge} promisc on")
  Shell.run("/bin/ip link set dev #{bridge} up")
  # And we add the VXLAN interface into the bridge
  Shell.run("brctl addif #{bridge} #{vxlan_iface}")
  Shell.run("ifconfig #{vxlan_iface} 0.0.0.0 up")
end

+ (Object) disable_ipv6

Disable IPv6



167
168
169
# File 'lib/distem/distemlib/nettools.rb', line 167

def self.disable_ipv6()
  Shell.run('sysctl -w net.ipv6.conf.all.disable_ipv6=1; true')
end

+ (Object) get_default_addr(cache = true)

Gets the IP address of the default network interface used for network communications

Returns

String object



69
70
71
72
73
74
75
# File 'lib/distem/distemlib/nettools.rb', line 69

def self.get_default_addr(cache=true)
  if !@@addr_default or !cache
    iface = self.get_default_iface()
    @@addr_default = self.get_iface_addr(iface).strip
  end
  return @@addr_default
end

+ (Object) get_default_gateway

Gets the IP address of the default gateway

Returns

String object



80
81
82
83
# File 'lib/distem/distemlib/nettools.rb', line 80

def self.get_default_gateway
  cmdret = Shell.run("/bin/ip route list")
  return cmdret.lines.grep(/^default /).first.gsub(/.* via ([0-9.]+).*/, '\1').chomp
end

+ (Object) get_default_iface

Gets the name of the default network interface used for network communications

Returns

String object



23
24
25
26
27
28
29
30
# File 'lib/distem/distemlib/nettools.rb', line 23

def self.get_default_iface
  defroute = Shell.run("/bin/ip route list").split(/\n/).grep(/^default /)
  if defroute.empty?
    return ""
  else
    return defroute[0].gsub(/.* dev ([^\s]+)( .*)?/, '\1')
  end
end

+ (Object) get_iface_addr(iface)

Gets the IP address of a specified network interface

Attributes

  • iface The network interface name (String)

Returns

String object



48
49
50
51
52
53
54
# File 'lib/distem/distemlib/nettools.rb', line 48

def self.get_iface_addr(iface)
  cmdret = Shell.run("/sbin/ifconfig #{iface}")
  # | grep 'inet addr' | awk '{print \$2}' | cut -d':' -f2 | tr -d '\n'")
  ret=""
  cmdret.each_line { |s| ret=s.split[1].split(":")[1] if s.include?("inet addr") }
  return ret
end

+ (Object) get_iface_config(iface)

Gets the inet interface configuration in a form suitable for 'ip addr add'

Attributes

  • iface The network interface name (String)

Returns

String object



62
63
64
# File 'lib/distem/distemlib/nettools.rb', line 62

def self.get_iface_config(iface)
  return Shell.run("/bin/ip addr show dev #{iface}").split(/\n/).grep(/inet /)[0].gsub(/.*inet ([^\s]+ brd [^\s]+).*/, '\1').chomp
end

+ (Object) get_iface_mtu(vnode, viface)

Gets the current MTU of a virtual network interface

Attributes

  • vnode The VNode object

  • viface The VIface object

Returns

Integer object



206
207
208
209
210
# File 'lib/distem/distemlib/nettools.rb', line 206

def self.get_iface_mtu(vnode,viface)
  iface = "#{vnode.name}-#{viface.name}-#{viface.id}"
  cmdret = Shell.run("/sbin/ifconfig #{iface}")
  return cmdret.split("\n").grep(/.*MTU.*/)[0].gsub(/.*MTU:(\d+) .*/, '\1').to_i
end

+ (Object) get_iface_name(vnode, viface)

Gets the physical name of a virtual network interface

Attributes

  • vnode The VNode object

  • viface The VIface object

Returns

String object



189
190
191
192
193
194
195
196
197
# File 'lib/distem/distemlib/nettools.rb', line 189

def self.get_iface_name(vnode,viface)
  # >>> TODO: Remove vnode parameter)
  raise unless vnode.is_a?(Resource::VNode)
  raise unless viface.is_a?(Resource::VIface)

  ret = "#{vnode.name}-#{viface.name}-#{viface.id}"
  binf = (ret.size >= IFNAMEMAXSIZE ? ret.size-IFNAMEMAXSIZE : 0)
  ret = ret[binf..ret.size]
end

+ (Object) get_netmask(iface)

Get the netmask of an interface

Attributes

  • iface The network interface name (String)

Returns

String object



37
38
39
40
# File 'lib/distem/distemlib/nettools.rb', line 37

def self.get_netmask(iface)
  cmd = Shell.run("ifconfig #{iface}")
  return cmd.split(/\n/).grep(/Mask/).first.gsub(/.*Mask:(.*)$/,'\1')
end

+ (Boolean) localaddr?(address)

Check if an IP address is local to this physical node

Attributes

  • address The IP address (String)

Returns

Boolean value

Returns:

  • (Boolean)


218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/distem/distemlib/nettools.rb', line 218

def self.localaddr?(address)
  raise unless address.is_a?(String)

  begin
    target = Resolv.getaddress(address)
  rescue Resolv::ResolvError
    raise Lib::InvalidParameterError, address
  end

  #Checking if the address is the loopback
  begin
    ret = (Resolv.getnames(target).include?(LOCALHOST))
  rescue Resolv::ResolvError
    ret = false
  end

  ret = (target == LOCALHOST) unless ret

  #Checking if the address is the one of the default interface
  ret = (Lib::NetTools.get_default_addr == target) unless ret

  #Checking if the address is the one of the ip associated with the hostname of the machine
  unless ret
    begin
      ret = (Resolv.getaddress(Socket.gethostname) == target)
    rescue Resolv::ResolvError
      ret = false
    end
  end

  return ret
end

+ (Object) remove_vxlan_interface(id)

Remove a VXLAN interface and its related bridge

Attributes

  • id identifier of the VXLAN



280
281
282
283
284
285
286
287
# File 'lib/distem/distemlib/nettools.rb', line 280

def self.remove_vxlan_interface(id)
  vxlan_iface = VXLAN_INTERFACE_PREFIX + id.to_s
  bridge = VXLAN_BRIDGE_PREFIX + id.to_s
  Shell.run("brctl delif #{bridge} #{vxlan_iface}")
  Shell.run("ip link del #{vxlan_iface}")
  Shell.run("ifconfig #{bridge} down")
  Shell.run("brctl delbr #{bridge}")
end

+ (Object) set_arp_cache

Set up the ARP cache



140
141
142
143
144
145
146
# File 'lib/distem/distemlib/nettools.rb', line 140

def self.set_arp_cache()
  Shell.run("sysctl -w net.ipv4.neigh.default.base_reachable_time=86400")
  Shell.run("sysctl -w net.ipv4.neigh.default.gc_stale_time=86400")
  Shell.run("sysctl -w net.ipv4.neigh.default.gc_thresh1=100000000")
  Shell.run("sysctl -w net.ipv4.neigh.default.gc_thresh2=100000000")
  Shell.run("sysctl -w net.ipv4.neigh.default.gc_thresh3=100000000")
end

+ (Object) set_bridge(root_interface, default_gw)



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
# File 'lib/distem/distemlib/nettools.rb', line 85

def self.set_bridge(root_interface, default_gw)
  str = Shell.run("ifconfig")
  bridge_name = "br_#{root_interface}"
  unless str.include?(bridge_name)
    @@br_info[bridge_name] = [root_interface, self.get_iface_addr(root_interface), self.get_netmask(root_interface)]
    # needs to be done before we break eth0
    cfg = self.get_iface_config(root_interface)
    Shell.run("ethtool -G #{root_interface} rx 4096 tx 4096 || true")

    Shell.run("brctl addbr #{bridge_name}")
    Shell.run("brctl setfd #{bridge_name} 0")
    Shell.run("brctl setageing #{bridge_name} 3000000")
    Shell.run("/bin/ip addr add dev #{bridge_name} #{cfg}")
    Shell.run("/bin/ip link set dev #{bridge_name} promisc on")
    Shell.run("/bin/ip link set dev #{bridge_name} up")
    Shell.run("brctl addif #{bridge_name} #{root_interface}")
    Shell.run("ifconfig #{root_interface} 0.0.0.0 up")
    # Set the default route only if the default interface has been added into the bridge, in
    # this case the default gateway is passed as a parameter to set_bridge
    if default_gw
      iface = self.get_default_iface()
      unless iface.empty?
        Shell.run("ip route del default dev #{iface}")
      end
      Shell.run("ip route add default dev #{bridge_name} via #{default_gw}")
    end
    return bridge_name
  else
    return nil
  end
end

+ (Object) set_ifb(nb = 64)

Set up the IFB module



135
136
137
# File 'lib/distem/distemlib/nettools.rb', line 135

def self.set_ifb(nb=64)
  Shell.run("modprobe ifb numifbs=#{nb}")
end

+ (Object) set_new_nic(address, netmask, iface)

Create a new NIC network interface on the physical node (used to communicate with the VNodes, see Daemon::Admin)



154
155
156
157
158
159
# File 'lib/distem/distemlib/nettools.rb', line 154

def self.set_new_nic(address,netmask,iface)
  new_iface = "#{iface}:#{@@nic_count}"
  Shell.run("ifconfig #{new_iface} #{address} netmask #{netmask}")
  @@nic_count += 1
  return new_iface
end

+ (Object) set_resource(max_vifaces, set_bridge)

Set up a physical machine network properties

Attributes

  • max_vifaces the maximum number of virtual network interfaces that'll be set on this physical machine

  • set_bridge boolean specifying if a bridge has to be created



175
176
177
178
179
180
# File 'lib/distem/distemlib/nettools.rb', line 175

def self.set_resource(max_vifaces,set_bridge)
  disable_ipv6()
  set_arp_cache()
  set_bridge() if set_bridge
  set_ifb(max_vifaces)
end

+ (Object) unset_bridge(brname, default_gw)

Unset the bridge and restore the default interface, if possible



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/distem/distemlib/nettools.rb', line 118

def self.unset_bridge(brname, default_gw)
  interface, ip, netmask = @@br_info[brname]
  @@br_info.delete(brname)
  cmd = ""
  Dir.glob("/sys/class/net/#{brname}/brif/*").each { |i|
    cmd += "brctl delif #{brname} #{File.basename(i)};"
  }
  cmd += "ip link set #{brname} down;"
  cmd += "brctl delbr #{brname};"
  cmd += "ifconfig #{interface} #{ip} netmask #{netmask}"
  if default_gw
    cmd += ";route add -net 0.0.0.0 gw #{default_gw} dev #{interface}"
  end
  Shell.run(cmd)
end

+ (Object) unset_ifb

Clean the IFB module



149
150
151
# File 'lib/distem/distemlib/nettools.rb', line 149

def self.unset_ifb()
  Shell.run("rmmod ifb")
end

+ (Object) unset_nic(name)

Unset NIC



162
163
164
# File 'lib/distem/distemlib/nettools.rb', line 162

def self.unset_nic(name)
  Shell.run("ifconfig #{name} down")
end

Instance Method Details

- (Object) DELETE brname



120
# File 'lib/distem/distemlib/nettools.rb', line 120

@@br_info.delete(brname)