Work on test case for secure channel

This commit is contained in:
Eishun Kondoh 2017-11-20 16:57:37 +09:00
parent e52fe31b79
commit 2c0b0024a1
11 changed files with 603 additions and 16 deletions

View file

@ -1,5 +1,439 @@
defmodule FlayTest do
use ExUnit.Case
use Bitwise
@vlan_trunk_port 1
@access_port 2
@vxlan_port 3
@bootnet_vid 0x1000 ||| 5
@user_vid 0x1000 ||| 123
@mcast {"010000000000", "010000000000"}
@mac "010203040506"
@sdl_vmac "000000000001"
@trusted_macs [
"0800274d3297",
"0800274d3298",
"0800274d3299"
]
import Record
# Extract Erlang record for klarna/brod
for {name, schema} <- extract_all(from_lib: "pkt/include/pkt.hrl") do
defrecord(name, schema)
end
setup do
Code.load_file("test/flay.ex")
Code.load_file("test/pf.ex")
Application.put_env(:tres, :protocol, :tcp, persistent: true)
Application.put_env(:tres, :port, 6633, persistent: true)
Application.put_env(:tres, :mac_connections, 1, persistent: true)
Application.put_env(:tres, :mac_acceptors, 1, persistent: true)
Application.put_env(:tres, :callback_module, Flay, persistent: true)
Application.put_env(:tres, :callback_args, self(), persistent: true)
Application.start(:binpp)
Application.start(:pkt)
Application.start(:epcap)
Application.start(:ranch)
Application.start(:tres)
wait_for_connected()
end
describe "switch:merged_handler" do
test "OFPMP_DESC" do
%Openflow.Multipart.Desc.Reply{} = GenServer.call(Flay, :desc_stats, 5000)
end
test "Flow install" do
options = [cookie: 0x8000000000000000]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(
in_port: @vlan_trunk_port,
eth_dst: "ffffffffffff",
vlan_vid: {0x0000, 0x1fff},
eth_type: 0x88cc
)
ins = Openflow.Instruction.ApplyActions.new(Openflow.Action.Output.new(:controller))
options = [
cookie: 0x4000000000000000,
table_id: 0,
priority: 200,
match: match,
instructions: [ins]
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# LLDP Packet to vlan trunk port mac_address
src = "00000000000a"
src_mac = <<(String.to_integer(src, 16))::48>>
dst = "ffffffffffff"
dst_mac = <<(String.to_integer(dst, 16))::48>>
lldp = lldp(pdus: [
{:chassis_id, :mac_address, src_mac},
{:port_id, :mac_address, src_mac},
{:ttl, 120}
])
ether = ether(shost: src_mac, dhost: dst_mac, type: 0x88cc)
_packet = <<(:pkt.ether(ether))::bytes, (:pkt.lldp(lldp))::bytes>>
%Openflow.Multipart.PortDesc.Reply{ports: ports} = GenServer.call(Flay, :port_desc_stats, 5000)
for port <- ports do
match = Openflow.Match.new(in_port: port.number, eth_src: port.hw_addr)
options = [
cookie: 0x4000000000000000,
table_id: 0,
priority: 201,
match: match,
instructions: []
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# ARP Packet to vlan_trunk port mac address
arp = arp(arp_sha: src_mac, arp_sha: dst_mac)
ether = ether(shost: src_mac, dhost: dst_mac, type: 0x0806)
_packet = <<(:pkt.ether(ether))::bytes, (:pkt.arp(arp))::bytes>>
end
refute_receive %Openflow.ErrorMsg{}, 1000
end
end
describe "switch:uplink_escalation_flow" do
test "Flow install" do
match = Openflow.Match.new(eth_type: 0x0806)
action = Openflow.Action.Output.new(:controller)
ins = Openflow.Instruction.ApplyActions.new(action)
options = [
cookie: 0x2000000000000000,
table_id: 0,
priority: 10,
match: match,
instructions: ins
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(eth_type: 0x0800, ip_proto: 17, udp_dst: 67)
action = Openflow.Action.Output.new(:controller)
ins = Openflow.Instruction.ApplyActions.new(action)
options = [
cookie: 0x2000000000000000,
table_id: 0,
priority: 10,
match: match,
instructions: ins
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(in_port: @vlan_trunk_port)
options = [
cookie: 0x2000000000000000,
table_id: 0,
priority: 11,
match: match,
instructions: []
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
refute_receive %Openflow.ErrorMsg{}, 1000
end
end
describe "associate:register_bootstrap_rule" do
test "Flow install" do
cookie = :crypto.strong_rand_bytes(8) |> :binary.decode_unsigned(:big)
match = Openflow.Match.new(in_port: @access_port, eth_src: @mac)
actions = [
Openflow.Action.PushVlan.new,
Openflow.Action.SetField.new({:vlan_vid, @bootnet_vid}),
Openflow.Action.Output.new(@vlan_trunk_port)
]
ins = Openflow.Instruction.ApplyActions.new(actions)
options =
[table_id: 0,
priority: 50,
cookie: cookie,
idle_timeout: 300,
hard_timeout: 300,
flags: [:send_flow_rem],
match: match,
instructions: [ins]]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# trusted mac
match = Openflow.Match.new(in_port: @vlan_trunk_port, vlan_vid: @bootnet_vid, eth_dst: @mcast)
actions = [
Openflow.Action.PopVlan.new,
Openflow.Action.Output.new(@access_port)
]
ins = Openflow.Instruction.ApplyActions.new(actions)
options =
[table_id: 0,
priority: 50,
cookie: cookie,
idle_timeout: 300,
hard_timeout: 300,
flags: [:send_flow_rem],
match: match,
instructions: [ins]]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(in_port: @vlan_trunk_port, vlan_vid: @bootnet_vid, eth_dst: @mac)
actions = [
Openflow.Action.PopVlan.new,
Openflow.Action.Output.new(@access_port)
]
ins = Openflow.Instruction.ApplyActions.new(actions)
options =
[table_id: 0,
priority: 50,
cookie: cookie,
idle_timeout: 300,
hard_timeout: 300,
flags: [:send_flow_rem],
match: match,
instructions: [ins]]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(in_port: @vlan_trunk_port, eth_src: @mac)
options =
[table_id: 0,
priority: 29,
cookie: cookie,
idle_timeout: 300,
hard_timeout: 300,
flags: [:send_flow_rem],
match: match]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# Trunk Port, w/Trusted MAC -> Pop VLAN -> Access Port
for trusted <- @trusted_macs do
match = Openflow.Match.new(
in_port: @vlan_trunk_port,
eth_src: trusted,
eth_dst: @mac,
vlan_vid: @bootnet_vid
)
actions = [
Openflow.Action.PopVlan.new,
Openflow.Action.Output.new(@access_port)
]
ins = Openflow.Instruction.ApplyActions.new(actions)
options =
[table_id: 0,
priority: 50,
cookie: cookie,
idle_timeout: 300,
hard_timeout: 300,
flags: [:send_flow_rem],
match: match,
instructions: ins]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(eth_src: trusted)
options =
[table_id: 0,
priority: 29,
cookie: cookie,
idle_timeout: 300,
hard_timeout: 300,
flags: [:send_flow_rem],
match: match]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
end
refute_receive %Openflow.ErrorMsg{}, 1000
end
end
describe "associate:register_usernet_rule" do
test "Flow install" do
# BOOTNET_USE_USER_NETWORK
#
# Reply from SDL to the authorized client
cookie = :crypto.strong_rand_bytes(8) |> :binary.decode_unsigned(:big)
match = Openflow.Match.new(in_port: @vxlan_port, eth_dst: @mac)
action = Openflow.Action.Output.new(@access_port)
ins = Openflow.Instruction.ApplyActions.new(action)
options = [
cookie: cookie,
table_id: 0,
priority: 40,
idle_timeout: 32_768,
hard_timeout: 32_768,
match: match,
instructions: [ins]
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# HTTP request to the `CaptivePortal` via the SDL controller
match = Openflow.Match.new(
eth_type: 0x0800,
vlan_vid: {0x1000, 0x1000},
ip_proto: 6,
tcp_dst: 443,
ipv4_dst: {192,168,5,4}
)
actions = [
Openflow.Action.PopVlan.new,
Openflow.Action.SetField.new({:eth_dst, @sdl_vmac}),
Openflow.Action.Output.new(@vxlan_port)
]
ins = Openflow.Instruction.ApplyActions.new(actions)
options = [
cookie: 0x2000000000000001,
table_id: 1,
priority: 30,
match: match,
instructions: [ins]
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(
eth_type: 0x0800,
vlan_vid: {0x1000, 0x1000},
ip_proto: 6,
tcp_dst: 80,
ipv4_dst: {192,168,5,5}
)
actions = [
Openflow.Action.PopVlan.new,
Openflow.Action.SetField.new({:eth_dst, @sdl_vmac}),
Openflow.Action.Output.new(@vxlan_port)
]
ins = Openflow.Instruction.ApplyActions.new(actions)
options = [
cookie: 0x2000000000000001,
table_id: 1,
priority: 30,
match: match,
instructions: [ins]
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# Access Port, w/sMAC -> Push VLAN -> Table1
# Table1, w/dMAC, w/VLAN -> Pop VLAN -> Access Port
match = Openflow.Match.new(in_port: @access_port, eth_src: @mac)
actions = [
Openflow.Action.PushVlan.new,
Openflow.Action.SetField.new({:vlan_vid, @bootnet_vid})
]
insts = [
Openflow.Instruction.ApplyActions.new(actions),
Openflow.Instruction.GotoTable.new(1)
]
options = [
cookie: cookie,
table_id: 0,
priority: 20,
idle_timeout: 32_768,
hard_timeout: 32_768,
flags: [:send_flow_rem],
match: match,
instructions: insts
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(in_port: @vlan_trunk_port, eth_src: @mac)
options = [
cookie: cookie,
table_id: 0,
priority: 19,
idle_timeout: 32_768,
hard_timeout: 32_768,
flags: [:send_flow_rem],
match: match,
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(eth_src: @mac)
actions = [Openflow.Action.Output.new(:controller)]
insts = [Openflow.Instruction.ApplyActions.new(actions)]
options = [
cookie: cookie,
table_id: 0,
priority: 18,
idle_timeout: 32_768,
hard_timeout: 32_768,
flags: [:send_flow_rem],
match: match,
instructions: insts
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(vlan_vid: {0x1000, 0x1000}, eth_dst: @mac)
actions = [
Openflow.Action.PopVlan.new,
Openflow.Action.Output.new(@access_port)
]
insts = [Openflow.Instruction.ApplyActions.new(actions)]
options = [
cookie: cookie,
table_id: 1,
priority: 50,
idle_timeout: 32_768,
hard_timeout: 32_768,
flags: [:send_flow_rem],
match: match,
instructions: insts
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
# VLAN 毎に登録する共通ルール
# Table1, w/VLAN -+-> Trunk
# +-> Pop VLAN -> Access Ports
# Trunk Port, w/VLAN -> Table1
match = Openflow.Match.new(vlan_vid: @user_vid, eth_dst: @mcast)
actions = [
Openflow.Action.Output.new(@vlan_trunk_port),
Openflow.Action.PopVlan.new,
Openflow.Action.Output.new(@access_port)
]
insts = [Openflow.Instruction.ApplyActions.new(actions)]
options = [
cookie: 0x200000000000001,
table_id: 1,
priority: 60,
match: match,
instructions: insts
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(vlan_vid: @user_vid)
actions = [
Openflow.Action.Output.new(@vlan_trunk_port),
Openflow.Action.PopVlan.new,
Openflow.Action.Output.new(@access_port)
]
insts = [Openflow.Instruction.ApplyActions.new(actions)]
options = [
cookie: 0x200000000000001,
table_id: 1,
priority: 20,
match: match,
instructions: insts
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
match = Openflow.Match.new(in_port: @vlan_trunk_port, vlan_vid: @user_vid)
insts = [Openflow.Instruction.GotoTable.new(1)]
options = [
cookie: 0x200000000000001,
table_id: 0,
priority: 50,
match: match,
instructions: insts
]
:ok = GenServer.cast(Flay, {:flow_install, options, self()})
refute_receive %Openflow.ErrorMsg{}, 1000
end
end
defp wait_for_connected do
case Process.whereis(Flay) do
nil ->
wait_for_connected()
pid when is_pid(pid) ->
:ok
end
end
end