VLAN trunk test and NAT test
This commit is contained in:
parent
49d40bf2c0
commit
9b7fb2dc96
5 changed files with 112 additions and 29 deletions
|
|
@ -5,15 +5,16 @@ use Mix.Config
|
||||||
config :heckle,
|
config :heckle,
|
||||||
vlan_tagging: true,
|
vlan_tagging: true,
|
||||||
vlan_id: 123,
|
vlan_id: 123,
|
||||||
vlan_trunk: "1",
|
vlan_trunk1: "1",
|
||||||
access_port1: "3",
|
vlan_trunk2: "4",
|
||||||
access_port2: "4",
|
access_port1: "2",
|
||||||
receiver_mac: "00000000000f",
|
access_port2: "3",
|
||||||
receiver_ip: {8,8,8,8},
|
receiver_mac: "1a2c3d0e0191",
|
||||||
sender_mac: "001122334455",
|
receiver_ip: {192,168,123,1},
|
||||||
inside_local: {192,168,5,10},
|
sender_mac: "cec9bd531dfc",
|
||||||
outside_local: {192,168,255,1},
|
inside_local: {192,168,11,1},
|
||||||
flow_pattern: :bum # :nat || :bum
|
outside_local: {192,168,123,2},
|
||||||
|
flow_pattern: :nat # :nat || :bum
|
||||||
|
|
||||||
config :tres,
|
config :tres,
|
||||||
protocol: :tcp,
|
protocol: :tcp,
|
||||||
|
|
@ -24,7 +25,7 @@ config :tres,
|
||||||
callback_args: ["0002b05ada98d790"]
|
callback_args: ["0002b05ada98d790"]
|
||||||
|
|
||||||
config :logger,
|
config :logger,
|
||||||
level: :debug,
|
level: :info,
|
||||||
format: "$date $time [$level] $metadata$message\n",
|
format: "$date $time [$level] $metadata$message\n",
|
||||||
metadata: [:application],
|
metadata: [:application],
|
||||||
handle_otp_reports: true
|
handle_otp_reports: true
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,12 @@ defmodule Heckle.Controller do
|
||||||
conn_ref: nil,
|
conn_ref: nil,
|
||||||
access_port1_name: nil,
|
access_port1_name: nil,
|
||||||
access_port2_name: nil,
|
access_port2_name: nil,
|
||||||
trunk_port_name: nil,
|
trunk_port1_name: nil,
|
||||||
|
trunk_port2_name: nil,
|
||||||
access_port1: nil,
|
access_port1: nil,
|
||||||
access_port2: nil,
|
access_port2: nil,
|
||||||
trunk_port: nil,
|
trunk_port1: nil,
|
||||||
|
trunk_port2: nil,
|
||||||
vlan_tagging: nil,
|
vlan_tagging: nil,
|
||||||
vlan_id: nil,
|
vlan_id: nil,
|
||||||
receiver_mac: nil,
|
receiver_mac: nil,
|
||||||
|
|
@ -44,6 +46,8 @@ defmodule Heckle.Controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_cast(:send_flows, state) do
|
def handle_cast(:send_flows, state) do
|
||||||
|
:ok = print_flows(state)
|
||||||
|
|
||||||
state
|
state
|
||||||
|> FlowPatterns.flows
|
|> FlowPatterns.flows
|
||||||
|> Enum.each(&send_flow_mod_add(state.dpid, &1))
|
|> Enum.each(&send_flow_mod_add(state.dpid, &1))
|
||||||
|
|
@ -67,13 +71,31 @@ defmodule Heckle.Controller do
|
||||||
:ok = GenServer.cast(self(), :send_flows)
|
:ok = GenServer.cast(self(), :send_flows)
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
end
|
end
|
||||||
|
def handle_info(%Flow.Reply{flows: flows}, state) do
|
||||||
|
for flow <- flows do
|
||||||
|
:ok = info(
|
||||||
|
"table_id: #{flow.table_id} " <>
|
||||||
|
"pkt_count: #{flow.packet_count} "<>
|
||||||
|
"byt_count: #{flow.byte_count} "<>
|
||||||
|
"match: #{inspect(flow.match)} "<>
|
||||||
|
"insts: #{inspect(flow.instructions)} "
|
||||||
|
)
|
||||||
|
end
|
||||||
|
{:noreply, state}
|
||||||
|
end
|
||||||
def handle_info(%PortDesc.Reply{ports: ports}, state) do
|
def handle_info(%PortDesc.Reply{ports: ports}, state) do
|
||||||
info("Received Port Desc")
|
info("Received Port Desc")
|
||||||
access_port1 = Enum.find(ports, fn(port) -> port.name == state.access_port1_name end)
|
access_port1 = Enum.find(ports, fn(port) -> port.name == state.access_port1_name end)
|
||||||
access_port2 = Enum.find(ports, fn(port) -> port.name == state.access_port2_name end)
|
access_port2 = Enum.find(ports, fn(port) -> port.name == state.access_port2_name end)
|
||||||
trunk_port = Enum.find(ports, fn(port) -> port.name == state.trunk_port_name end)
|
trunk_port1 = Enum.find(ports, fn(port) -> port.name == state.trunk_port1_name end)
|
||||||
|
trunk_port2 = Enum.find(ports, fn(port) -> port.name == state.trunk_port2_name end)
|
||||||
:ok = desc_stats_request(state.dpid)
|
:ok = desc_stats_request(state.dpid)
|
||||||
{:noreply, %{state|access_port1: access_port1, access_port2: access_port2, trunk_port: trunk_port}}
|
{:noreply, %{state|
|
||||||
|
access_port1: access_port1,
|
||||||
|
access_port2: access_port2,
|
||||||
|
trunk_port1: trunk_port1,
|
||||||
|
trunk_port2: trunk_port2}
|
||||||
|
}
|
||||||
end
|
end
|
||||||
def handle_info(%ErrorMsg{code: code, type: type, data: data, xid: xid}, state) do
|
def handle_info(%ErrorMsg{code: code, type: type, data: data, xid: xid}, state) do
|
||||||
:ok = warn("Request Failed(xid: #{xid}):"<>
|
:ok = warn("Request Failed(xid: #{xid}):"<>
|
||||||
|
|
@ -83,11 +105,18 @@ defmodule Heckle.Controller do
|
||||||
" dpid: #{inspect(state.dpid)}")
|
" dpid: #{inspect(state.dpid)}")
|
||||||
{:stop, :request_failed, state}
|
{:stop, :request_failed, state}
|
||||||
end
|
end
|
||||||
|
def handle_info(%PacketIn{data: data}, state) do
|
||||||
|
:ok = warn("Table miss occured:"<>
|
||||||
|
" data: #{inspect(:pkt.decapsulate(data))}"<>
|
||||||
|
" dpid: #{inspect(state.dpid)}")
|
||||||
|
{:noreply, state}
|
||||||
|
end
|
||||||
def handle_info({:'DOWN', ref, :process, _pid, _reason}, %State{conn_ref: ref} = state) do
|
def handle_info({:'DOWN', ref, :process, _pid, _reason}, %State{conn_ref: ref} = state) do
|
||||||
:ok = debug("Switch Disconnected: dpid: #{inspect(state.dpid)}")
|
:ok = debug("Switch Disconnected: dpid: #{inspect(state.dpid)}")
|
||||||
{:stop, :normal, state}
|
{:stop, :normal, state}
|
||||||
end
|
end
|
||||||
def handle_info(_info, state) do
|
def handle_info(info, state) do
|
||||||
|
:ok = info("Unhandled message: #{inspect(info)}")
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -101,7 +130,8 @@ defmodule Heckle.Controller do
|
||||||
conn_ref: conn_ref,
|
conn_ref: conn_ref,
|
||||||
access_port1_name: config[:access_port1],
|
access_port1_name: config[:access_port1],
|
||||||
access_port2_name: config[:access_port2],
|
access_port2_name: config[:access_port2],
|
||||||
trunk_port_name: config[:vlan_trunk],
|
trunk_port1_name: config[:vlan_trunk1],
|
||||||
|
trunk_port2_name: config[:vlan_trunk2],
|
||||||
vlan_tagging: config[:vlan_tagging] || true,
|
vlan_tagging: config[:vlan_tagging] || true,
|
||||||
vlan_id: 0x1000 ||| (config[:vlan_id] || 0),
|
vlan_id: 0x1000 ||| (config[:vlan_id] || 0),
|
||||||
receiver_mac: config[:receiver_mac],
|
receiver_mac: config[:receiver_mac],
|
||||||
|
|
@ -130,4 +160,42 @@ defmodule Heckle.Controller do
|
||||||
defp set_config(dpid) do
|
defp set_config(dpid) do
|
||||||
:ok = send_message(SetConfig.new(miss_send_len: :no_buffer), dpid)
|
:ok = send_message(SetConfig.new(miss_send_len: :no_buffer), dpid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp print_flows(state) do
|
||||||
|
state
|
||||||
|
|> FlowPatterns.flows
|
||||||
|
|> Enum.each(&print_flow/1)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp print_flow(flow_opts) do
|
||||||
|
flow_opts
|
||||||
|
|> FlowMod.new
|
||||||
|
|> Openflow.to_binary
|
||||||
|
|> binary_to_space_delimited_hex
|
||||||
|
|> ofp_print_cmd
|
||||||
|
|> Logger.info
|
||||||
|
end
|
||||||
|
|
||||||
|
defp ofp_print_cmd(print_args) do
|
||||||
|
{result, _code} = System.cmd("ovs-ofctl", ["ofp-print", "#{print_args}"])
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
defp binary_to_space_delimited_hex(binary) do
|
||||||
|
binary
|
||||||
|
|> split_to_hex_string
|
||||||
|
|> Enum.join(" ")
|
||||||
|
|> String.downcase
|
||||||
|
end
|
||||||
|
|
||||||
|
defp split_to_hex_string(binary) do
|
||||||
|
for <<int <- binary>>, do: integer_to_hex(int)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp integer_to_hex(int) do
|
||||||
|
case Integer.to_string(int, 16) do
|
||||||
|
<<d>> -> <<48, d>>
|
||||||
|
dd -> dd
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ defmodule Heckle.FlowPatterns do
|
||||||
ApplyActions.new([
|
ApplyActions.new([
|
||||||
SetField.new({:eth_dst, state.receiver_mac}),
|
SetField.new({:eth_dst, state.receiver_mac}),
|
||||||
SetField.new({:ipv4_src, state.outside_local}),
|
SetField.new({:ipv4_src, state.outside_local}),
|
||||||
Output.new(state.trunk_port.number)
|
Output.new(state.trunk_port2.number)
|
||||||
])]
|
])]
|
||||||
],
|
],
|
||||||
[table_id: 1,
|
[table_id: 1,
|
||||||
|
|
@ -29,12 +29,15 @@ defmodule Heckle.FlowPatterns do
|
||||||
eth_dst: state.sender_mac,
|
eth_dst: state.sender_mac,
|
||||||
eth_src: state.receiver_mac,
|
eth_src: state.receiver_mac,
|
||||||
eth_type: 0x0800,
|
eth_type: 0x0800,
|
||||||
|
vlan_vid: 123,
|
||||||
ipv4_src: state.receiver_ip,
|
ipv4_src: state.receiver_ip,
|
||||||
ipv4_dst: state.outside_local
|
ipv4_dst: state.outside_local
|
||||||
),
|
),
|
||||||
instructions: [
|
instructions: [
|
||||||
ApplyActions.new([
|
ApplyActions.new([
|
||||||
|
PopVlan.new,
|
||||||
SetField.new({:eth_src, state.receiver_mac}),
|
SetField.new({:eth_src, state.receiver_mac}),
|
||||||
|
SetField.new({:eth_dst, state.sender_mac}),
|
||||||
SetField.new({:ipv4_dst, state.inside_local}),
|
SetField.new({:ipv4_dst, state.inside_local}),
|
||||||
Output.new(state.access_port1.number)
|
Output.new(state.access_port1.number)
|
||||||
])]
|
])]
|
||||||
|
|
@ -51,7 +54,7 @@ defmodule Heckle.FlowPatterns do
|
||||||
),
|
),
|
||||||
instructions: [
|
instructions: [
|
||||||
ApplyActions.new([
|
ApplyActions.new([
|
||||||
Openflow.Action.Output.new(state.trunk_port.number),
|
Openflow.Action.Output.new(state.trunk_port1.number),
|
||||||
Openflow.Action.PopVlan.new,
|
Openflow.Action.PopVlan.new,
|
||||||
Openflow.Action.Output.new(state.access_port1.number),
|
Openflow.Action.Output.new(state.access_port1.number),
|
||||||
Openflow.Action.Output.new(state.access_port2.number)
|
Openflow.Action.Output.new(state.access_port2.number)
|
||||||
|
|
@ -67,23 +70,26 @@ defmodule Heckle.FlowPatterns do
|
||||||
priority: 50,
|
priority: 50,
|
||||||
cookie: 0x1000000000000001,
|
cookie: 0x1000000000000001,
|
||||||
match: Match.new(
|
match: Match.new(
|
||||||
in_port: state.trunk_port.number,
|
in_port: state.trunk_port1.number,
|
||||||
vlan_vid: state.vlan_id
|
vlan_vid: state.vlan_id
|
||||||
),
|
),
|
||||||
instructions: [
|
instructions: [GotoTable.new(1)]
|
||||||
ApplyActions.new([
|
],
|
||||||
PushVlan.new,
|
[table_id: 0,
|
||||||
SetField.new({:vlan_vid, state.vlan_id})
|
priority: 50,
|
||||||
]),
|
cookie: 0x1000000000000001,
|
||||||
GotoTable.new(1)
|
match: Match.new(
|
||||||
]
|
in_port: state.trunk_port2.number,
|
||||||
|
vlan_vid: state.vlan_id
|
||||||
|
),
|
||||||
|
instructions: [GotoTable.new(1)]
|
||||||
],
|
],
|
||||||
[table_id: 0,
|
[table_id: 0,
|
||||||
priority: 20,
|
priority: 20,
|
||||||
cookie: 0x1000000000000001,
|
cookie: 0x1000000000000001,
|
||||||
match: Match.new(
|
match: Match.new(
|
||||||
in_port: state.access_port1.number,
|
in_port: state.access_port1.number,
|
||||||
eth_src: state.sender_mac
|
eth_src: state.sender_mac,
|
||||||
),
|
),
|
||||||
instructions: [
|
instructions: [
|
||||||
ApplyActions.new([
|
ApplyActions.new([
|
||||||
|
|
@ -98,7 +104,7 @@ defmodule Heckle.FlowPatterns do
|
||||||
cookie: 0x1000000000000001,
|
cookie: 0x1000000000000001,
|
||||||
match: Match.new(
|
match: Match.new(
|
||||||
in_port: state.access_port2.number,
|
in_port: state.access_port2.number,
|
||||||
eth_src: state.sender_mac
|
eth_src: state.sender_mac,
|
||||||
),
|
),
|
||||||
instructions: [
|
instructions: [
|
||||||
ApplyActions.new([
|
ApplyActions.new([
|
||||||
|
|
@ -108,6 +114,12 @@ defmodule Heckle.FlowPatterns do
|
||||||
GotoTable.new(1)
|
GotoTable.new(1)
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
[table_id: 0,
|
||||||
|
priority: 1,
|
||||||
|
match: Match.new,
|
||||||
|
cookie: 0x1000000000000001,
|
||||||
|
instructions: [ApplyActions.new(Output.new(:controller))]
|
||||||
|
],
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ defmodule Heckle.Mixfile do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp deps do
|
defp deps do
|
||||||
[{:tres, path: @tres_path}]
|
[{:tres, path: @tres_path},
|
||||||
|
{:pkt, github: "msantos/pkt", branch: "master"}]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
%{"binpp": {:git, "https://github.com/jtendo/binpp.git", "64bd68d215d1a6cd35871e7c134d7fe2e46214ea", [branch: "master"]},
|
%{"binpp": {:git, "https://github.com/jtendo/binpp.git", "64bd68d215d1a6cd35871e7c134d7fe2e46214ea", [branch: "master"]},
|
||||||
"eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]},
|
"eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]},
|
||||||
"jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]},
|
"jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]},
|
||||||
|
"pkt": {:git, "https://github.com/msantos/pkt.git", "3afb1967f34324c1dec5035a6e36232da815c2e6", [branch: "master"]},
|
||||||
"ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [], [], "hexpm"},
|
"ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [], [], "hexpm"},
|
||||||
"uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}}
|
"uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue