+--------------+ +--------------+
| 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
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