From 37754a6ca4be3e2395ebd31d96e87e8b776ccc23 Mon Sep 17 00:00:00 2001 From: Eishun Kondoh Date: Sun, 28 Apr 2019 14:48:28 +0900 Subject: [PATCH] quality: Add test cases for group_mod message --- lib/openflow/action.ex | 59 ++++++++++++++++++++++++++++ lib/openflow/actions/experimenter.ex | 2 + lib/openflow/buckets.ex | 34 ++++++++++------ lib/openflow/flow_mod.ex | 5 +-- lib/openflow/get_config/reply.ex | 2 + lib/openflow/group_mod.ex | 38 +++++++++++++++--- lib/openflow/port.ex | 11 ++++++ test/ofp_group_mod_test.exs | 12 +++++- 8 files changed, 142 insertions(+), 21 deletions(-) diff --git a/lib/openflow/action.ex b/lib/openflow/action.ex index 6ffbe57..5690467 100644 --- a/lib/openflow/action.ex +++ b/lib/openflow/action.ex @@ -1,4 +1,63 @@ defmodule Openflow.Action do + @moduledoc """ + Openflow parser handler + """ + + @type type :: + Openflow.Action.Output.t() + | Openflow.Action.CopyTtlOut.t() + | Openflow.Action.CopyTtlIn.t() + | Openflow.Action.SetMplsTtl.t() + | Openflow.Action.DecMplsTtl.t() + | Openflow.Action.PushVlan.t() + | Openflow.Action.PopVlan.t() + | Openflow.Action.PushMpls.t() + | Openflow.Action.PopMpls.t() + | Openflow.Action.SetQueue.t() + | Openflow.Action.Group.t() + | Openflow.Action.SetNwTtl.t() + | Openflow.Action.DecNwTtl.t() + | Openflow.Action.SetField.t() + | Openflow.Action.PushPbb.t() + | Openflow.Action.PopPbb.t() + | Openflow.Action.NxResubmit.t() + | Openflow.Action.NxSetTunnel.t() + | Openflow.Action.NxRegMove.t() + | Openflow.Action.NxRegLoad.t() + | Openflow.Action.NxNote.t() + | Openflow.Action.NxSetTunnel64.t() + | Openflow.Action.NxMultipath.t() + | Openflow.Action.NxBundle.t() + | Openflow.Action.NxBundleLoad.t() + | Openflow.Action.NxResubmitTable.t() + | Openflow.Action.NxOutputReg.t() + | Openflow.Action.NxLearn.t() + | Openflow.Action.NxExit.t() + | Openflow.Action.NxDecTtl.t() + | Openflow.Action.NxFinTimeout.t() + | Openflow.Action.NxController.t() + | Openflow.Action.NxDecTtlCntIds.t() + | Openflow.Action.NxWriteMetadata.t() + | Openflow.Action.NxPushMpls.t() + | Openflow.Action.NxPopMpls.t() + | Openflow.Action.NxStackPush.t() + | Openflow.Action.NxStackPop.t() + | Openflow.Action.NxSample.t() + | Openflow.Action.NxOutputReg2.t() + | Openflow.Action.NxRegLoad2.t() + | Openflow.Action.NxConjunction.t() + | Openflow.Action.NxConntrack.t() + | Openflow.Action.NxNat.t() + | Openflow.Action.NxController2.t() + | Openflow.Action.NxSample2.t() + | Openflow.Action.NxOutputTrunc.t() + | Openflow.Action.NxGroup.t() + | Openflow.Action.NxSample3.t() + | Openflow.Action.NxClone.t() + | Openflow.Action.NxCtClear.t() + | Openflow.Action.NxResubmitTableCt.t() + | Openflow.Action.NxLearn2.t() + def read(action_bin) do do_read([], action_bin) end diff --git a/lib/openflow/actions/experimenter.ex b/lib/openflow/actions/experimenter.ex index 2ff6d3a..16b3302 100644 --- a/lib/openflow/actions/experimenter.ex +++ b/lib/openflow/actions/experimenter.ex @@ -3,6 +3,8 @@ defmodule Openflow.Action.Experimenter do alias __MODULE__ + @type t :: %Experimenter{exp_id: 0..0xFFFFFFFF, data: binary()} + @experimter_size 8 def ofpat, do: 0xFFFF diff --git a/lib/openflow/buckets.ex b/lib/openflow/buckets.ex index 005db35..8390452 100644 --- a/lib/openflow/buckets.ex +++ b/lib/openflow/buckets.ex @@ -8,23 +8,35 @@ defmodule Openflow.Bucket do alias __MODULE__ + @type t :: %Bucket{ + weight: 0..0xFFFF, + watch_port: Openflow.Port.no(), + watch_group: Openflow.GroupMod.id(), + actions: [Openflow.Actions.type()] + } + @header_size 16 + @spec new( + weight: 0..0xFFFF, + watch_port: Openflow.Port.no(), + watch_group: Openflow.GroupMod.id(), + actions: [Openflow.Actions.type()] + ) :: t() def new(options) do - weight = Keyword.get(options, :weight, 0) - watch_port = Keyword.get(options, :watch_port, :any) - watch_group = Keyword.get(options, :watch_group, :any) - actions = Keyword.get(options, :actions, []) - %Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} + %Bucket{ + weight: options[:weight] || 0, + watch_port: options[:watch_port] || :any, + watch_group: options[:watch_group] || :any, + actions: options[:actions] || [] + } end - def read(buckets_bin) do - do_read([], buckets_bin) - end + @spec read(<<_::_*128>>) :: [t()] + def read(buckets_bin), do: do_read([], buckets_bin) - def to_binary(buckets) do - to_binary("", buckets) - end + @spec read([t()]) :: <<_::_*128>> + def to_binary(buckets), do: to_binary("", buckets) # private functions diff --git a/lib/openflow/flow_mod.ex b/lib/openflow/flow_mod.ex index 038fdd4..2607a5f 100644 --- a/lib/openflow/flow_mod.ex +++ b/lib/openflow/flow_mod.ex @@ -25,10 +25,9 @@ defmodule Openflow.FlowMod do @type command :: :add | :modify | :modify_strict | :delete | :delete_strict - @type out_port :: - 0..0xFFFFFFFF | :max | :table | :normal | :flood | :all | :controller | :local | :any + @type out_port :: Openflow.Port.number() - @type out_group :: 0..0xFFFFFFFF | :max | :all | :any + @type out_group :: Openflow.GroupMod.id() @type flags :: [ :send_flow_rem | :check_overlap | :reset_counts | :no_packet_counts | :no_byte_counts diff --git a/lib/openflow/get_config/reply.ex b/lib/openflow/get_config/reply.ex index 12712b5..f717a2b 100644 --- a/lib/openflow/get_config/reply.ex +++ b/lib/openflow/get_config/reply.ex @@ -26,12 +26,14 @@ defmodule Openflow.GetConfig.Reply do @spec ofp_type() :: t() def ofp_type, do: 8 + @spec read(<<_::32>>) :: t() def read(<>) do flags = Openflow.Enums.int_to_flags(flags_int, :config_flags) miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len) %Reply{flags: flags, miss_send_len: miss_send_len} end + @spec to_binary(t()) :: <<_::32>> def to_binary(%Reply{flags: flags, miss_send_len: miss_send_len0}) do flags_int = Openflow.Enums.flags_to_int(flags, :config_flags) miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len) diff --git a/lib/openflow/group_mod.ex b/lib/openflow/group_mod.ex index 6f76684..4cff99d 100644 --- a/lib/openflow/group_mod.ex +++ b/lib/openflow/group_mod.ex @@ -12,17 +12,42 @@ defmodule Openflow.GroupMod do alias __MODULE__ + @type command :: :add | :delete | :modify + @type type :: :add | :select | :indirect | :fast_failover + @type id :: :max | :all | :any | 0..0xFFFFFFFF + + @type t :: %GroupMod{ + version: 4, + datapath_id: String.t() | nil, + aux_id: 0..0xF | nil, + xid: 0..0xFFFFFFFF, + command: command(), + type: type(), + group_id: id(), + buckets: [Openflow.Bucket.t()] + } + + @spec ofp_type() :: 15 def ofp_type, do: 15 + @spec new( + xid: 0..0xFFFFFFFF, + command: command(), + type: type(), + group_id: id(), + buckets: [Openflow.Bucket.t()] + ) :: t() def new(options \\ []) do - xid = Keyword.get(options, :xid, 0) - command = Keyword.get(options, :command, :add) - type = Keyword.get(options, :type, :all) - group_id = Keyword.get(options, :group_id, 0) - buckets = Keyword.get(options, :buckets, []) - %GroupMod{xid: xid, command: command, type: type, group_id: group_id, buckets: buckets} + %GroupMod{ + xid: options[:xid] || 0, + command: options[:command] || :add, + type: options[:type] || :all, + group_id: options[:group_id] || 0, + buckets: options[:buckets] || [] + } end + @spec read(<<_::64, _::_*128>>) :: t() def read(<>) do command = Openflow.Utils.get_enum(command_int, :group_mod_command) type = Openflow.Utils.get_enum(type_int, :group_type) @@ -31,6 +56,7 @@ defmodule Openflow.GroupMod do %GroupMod{command: command, type: type, group_id: group_id, buckets: buckets} end + @spec to_binary(t()) :: <<_::64, _::_*128>> def to_binary(%GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}) do command_int = Openflow.Utils.get_enum(command, :group_mod_command) type_int = Openflow.Utils.get_enum(type, :group_type) diff --git a/lib/openflow/port.ex b/lib/openflow/port.ex index 099b0bc..f500fa3 100644 --- a/lib/openflow/port.ex +++ b/lib/openflow/port.ex @@ -17,6 +17,17 @@ defmodule Openflow.Port do alias __MODULE__ + @type no :: + 0..0xFFFFFFFF + | :max + | :table + | :normal + | :flood + | :all + | :controller + | :local + | :any + def read( < Openflow.read() + |> elem(1) + |> Map.to_list() + |> Openflow.GroupMod.new() + |> Openflow.to_binary() + |> Openflow.read() + |> elem(1) assert group_mod.version == 4 assert group_mod.xid == 0