diff --git a/lib/openflow/actions/nx_bundle.ex b/lib/openflow/actions/nx_bundle.ex index 04190a9..0b93371 100644 --- a/lib/openflow/actions/nx_bundle.ex +++ b/lib/openflow/actions/nx_bundle.ex @@ -14,6 +14,32 @@ defmodule Openflow.Action.NxBundle do alias __MODULE__ alias Openflow.Action.Experimenter + @type algorithm :: :active_backup | :highest_random_weight + @type hash_field :: + :eth_src + | :symmetric_l4 + | :symmetric_l3l4 + | :symmetric_l3l4_udp + | :nw_src + | :nw_dst + + @type t :: %NxBundle{ + algorithm: algorithm(), + hash_field: hash_field(), + basis: non_neg_integer(), + slave_type: :nx_in_port, + n_slaves: non_neg_integer(), + slaves: [pos_integer()] + } + + @spec new( + algorithm: algorithm(), + hash_field: hash_field(), + basis: non_neg_integer(), + slave_type: :nx_in_port, + n_slaves: non_neg_integer(), + slaves: [pos_integer()] + ) :: t() def new(options \\ []) do slaves = options[:slaves] || [] diff --git a/lib/openflow/actions/nx_bundle_load.ex b/lib/openflow/actions/nx_bundle_load.ex index 7548329..743689c 100644 --- a/lib/openflow/actions/nx_bundle_load.ex +++ b/lib/openflow/actions/nx_bundle_load.ex @@ -19,6 +19,38 @@ defmodule Openflow.Action.NxBundleLoad do alias __MODULE__ alias Openflow.Action.Experimenter + @type algorithm :: :active_backup | :highest_random_weight + @type hash_field :: + :eth_src + | :symmetric_l4 + | :symmetric_l3l4 + | :symmetric_l3l4_udp + | :nw_src + | :nw_dst + + @type t :: %NxBundleLoad{ + algorithm: algorithm(), + hash_field: hash_field(), + basis: non_neg_integer(), + slave_type: :nx_in_port, + n_slaves: non_neg_integer(), + slaves: [pos_integer()], + offset: non_neg_integer(), + n_bits: pos_integer(), + dst_field: atom() + } + + @spec new( + algorithm: algorithm(), + hash_field: hash_field(), + basis: non_neg_integer(), + slave_type: :nx_in_port, + n_slaves: non_neg_integer(), + slaves: [pos_integer()], + offset: non_neg_integer(), + n_bits: pos_integer(), + dst_field: atom() + ) :: t() def new(options \\ []) do dst_field = options[:dst_field] || raise "dst_field must be specified" default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) @@ -32,7 +64,7 @@ defmodule Openflow.Action.NxBundleLoad do slaves: slaves, offset: options[:offset] || 0, n_bits: options[:n_bits] || default_n_bits, - dst_field: options[:dst_field] + dst_field: dst_field } end diff --git a/lib/openflow/actions/nx_flow_spec_load.ex b/lib/openflow/actions/nx_flow_spec_load.ex index dcdbf86..bd7a849 100644 --- a/lib/openflow/actions/nx_flow_spec_load.ex +++ b/lib/openflow/actions/nx_flow_spec_load.ex @@ -13,12 +13,28 @@ defmodule Openflow.Action.NxFlowSpecLoad do alias __MODULE__ + @type t :: %NxFlowSpecLoad{ + src: atom(), + dst: atom(), + n_bits: non_neg_integer(), + src_offset: non_neg_integer(), + dst_offset: non_neg_integer() + } + + @spec new( + src: atom(), + dst: atom(), + n_bits: non_neg_integer(), + src_offset: non_neg_integer(), + dst_offset: non_neg_integer() + ) :: t() def new(options) do - dst = options[:dst] + dst = options[:dst] || raise(":dst must be specified") + src = options[:src] || raise(":src must be specified") n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) %NxFlowSpecLoad{ - src: options[:src], + src: src, dst: dst, n_bits: n_bits, src_offset: options[:src_offset] || 0, diff --git a/test/ofp_action_test.exs b/test/ofp_action_test.exs index 22579b9..8d6cd71 100644 --- a/test/ofp_action_test.exs +++ b/test/ofp_action_test.exs @@ -178,6 +178,8 @@ defmodule OfpActionTest do bundle = Openflow.Action.NxBundle.new( algorithm: :highest_random_weight, + hash_field: :eth_src, + basis: 0, slaves: [4, 8] ) @@ -185,6 +187,15 @@ defmodule OfpActionTest do assert actions_bin == packet assert actions == [bundle] end + + test "with no option" do + bundle = Openflow.Action.NxBundle.new() + assert bundle.algorithm == :active_backup + assert bundle.hash_field == :eth_src + assert bundle.basis == 0 + assert bundle.n_slaves == 0 + assert bundle.slaves == [] + end end describe "Openflow.Action.NxBundleLoad" do @@ -196,7 +207,10 @@ defmodule OfpActionTest do bundle_load = Openflow.Action.NxBundleLoad.new( algorithm: :highest_random_weight, + hash_field: :eth_src, + basis: 0, slaves: [4, 8], + offset: 0, dst_field: :reg0 ) @@ -769,6 +783,8 @@ defmodule OfpActionTest do Openflow.Action.NxFlowSpecMatch.new( src: :in_port, dst: :reg0, + src_offset: 0, + dst_offset: 0, n_bits: 16 ) @@ -799,6 +815,49 @@ defmodule OfpActionTest do end end + describe "Openflow.Action.NxFlowSpecLoad" do + test "with src = 0xdeadbeef and dst: :reg0" do + flow_spec = Openflow.Action.NxFlowSpecLoad.new(src: 0xDEADBEEF, dst: :reg0) + + flow_spec + |> Openflow.Action.NxFlowSpec.to_binary() + |> Openflow.Action.NxFlowSpec.read() + |> Enum.at(0) + |> Kernel.==(flow_spec) + |> assert() + end + + test "with src = :in_port and dst: :reg0" do + flow_spec = + Openflow.Action.NxFlowSpecLoad.new( + src: :in_port, + dst: :reg0, + src_offset: 0, + dst_offset: 0, + n_bits: 16 + ) + + flow_spec + |> Openflow.Action.NxFlowSpec.to_binary() + |> Openflow.Action.NxFlowSpec.read() + |> Enum.at(0) + |> Kernel.==(flow_spec) + |> assert() + end + + test "with no dst option" do + assert_raise RuntimeError, ":dst must be specified", fn -> + Openflow.Action.NxFlowSpecLoad.new(src: :in_port) + end + end + + test "with no src option" do + assert_raise RuntimeError, ":src must be specified", fn -> + Openflow.Action.NxFlowSpecLoad.new(dst: :reg0) + end + end + end + describe "Openflow.Action.NxMultipath" do test "with multipath" do test_file = "test/packet_data/nx_multipath.raw"