quality: Add test cases for group_mod message
This commit is contained in:
parent
ca07b47575
commit
37754a6ca4
8 changed files with 142 additions and 21 deletions
|
|
@ -1,4 +1,63 @@
|
||||||
defmodule Openflow.Action do
|
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
|
def read(action_bin) do
|
||||||
do_read([], action_bin)
|
do_read([], action_bin)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ defmodule Openflow.Action.Experimenter do
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
|
@type t :: %Experimenter{exp_id: 0..0xFFFFFFFF, data: binary()}
|
||||||
|
|
||||||
@experimter_size 8
|
@experimter_size 8
|
||||||
|
|
||||||
def ofpat, do: 0xFFFF
|
def ofpat, do: 0xFFFF
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,35 @@ defmodule Openflow.Bucket do
|
||||||
|
|
||||||
alias __MODULE__
|
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
|
@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
|
def new(options) do
|
||||||
weight = Keyword.get(options, :weight, 0)
|
%Bucket{
|
||||||
watch_port = Keyword.get(options, :watch_port, :any)
|
weight: options[:weight] || 0,
|
||||||
watch_group = Keyword.get(options, :watch_group, :any)
|
watch_port: options[:watch_port] || :any,
|
||||||
actions = Keyword.get(options, :actions, [])
|
watch_group: options[:watch_group] || :any,
|
||||||
%Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions}
|
actions: options[:actions] || []
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def read(buckets_bin) do
|
@spec read(<<_::_*128>>) :: [t()]
|
||||||
do_read([], buckets_bin)
|
def read(buckets_bin), do: do_read([], buckets_bin)
|
||||||
end
|
|
||||||
|
|
||||||
def to_binary(buckets) do
|
@spec read([t()]) :: <<_::_*128>>
|
||||||
to_binary("", buckets)
|
def to_binary(buckets), do: to_binary("", buckets)
|
||||||
end
|
|
||||||
|
|
||||||
# private functions
|
# private functions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,9 @@ defmodule Openflow.FlowMod do
|
||||||
|
|
||||||
@type command :: :add | :modify | :modify_strict | :delete | :delete_strict
|
@type command :: :add | :modify | :modify_strict | :delete | :delete_strict
|
||||||
|
|
||||||
@type out_port ::
|
@type out_port :: Openflow.Port.number()
|
||||||
0..0xFFFFFFFF | :max | :table | :normal | :flood | :all | :controller | :local | :any
|
|
||||||
|
|
||||||
@type out_group :: 0..0xFFFFFFFF | :max | :all | :any
|
@type out_group :: Openflow.GroupMod.id()
|
||||||
|
|
||||||
@type flags :: [
|
@type flags :: [
|
||||||
:send_flow_rem | :check_overlap | :reset_counts | :no_packet_counts | :no_byte_counts
|
:send_flow_rem | :check_overlap | :reset_counts | :no_packet_counts | :no_byte_counts
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,14 @@ defmodule Openflow.GetConfig.Reply do
|
||||||
@spec ofp_type() :: t()
|
@spec ofp_type() :: t()
|
||||||
def ofp_type, do: 8
|
def ofp_type, do: 8
|
||||||
|
|
||||||
|
@spec read(<<_::32>>) :: t()
|
||||||
def read(<<flags_int::16, miss_send_len0::16>>) do
|
def read(<<flags_int::16, miss_send_len0::16>>) do
|
||||||
flags = Openflow.Enums.int_to_flags(flags_int, :config_flags)
|
flags = Openflow.Enums.int_to_flags(flags_int, :config_flags)
|
||||||
miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len)
|
miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len)
|
||||||
%Reply{flags: flags, miss_send_len: miss_send_len}
|
%Reply{flags: flags, miss_send_len: miss_send_len}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec to_binary(t()) :: <<_::32>>
|
||||||
def to_binary(%Reply{flags: flags, miss_send_len: miss_send_len0}) do
|
def to_binary(%Reply{flags: flags, miss_send_len: miss_send_len0}) do
|
||||||
flags_int = Openflow.Enums.flags_to_int(flags, :config_flags)
|
flags_int = Openflow.Enums.flags_to_int(flags, :config_flags)
|
||||||
miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len)
|
miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len)
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,42 @@ defmodule Openflow.GroupMod do
|
||||||
|
|
||||||
alias __MODULE__
|
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
|
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
|
def new(options \\ []) do
|
||||||
xid = Keyword.get(options, :xid, 0)
|
%GroupMod{
|
||||||
command = Keyword.get(options, :command, :add)
|
xid: options[:xid] || 0,
|
||||||
type = Keyword.get(options, :type, :all)
|
command: options[:command] || :add,
|
||||||
group_id = Keyword.get(options, :group_id, 0)
|
type: options[:type] || :all,
|
||||||
buckets = Keyword.get(options, :buckets, [])
|
group_id: options[:group_id] || 0,
|
||||||
%GroupMod{xid: xid, command: command, type: type, group_id: group_id, buckets: buckets}
|
buckets: options[:buckets] || []
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec read(<<_::64, _::_*128>>) :: t()
|
||||||
def read(<<command_int::16, type_int::8, _::8, group_id_int::32, buckets_bin::bytes>>) do
|
def read(<<command_int::16, type_int::8, _::8, group_id_int::32, buckets_bin::bytes>>) do
|
||||||
command = Openflow.Utils.get_enum(command_int, :group_mod_command)
|
command = Openflow.Utils.get_enum(command_int, :group_mod_command)
|
||||||
type = Openflow.Utils.get_enum(type_int, :group_type)
|
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}
|
%GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec to_binary(t()) :: <<_::64, _::_*128>>
|
||||||
def to_binary(%GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}) do
|
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)
|
command_int = Openflow.Utils.get_enum(command, :group_mod_command)
|
||||||
type_int = Openflow.Utils.get_enum(type, :group_type)
|
type_int = Openflow.Utils.get_enum(type, :group_type)
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,17 @@ defmodule Openflow.Port do
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
|
@type no ::
|
||||||
|
0..0xFFFFFFFF
|
||||||
|
| :max
|
||||||
|
| :table
|
||||||
|
| :normal
|
||||||
|
| :flood
|
||||||
|
| :all
|
||||||
|
| :controller
|
||||||
|
| :local
|
||||||
|
| :any
|
||||||
|
|
||||||
def read(
|
def read(
|
||||||
<<port_no_int::32, _::size(4)-unit(8), hw_addr_bin::6-bytes, _::size(2)-unit(8),
|
<<port_no_int::32, _::size(4)-unit(8), hw_addr_bin::6-bytes, _::size(2)-unit(8),
|
||||||
name_bin::size(@ofp_max_port_name_len)-bytes, config_int::32, state_int::32,
|
name_bin::size(@ofp_max_port_name_len)-bytes, config_int::32, state_int::32,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,17 @@ defmodule OfpGroupModTest do
|
||||||
describe "Openflow.read/1" do
|
describe "Openflow.read/1" do
|
||||||
test "with OFP_GROUP_MOD packet" do
|
test "with OFP_GROUP_MOD packet" do
|
||||||
binary = File.read!("test/packet_data/4-21-ofp_group_mod.packet")
|
binary = File.read!("test/packet_data/4-21-ofp_group_mod.packet")
|
||||||
{:ok, group_mod, ""} = Openflow.read(binary)
|
{:ok, _group_mod, ""} = Openflow.read(binary)
|
||||||
|
|
||||||
|
group_mod =
|
||||||
|
binary
|
||||||
|
|> 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.version == 4
|
||||||
assert group_mod.xid == 0
|
assert group_mod.xid == 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue