From f2297c551a84831619dad38409cd21a284f66710 Mon Sep 17 00:00:00 2001 From: Eishun Kondoh Date: Fri, 1 Dec 2017 11:11:11 +0900 Subject: [PATCH] Add an example controller for hardware switch test --- examples/heckle/.gitignore | 20 +++ examples/heckle/README.md | 21 +++ examples/heckle/config/config.exs | 30 ++++ examples/heckle/lib/heckle.ex | 18 +++ examples/heckle/lib/heckle/application.ex | 20 +++ examples/heckle/lib/heckle/controller.ex | 133 ++++++++++++++++++ examples/heckle/lib/heckle/flow_patterns.ex | 113 +++++++++++++++ .../heckle/lib/heckle/pipeline_profiles.ex | 31 ++++ examples/heckle/mix.exs | 22 +++ examples/heckle/mix.lock | 5 + examples/heckle/test/heckle_test.exs | 8 ++ examples/heckle/test/test_helper.exs | 1 + lib/tres/secure_channel.ex | 11 +- src/tres_xact_kv.erl | 9 +- test/flay.ex | 8 +- test/flog_test.exs | 101 ++++++++----- 16 files changed, 501 insertions(+), 50 deletions(-) create mode 100644 examples/heckle/.gitignore create mode 100644 examples/heckle/README.md create mode 100644 examples/heckle/config/config.exs create mode 100644 examples/heckle/lib/heckle.ex create mode 100644 examples/heckle/lib/heckle/application.ex create mode 100644 examples/heckle/lib/heckle/controller.ex create mode 100644 examples/heckle/lib/heckle/flow_patterns.ex create mode 100644 examples/heckle/lib/heckle/pipeline_profiles.ex create mode 100644 examples/heckle/mix.exs create mode 100644 examples/heckle/mix.lock create mode 100644 examples/heckle/test/heckle_test.exs create mode 100644 examples/heckle/test/test_helper.exs diff --git a/examples/heckle/.gitignore b/examples/heckle/.gitignore new file mode 100644 index 0000000..12179ea --- /dev/null +++ b/examples/heckle/.gitignore @@ -0,0 +1,20 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez diff --git a/examples/heckle/README.md b/examples/heckle/README.md new file mode 100644 index 0000000..eabaf9d --- /dev/null +++ b/examples/heckle/README.md @@ -0,0 +1,21 @@ +# Heckle + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `heckle` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:heckle, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at [https://hexdocs.pm/heckle](https://hexdocs.pm/heckle). + diff --git a/examples/heckle/config/config.exs b/examples/heckle/config/config.exs new file mode 100644 index 0000000..b8b1eed --- /dev/null +++ b/examples/heckle/config/config.exs @@ -0,0 +1,30 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +config :heckle, + vlan_tagging: true, + vlan_id: 123, + vlan_trunk: "veth0", + access_port1: "veth4", + access_port2: "veth3", + receiver_mac: "00000000000f", + receiver_ip: {8,8,8,8}, + sender_mac: "001122334455", + inside_local: {192,168,5,10}, + outside_local: {192,168,255,1}, + flow_pattern: :bum + +config :tres, + protocol: :tcp, + port: 6653, + max_connections: 10, + num_acceptors: 10, + callback_module: Heckle.Controller, + callback_args: ["0000d2851d52d749"] + +config :logger, + level: :debug, + format: "$date $time [$level] $metadata$message\n", + metadata: [:application], + handle_otp_reports: true diff --git a/examples/heckle/lib/heckle.ex b/examples/heckle/lib/heckle.ex new file mode 100644 index 0000000..ff5d007 --- /dev/null +++ b/examples/heckle/lib/heckle.ex @@ -0,0 +1,18 @@ +defmodule Heckle do + @moduledoc """ + Documentation for Heckle. + """ + + @doc """ + Hello world. + + ## Examples + + iex> Heckle.hello + :world + + """ + def hello do + :world + end +end diff --git a/examples/heckle/lib/heckle/application.ex b/examples/heckle/lib/heckle/application.ex new file mode 100644 index 0000000..7f46096 --- /dev/null +++ b/examples/heckle/lib/heckle/application.ex @@ -0,0 +1,20 @@ +defmodule Heckle.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + def start(_type, _args) do + # List all child processes to be supervised + children = [ + # Starts a worker by calling: Heckle.Worker.start_link(arg) + # {Heckle.Worker, arg}, + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: Heckle.Supervisor] + Supervisor.start_link(children, opts) + end +end diff --git a/examples/heckle/lib/heckle/controller.ex b/examples/heckle/lib/heckle/controller.ex new file mode 100644 index 0000000..f4944e9 --- /dev/null +++ b/examples/heckle/lib/heckle/controller.ex @@ -0,0 +1,133 @@ +defmodule Heckle.Controller do + use GenServer + use Bitwise + use Tres.Controller + + import Logger + + alias Heckle.PipelineProfiles + alias Heckle.FlowPatterns + + defmodule State do + defstruct [ + dpid: nil, + conn_ref: nil, + access_port1_name: nil, + access_port2_name: nil, + trunk_port_name: nil, + access_port1: nil, + access_port2: nil, + trunk_port: nil, + vlan_tagging: nil, + vlan_id: nil, + receiver_mac: nil, + receiver_ip: nil, + sender_mac: nil, + inside_local: nil, + outside_local: nil, + flow_pattern: nil + ] + end + + def start_link(dpid, args) do + GenServer.start(__MODULE__, [dpid, args]) + end + + def init([{dpid, _aux_id}, [dpid]]) do + :ok = info("Switch Ready: dpid: #{inspect(dpid)} on #{inspect(self())}") + state = init_state(dpid) + {:ok, state} + end + def init([{dpid, _aux_id}, [_dpid]]) do + :ok = info("Switch Ready: dpid: #{inspect(dpid)} but not acceptable") + :ignore + end + + def handle_cast(:send_flows, state) do + state + |> FlowPatterns.flows + |> Enum.each(&send_flow_mod_add(state.dpid, &1)) + {:noreply, state} + end + + def handle_info(%Desc.Reply{mfr_desc: "Aruba"} = desc, %State{dpid: dpid} = state) do + info("Switch Desc: mfr = #{desc.mfr_desc} hw = #{desc.hw_desc} sw = #{desc.sw_desc}") + :ok = PipelineProfiles.of_aruba() + |> TableFeatures.Request.new + |> send_message(dpid) + {:noreply, state} + end + def handle_info(%Desc.Reply{} = desc, state) do + :ok = info("Switch Desc: mfr = #{desc.mfr_desc} hw = #{desc.hw_desc} sw = #{desc.sw_desc}") + :ok = GenServer.cast(self(), :send_flows) + {:noreply, state} + end + def handle_info(%TableFeatures.Reply{xid: xid}, state) do + :ok = info("Pipeline modification is success (xid: #{xid})") + :ok = GenServer.cast(self(), :send_flows) + {:noreply, state} + end + def handle_info(%PortDesc.Reply{ports: ports}, state) do + info("Received Port Desc") + 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) + trunk_port = Enum.find(ports, fn(port) -> port.name == state.trunk_port_name end) + :ok = desc_stats_request(state.dpid) + {:noreply, %{state|access_port1: access_port1, access_port2: access_port2, trunk_port: trunk_port}} + end + def handle_info(%ErrorMsg{code: code, type: type, data: data, xid: xid}, state) do + :ok = warn("Request Failed(xid: #{xid}):"<> + " code: #{code}"<> + " type: #{type}"<> + " data: #{inspect(data)}"<> + " dpid: #{inspect(state.dpid)}") + {:stop, :request_failed, state} + end + def handle_info({:'DOWN', ref, :process, _pid, _reason}, %State{conn_ref: ref} = state) do + :ok = debug("Switch Disconnected: dpid: #{inspect(state.dpid)}") + {:stop, :normal, state} + end + def handle_info(_info, state) do + {:noreply, state} + end + + # private functions + defp init_state(dpid) do + :ok = init_datapath(dpid) + conn_ref = SwitchRegistry.monitor(dpid) + config = Application.get_all_env(:heckle) + %State{ + dpid: dpid, + conn_ref: conn_ref, + access_port1_name: config[:access_port1], + access_port2_name: config[:access_port2], + trunk_port_name: config[:vlan_trunk], + vlan_tagging: config[:vlan_tagging] || true, + vlan_id: 0x1000 ||| (config[:vlan_id] || 0), + receiver_mac: config[:receiver_mac], + receiver_ip: config[:receiver_ip], + sender_mac: config[:sender_mac], + inside_local: config[:inside_local], + outside_local: config[:outside_local], + flow_pattern: config[:flow_pattern] || :nat + } + end + + defp init_datapath(dpid) do + :ok = send_flow_mod_delete(dpid) + :ok = port_desc_stats_request(dpid) + :ok = set_config(dpid) + end + + defp desc_stats_request(dpid) do + :ok = send_message(Desc.Request.new, dpid) + end + + defp port_desc_stats_request(dpid) do + :ok = send_message(PortDesc.Request.new, dpid) + end + + defp set_config(dpid) do + :ok = send_message(SetConfig.new(miss_send_len: :no_buffer), dpid) + end +end diff --git a/examples/heckle/lib/heckle/flow_patterns.ex b/examples/heckle/lib/heckle/flow_patterns.ex new file mode 100644 index 0000000..2a8cad2 --- /dev/null +++ b/examples/heckle/lib/heckle/flow_patterns.ex @@ -0,0 +1,113 @@ +defmodule Heckle.FlowPatterns do + use Bitwise + use Tres.Controller + + @mcast {"010000000000", "010000000000"} + + def flows(%Heckle.Controller.State{flow_pattern: :nat} = state) do + [[table_id: 1, + priority: 30, + cookie: 0x3000000000000001, + match: Match.new( + eth_dst: state.receiver_mac, + eth_src: state.sender_mac, + eth_type: 0x0800, + ipv4_src: state.inside_local, + ipv4_dst: state.receiver_ip + ), + instructions: [ + ApplyActions.new([ + SetField.new({:eth_dst, state.receiver_mac}), + SetField.new({:ipv4_src, state.outside_local}), + Output.new(state.trunk_port.number) + ])] + ], + [table_id: 1, + priority: 30, + cookie: 0x3000000000000001, + match: Match.new( + eth_dst: state.sender_mac, + eth_src: state.receiver_mac, + eth_type: 0x0800, + ipv4_src: state.receiver_ip, + ipv4_dst: state.outside_local + ), + instructions: [ + ApplyActions.new([ + SetField.new({:eth_src, state.receiver_mac}), + SetField.new({:ipv4_dst, state.inside_local}), + Output.new(state.access_port1.number) + ])] + ], + ] ++ classifier(state) + end + def flows(%Heckle.Controller.State{flow_pattern: :bum} = state) do + [[table_id: 1, + priority: 30, + cookie: 0x3000000000000001, + match: Match.new( + vlan_vid: state.vlan_id, + eth_dst: @mcast + ), + instructions: [ + ApplyActions.new([ + Openflow.Action.Output.new(state.trunk_port.number), + Openflow.Action.PopVlan.new, + Openflow.Action.Output.new(state.access_port1.number), + Openflow.Action.Output.new(state.access_port2.number) + ])] + ]] ++ classifier(state) + end + + # private functions + + defp classifier(state) do + [ + [table_id: 0, + priority: 50, + cookie: 0x1000000000000001, + match: Match.new( + in_port: state.trunk_port.number, + vlan_vid: state.vlan_id + ), + instructions: [ + ApplyActions.new([ + PushVlan.new, + SetField.new({:vlan_vid, state.vlan_id}) + ]), + GotoTable.new(1) + ] + ], + [table_id: 0, + priority: 20, + cookie: 0x1000000000000001, + match: Match.new( + in_port: state.access_port1.number, + eth_src: state.sender_mac + ), + instructions: [ + ApplyActions.new([ + PushVlan.new, + SetField.new({:vlan_vid, state.vlan_id}) + ]), + GotoTable.new(1) + ] + ], + [table_id: 0, + priority: 20, + cookie: 0x1000000000000001, + match: Match.new( + in_port: state.access_port2.number, + eth_src: state.sender_mac + ), + instructions: [ + ApplyActions.new([ + PushVlan.new, + SetField.new({:vlan_vid, state.vlan_id}) + ]), + GotoTable.new(1) + ] + ], + ] + end +end diff --git a/examples/heckle/lib/heckle/pipeline_profiles.ex b/examples/heckle/lib/heckle/pipeline_profiles.ex new file mode 100644 index 0000000..492febd --- /dev/null +++ b/examples/heckle/lib/heckle/pipeline_profiles.ex @@ -0,0 +1,31 @@ +defmodule Heckle.PipelineProfiles do + use Tres.Controller + + def of_aruba do + [ + TableFeatures.Body.new( + table_id: 0, + name: "classifier", + max_entries: 10, + config: [:table_miss_mask], # deprecated mask. + match: [:in_port, :masked_eth_src], + wildcards: [:in_port, :masked_eth_src], + instructions: [GotoTable], + write_actions: [Output], + next_tables: [1], + ), + TableFeatures.Body.new( + table_id: 1, + name: "NAT", + max_entries: 10, + config: [:table_miss_mask], + match: [:eth_dst, :eth_src, :eth_type, :ipv4_src, :ipv4_dst], + wildcards: [:eth_dst, :eth_src, :eth_type, :ipv4_src, :ipv4_dst], + instructions: [ApplyActions], + write_actions: [SetField, PopVlan, PushVlan, Output], + apply_setfield: [:eth_dst, :vlan_vid, :ipv4_src, :ipv4_dst], + next_tables: [], + ) + ] + end +end diff --git a/examples/heckle/mix.exs b/examples/heckle/mix.exs new file mode 100644 index 0000000..ad0528a --- /dev/null +++ b/examples/heckle/mix.exs @@ -0,0 +1,22 @@ +defmodule Heckle.Mixfile do + use Mix.Project + + @tres_path "../../../tres" + + def project do + [app: :heckle, + version: "0.1.0", + elixir: "~> 1.5", + start_permanent: Mix.env == :prod, + deps: deps()] + end + + def application do + [extra_applications: [:logger, :tres], + mod: {Heckle.Application, []}] + end + + defp deps do + [{:tres, path: @tres_path}] + end +end diff --git a/examples/heckle/mix.lock b/examples/heckle/mix.lock new file mode 100644 index 0000000..eeade00 --- /dev/null +++ b/examples/heckle/mix.lock @@ -0,0 +1,5 @@ +%{"binpp": {:git, "https://github.com/jtendo/binpp.git", "64bd68d215d1a6cd35871e7c134d7fe2e46214ea", [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"]}, + "ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [], [], "hexpm"}, + "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}} diff --git a/examples/heckle/test/heckle_test.exs b/examples/heckle/test/heckle_test.exs new file mode 100644 index 0000000..855f884 --- /dev/null +++ b/examples/heckle/test/heckle_test.exs @@ -0,0 +1,8 @@ +defmodule HeckleTest do + use ExUnit.Case + doctest Heckle + + test "greets the world" do + assert Heckle.hello() == :world + end +end diff --git a/examples/heckle/test/test_helper.exs b/examples/heckle/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/examples/heckle/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/lib/tres/secure_channel.ex b/lib/tres/secure_channel.ex index dbd7c41..1e3153a 100644 --- a/lib/tres/secure_channel.ex +++ b/lib/tres/secure_channel.ex @@ -189,10 +189,13 @@ defmodule Tres.SecureChannel do :keep_state_and_data end defp handle_CONNECTED(:cast, {:send_message, message} = action, state_data) do - if Queue.is_empty(state_data.action_queue), - do: xactional_send_message(message, state_data) - action_queue = Queue.in(action, state_data.action_queue) - {:keep_state, %{state_data|action_queue: action_queue}} + new_action_queue = if XACT_KV.is_empty(state_data.xact_kv_ref) do + xactional_send_message(message, state_data) + state_data.action_queue + else + Queue.in(action, state_data.action_queue) + end + {:keep_state, %{state_data|action_queue: new_action_queue}} end # WATING state diff --git a/src/tres_xact_kv.erl b/src/tres_xact_kv.erl index e7a99a1..cb6c33a 100644 --- a/src/tres_xact_kv.erl +++ b/src/tres_xact_kv.erl @@ -3,7 +3,7 @@ -include_lib("stdlib/include/ms_transform.hrl"). -export([create/0, drop/1]). --export([insert/3, update/3, get/2, delete/2, is_exists/2]). +-export([insert/3, update/3, get/2, delete/2, is_exists/2, is_empty/1]). -define(TABLE, xact_kv). -define(ENTRY, xact_entry). @@ -44,6 +44,13 @@ is_exists(Tid, Xid) -> [] -> false end. +-spec is_empty(reference()) -> boolean(). +is_empty(Tid) -> + case ets:info(Tid, size) of + 0 -> true; + _ -> false + end. + %% Private functions ms_for_exists(Xid) -> diff --git a/test/flay.ex b/test/flay.ex index 101bc3b..a6fbccf 100644 --- a/test/flay.ex +++ b/test/flay.ex @@ -195,9 +195,7 @@ defmodule Flay do :udp_dst, :tcp_dst, :ipv4_src, - :ipv4_dst, - :arp_spa, - :arp_tpa + :ipv4_dst ], wildcards: [ :eth_type, @@ -208,9 +206,7 @@ defmodule Flay do :udp_dst, :tcp_dst, :ipv4_src, - :ipv4_dst, - :arp_spa, - :arp_tpa + :ipv4_dst ], instructions: [ Openflow.Instruction.GotoTable, diff --git a/test/flog_test.exs b/test/flog_test.exs index 1148f6c..3037cc7 100644 --- a/test/flog_test.exs +++ b/test/flog_test.exs @@ -74,7 +74,8 @@ defmodule FlogTest do priority: 0 ] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -89,7 +90,7 @@ defmodule FlogTest do arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] Pf.inject!(pid1, packet, payload) - refute_receive {@vlan_trunk_port_sniffer, ^packet}, 3000 + refute_receive {@vlan_trunk_port_sniffer, ^packet}, 1000 Pf.stop(pid1) Pf.stop(pid2) end @@ -114,7 +115,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 {:ok, pid1} = Pf.start_link(@access_port1_sniffer) {:ok, pid2} = Pf.start_link(@vlan_trunk_port_sniffer) @@ -129,9 +131,9 @@ defmodule FlogTest do ] Pf.inject!(pid2, packet) in_port = state.vlan_trunk.number - assert_receive %Openflow.PacketIn{in_port: ^in_port}, 3000 - refute_receive {@vlan_trunk_port_sniffer, [^packet, ""]}, 3000 - refute_receive {@access_port1_sniffer, [^packet, ""]}, 3000 + assert_receive %Openflow.PacketIn{in_port: ^in_port}, 1000 + refute_receive {@vlan_trunk_port_sniffer, [^packet, ""]}, 1000 + refute_receive {@access_port1_sniffer, [^packet, ""]}, 1000 Pf.stop(pid1) Pf.stop(pid2) end @@ -148,25 +150,27 @@ defmodule FlogTest do priority: 201, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end end describe("switch:uplink_escalation_flow:" <> - "table=0,priority=10,cookie=0x3000000000000000,arp,actions=controller") do + "table=0,priority=10,cookie=0x1000000000000000,arp,actions=controller") do test "Install Flow", state do match = Openflow.Match.new(eth_type: 0x0806) action = Openflow.Action.Output.new(:controller) ins = Openflow.Instruction.ApplyActions.new(action) options = - [cookie: 0x3000000000000000, + [cookie: 0x1000000000000000, table_id: 0, priority: 10, match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 {:ok, pid1} = Pf.start_link(@access_port1_sniffer) {:ok, pid2} = Pf.start_link(@vlan_trunk_port_sniffer) @@ -180,27 +184,28 @@ defmodule FlogTest do ] Pf.inject!(pid1, packet, payload) in_port = state.port.number - assert_receive %Openflow.PacketIn{in_port: ^in_port}, 3000 - refute_receive {@vlan_trunk_port_sniffer, ^packet}, 3000 + assert_receive %Openflow.PacketIn{in_port: ^in_port}, 1000 + refute_receive {@vlan_trunk_port_sniffer, ^packet}, 1000 Pf.stop(pid1) Pf.stop(pid2) end end describe("switch:uplink_escalation_flow:" <> - "table=0,priority=10,cookie=0x3000000000000000,udp,udp_dst=67,actions=controller") do + "table=0,priority=10,cookie=0x1000000000000000,udp,udp_dst=67,actions=controller") do test "Install Flow", state do 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: 0x3000000000000000, + [cookie: 0x1000000000000000, table_id: 0, priority: 10, match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 {:ok, pid1} = Pf.start_link(@access_port1_sniffer) {:ok, pid2} = Pf.start_link(@vlan_trunk_port_sniffer) @@ -220,24 +225,25 @@ defmodule FlogTest do ] Pf.inject!(pid1, packet, <>) in_port = state.port.number - assert_receive %Openflow.PacketIn{in_port: ^in_port}, 3000 - refute_receive {@vlan_trunk_port_sniffer, ^packet}, 3000 + assert_receive %Openflow.PacketIn{in_port: ^in_port}, 1000 + refute_receive {@vlan_trunk_port_sniffer, ^packet}, 1000 Pf.stop(pid1) Pf.stop(pid2) end end describe("switch:uplink_escalation_flow:" <> - "table=0,priority=11,cookie=0x3000000000000000,in_port={trunk_port},actions=drop") do + "table=0,priority=11,cookie=0x1000000000000000,in_port={trunk_port},actions=drop") do test "Install Flow", state do match = Openflow.Match.new(in_port: state.vlan_trunk.number) options = - [cookie: 0x3000000000000000, + [cookie: 0x1000000000000000, table_id: 0, priority: 11, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -252,7 +258,7 @@ defmodule FlogTest do arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] Pf.inject!(pid2, packet, payload) - refute_receive {@access_port1_sniffer, ^packet}, 3000 + refute_receive {@access_port1_sniffer, ^packet}, 1000 Pf.stop(pid1) Pf.stop(pid2) end @@ -283,7 +289,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -332,7 +339,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -385,7 +393,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -428,7 +437,8 @@ defmodule FlogTest do hard_timeout: state.timeout, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -476,7 +486,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -521,7 +532,8 @@ defmodule FlogTest do hard_timeout: state.timeout, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end end @@ -541,7 +553,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -568,7 +581,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -596,7 +610,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(TCP:443)" do @@ -652,7 +667,8 @@ defmodule FlogTest do match: match, instructions: [ins]] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(TCP:80)" do @@ -698,7 +714,8 @@ defmodule FlogTest do hard_timeout: state.timeout, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -719,7 +736,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -742,7 +760,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP)" do @@ -758,7 +777,7 @@ defmodule FlogTest do packet = [vlan_ether_header, vlan_header, arp_header] expect = [ether_header, arp_header] Pf.inject!(pid2, packet) - assert_receive {@access_port1_sniffer, ^expect}, 3000 + assert_receive {@access_port1_sniffer, ^expect}, 1000 Pf.stop(pid1) Pf.stop(pid2) end @@ -783,7 +802,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(ARP) from VLAN TRUNK" do @@ -848,7 +868,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -881,7 +902,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -913,7 +935,8 @@ defmodule FlogTest do match: match, instructions: ins] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - refute_receive %Openflow.ErrorMsg{}, 3000 + :timer.sleep 1000 + refute_receive %Openflow.ErrorMsg{}, 1000 end test "Inject Packet(TCP:80)" do