Refactored nicira extended actions
This commit is contained in:
parent
efd08cf6dd
commit
ffcba91395
51 changed files with 1015 additions and 819 deletions
|
|
@ -23,8 +23,9 @@ defmodule Openflow.Action.NxController2 do
|
|||
@nx_ctlr_no_meter 0
|
||||
|
||||
alias __MODULE__
|
||||
alias Openflow.Action.Experimenter
|
||||
|
||||
def new(options) do
|
||||
def new(options \\ []) do
|
||||
%NxController2{
|
||||
max_len: options[:max_len] || :no_buffer,
|
||||
id: options[:id] || 0,
|
||||
|
|
@ -36,14 +37,14 @@ defmodule Openflow.Action.NxController2 do
|
|||
end
|
||||
|
||||
def to_binary(%NxController2{} = ctl) do
|
||||
ext_header = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>
|
||||
prop_keys = get_prop_key(ctl)
|
||||
props_bin = encode_prop("", prop_keys, ctl)
|
||||
exp_body = <<ext_header::bytes, props_bin::bytes>>
|
||||
exp_body_size = byte_size(exp_body)
|
||||
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
|
||||
length = 4 + exp_body_size + padding_length
|
||||
<<0xFFFF::16, length::16, exp_body::bytes>>
|
||||
props_bin = encode_props(ctl)
|
||||
|
||||
Experimenter.pack_exp_header(<<
|
||||
@experimenter::32,
|
||||
@nxast::16,
|
||||
0::size(6)-unit(8),
|
||||
props_bin::bytes
|
||||
>>)
|
||||
end
|
||||
|
||||
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), body::bytes>>) do
|
||||
|
|
@ -53,101 +54,144 @@ defmodule Openflow.Action.NxController2 do
|
|||
|
||||
# private functions
|
||||
|
||||
defp get_prop_key(ctl) do
|
||||
defp encode_props(ctl) do
|
||||
ctl
|
||||
|> Map.from_struct()
|
||||
|> Enum.map(fn {k, v} -> if(not is_nil(v), do: k, else: nil) end)
|
||||
|> Enum.filter(fn v -> not is_nil(v) end)
|
||||
|> Enum.reduce(<<>>, &encode_prop/2)
|
||||
end
|
||||
|
||||
defp encode_prop(acc, [], _ctl), do: acc
|
||||
defp encode_prop({:max_len, value}, acc)
|
||||
when value != :no_buffer or value < 0xFFFF do
|
||||
pad_length = 2
|
||||
prop_length = @prop_header_size + 2 + pad_length
|
||||
max_len_int = Openflow.Utils.get_enum(value, :controller_max_len)
|
||||
|
||||
defp encode_prop(acc, [prop | rest], ctl) do
|
||||
value = Map.get(ctl, prop)
|
||||
<<
|
||||
acc::bytes,
|
||||
@prop_max_len::16,
|
||||
prop_length::16,
|
||||
max_len_int::16,
|
||||
0::size(pad_length)-unit(8)
|
||||
>>
|
||||
end
|
||||
|
||||
prop_bin =
|
||||
cond do
|
||||
prop == :max_len and (value != :no_buffer or value < 0xFFFF) ->
|
||||
padding_length = 2
|
||||
prop_length = @prop_header_size + 2 + padding_length
|
||||
max_len_int = Openflow.Utils.get_enum(value, :controller_max_len)
|
||||
<<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>>
|
||||
defp encode_prop({:id, value}, acc) do
|
||||
pad_length = 2
|
||||
prop_length = @prop_header_size + 2 + pad_length
|
||||
|
||||
prop == :id ->
|
||||
padding_length = 2
|
||||
prop_length = @prop_header_size + 2 + padding_length
|
||||
<<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>>
|
||||
<<
|
||||
acc::bytes,
|
||||
@prop_ctl_id::16,
|
||||
prop_length::16,
|
||||
value::16,
|
||||
0::size(pad_length)-unit(8)
|
||||
>>
|
||||
end
|
||||
|
||||
prop == :reason and value != :action ->
|
||||
padding_length = 3
|
||||
prop_length = @prop_header_size + 1 + padding_length
|
||||
reason_int = Openflow.Utils.get_enum(value, :packet_in_reason)
|
||||
<<@prop_reason::16, prop_length::16, reason_int::8, 0::size(padding_length)-unit(8)>>
|
||||
defp encode_prop({:reason, reason}, acc)
|
||||
when reason != :action do
|
||||
padding_length = 3
|
||||
prop_length = @prop_header_size + 1 + padding_length
|
||||
reason_int = Openflow.Utils.get_enum(reason, :packet_in_reason)
|
||||
|
||||
prop == :userdata and byte_size(value) > 0 ->
|
||||
prop_length = @prop_header_size + byte_size(value)
|
||||
padding_length = Openflow.Utils.padding(prop_length, 8)
|
||||
<<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>>
|
||||
<<
|
||||
acc::bytes,
|
||||
@prop_reason::16,
|
||||
prop_length::16,
|
||||
reason_int::8,
|
||||
0::size(padding_length)-unit(8)
|
||||
>>
|
||||
end
|
||||
|
||||
prop == :pause and value == true ->
|
||||
padding_length = 4
|
||||
prop_length = @prop_header_size + padding_length
|
||||
<<@prop_pause::16, prop_length::16, 0::size(padding_length)-unit(8)>>
|
||||
defp encode_prop({:userdata, value}, acc)
|
||||
when byte_size(value) > 0 do
|
||||
prop_length = @prop_header_size + byte_size(value)
|
||||
padding_length = Openflow.Utils.padding(prop_length, 8)
|
||||
|
||||
prop == :meter_id and value != @nx_ctlr_no_meter ->
|
||||
prop_length = @prop_header_size + 4
|
||||
<<@prop_meter_id::16, prop_length::16, value::32>>
|
||||
<<
|
||||
acc::bytes,
|
||||
@prop_userdata::16,
|
||||
prop_length::16,
|
||||
value::bytes,
|
||||
0::size(padding_length)-unit(8)
|
||||
>>
|
||||
end
|
||||
|
||||
true ->
|
||||
""
|
||||
end
|
||||
defp encode_prop({:pause, true}, acc) do
|
||||
padding_length = 4
|
||||
prop_length = @prop_header_size + padding_length
|
||||
|
||||
encode_prop(<<acc::bytes, prop_bin::bytes>>, rest, ctl)
|
||||
<<
|
||||
acc::bytes,
|
||||
@prop_pause::16,
|
||||
prop_length::16,
|
||||
0::size(padding_length)-unit(8)
|
||||
>>
|
||||
end
|
||||
|
||||
defp encode_prop({:meter_id, value}, acc)
|
||||
when value != @nx_ctlr_no_meter do
|
||||
prop_length = @prop_header_size + 4
|
||||
|
||||
<<
|
||||
acc::bytes,
|
||||
@prop_meter_id::16,
|
||||
prop_length::16,
|
||||
value::32
|
||||
>>
|
||||
end
|
||||
|
||||
defp encode_prop(_, acc) do
|
||||
acc
|
||||
end
|
||||
|
||||
defp decode_prop(ctl, ""), do: ctl
|
||||
|
||||
defp decode_prop(ctl, <<prop_type_int::16, _::bytes>> = bin) do
|
||||
prop_type = Openflow.Enums.to_atom(prop_type_int, :nx_action_controller2_prop_type)
|
||||
defp decode_prop(
|
||||
ctl,
|
||||
<<
|
||||
@prop_max_len::16,
|
||||
_prop_length::16,
|
||||
max_len_int::16,
|
||||
_::size(2)-unit(8),
|
||||
rest::bytes
|
||||
>>
|
||||
) do
|
||||
max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len)
|
||||
decode_prop(%{ctl | max_len: max_len}, rest)
|
||||
end
|
||||
|
||||
case prop_type do
|
||||
:max_len ->
|
||||
<<@prop_max_len::16, _prop_length::16, max_len_int::16, _::size(2)-unit(8), rest::bytes>> =
|
||||
bin
|
||||
defp decode_prop(
|
||||
ctl,
|
||||
<<@prop_reason::16, _prop_length::16, reason_int::8, _::size(3)-unit(8), rest::bytes>>
|
||||
) do
|
||||
reason = Openflow.Utils.get_enum(reason_int, :packet_in_reason)
|
||||
decode_prop(%{ctl | reason: reason}, rest)
|
||||
end
|
||||
|
||||
max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len)
|
||||
decode_prop(struct(ctl, %{max_len: max_len}), rest)
|
||||
defp decode_prop(
|
||||
ctl,
|
||||
<<@prop_ctl_id::16, _prop_length::16, controller_id::16, _::size(2)-unit(8),
|
||||
rest::bytes>>
|
||||
) do
|
||||
decode_prop(%{ctl | id: controller_id}, rest)
|
||||
end
|
||||
|
||||
:controller_id ->
|
||||
<<@prop_ctl_id::16, _prop_length::16, controller_id::16, _::size(2)-unit(8), rest::bytes>> =
|
||||
bin
|
||||
defp decode_prop(
|
||||
ctl,
|
||||
<<@prop_userdata::16, prop_length::16, remains::bytes>>
|
||||
) do
|
||||
userdata_len = prop_length - 4
|
||||
padding_length = Openflow.Utils.padding(prop_length, 8)
|
||||
<<userdata::size(userdata_len)-bytes, _::size(padding_length)-unit(8), rest::bytes>> = remains
|
||||
decode_prop(%{ctl | userdata: userdata}, rest)
|
||||
end
|
||||
|
||||
decode_prop(struct(ctl, %{controller_id: controller_id}), rest)
|
||||
defp decode_prop(ctl, <<@prop_pause::16, _::16, 0::size(4)-unit(8), rest::bytes>>) do
|
||||
decode_prop(%{ctl | pause: true}, rest)
|
||||
end
|
||||
|
||||
:reason ->
|
||||
<<@prop_reason::16, _prop_length::16, reason_int::8, _::size(3)-unit(8), rest::bytes>> =
|
||||
bin
|
||||
|
||||
reason = Openflow.Utils.get_enum(reason_int, :packet_in_reason)
|
||||
decode_prop(struct(ctl, %{reason: reason}), rest)
|
||||
|
||||
:userdata ->
|
||||
<<@prop_userdata::16, prop_length::16, remains::bytes>> = bin
|
||||
userdata_len = prop_length - 4
|
||||
padding_length = Openflow.Utils.padding(prop_length, 8)
|
||||
|
||||
<<userdata::size(userdata_len)-bytes, _::size(padding_length)-unit(8), rest::bytes>> =
|
||||
remains
|
||||
|
||||
decode_prop(struct(ctl, %{userdata: userdata}), rest)
|
||||
|
||||
:pause ->
|
||||
<<@prop_pause::16, _::16, 0::size(4)-unit(8), rest::bytes>> = bin
|
||||
decode_prop(struct(ctl, %{pause: true}), rest)
|
||||
|
||||
:meter_id ->
|
||||
<<@prop_meter_id::16, _::16, meter_id::32, rest::bytes>> = bin
|
||||
decode_prop(struct(ctl, %{meter_id: meter_id}), rest)
|
||||
end
|
||||
defp decode_prop(ctl, <<@prop_meter_id::16, _::16, meter_id::32, rest::bytes>>) do
|
||||
decode_prop(%{ctl | meter_id: meter_id}, rest)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue