Skip to content

Instantly share code, notes, and snippets.

@corestate55
Last active December 3, 2016 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save corestate55/91dd3e4dc54e858082ca082a4270c004 to your computer and use it in GitHub Desktop.
Save corestate55/91dd3e4dc54e858082ca082a4270c004 to your computer and use it in GitHub Desktop.
NetTester One-liner Example
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'net_tester'
require 'pry'
# parameter definition
nwdev = 'ens5'
pss_dpid = 0x1
mac_base = '00:ba:dc:ab:1e:'
p '# run net_tester'
NetTester.run(network_device: nwdev,
physical_switch_dpid: pss_dpid)
p '# wait ssw/psw connection'
sleep 10
p '# Create host11 in internal segment (ip:10.10.10.7, vlan:2025)'
host11 = NetTester::Netns.new(name: 'host11',
mac_address: mac_base + '01',
ip_address: '10.10.10.7',
netmask: 24,
gateway: '10.10.10.254',
virtual_port_number: 2,
physical_port_number: 6,
vlan_id: 2025)
p '# Create host21 in internal segment (ip:10.10.10.9, vlan:2025)'
host21 = NetTester::Netns.new(name: 'host21',
mac_address: mac_base + '02',
ip_address: '10.10.10.9',
netmask: 24,
gateway: '10.10.10.254',
virtual_port_number: 3,
physical_port_number: 10,
vlan_id: 2025)
# into pry console
binding.pry
# cleanup
NetTester.kill
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'net_tester'
require 'phut'
require 'pry'
# parameter definition
nwdev = 'ens5'
pss_dpid = 0x1
mac_base = '00:ba:dc:ab:1e:'
## trunk ports
# psw/6 -- L2SW1/port9
# psw/7 -- L2SW1/port10
# psw/10 -- L2SW2/port9
# psw/11 -- L2SW2/port10
patch_list = [
# hostname, segment, ip(/24), ssw-port, psw-port
{ host: 'int11', seg: :internal, ip: '10.10.10.7', ssw: 2, psw: 6 },
{ host: 'int12', seg: :internal, ip: '10.10.10.8', ssw: 3, psw: 7 },
{ host: 'int21', seg: :internal, ip: '10.10.10.9', ssw: 4, psw: 10 },
{ host: 'int22', seg: :internal, ip: '10.10.10.10',ssw: 5, psw: 11 },
{ host: 'dmz11', seg: :dmz, ip: '10.10.0.110', ssw:6, psw: 6 },
{ host: 'dmz12', seg: :dmz, ip: '10.10.0.111', ssw:7, psw: 7 },
{ host: 'dmz21', seg: :dmz, ip: '10.10.0.112', ssw:8, psw: 10 },
{ host: 'dmz22', seg: :dmz, ip: '10.10.0.113', ssw:9, psw: 11 }
]
seg = {
internal: { netmask: 24, vlan: 2025, gateway: '10.10.10.254' },
dmz: { netmask: 24, vlan: 2023, gateway: '10.10.0.1' }
}
######################################################################
p '# run net_tester'
NetTester.run(network_device: nwdev,
physical_switch_dpid: pss_dpid)
p '# wait ssw/psw connection'
sleep 10
p '# create host'
host = {}
patch_list.each_with_index do |patch, i|
p "## host: #{patch[:host]}"
h = NetTester::Netns.new(name: patch[:host],
mac_address: mac_base + sprintf("%02x", i+1),
ip_address: patch[:ip],
netmask: seg[patch[:seg]][:netmask],
gateway: seg[patch[:seg]][:gateway],
virtual_port_number: patch[:ssw],
physical_port_number: patch[:psw],
vlan_id: seg[patch[:seg]][:vlan])
host[patch[:host]] = h
end
# into pry console
binding.pry
# cleanup
NetTester.kill

Simple NetTester Example

環境メモ

 +--------------+ +--------------+
 | L2SW1        | | L2SW2        |
 |              | |              |
 | port9 port10 | | port9 port10 |
 *--+--------+--+ *--+--------+--+
    |        |       |        |
 +--+--------+-------+--------+--+
 | port6 port7     port10 port11 |             OVS (dpid: 0xdad1c001)
 |                               +--- ens5 --- port1
 | OpenFlow Switch 1 (dpid: 0x1) |
 +-------------------------------+

L2SW1/2の port 9-10 は、Trunk port (vlan 2023-2026) です。

基本編

example1.rb の解説

  • NetTester.run の後の sleep ?
  • OFSが接続しに来るのを待ってる。sleepしないとOFSが操作可能になってない状態で操作しようとしてコケたりしたので。
  • virtual_port_number の説明
  • port1 は 物理NIC(ens5)に接続される。
  • テスト用ノードは 2 以降であれば何使ってもいい
  • NetTester examples では自動的にインクリメントするようにしてたはず。

example1.rb 実行 (Tester set 1, 192.168.20.166)

hagiwara@install_nettester_test:~/net-tester$ bundle exec ruby example1.rb
"# run net_tester"
"# wait ssw/psw connection"
"# Create host11 in internal segment (ip:10.10.10.7, vlan:2025)"
"# Create host21 in internal segment (ip:10.10.10.9, vlan:2025)"


From: /home/hagiwara/net-tester/net_tester_examples.rb @ line 39 :


    34:                               virtual_port_number: 3,
    35:                               physical_port_number: 10,
    36:                               vlan_id: 2025)
    37:
    38: # into pry console
 => 39: binding.pry


[1] pry(main)> 

なんの変数があるのかを調べる (pry how-to)

[3] pry(main)> ls
self.methods: inspect  to_s
locals:
  _   _dir_  _file_  _out_  host11  lib       nwdev
  __  _ex_   _in_    _pry_  host21  mac_base  pss_dpid
[4] pry(main)> 

使うのは host11, host21 host11 の持っている情報を掘り下げてみる。

[4] pry(main)> cd host11
[5] pry(#<NetTester::Netns>):1> ls
NetTester::Netns#methods: method_missing
self.methods: __pry__
instance variables: @netns  @physical_port_number  @virtual_port_number  @vlan_id
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
[6] pry(#<NetTester::Netns>):1> puts @physical_port_number
6
=> nil
[7] pry(#<NetTester::Netns>):1>

[12] pry(#<NetTester::Netns>):1> puts @netns.class
Phut::Netns
=> nil
[13] pry(#<NetTester::Netns>):1> 

@netns が本体なのでそっちにいってみる。

[13] pry(#<NetTester::Netns>):1> cd @netns
[14] pry(#<Phut::Netns>):2> ls
Phut::ShellRunner#methods: sh  sudo
Phut::Netns#methods:
  device   exec        mac_address  netmask  run   vlan
  device=  ip_address  name         route    stop
self.methods: __pry__
instance variables: @ip_address  @mac_address  @name  @netmask  @route  @vlan
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
[15] pry(#<Phut::Netns>):2> 

host11 の実態 → network namespace の情報を見てみる。

[18] pry(#<Phut::Netns>):2> puts "#{@name}, ip:#{@ip_address}/#{@netmask}"
host11, ip:10.10.10.7/24
=> nil
[19] pry(#<Phut::Netns>):2>

もどる

[19] pry(#<Phut::Netns>):2> cd
[20] pry(main)>

host21 についても同様。

[25] pry(main)> puts host21.ip_address
10.10.10.9
=> nil
[26] pry(main)>

NetTester::Netns は、こんな感じで network namespace なノードを作るAPIを提供している。

OS 上からも見てみる。 (dot ではじまると shell mode command)

[41] pry(main)> .ip netns list
host21 (id: 1)
host11 (id: 0)
[42] pry(main)> .sudo ip netns exec host11 ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
4295: L0_host11@if4294: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:ba:dc:ab:1e:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.10.7/24 scope global L0_host11
       valid_lft forever preferred_lft forever
    inet6 fe80::2ba:dcff:feab:1e01/64 scope link
       valid_lft forever preferred_lft forever
[43] pry(main)>

OpenFlow Rule を見てもいいかもしれないけど…

つくったテスト用ノード上でコマンドを実行してみる。

[28] pry(main)> puts host11.exec("ip addr show")
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
4295: L0_host11@if4294: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:ba:dc:ab:1e:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.10.7/24 scope global L0_host11
       valid_lft forever preferred_lft forever
    inet6 fe80::2ba:dcff:feab:1e01/64 scope link
       valid_lft forever preferred_lft forever
=> nil
[29] pry(main)> 

これは、 host11 namespace 上でのコマンド実行。

ping してみる (うらで sudo tcpdump -i ens5 してもいいだろう)

[31] pry(main)> puts host11.exec("ping -c3 #{host21.ip_address}")
PING 10.10.10.9 (10.10.10.9) 56(84) bytes of data.
64 bytes from 10.10.10.9: icmp_seq=1 ttl=64 time=0.514 ms
64 bytes from 10.10.10.9: icmp_seq=2 ttl=64 time=0.336 ms
64 bytes from 10.10.10.9: icmp_seq=3 ttl=64 time=0.311 ms


--- 10.10.10.9 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.311/0.387/0.514/0.090 ms
=> nil
[32] pry(main)> 

ちょっと応用編

example2.rb の解説

実行

hagiwara@install_nettester_test:~/net-tester$ bundle exec ruby example2.rb
"# run net_tester"
"# wait ssw/psw connection"
"# create host"
"## host: int11"
"## host: int12"
"## host: int21"
"## host: int22"
"## host: dmz11"
"## host: dmz12"
"## host: dmz21"
"## host: dmz22"


From: /home/hagiwara/net-tester/example2.rb @ line 60 :


    55:                            vlan_id: seg[patch[:seg]][:vlan])
    56:   host[patch[:host]] = h
    57: end
    58:
    59: # into pry console
 => 60: binding.pry
    61:


[1] pry(main)> 

いろいろつくってあるのを確認。

[1] pry(main)> ls
self.methods: inspect  to_s
locals:
  _   _dir_  _file_  _out_  host  mac_base  patch_list  seg
  __  _ex_   _in_    _pry_  lib   nwdev     pss_dpid
[2] pry(main)> p host.size
8
=> 8
[3] pry(main)>
[4] pry(main)> host.keys
=> ["int11", "int12", "int21", "int22", "dmz11", "dmz12", "dmz21", "dmz22"]
[5] pry(main)> 

いろんな組み合わせが作れる。 たとえば、全部のホストの組み合わせとか。

[10] pry(main)> host.keys.product(host.keys)
=> [["int11", "int11"],
 ["int11", "int12"],
 ["int11", "int21"],
 ["int11", "int22"],
 ["int11", "dmz11"],
 ["int11", "dmz12"],
 ["int11", "dmz21"],
 ["int11", "dmz22"],
 ["int12", "int11"],
 ["int12", "int12"],
 ["int12", "int21"],
 ["int12", "int22"],
 ["int12", "dmz11"],
 ["int12", "dmz12"],
 ["int12", "dmz21"],
 ["int12", "dmz22"],
 ["int21", "int11"],
 ["int21", "int12"],
 ["int21", "int21"],
(省略)

host.values にすると NetTester::Netns インスタンスが取れるので、これをうまく使うと、すべてのホスト間での ping ができたりする。(fullmesh ping, mininet の pingall コマンド)

[13] pry(main)> host.values.product(host.values) do |src, dst|
[13] pry(main)*   next if src.name == dst.name
[13] pry(main)*   puts "\n##{src.name} => #{dst.name}"
[13] pry(main)*   puts src.exec("ping -c3 #{dst.ip_address}")
[13] pry(main)* end

あるいは、とりあえず直近の default gateway に対して ping が届くかどうかのテストなんかもできる。

とりあえず default gateway の確認。

[18] pry(main)> cd host['int11']
[19] pry(#<NetTester::Netns>):1> ls
NetTester::Netns#methods: method_missing
self.methods: __pry__
instance variables: @netns  @physical_port_number  @virtual_port_number  @vlan_id
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
[20] pry(#<NetTester::Netns>):1> cd netns
Error: Bad object path: "netns"
Failed trying to resolve: "netns"
Exception: #<NoMethodError: undefined method `netns' for #<Phut::Netns:0x0000000194bbe0>
Did you mean?  netmask>
[21] pry(#<NetTester::Netns>):1> cd @netns
[22] pry(#<Phut::Netns>):2> ls
Phut::ShellRunner#methods: sh  sudo
Phut::Netns#methods:
  device   exec        mac_address  netmask  run   vlan
  device=  ip_address  name         route    stop
self.methods: __pry__
instance variables: @ip_address  @mac_address  @name  @netmask  @route  @vlan
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
[23] pry(#<Phut::Netns>):2> cd route
[25] pry(#<Phut::Route>):3> ls
Phut::ShellRunner#methods: sh  sudo
Phut::Route#methods: add  gateway  net
self.methods: __pry__
instance variables: @gateway  @net
locals: _  __  _dir_  _ex_  _file_  _in_  _out_  _pry_
[26] pry(#<Phut::Route>):3> cd

テスト用ノードの default gateway ip の取得…

[27] pry(main)> puts host['int11'].route.gateway
10.10.10.254
=> nil
[28] pry(main)> 

default gateway への ping 実行

[28] pry(main)> host.values.each do |each|
[28] pry(main)*   gw = each.route.gateway
[28] pry(main)*   puts "\n##{each.name} => gw:#{gw}"
[28] pry(main)*   puts each.exec("ping -c3 #{gw}")
[28] pry(main)* end

予備

Clearning

基本

net_tester kill (基本これで一通り消える)

bundle exec net_tester kill

うまくいかないときは何か残ってないか確認する

Check trema process

ps | grep ruby
bundle exec trema killall --all

Check netns

ip netns list
sudo ip -all netns delete

Check veth interfaces

ip link show
# 残ってたら ip link delete dev <device> で “L*” なのを全部消す

Check OVS bridge (ダディクールが残ってるなら消す)

sudo ovs-vsctl list-br
sudo ovs-vsctl del-br test_0xdad1c001

スイッチの状態をクリア

  • $HOME=/home/hagiwara
  • 環境変数の設定を忘れずに
cd ~/expectacle
export L2SW_USER=`exe/readne`
export L2SW_PASS=`exe/readne`
bundle exec run_command -r -c c3750_teardown.yml -h l2switch.yml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment