tres/lib/openflow/buckets.ex
2019-05-05 23:39:46 +09:00

83 lines
2.3 KiB
Elixir

defmodule Openflow.Bucket do
defstruct(
weight: 0,
watch_port: 0,
watch_group: 0,
actions: []
)
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
%Bucket{
weight: options[:weight] || 0,
watch_port: options[:watch_port] || :any,
watch_group: options[:watch_group] || :any,
actions: options[:actions] || []
}
end
@spec read(<<_::_*128>>) :: [t()]
def read(buckets_bin), do: do_read([], buckets_bin)
@spec read([t()]) :: <<_::_*128>>
def to_binary(buckets), do: to_binary("", buckets)
# private functions
defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(
acc,
<<length::16, weight::16, watch_port_int::32, watch_group_int::32, _::size(4)-unit(8),
binary::bytes>>
) do
actions_len = length - @header_size
<<actions_bin::size(actions_len)-bytes, rest::bytes>> = binary
watch_port = Openflow.Utils.get_enum(watch_port_int, :openflow13_port_no)
watch_group = Openflow.Utils.get_enum(watch_group_int, :group_id)
actions = Openflow.Action.read(actions_bin)
bucket = %Bucket{
weight: weight,
watch_port: watch_port,
watch_group: watch_group,
actions: actions
}
do_read([bucket | acc], rest)
end
defp to_binary(acc, []), do: acc
defp to_binary(acc, [bucket | rest]) do
%Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} =
bucket
watch_port_int = Openflow.Utils.get_enum(watch_port, :openflow13_port_no)
watch_group_int = Openflow.Utils.get_enum(watch_group, :group_id)
actions_bin = Openflow.Action.to_binary(actions)
length = byte_size(actions_bin) + @header_size
bucket_bin =
<<length::16, weight::16, watch_port_int::32, watch_group_int::32, 0::size(4)-unit(8),
actions_bin::bytes>>
to_binary(<<acc::bytes, bucket_bin::bytes>>, rest)
end
end