Formatted

This commit is contained in:
Eishun Kondoh 2018-01-30 22:47:31 +09:00
parent 5fc01a9bec
commit 7635272fbd
150 changed files with 5055 additions and 4032 deletions

18
.formatter.exs Normal file
View file

@ -0,0 +1,18 @@
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"],
locals_without_parens: [
# Formatter tests
assert_format: 2,
assert_format: 3,
assert_same: 1,
assert_same: 2,
# Errors tests
assert_eval_raise: 3,
# Mix tests
in_fixture: 2,
in_tmp: 2
]
]

View file

@ -8,20 +8,23 @@ defmodule Openflow do
when byte_size(binary) < @ofp_header_size do when byte_size(binary) < @ofp_header_size do
{:error, :binary_too_small} {:error, :binary_too_small}
end end
def read(<<_v::8, _t::8, len::16, _x::32, _r::bytes>> = binary) def read(<<_v::8, _t::8, len::16, _x::32, _r::bytes>> = binary)
when byte_size(binary) < len do when byte_size(binary) < len do
{:error, :binary_too_small} {:error, :binary_too_small}
end end
def read(<<ver::8, type::8, len::16, xid::32, binary2::bytes>>) do def read(<<ver::8, type::8, len::16, xid::32, binary2::bytes>>) do
body_len = len - @ofp_header_size body_len = len - @ofp_header_size
<<body_bin::bytes-size(body_len), rest::bytes>> = binary2 <<body_bin::bytes-size(body_len), rest::bytes>> = binary2
result = type result =
type
|> Openflow.Enums.to_atom(:openflow_codec) |> Openflow.Enums.to_atom(:openflow_codec)
|> do_read(body_bin) |> do_read(body_bin)
case result do case result do
{:ok, struct} -> {:ok, %{struct|version: ver, xid: xid}, rest} {:ok, struct} -> {:ok, %{struct | version: ver, xid: xid}, rest}
{:error, reason} -> {:error, reason} {:error, reason} -> {:error, reason}
end end
end end
@ -30,19 +33,23 @@ defmodule Openflow do
binaries = for message <- messages, do: to_binary(message) binaries = for message <- messages, do: to_binary(message)
Enum.join(binaries, "") Enum.join(binaries, "")
end end
def to_binary(%{__struct__: encoder, version: version, xid: xid} = msg) do def to_binary(%{__struct__: encoder, version: version, xid: xid} = msg) do
case encoder.to_binary(msg) do case encoder.to_binary(msg) do
body_bin when is_binary(body_bin) -> body_bin when is_binary(body_bin) ->
length = @ofp_header_size + byte_size(body_bin) length = @ofp_header_size + byte_size(body_bin)
<<version::8, (encoder.ofp_type)::8, length::16, xid::32, body_bin::bytes>> <<version::8, encoder.ofp_type::8, length::16, xid::32, body_bin::bytes>>
{:error, reason} -> {:error, reason} ->
{:error, reason} {:error, reason}
end end
end end
def append_body(nil, message), do: message def append_body(nil, message), do: message
def append_body(message, continue) do def append_body(message, continue) do
mod = message.__struct__ mod = message.__struct__
if function_exported?(mod, :append_body, 2) do if function_exported?(mod, :append_body, 2) do
mod.append_body(message, continue) mod.append_body(message, continue)
else else
@ -55,6 +62,7 @@ defmodule Openflow do
defp do_read({:error, reason}, _) do defp do_read({:error, reason}, _) do
{:error, reason} {:error, reason}
end end
defp do_read(decoder, body_bin) do defp do_read(decoder, body_bin) do
case decoder.read(body_bin) do case decoder.read(body_bin) do
{:error, reason} -> {:error, reason} {:error, reason} -> {:error, reason}

View file

@ -1,5 +1,4 @@
defmodule Openflow.Action do defmodule Openflow.Action do
def read(action_bin) do def read(action_bin) do
do_read([], action_bin) do_read([], action_bin)
end end
@ -7,6 +6,7 @@ defmodule Openflow.Action do
def to_binary(actions) when is_list(actions) do def to_binary(actions) when is_list(actions) do
to_binary(<<>>, actions) to_binary(<<>>, actions)
end end
def to_binary(action) do def to_binary(action) do
to_binary([action]) to_binary([action])
end end
@ -15,15 +15,17 @@ defmodule Openflow.Action do
defp do_read(acc, <<>>), do: Enum.reverse(acc) defp do_read(acc, <<>>), do: Enum.reverse(acc)
defp do_read(acc, <<0::32, _::bytes>>), do: Enum.reverse(acc) defp do_read(acc, <<0::32, _::bytes>>), do: Enum.reverse(acc)
defp do_read(acc, <<type::16, length::16, _::bytes>> = binary) do defp do_read(acc, <<type::16, length::16, _::bytes>> = binary) do
<<action_bin::size(length)-bytes, rest::bytes>> = binary <<action_bin::size(length)-bytes, rest::bytes>> = binary
codec = Openflow.Enums.to_atom(type, :action_type) codec = Openflow.Enums.to_atom(type, :action_type)
do_read([codec.read(action_bin)|acc], rest) do_read([codec.read(action_bin) | acc], rest)
end end
defp to_binary(acc, []), do: acc defp to_binary(acc, []), do: acc
defp to_binary(acc, [action|rest]) do
defp to_binary(acc, [action | rest]) do
codec = action.__struct__ codec = action.__struct__
to_binary(<<acc::bytes, (codec.to_binary(action))::bytes>>, rest) to_binary(<<acc::bytes, codec.to_binary(action)::bytes>>, rest)
end end
end end

View file

@ -5,7 +5,7 @@ defmodule Openflow.Action.Experimenter do
@experimter_size 8 @experimter_size 8
def ofpat, do: 0xffff def ofpat, do: 0xFFFF
def new(exp_id, data \\ "") do def new(exp_id, data \\ "") do
%Experimenter{exp_id: exp_id, data: data} %Experimenter{exp_id: exp_id, data: data}
@ -13,17 +13,19 @@ defmodule Openflow.Action.Experimenter do
def to_binary(%Experimenter{exp_id: exp_id, data: data}) do def to_binary(%Experimenter{exp_id: exp_id, data: data}) do
length = @experimter_size + byte_size(data) length = @experimter_size + byte_size(data)
<<0xffff::16, length::16, exp_id::32, data::bytes>> <<0xFFFF::16, length::16, exp_id::32, data::bytes>>
end end
def read(<<0xffff::16, _length::16, exp_id::32, exp_type::16, data::bytes>>) do def read(<<0xFFFF::16, _length::16, exp_id::32, exp_type::16, data::bytes>>) do
case Openflow.Utils.get_enum(exp_id, :action_vendor) do case Openflow.Utils.get_enum(exp_id, :action_vendor) do
vendor_id when is_integer(vendor_id) -> vendor_id when is_integer(vendor_id) ->
%Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>} %Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
vendor when is_atom(vendor) -> vendor when is_atom(vendor) ->
case Openflow.Utils.get_enum(exp_type, vendor) do case Openflow.Utils.get_enum(exp_type, vendor) do
codec when is_atom(codec) -> codec when is_atom(codec) ->
codec.read(<<exp_id::32, exp_type::16, data::bytes>>) codec.read(<<exp_id::32, exp_type::16, data::bytes>>)
exp_type when is_integer(exp_type) -> exp_type when is_integer(exp_type) ->
%Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>} %Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
end end

View file

@ -15,36 +15,44 @@ defmodule Openflow.Action.NxBundle do
def new(options) do def new(options) do
slaves = options[:slaves] || [] slaves = options[:slaves] || []
%NxBundle{algorithm: options[:algorithm] || :active_backup,
%NxBundle{
algorithm: options[:algorithm] || :active_backup,
hash_field: options[:hash_field] || :eth_src, hash_field: options[:hash_field] || :eth_src,
basis: options[:basis] || 0, basis: options[:basis] || 0,
n_slaves: length(slaves), n_slaves: length(slaves),
slaves: slaves} slaves: slaves
}
end end
def to_binary(%NxBundle{algorithm: alg, def to_binary(%NxBundle{
algorithm: alg,
hash_field: hash_field, hash_field: hash_field,
basis: basis, basis: basis,
slave_type: slave_type, slave_type: slave_type,
n_slaves: n_slaves, n_slaves: n_slaves,
slaves: slaves}) do slaves: slaves
}) do
hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields)
alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm) alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm)
slave_type_bin = Openflow.Match.codec_header(slave_type) slave_type_bin = Openflow.Match.codec_header(slave_type)
slaves_bin = codec_slaves(slaves) slaves_bin = codec_slaves(slaves)
body = <<alg_int::16, hash_field_int::16, basis::16,
slave_type_bin::4-bytes, n_slaves::16, 0::16, 0::size(4)-unit(8), 0::32, body =
slaves_bin::bytes>> <<alg_int::16, hash_field_int::16, basis::16, slave_type_bin::4-bytes, n_slaves::16, 0::16,
0::size(4)-unit(8), 0::32, slaves_bin::bytes>>
exp_body = <<@experimenter::32, @nxast::16, body::bytes>> exp_body = <<@experimenter::32, @nxast::16, body::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<alg_int::16, hash_field_int::16, basis::16, <<alg_int::16, hash_field_int::16, basis::16, slave_type_bin::4-bytes, n_slaves::16, _::16,
slave_type_bin::4-bytes, n_slaves::16, _::16, _::32, _::32, rest::bytes>> = body _::32, _::32, rest::bytes>> = body
slave_len = n_slaves * 2 slave_len = n_slaves * 2
<<slaves_bin::size(slave_len)-bytes, _::bytes>> = rest <<slaves_bin::size(slave_len)-bytes, _::bytes>> = rest
alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm) alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm)
@ -52,23 +60,29 @@ defmodule Openflow.Action.NxBundle do
slave_type = Openflow.Match.codec_header(slave_type_bin) slave_type = Openflow.Match.codec_header(slave_type_bin)
slaves = codec_slaves(slaves_bin) slaves = codec_slaves(slaves_bin)
n_slaves = length(slaves) n_slaves = length(slaves)
%NxBundle{algorithm: alg,
%NxBundle{
algorithm: alg,
hash_field: hash_field, hash_field: hash_field,
basis: basis, basis: basis,
slave_type: slave_type, slave_type: slave_type,
n_slaves: n_slaves, n_slaves: n_slaves,
slaves: slaves} slaves: slaves
}
end end
# private functions # private functions
defp codec_slaves(slaves) when is_list(slaves) do defp codec_slaves(slaves) when is_list(slaves) do
slaves1 = for slave <- slaves do slaves1 =
for slave <- slaves do
slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no)
<<slave_int::16>> <<slave_int::16>>
end end
Enum.join(slaves1, "") Enum.join(slaves1, "")
end end
defp codec_slaves(slaves) when is_binary(slaves) do defp codec_slaves(slaves) when is_binary(slaves) do
for <<slave_int::16 <- slaves>> do for <<slave_int::16 <- slaves>> do
Openflow.Utils.get_enum(slave_int, :openflow10_port_no) Openflow.Utils.get_enum(slave_int, :openflow10_port_no)

View file

@ -22,17 +22,21 @@ defmodule Openflow.Action.NxBundleLoad do
dst_field = options[:dst_field] dst_field = options[:dst_field]
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
slaves = options[:slaves] || [] slaves = options[:slaves] || []
%NxBundleLoad{algorithm: options[:algorithm] || :active_backup,
%NxBundleLoad{
algorithm: options[:algorithm] || :active_backup,
hash_field: options[:hash_field] || :eth_src, hash_field: options[:hash_field] || :eth_src,
basis: options[:basis] || 0, basis: options[:basis] || 0,
n_slaves: length(slaves), n_slaves: length(slaves),
slaves: slaves, slaves: slaves,
offset: options[:offset] || 0, offset: options[:offset] || 0,
n_bits: options[:n_bits] || default_n_bits, n_bits: options[:n_bits] || default_n_bits,
dst_field: options[:dst_field]} dst_field: options[:dst_field]
}
end end
def to_binary(%NxBundleLoad{algorithm: alg, def to_binary(%NxBundleLoad{
algorithm: alg,
hash_field: hash_field, hash_field: hash_field,
basis: basis, basis: basis,
slave_type: slave_type, slave_type: slave_type,
@ -40,27 +44,30 @@ defmodule Openflow.Action.NxBundleLoad do
slaves: slaves, slaves: slaves,
offset: ofs, offset: ofs,
n_bits: n_bits, n_bits: n_bits,
dst_field: dst_field}) do dst_field: dst_field
}) do
hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields)
alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm) alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm)
slave_type_bin = Openflow.Match.codec_header(slave_type) slave_type_bin = Openflow.Match.codec_header(slave_type)
slaves_bin = codec_slaves(slaves) slaves_bin = codec_slaves(slaves)
ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) ofs_nbits = ofs <<< 6 ||| n_bits - 1
dst_field_bin = Openflow.Match.codec_header(dst_field) dst_field_bin = Openflow.Match.codec_header(dst_field)
body = <<alg_int::16, hash_field_int::16, basis::16,
slave_type_bin::4-bytes, n_slaves::16, ofs_nbits::16, body =
dst_field_bin::4-bytes, 0::32, slaves_bin::bytes>> <<alg_int::16, hash_field_int::16, basis::16, slave_type_bin::4-bytes, n_slaves::16,
ofs_nbits::16, dst_field_bin::4-bytes, 0::32, slaves_bin::bytes>>
exp_body = <<@experimenter::32, @nxast::16, body::bytes>> exp_body = <<@experimenter::32, @nxast::16, body::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<alg_int::16, hash_field_int::16, basis::16, <<alg_int::16, hash_field_int::16, basis::16, slave_type_bin::4-bytes, n_slaves::16, ofs::10,
slave_type_bin::4-bytes, n_slaves::16, ofs::10, n_bits::6, n_bits::6, dst_field_bin::4-bytes, _reserved::32, rest::bytes>> = body
dst_field_bin::4-bytes, _reserved::32, rest::bytes>> = body
slave_len = n_slaves * 2 slave_len = n_slaves * 2
<<slaves_bin::size(slave_len)-bytes, _::bytes>> = rest <<slaves_bin::size(slave_len)-bytes, _::bytes>> = rest
alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm) alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm)
@ -69,7 +76,9 @@ defmodule Openflow.Action.NxBundleLoad do
slaves = codec_slaves(slaves_bin) slaves = codec_slaves(slaves_bin)
n_slaves = length(slaves) n_slaves = length(slaves)
dst_field = Openflow.Match.codec_header(dst_field_bin) dst_field = Openflow.Match.codec_header(dst_field_bin)
%NxBundleLoad{algorithm: alg,
%NxBundleLoad{
algorithm: alg,
hash_field: hash_field, hash_field: hash_field,
basis: basis, basis: basis,
slave_type: slave_type, slave_type: slave_type,
@ -77,18 +86,22 @@ defmodule Openflow.Action.NxBundleLoad do
slaves: slaves, slaves: slaves,
offset: ofs, offset: ofs,
n_bits: n_bits + 1, n_bits: n_bits + 1,
dst_field: dst_field} dst_field: dst_field
}
end end
# private functions # private functions
defp codec_slaves(slaves) when is_list(slaves) do defp codec_slaves(slaves) when is_list(slaves) do
slaves1 = for slave <- slaves do slaves1 =
for slave <- slaves do
slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no)
<<slave_int::16>> <<slave_int::16>>
end end
Enum.join(slaves1, "") Enum.join(slaves1, "")
end end
defp codec_slaves(slaves) when is_binary(slaves) do defp codec_slaves(slaves) when is_binary(slaves) do
for <<slave_int::16 <- slaves>> do for <<slave_int::16 <- slaves>> do
Openflow.Utils.get_enum(slave_int, :openflow10_port_no) Openflow.Utils.get_enum(slave_int, :openflow10_port_no)

View file

@ -1,7 +1,5 @@
defmodule Openflow.Action.NxClone do defmodule Openflow.Action.NxClone do
defstruct( defstruct(actions: [])
actions: []
)
@experimenter 0x00002320 @experimenter 0x00002320
@nxast 42 @nxast 42
@ -18,7 +16,7 @@ defmodule Openflow.Action.NxClone do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>>) do def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>>) do

View file

@ -11,14 +11,16 @@ defmodule Openflow.Action.NxConjunction do
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
%NxConjunction{clause: options[:clause] || 0, %NxConjunction{
clause: options[:clause] || 0,
n_clauses: options[:n_clauses] || 0, n_clauses: options[:n_clauses] || 0,
id: options[:id] || 0} id: options[:id] || 0
}
end end
def to_binary(%NxConjunction{clause: clause, n_clauses: n_clauses, id: id}) do def to_binary(%NxConjunction{clause: clause, n_clauses: n_clauses, id: id}) do
exp_body = <<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>> exp_body = <<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>>
<<0xffff::16, 16::16, exp_body::bytes>> <<0xFFFF::16, 16::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>>) do def read(<<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>>) do

View file

@ -18,14 +18,16 @@ defmodule Openflow.Action.NxConntrack do
alias __MODULE__ alias __MODULE__
def new(options \\ []) do def new(options \\ []) do
%NxConntrack{flags: options[:flags] || [], %NxConntrack{
flags: options[:flags] || [],
zone_src: options[:zone_src], zone_src: options[:zone_src],
zone_imm: options[:zone_imm] || 0, zone_imm: options[:zone_imm] || 0,
zone_offset: options[:zone_offset], zone_offset: options[:zone_offset],
zone_n_bits: options[:zone_n_bits], zone_n_bits: options[:zone_n_bits],
recirc_table: options[:recirc_table] || 255, recirc_table: options[:recirc_table] || 255,
alg: options[:alg] || 0, alg: options[:alg] || 0,
exec: options[:exec] || []} exec: options[:exec] || []
}
end end
def to_binary(%NxConntrack{ def to_binary(%NxConntrack{
@ -36,43 +38,53 @@ defmodule Openflow.Action.NxConntrack do
zone_imm: zone_imm, zone_imm: zone_imm,
recirc_table: recirc_table, recirc_table: recirc_table,
alg: alg, alg: alg,
exec: exec}) do exec: exec
}) do
flags_int = Openflow.Enums.flags_to_int(flags, :nx_conntrack_flags) flags_int = Openflow.Enums.flags_to_int(flags, :nx_conntrack_flags)
{src_bin, ofs_nbits} = if not (is_nil(zone_src)) do
{src_bin, ofs_nbits} =
if not is_nil(zone_src) do
zone_src_bin = Openflow.Match.codec_header(zone_src) zone_src_bin = Openflow.Match.codec_header(zone_src)
{zone_src_bin, (zone_ofs <<< 6) ||| (zone_n_bits - 1)} {zone_src_bin, zone_ofs <<< 6 ||| zone_n_bits - 1}
else else
{<<0::32>>, zone_imm} {<<0::32>>, zone_imm}
end end
exec_bin = Openflow.Action.to_binary(exec) exec_bin = Openflow.Action.to_binary(exec)
exp_body = <<@experimenter::32, @nxast::16, flags_int::16,
src_bin::bytes, ofs_nbits::16, recirc_table::8, exp_body =
0::size(3)-unit(8), alg::16, exec_bin::bytes>> <<@experimenter::32, @nxast::16, flags_int::16, src_bin::bytes, ofs_nbits::16,
recirc_table::8, 0::size(3)-unit(8), alg::16, exec_bin::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, flags_int::16, def read(
src_bin::4-bytes, ofs_nbits::16-bits, recirc_table::8, <<@experimenter::32, @nxast::16, flags_int::16, src_bin::4-bytes, ofs_nbits::16-bits,
_::size(3)-unit(8), alg::16, exec_bin::bytes>>) do recirc_table::8, _::size(3)-unit(8), alg::16, exec_bin::bytes>>
) do
flags = Openflow.Enums.int_to_flags(flags_int, :nx_conntrack_flags) flags = Openflow.Enums.int_to_flags(flags_int, :nx_conntrack_flags)
exec = Openflow.Action.read(exec_bin) exec = Openflow.Action.read(exec_bin)
ct = %NxConntrack{ ct = %NxConntrack{
flags: flags, flags: flags,
recirc_table: recirc_table, recirc_table: recirc_table,
alg: alg, alg: alg,
exec: exec exec: exec
} }
case src_bin do case src_bin do
<<0::32>> -> <<0::32>> ->
<<zone_imm::16>> = ofs_nbits <<zone_imm::16>> = ofs_nbits
%{ct|zone_imm: zone_imm} %{ct | zone_imm: zone_imm}
binary when is_binary(binary) -> binary when is_binary(binary) ->
zone_src = Openflow.Match.codec_header(binary) zone_src = Openflow.Match.codec_header(binary)
<<ofs::10, n_bits::6>> = ofs_nbits <<ofs::10, n_bits::6>> = ofs_nbits
%{ct|zone_src: zone_src, zone_offset: ofs, zone_n_bits: n_bits + 1} %{ct | zone_src: zone_src, zone_offset: ofs, zone_n_bits: n_bits + 1}
end end
end end
end end

View file

@ -11,19 +11,27 @@ defmodule Openflow.Action.NxController do
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
%NxController{max_len: options[:max_len] || :no_buffer, %NxController{
max_len: options[:max_len] || :no_buffer,
id: options[:id] || 0, id: options[:id] || 0,
reason: options[:reason] || :action} reason: options[:reason] || :action
}
end end
def to_binary(%NxController{max_len: max_len, id: controller_id, reason: reason}) do def to_binary(%NxController{max_len: max_len, id: controller_id, reason: reason}) do
max_len_int = Openflow.Utils.get_enum(max_len, :controller_max_len) max_len_int = Openflow.Utils.get_enum(max_len, :controller_max_len)
reason_int = Openflow.Enums.to_int(reason, :packet_in_reason) reason_int = Openflow.Enums.to_int(reason, :packet_in_reason)
exp_body = <<@experimenter::32, @nxast::16, max_len_int::16, controller_id::16, reason_int::8, 0::8>>
<<0xffff::16, 16::16, exp_body::bytes>> exp_body =
<<@experimenter::32, @nxast::16, max_len_int::16, controller_id::16, reason_int::8, 0::8>>
<<0xFFFF::16, 16::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, max_len_int::16, controller_id::16, reason_int::8, _::bytes>>) do def read(
<<@experimenter::32, @nxast::16, max_len_int::16, controller_id::16, reason_int::8,
_::bytes>>
) do
max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len) max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len)
reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason) reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason)
%NxController{max_len: max_len, id: controller_id, reason: reason} %NxController{max_len: max_len, id: controller_id, reason: reason}

View file

@ -21,11 +21,13 @@ defmodule Openflow.Action.NxController2 do
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
%NxController2{max_len: options[:max_len] || :no_buffer, %NxController2{
max_len: options[:max_len] || :no_buffer,
id: options[:id] || 0, id: options[:id] || 0,
reason: options[:reason] || :action, reason: options[:reason] || :action,
userdata: options[:userdata], userdata: options[:userdata],
pause: options[:pause] || false} pause: options[:pause] || false
}
end end
def to_binary(%NxController2{} = ctl) do def to_binary(%NxController2{} = ctl) do
@ -36,7 +38,7 @@ defmodule Openflow.Action.NxController2 do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes>> <<0xFFFF::16, length::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), body::bytes>>) do def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), body::bytes>>) do
@ -48,64 +50,88 @@ defmodule Openflow.Action.NxController2 do
defp get_prop_key(ctl) do defp get_prop_key(ctl) do
ctl ctl
|> Map.from_struct |> Map.from_struct()
|> Enum.map(fn({k, v}) -> if(not is_nil(v), do: k, else: nil) end) |> 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.filter(fn v -> not is_nil(v) end)
end end
defp encode_prop(acc, [], _ctl), do: acc defp encode_prop(acc, [], _ctl), do: acc
defp encode_prop(acc, [prop|rest], ctl) do
defp encode_prop(acc, [prop | rest], ctl) do
value = Map.get(ctl, prop) value = Map.get(ctl, prop)
prop_bin = cond do
prop == :max_len and (value != :no_buffer or value < 0xffff) -> prop_bin =
cond do
prop == :max_len and (value != :no_buffer or value < 0xFFFF) ->
padding_length = 2 padding_length = 2
prop_length = @prop_header_size + 2 + padding_length prop_length = @prop_header_size + 2 + padding_length
max_len_int = Openflow.Utils.get_enum(value, :controller_max_len) 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)>> <<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>>
prop == :id -> prop == :id ->
padding_length = 2 padding_length = 2
prop_length = @prop_header_size + 2 + padding_length prop_length = @prop_header_size + 2 + padding_length
<<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>> <<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>>
prop == :reason and value != :action -> prop == :reason and value != :action ->
padding_length = 3 padding_length = 3
prop_length = @prop_header_size + 1 + padding_length prop_length = @prop_header_size + 1 + padding_length
reason_int = Openflow.Utils.get_enum(value, :packet_in_reason) 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)>> <<@prop_reason::16, prop_length::16, reason_int::8, 0::size(padding_length)-unit(8)>>
prop == :userdata and byte_size(value) > 0 -> prop == :userdata and byte_size(value) > 0 ->
prop_length = @prop_header_size + byte_size(value) prop_length = @prop_header_size + byte_size(value)
padding_length = Openflow.Utils.padding(prop_length, 8) padding_length = Openflow.Utils.padding(prop_length, 8)
<<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>> <<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>>
prop == :pause and value == true -> prop == :pause and value == true ->
padding_length = 4 padding_length = 4
prop_length = @prop_header_size + padding_length prop_length = @prop_header_size + padding_length
<<@prop_pause::16, prop_length::16, 0::size(padding_length)-unit(8)>> <<@prop_pause::16, prop_length::16, 0::size(padding_length)-unit(8)>>
true -> true ->
"" ""
end end
encode_prop(<<acc::bytes, prop_bin::bytes>>, rest, ctl) encode_prop(<<acc::bytes, prop_bin::bytes>>, rest, ctl)
end end
defp decode_prop(ctl, ""), do: ctl defp decode_prop(ctl, ""), do: ctl
defp decode_prop(ctl, <<prop_type_int::16, _::bytes>> = bin) do 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) prop_type = Openflow.Enums.to_atom(prop_type_int, :nx_action_controller2_prop_type)
case prop_type do case prop_type do
:max_len -> :max_len ->
<<@prop_max_len::16, _prop_length::16, max_len_int::16, _::size(2)-unit(8), rest::bytes>> = bin <<@prop_max_len::16, _prop_length::16, max_len_int::16, _::size(2)-unit(8), rest::bytes>> =
bin
max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len) max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len)
decode_prop(struct(ctl, %{max_len: max_len}), rest) decode_prop(struct(ctl, %{max_len: max_len}), rest)
:controller_id -> :controller_id ->
<<@prop_ctl_id::16, _prop_length::16, controller_id::16, _::size(2)-unit(8), rest::bytes>> = bin <<@prop_ctl_id::16, _prop_length::16, controller_id::16, _::size(2)-unit(8), rest::bytes>> =
bin
decode_prop(struct(ctl, %{controller_id: controller_id}), rest) decode_prop(struct(ctl, %{controller_id: controller_id}), rest)
:reason -> :reason ->
<<@prop_reason::16, _prop_length::16, reason_int::8, _::size(3)-unit(8), rest::bytes>> = bin <<@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) reason = Openflow.Utils.get_enum(reason_int, :packet_in_reason)
decode_prop(struct(ctl, %{reason: reason}), rest) decode_prop(struct(ctl, %{reason: reason}), rest)
:userdata -> :userdata ->
<<@prop_userdata::16, prop_length::16, remains::bytes>> = bin <<@prop_userdata::16, prop_length::16, remains::bytes>> = bin
userdata_len = prop_length - 4 userdata_len = prop_length - 4
padding_length = Openflow.Utils.padding(prop_length, 8) padding_length = Openflow.Utils.padding(prop_length, 8)
<<userdata::size(userdata_len)-bytes, _::size(padding_length)-unit(8), rest::bytes>> = remains
<<userdata::size(userdata_len)-bytes, _::size(padding_length)-unit(8), rest::bytes>> =
remains
decode_prop(struct(ctl, %{userdata: userdata}), rest) decode_prop(struct(ctl, %{userdata: userdata}), rest)
:pause -> :pause ->
<<@prop_pause::16, _::16, 0::size(4)-unit(8), rest::bytes>> = bin <<@prop_pause::16, _::16, 0::size(4)-unit(8), rest::bytes>> = bin
decode_prop(struct(ctl, %{pause: true}), rest) decode_prop(struct(ctl, %{pause: true}), rest)

View file

@ -12,7 +12,7 @@ defmodule Openflow.Action.NxCtClear do
def to_binary(%NxCtClear{}) do def to_binary(%NxCtClear{}) do
exp_body = <<@experimenter::32, @nxast::16, 0::16, 0::size(4)-unit(8)>> exp_body = <<@experimenter::32, @nxast::16, 0::16, 0::size(4)-unit(8)>>
<<0xffff::16, 16::16, exp_body::bytes>> <<0xFFFF::16, 16::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do

View file

@ -12,7 +12,7 @@ defmodule Openflow.Action.NxDecMplsTtl do
def to_binary(%NxDecMplsTtl{}) do def to_binary(%NxDecMplsTtl{}) do
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>> exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>
<<0xffff::16, 16::16, exp_body::bytes>> <<0xFFFF::16, 16::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8)>>) do

View file

@ -12,7 +12,7 @@ defmodule Openflow.Action.NxDecTtl do
def to_binary(%NxDecTtl{}) do def to_binary(%NxDecTtl{}) do
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>> exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>
<<0xffff::16, 16::16, exp_body::bytes>> <<0xFFFF::16, 16::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do

View file

@ -12,14 +12,17 @@ defmodule Openflow.Action.NxDecTtlCntIds do
def to_binary(%NxDecTtlCntIds{ids: ids}) do def to_binary(%NxDecTtlCntIds{ids: ids}) do
n_controllers = length(ids) n_controllers = length(ids)
ids_bin = Enum.join((for id <- ids, do: <<id::16>>), "") ids_bin = Enum.join(for(id <- ids, do: <<id::16>>), "")
padding = Openflow.Utils.padding(n_controllers, 8) padding = Openflow.Utils.padding(n_controllers, 8)
exp_body = <<@experimenter::32, @nxast::16, n_controllers::16,
0::size(4)-unit(8), ids_bin::bytes, 0::size(padding)-unit(8)>> exp_body =
<<@experimenter::32, @nxast::16, n_controllers::16, 0::size(4)-unit(8), ids_bin::bytes,
0::size(padding)-unit(8)>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, n_controllers::16, body::bitstring>>) do def read(<<@experimenter::32, @nxast::16, n_controllers::16, body::bitstring>>) do

View file

@ -12,7 +12,7 @@ defmodule Openflow.Action.NxExit do
def to_binary(%NxExit{}) do def to_binary(%NxExit{}) do
exp_body = <<@experimenter::32, @nxast::16, 0::48>> exp_body = <<@experimenter::32, @nxast::16, 0::48>>
<<0xffff::16, 16::16, exp_body::bytes>> <<0xFFFF::16, 16::16, exp_body::bytes>>
end end
def read(<<@experimenter::32, @nxast::16, 0::48>>) do def read(<<@experimenter::32, @nxast::16, 0::48>>) do

View file

@ -10,13 +10,15 @@ defmodule Openflow.Action.NxFinTimeout do
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
%NxFinTimeout{idle_timeout: options[:idle_timeout] || 0, %NxFinTimeout{
hard_timeout: options[:hard_timeout] || 0} idle_timeout: options[:idle_timeout] || 0,
hard_timeout: options[:hard_timeout] || 0
}
end end
def to_binary(%NxFinTimeout{idle_timeout: fin_idle, hard_timeout: fin_hard}) do def to_binary(%NxFinTimeout{idle_timeout: fin_idle, hard_timeout: fin_hard}) do
exp_body = <<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16>> exp_body = <<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16>>
<<0xffff::16, 16::16, exp_body::bytes, 0::size(2)-unit(8)>> <<0xFFFF::16, 16::16, exp_body::bytes, 0::size(2)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16, _::size(2)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16, _::size(2)-unit(8)>>) do

View file

@ -1,5 +1,4 @@
defmodule Openflow.Action.NxFlowSpec do defmodule Openflow.Action.NxFlowSpec do
def read(flow_spec_bin) do def read(flow_spec_bin) do
do_read([], flow_spec_bin) do_read([], flow_spec_bin)
end end
@ -7,6 +6,7 @@ defmodule Openflow.Action.NxFlowSpec do
def to_binary(flow_specs) when is_list(flow_specs) do def to_binary(flow_specs) when is_list(flow_specs) do
to_binary(<<>>, flow_specs) to_binary(<<>>, flow_specs)
end end
def to_binary(flow_spec) do def to_binary(flow_spec) do
to_binary([flow_spec]) to_binary([flow_spec])
end end
@ -15,15 +15,17 @@ defmodule Openflow.Action.NxFlowSpec do
defp do_read(acc, <<>>), do: Enum.reverse(acc) defp do_read(acc, <<>>), do: Enum.reverse(acc)
defp do_read(acc, <<0::16, _::bitstring>>), do: Enum.reverse(acc) defp do_read(acc, <<0::16, _::bitstring>>), do: Enum.reverse(acc)
defp do_read(acc, <<_::2, _::1, type::2, _::bitstring>> = binary) do defp do_read(acc, <<_::2, _::1, type::2, _::bitstring>> = binary) do
codec = Openflow.Enums.to_atom(type, :nx_flow_spec_type) codec = Openflow.Enums.to_atom(type, :nx_flow_spec_type)
{flow_spec, rest} = codec.read(binary) {flow_spec, rest} = codec.read(binary)
do_read([flow_spec|acc], rest) do_read([flow_spec | acc], rest)
end end
defp to_binary(acc, []), do: acc defp to_binary(acc, []), do: acc
defp to_binary(acc, [flow_spec|rest]) do
defp to_binary(acc, [flow_spec | rest]) do
codec = flow_spec.__struct__ codec = flow_spec.__struct__
to_binary(<<acc::bytes, (codec.to_binary(flow_spec))::bytes>>, rest) to_binary(<<acc::bytes, codec.to_binary(flow_spec)::bytes>>, rest)
end end
end end

View file

@ -16,11 +16,14 @@ defmodule Openflow.Action.NxFlowSpecLoad do
def new(options) do def new(options) do
dst = options[:dst] dst = options[:dst]
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst)
%NxFlowSpecLoad{src: options[:src],
%NxFlowSpecLoad{
src: options[:src],
dst: dst, dst: dst,
n_bits: n_bits, n_bits: n_bits,
src_offset: options[:src_offset] || 0, src_offset: options[:src_offset] || 0,
dst_offset: options[:dst_offset] || 0} dst_offset: options[:dst_offset] || 0
}
end end
def to_binary(%NxFlowSpecLoad{} = fsm) do def to_binary(%NxFlowSpecLoad{} = fsm) do
@ -30,39 +33,49 @@ defmodule Openflow.Action.NxFlowSpecLoad do
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs dst_offset: dst_ofs
} = fsm } = fsm
{src_code, src_bin} = codec_src(fsm) {src_code, src_bin} = codec_src(fsm)
dst_bin = Openflow.Match.codec_header(dst_field) dst_bin = Openflow.Match.codec_header(dst_field)
case src_code do case src_code do
@learn_src_immediate -> @learn_src_immediate ->
<<0::2, src_code::1, @learn_dst::2, n_bits::11, <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, dst_bin::4-bytes,
src_bin::bytes, dst_bin::4-bytes, dst_ofs::16>> dst_ofs::16>>
@learn_src_field -> @learn_src_field ->
<<0::2, src_code::1, @learn_dst::2, n_bits::11, <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16,
src_bin::4-bytes, src_ofs::16, dst_bin::4-bytes, dst_ofs::16>> dst_bin::4-bytes, dst_ofs::16>>
end end
end end
def read(<<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, def read(
src_ofs::16, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>>) do <<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16,
dst_bin::4-bytes, dst_ofs::16, rest::bitstring>>
) do
src = Openflow.Match.codec_header(src_bin) src = Openflow.Match.codec_header(src_bin)
dst = Openflow.Match.codec_header(dst_bin) dst = Openflow.Match.codec_header(dst_bin)
flow_spec = %NxFlowSpecLoad{src: src,
flow_spec = %NxFlowSpecLoad{
src: src,
dst: dst, dst: dst,
n_bits: n_bits, n_bits: n_bits,
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs} dst_offset: dst_ofs
}
{flow_spec, rest} {flow_spec, rest}
end end
def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do
rounded_up_len = Openflow.Utils.pad_length(n_bits, 8) rounded_up_len = Openflow.Utils.pad_length(n_bits, 8)
rounded_up_nbits = n_bits + rounded_up_len rounded_up_nbits = n_bits + rounded_up_len
<<src_bin::size(rounded_up_nbits)-bits, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> = binary
<<src_bin::size(rounded_up_nbits)-bits, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> =
binary
dst = Openflow.Match.codec_header(dst_bin) dst = Openflow.Match.codec_header(dst_bin)
src = Openflow.Match.Field.codec(src_bin, dst) src = Openflow.Match.Field.codec(src_bin, dst)
flow_spec = %NxFlowSpecLoad{src: src, flow_spec = %NxFlowSpecLoad{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs}
dst: dst,
n_bits: n_bits,
dst_offset: dst_ofs}
{flow_spec, rest} {flow_spec, rest}
end end
@ -72,6 +85,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do
src_bin = Openflow.Match.codec_header(src_field) src_bin = Openflow.Match.codec_header(src_field)
{@learn_src_field, src_bin} {@learn_src_field, src_bin}
end end
defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do
src_bin = Openflow.Match.Field.codec(src, dst_field) src_bin = Openflow.Match.Field.codec(src, dst_field)
{@learn_src_immediate, src_bin} {@learn_src_immediate, src_bin}

View file

@ -16,11 +16,14 @@ defmodule Openflow.Action.NxFlowSpecMatch do
def new(options) do def new(options) do
dst = options[:dst] dst = options[:dst]
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst)
%NxFlowSpecMatch{src: options[:src],
%NxFlowSpecMatch{
src: options[:src],
dst: dst, dst: dst,
n_bits: n_bits, n_bits: n_bits,
src_offset: options[:src_offset] || 0, src_offset: options[:src_offset] || 0,
dst_offset: options[:dst_offset] || 0} dst_offset: options[:dst_offset] || 0
}
end end
def to_binary(%NxFlowSpecMatch{} = fsm) do def to_binary(%NxFlowSpecMatch{} = fsm) do
@ -30,39 +33,49 @@ defmodule Openflow.Action.NxFlowSpecMatch do
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs dst_offset: dst_ofs
} = fsm } = fsm
{src_code, src_bin} = codec_src(fsm) {src_code, src_bin} = codec_src(fsm)
dst_bin = Openflow.Match.codec_header(dst_field) dst_bin = Openflow.Match.codec_header(dst_field)
case src_code do case src_code do
@learn_src_immediate -> @learn_src_immediate ->
<<0::2, src_code::1, @learn_dst::2, n_bits::11, <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, dst_bin::4-bytes,
src_bin::bytes, dst_bin::4-bytes, dst_ofs::16>> dst_ofs::16>>
@learn_src_field -> @learn_src_field ->
<<0::2, src_code::1, @learn_dst::2, n_bits::11, <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, src_ofs::16,
src_bin::bytes, src_ofs::16, dst_bin::4-bytes, dst_ofs::16>> dst_bin::4-bytes, dst_ofs::16>>
end end
end end
def read(<<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, def read(
src_ofs::16, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>>) do <<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16,
dst_bin::4-bytes, dst_ofs::16, rest::bitstring>>
) do
src = Openflow.Match.codec_header(src_bin) src = Openflow.Match.codec_header(src_bin)
dst = Openflow.Match.codec_header(dst_bin) dst = Openflow.Match.codec_header(dst_bin)
flow_spec = %NxFlowSpecMatch{src: src,
flow_spec = %NxFlowSpecMatch{
src: src,
dst: dst, dst: dst,
n_bits: n_bits, n_bits: n_bits,
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs} dst_offset: dst_ofs
}
{flow_spec, rest} {flow_spec, rest}
end end
def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do
rounded_up_len = Openflow.Utils.pad_length(n_bits, 8) rounded_up_len = Openflow.Utils.pad_length(n_bits, 8)
rounded_up_nbits = n_bits + rounded_up_len rounded_up_nbits = n_bits + rounded_up_len
<<src_bin::size(rounded_up_nbits)-bits, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> = binary
<<src_bin::size(rounded_up_nbits)-bits, dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> =
binary
dst = Openflow.Match.codec_header(dst_bin) dst = Openflow.Match.codec_header(dst_bin)
src = Openflow.Match.Field.codec(src_bin, dst) src = Openflow.Match.Field.codec(src_bin, dst)
flow_spec = %NxFlowSpecMatch{src: src, flow_spec = %NxFlowSpecMatch{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs}
dst: dst,
n_bits: n_bits,
dst_offset: dst_ofs}
{flow_spec, rest} {flow_spec, rest}
end end
@ -72,6 +85,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do
src_bin = Openflow.Match.codec_header(src_field) src_bin = Openflow.Match.codec_header(src_field)
{@learn_src_field, src_bin} {@learn_src_field, src_bin}
end end
defp codec_src(%NxFlowSpecMatch{src: src, dst: dst_field}) do defp codec_src(%NxFlowSpecMatch{src: src, dst: dst_field}) do
src_bin = Openflow.Match.Field.codec(src, dst_field) src_bin = Openflow.Match.Field.codec(src, dst_field)
{@learn_src_immediate, src_bin} {@learn_src_immediate, src_bin}

View file

@ -13,24 +13,20 @@ defmodule Openflow.Action.NxFlowSpecOutput do
def new(options) do def new(options) do
src = options[:src] src = options[:src]
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(src) n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(src)
%NxFlowSpecOutput{n_bits: n_bits, %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: options[:src_offset] || 0}
src: src,
src_offset: options[:src_offset] || 0}
end end
def to_binary(%NxFlowSpecOutput{n_bits: n_bits, def to_binary(%NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs}) do
src: src,
src_offset: src_ofs}) do
src_bin = Openflow.Match.codec_header(src) src_bin = Openflow.Match.codec_header(src)
<<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16>> <<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16>>
end end
def read(<<0::2, @learn_src_field::1, @learn_dst::2, def read(
n_bits::11, src_bin::4-bytes, src_ofs::16, rest::bitstring>>) do <<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16,
rest::bitstring>>
) do
src = Openflow.Match.codec_header(src_bin) src = Openflow.Match.codec_header(src_bin)
flow_spec = %NxFlowSpecOutput{n_bits: n_bits, flow_spec = %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs}
src: src,
src_offset: src_ofs}
{flow_spec, rest} {flow_spec, rest}
end end
end end

View file

@ -17,18 +17,21 @@ defmodule Openflow.Action.NxLearn do
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
%NxLearn{idle_timeout: options[:idle_timeout] || 0, %NxLearn{
idle_timeout: options[:idle_timeout] || 0,
hard_timeout: options[:hard_timeout] || 0, hard_timeout: options[:hard_timeout] || 0,
priority: options[:priority] || 0, priority: options[:priority] || 0,
cookie: options[:cookie] || 0, cookie: options[:cookie] || 0,
flags: options[:flags] || [], flags: options[:flags] || [],
table_id: options[:table_id] || 0xff, table_id: options[:table_id] || 0xFF,
fin_idle_timeout: options[:fin_idle_timeout] || 0, fin_idle_timeout: options[:fin_idle_timeout] || 0,
fin_hard_timeout: options[:fin_hard_timeout] || 0, fin_hard_timeout: options[:fin_hard_timeout] || 0,
flow_specs: options[:flow_specs] || []} flow_specs: options[:flow_specs] || []
}
end end
def to_binary(%NxLearn{idle_timeout: idle, def to_binary(%NxLearn{
idle_timeout: idle,
hard_timeout: hard, hard_timeout: hard,
priority: prio, priority: prio,
cookie: cookie, cookie: cookie,
@ -36,27 +39,30 @@ defmodule Openflow.Action.NxLearn do
table_id: table_id, table_id: table_id,
fin_idle_timeout: fin_idle, fin_idle_timeout: fin_idle,
fin_hard_timeout: fin_hard, fin_hard_timeout: fin_hard,
flow_specs: flow_specs}) do flow_specs: flow_specs
}) do
flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag) flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag)
flow_specs_bin = Openflow.Action.NxFlowSpec.to_binary(flow_specs) flow_specs_bin = Openflow.Action.NxFlowSpec.to_binary(flow_specs)
exp_body = <<@experimenter::32, @nxast::16, idle::16, hard::16,
prio::16, cookie::64, flags_int::16, table_id::8, exp_body =
0::size(1)-unit(8), fin_idle::16, fin_hard::16, <<@experimenter::32, @nxast::16, idle::16, hard::16, prio::16, cookie::64, flags_int::16,
flow_specs_bin::bitstring>> table_id::8, 0::size(1)-unit(8), fin_idle::16, fin_hard::16, flow_specs_bin::bitstring>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bitstring>>) do def read(<<@experimenter::32, @nxast::16, body::bitstring>>) do
<<idle::16, hard::16, <<idle::16, hard::16, prio::16, cookie::64, flags_int::16, table_id::8, _pad::size(1)-unit(8),
prio::16, cookie::64, flags_int::16, table_id::8, fin_idle::16, fin_hard::16, flow_specs_bin::bitstring>> = body
_pad::size(1)-unit(8), fin_idle::16, fin_hard::16,
flow_specs_bin::bitstring>> = body
flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag) flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag)
flow_specs = Openflow.Action.NxFlowSpec.read(flow_specs_bin) flow_specs = Openflow.Action.NxFlowSpec.read(flow_specs_bin)
%NxLearn{idle_timeout: idle,
%NxLearn{
idle_timeout: idle,
hard_timeout: hard, hard_timeout: hard,
priority: prio, priority: prio,
cookie: cookie, cookie: cookie,
@ -64,6 +70,7 @@ defmodule Openflow.Action.NxLearn do
table_id: table_id, table_id: table_id,
fin_idle_timeout: fin_idle, fin_idle_timeout: fin_idle,
fin_hard_timeout: fin_hard, fin_hard_timeout: fin_hard,
flow_specs: flow_specs} flow_specs: flow_specs
}
end end
end end

View file

@ -20,21 +20,24 @@ defmodule Openflow.Action.NxLearn2 do
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
%NxLearn2{idle_timeout: options[:idle_timeout] || 0, %NxLearn2{
idle_timeout: options[:idle_timeout] || 0,
hard_timeout: options[:hard_timeout] || 0, hard_timeout: options[:hard_timeout] || 0,
priority: options[:priority] || 0, priority: options[:priority] || 0,
cookie: options[:cookie] || 0, cookie: options[:cookie] || 0,
flags: options[:flags] || [], flags: options[:flags] || [],
table_id: options[:table_id] || 0xff, table_id: options[:table_id] || 0xFF,
fin_idle_timeout: options[:fin_idle_timeout] || 0, fin_idle_timeout: options[:fin_idle_timeout] || 0,
fin_hard_timeout: options[:fin_hard_timeout] || 0, fin_hard_timeout: options[:fin_hard_timeout] || 0,
limit: options[:limit] || 0, limit: options[:limit] || 0,
result_dst_offset: options[:result_dst_offset] || 0, result_dst_offset: options[:result_dst_offset] || 0,
result_dst: options[:result_dst], result_dst: options[:result_dst],
flow_specs: options[:flow_specs] || []} flow_specs: options[:flow_specs] || []
}
end end
def to_binary(%NxLearn2{idle_timeout: idle, def to_binary(%NxLearn2{
idle_timeout: idle,
hard_timeout: hard, hard_timeout: hard,
priority: prio, priority: prio,
cookie: cookie, cookie: cookie,
@ -45,31 +48,38 @@ defmodule Openflow.Action.NxLearn2 do
limit: limit, limit: limit,
result_dst_offset: result_dst_ofs, result_dst_offset: result_dst_ofs,
result_dst: result_dst, result_dst: result_dst,
flow_specs: flow_specs}) do flow_specs: flow_specs
}) do
flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag) flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag)
result_dst_bin = if :write_result in flags do
result_dst_bin =
if :write_result in flags do
Openflow.Match.codec_header(result_dst) Openflow.Match.codec_header(result_dst)
else else
"" ""
end end
flow_specs_bin = Openflow.Action.NxFlowSpec.to_binary(flow_specs) flow_specs_bin = Openflow.Action.NxFlowSpec.to_binary(flow_specs)
exp_body = <<@experimenter::32, @nxast::16, idle::16, hard::16,
prio::16, cookie::64, flags_int::16, table_id::8, exp_body =
0::size(1)-unit(8), fin_idle::16, fin_hard::16, <<@experimenter::32, @nxast::16, idle::16, hard::16, prio::16, cookie::64, flags_int::16,
limit::32, result_dst_ofs::16, 0::size(2)-unit(8), table_id::8, 0::size(1)-unit(8), fin_idle::16, fin_hard::16, limit::32,
result_dst_bin::bytes, flow_specs_bin::bitstring>> result_dst_ofs::16, 0::size(2)-unit(8), result_dst_bin::bytes, flow_specs_bin::bitstring>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<idle::16, hard::16, prio::16, cookie::64, flags_int::16, table_id::8, <<idle::16, hard::16, prio::16, cookie::64, flags_int::16, table_id::8, 0::8, fin_idle::16,
0::8, fin_idle::16, fin_hard::16, limit::32, fin_hard::16, limit::32, result_dst_ofs::16, 0::size(2)-unit(8), rest::bytes>> = body
result_dst_ofs::16, 0::size(2)-unit(8), rest::bytes>> = body
flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag) flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag)
learn = %NxLearn2{idle_timeout: idle,
learn = %NxLearn2{
idle_timeout: idle,
hard_timeout: hard, hard_timeout: hard,
priority: prio, priority: prio,
cookie: cookie, cookie: cookie,
@ -78,7 +88,9 @@ defmodule Openflow.Action.NxLearn2 do
fin_idle_timeout: fin_idle, fin_idle_timeout: fin_idle,
fin_hard_timeout: fin_hard, fin_hard_timeout: fin_hard,
limit: limit, limit: limit,
result_dst_offset: result_dst_ofs} result_dst_offset: result_dst_ofs
}
if :write_result in flags do if :write_result in flags do
header_size = Openflow.Match.header_size(rest) header_size = Openflow.Match.header_size(rest)
<<result_dst_bin::size(header_size)-bytes, flow_specs_bin::bytes>> = rest <<result_dst_bin::size(header_size)-bytes, flow_specs_bin::bytes>> = rest

View file

@ -27,52 +27,62 @@ defmodule Openflow.Action.NxMultipath do
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
n_bits = Keyword.get(options, :n_bits, default_n_bits) n_bits = Keyword.get(options, :n_bits, default_n_bits)
ofs = Keyword.get(options, :offset, 0) ofs = Keyword.get(options, :offset, 0)
%NxMultipath{hash_field: hash_field,
%NxMultipath{
hash_field: hash_field,
basis: basis, basis: basis,
algorithm: alg, algorithm: alg,
max_link: max_link, max_link: max_link,
offset: ofs, offset: ofs,
n_bits: n_bits, n_bits: n_bits,
argument: arg, argument: arg,
dst_field: dst_field} dst_field: dst_field
}
end end
def to_binary(%NxMultipath{hash_field: hash_field, def to_binary(%NxMultipath{
hash_field: hash_field,
basis: basis, basis: basis,
algorithm: alg, algorithm: alg,
max_link: max_link, max_link: max_link,
argument: arg, argument: arg,
offset: ofs, offset: ofs,
n_bits: n_bits, n_bits: n_bits,
dst_field: dst_field}) do dst_field: dst_field
}) do
hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields)
alg_int = Openflow.Enums.to_int(alg, :nx_mp_algorithm) alg_int = Openflow.Enums.to_int(alg, :nx_mp_algorithm)
dst_field_bin = Openflow.Match.codec_header(dst_field) dst_field_bin = Openflow.Match.codec_header(dst_field)
ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) ofs_nbits = ofs <<< 6 ||| n_bits - 1
body = <<hash_field_int::16, basis::16, 0::size(2)-unit(8),
alg_int::16, max_link::16, arg::32, 0::size(2)-unit(8), body =
ofs_nbits::16, dst_field_bin::4-bytes>> <<hash_field_int::16, basis::16, 0::size(2)-unit(8), alg_int::16, max_link::16, arg::32,
0::size(2)-unit(8), ofs_nbits::16, dst_field_bin::4-bytes>>
exp_body = <<@experimenter::32, @nxast::16, body::bytes>> exp_body = <<@experimenter::32, @nxast::16, body::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<hash_field_int::16, basis::16, _::size(2)-unit(8), <<hash_field_int::16, basis::16, _::size(2)-unit(8), alg_int::16, max_link::16, arg::32,
alg_int::16, max_link::16, arg::32, _::size(2)-unit(8), _::size(2)-unit(8), ofs::10, n_bits::6, dst_field_bin::4-bytes>> = body
ofs::10, n_bits::6, dst_field_bin::4-bytes>> = body
hash_field = Openflow.Enums.to_atom(hash_field_int, :nx_hash_fields) hash_field = Openflow.Enums.to_atom(hash_field_int, :nx_hash_fields)
alg = Openflow.Enums.to_atom(alg_int, :nx_mp_algorithm) alg = Openflow.Enums.to_atom(alg_int, :nx_mp_algorithm)
dst_field = Openflow.Match.codec_header(dst_field_bin) dst_field = Openflow.Match.codec_header(dst_field_bin)
%NxMultipath{hash_field: hash_field,
%NxMultipath{
hash_field: hash_field,
basis: basis, basis: basis,
algorithm: alg, algorithm: alg,
max_link: max_link, max_link: max_link,
argument: arg, argument: arg,
offset: ofs, offset: ofs,
n_bits: n_bits + 1, n_bits: n_bits + 1,
dst_field: dst_field} dst_field: dst_field
}
end end
end end

View file

@ -22,30 +22,38 @@ defmodule Openflow.Action.NxNat do
ipv6_max = Keyword.get(options, :ipv6_max) ipv6_max = Keyword.get(options, :ipv6_max)
proto_min = Keyword.get(options, :proto_min) proto_min = Keyword.get(options, :proto_min)
proto_max = Keyword.get(options, :proto_max) proto_max = Keyword.get(options, :proto_max)
%NxNat{flags: flags,
%NxNat{
flags: flags,
ipv4_min: ipv4_min, ipv4_min: ipv4_min,
ipv4_max: ipv4_max, ipv4_max: ipv4_max,
ipv6_min: ipv6_min, ipv6_min: ipv6_min,
ipv6_max: ipv6_max, ipv6_max: ipv6_max,
proto_min: proto_min, proto_min: proto_min,
proto_max: proto_max} proto_max: proto_max
}
end end
def to_binary(%NxNat{flags: flags} = nat) do def to_binary(%NxNat{flags: flags} = nat) do
flags_int = Openflow.Enums.flags_to_int(flags, :nx_nat_flags) flags_int = Openflow.Enums.flags_to_int(flags, :nx_nat_flags)
range_flags = range_flags =
nat nat
|> get_ranges |> get_ranges
|> Openflow.Enums.flags_to_int(:nx_nat_range) |> Openflow.Enums.flags_to_int(:nx_nat_range)
|> Openflow.Enums.int_to_flags(:nx_nat_range) |> Openflow.Enums.int_to_flags(:nx_nat_range)
ranges_bin = encode_ranges("", range_flags, nat) ranges_bin = encode_ranges("", range_flags, nat)
range_flags_int = Openflow.Enums.flags_to_int(range_flags, :nx_nat_range) range_flags_int = Openflow.Enums.flags_to_int(range_flags, :nx_nat_range)
exp_body = <<@experimenter::32, @nxast::16, 0::size(2)-unit(8),
flags_int::16, range_flags_int::16, ranges_bin::bytes>> exp_body =
<<@experimenter::32, @nxast::16, 0::size(2)-unit(8), flags_int::16, range_flags_int::16,
ranges_bin::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
@ -59,33 +67,43 @@ defmodule Openflow.Action.NxNat do
defp get_ranges(nat) do defp get_ranges(nat) do
nat nat
|> Map.from_struct |> Map.from_struct()
|> Map.delete(:flags) |> Map.delete(:flags)
|> Enum.map(fn({k, v}) -> if(not is_nil(v), do: k, else: nil) end) |> 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.filter(fn v -> not is_nil(v) end)
end end
defp encode_ranges(acc, [], _nat), do: acc defp encode_ranges(acc, [], _nat), do: acc
defp encode_ranges(acc, [range|rest], nat) do
defp encode_ranges(acc, [range | rest], nat) do
cond do cond do
range == :ipv4_min or range == :ipv4_max -> range == :ipv4_min or range == :ipv4_max ->
case Map.get(nat, range) do case Map.get(nat, range) do
{a1, a2, a3, a4} -> {a1, a2, a3, a4} ->
encode_ranges(<<acc::bytes, a1, a2, a3, a4>>, rest, nat) encode_ranges(<<acc::bytes, a1, a2, a3, a4>>, rest, nat)
"" -> "" ->
encode_ranges(<<acc::bytes>>, rest, nat) encode_ranges(<<acc::bytes>>, rest, nat)
end end
range == :ipv6_min or range == :ipv6_max -> range == :ipv6_min or range == :ipv6_max ->
case Map.get(nat, range) do case Map.get(nat, range) do
{a1, a2, a3, a4, a5, a6, a7, a8} -> {a1, a2, a3, a4, a5, a6, a7, a8} ->
encode_ranges(<<acc::bytes, a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>, rest, nat) encode_ranges(
<<acc::bytes, a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>,
rest,
nat
)
"" -> "" ->
encode_ranges(<<acc::bytes>>, rest, nat) encode_ranges(<<acc::bytes>>, rest, nat)
end end
range == :proto_min or range == :proto_max -> range == :proto_min or range == :proto_max ->
case Map.get(nat, range) do case Map.get(nat, range) do
proto when is_integer(proto) and proto in (1..0xffff) -> proto when is_integer(proto) and proto in 1..0xFFFF ->
encode_ranges(<<acc::bytes, proto::16>>, rest, nat) encode_ranges(<<acc::bytes, proto::16>>, rest, nat)
_ -> _ ->
encode_ranges(<<acc::bytes>>, rest, nat) encode_ranges(<<acc::bytes>>, rest, nat)
end end
@ -93,26 +111,32 @@ defmodule Openflow.Action.NxNat do
end end
defp decode_ranges(nat, [], _), do: nat defp decode_ranges(nat, [], _), do: nat
defp decode_ranges(nat, [range|ranges], bin) do
defp decode_ranges(nat, [range | ranges], bin) do
cond do cond do
range == :ipv4_min or range == :ipv4_max -> range == :ipv4_min or range == :ipv4_max ->
case bin do case bin do
<<a1, a2, a3, a4, rest::bytes>> -> <<a1, a2, a3, a4, rest::bytes>> ->
decode_ranges(struct(nat, %{range => {a1, a2, a3, a4}}), ranges, rest) decode_ranges(struct(nat, %{range => {a1, a2, a3, a4}}), ranges, rest)
rest -> rest ->
decode_ranges(struct(nat, %{range => ""}), ranges, rest) decode_ranges(struct(nat, %{range => ""}), ranges, rest)
end end
range == :ipv6_min or range == :ipv6_max -> range == :ipv6_min or range == :ipv6_max ->
case bin do case bin do
<<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16, rest::bytes>> -> <<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16, rest::bytes>> ->
decode_ranges(struct(nat, %{range => {a1, a2, a3, a4, a5, a6, a7, a8}}), ranges, rest) decode_ranges(struct(nat, %{range => {a1, a2, a3, a4, a5, a6, a7, a8}}), ranges, rest)
rest -> rest ->
decode_ranges(struct(nat, %{range => ""}), ranges, rest) decode_ranges(struct(nat, %{range => ""}), ranges, rest)
end end
range == :proto_min or range == :proto_max -> range == :proto_min or range == :proto_max ->
case bin do case bin do
<<proto::16, rest::bytes>> when proto in (1..0xffff) -> <<proto::16, rest::bytes>> when proto in 1..0xFFFF ->
decode_ranges(struct(nat, %{range => proto}), ranges, rest) decode_ranges(struct(nat, %{range => proto}), ranges, rest)
rest -> rest ->
decode_ranges(struct(nat, %{range => ""}), ranges, rest) decode_ranges(struct(nat, %{range => ""}), ranges, rest)
end end

View file

@ -16,7 +16,7 @@ defmodule Openflow.Action.NxNote do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, note_bin::bytes>>) do def read(<<@experimenter::32, @nxast::16, note_bin::bytes>>) do

View file

@ -19,34 +19,25 @@ defmodule Openflow.Action.NxOutputReg do
n_bits = Keyword.get(options, :n_bits, default_n_bits) n_bits = Keyword.get(options, :n_bits, default_n_bits)
ofs = Keyword.get(options, :offset, 0) ofs = Keyword.get(options, :offset, 0)
max_len = Keyword.get(options, :max_len, :no_buffer) max_len = Keyword.get(options, :max_len, :no_buffer)
%NxOutputReg{n_bits: n_bits, %NxOutputReg{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}
offset: ofs,
src_field: src_field,
max_len: max_len}
end end
def to_binary(%NxOutputReg{n_bits: n_bits, def to_binary(%NxOutputReg{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}) do
offset: ofs,
src_field: src_field,
max_len: max_len}) do
src_field_bin = Openflow.Match.codec_header(src_field) src_field_bin = Openflow.Match.codec_header(src_field)
ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) ofs_nbits = ofs <<< 6 ||| n_bits - 1
max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len)
body = <<ofs_nbits::16, src_field_bin::4-bytes, max_len::16, 0::size(6)-unit(8)>> body = <<ofs_nbits::16, src_field_bin::4-bytes, max_len::16, 0::size(6)-unit(8)>>
exp_body = <<@experimenter::32, @nxast::16, body::bytes>> exp_body = <<@experimenter::32, @nxast::16, body::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<ofs::10, n_bits::6, src_field_bin::4-bytes, max_len::16, _::size(6)-unit(8)>> = body <<ofs::10, n_bits::6, src_field_bin::4-bytes, max_len::16, _::size(6)-unit(8)>> = body
src_field = Openflow.Match.codec_header(src_field_bin) src_field = Openflow.Match.codec_header(src_field_bin)
max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len)
%NxOutputReg{n_bits: n_bits + 1, %NxOutputReg{n_bits: n_bits + 1, offset: ofs, src_field: src_field, max_len: max_len}
offset: ofs,
src_field: src_field,
max_len: max_len}
end end
end end

View file

@ -24,7 +24,7 @@ defmodule Openflow.Action.NxOutputReg2 do
def to_binary(%NxOutputReg2{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}) do def to_binary(%NxOutputReg2{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}) do
src_field_bin = Openflow.Match.codec_header(src_field) src_field_bin = Openflow.Match.codec_header(src_field)
ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) ofs_nbits = ofs <<< 6 ||| n_bits - 1
max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len)
padding = Openflow.Utils.padding(byte_size(src_field_bin), 10) padding = Openflow.Utils.padding(byte_size(src_field_bin), 10)
body = <<ofs_nbits::16, max_len::16, src_field_bin::bytes, 0::size(padding)-unit(8)>> body = <<ofs_nbits::16, max_len::16, src_field_bin::bytes, 0::size(padding)-unit(8)>>
@ -32,20 +32,23 @@ defmodule Openflow.Action.NxOutputReg2 do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<ofs::10, n_bits::6, max_len::16, oxm_header::4-bytes, rest::bitstring>> = body <<ofs::10, n_bits::6, max_len::16, oxm_header::4-bytes, rest::bitstring>> = body
exp_size = match_header_size(oxm_header) - 4 exp_size = match_header_size(oxm_header) - 4
<<experimenter_int::size(exp_size)-unit(8), _padding::bytes>> = rest <<experimenter_int::size(exp_size)-unit(8), _padding::bytes>> = rest
src_field = Openflow.Match.codec_header(<<oxm_header::bytes, experimenter_int::size(exp_size)-unit(8)>>)
src_field =
Openflow.Match.codec_header(<<oxm_header::bytes, experimenter_int::size(exp_size)-unit(8)>>)
max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len)
%NxOutputReg2{n_bits: n_bits + 1, offset: ofs, src_field: src_field, max_len: max_len} %NxOutputReg2{n_bits: n_bits + 1, offset: ofs, src_field: src_field, max_len: max_len}
end end
# private functions # private functions
defp match_header_size(<<0xffff::16, _::bytes>>), do: 8 defp match_header_size(<<0xFFFF::16, _::bytes>>), do: 8
defp match_header_size(<<_::16, _::bytes>>), do: 4 defp match_header_size(<<_::16, _::bytes>>), do: 4
end end

View file

@ -21,7 +21,7 @@ defmodule Openflow.Action.NxOutputTrunc do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>>) do def read(<<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>>) do

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxPopMpls do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxPopQueue do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>) do

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxPushMpls do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do

View file

@ -19,36 +19,27 @@ defmodule Openflow.Action.NxRegLoad do
n_bits = Keyword.get(options, :n_bits, default_n_bits) n_bits = Keyword.get(options, :n_bits, default_n_bits)
ofs = Keyword.get(options, :offset, 0) ofs = Keyword.get(options, :offset, 0)
value = Keyword.get(options, :value) value = Keyword.get(options, :value)
%NxRegLoad{n_bits: n_bits, %NxRegLoad{n_bits: n_bits, offset: ofs, dst_field: dst_field, value: value}
offset: ofs,
dst_field: dst_field,
value: value}
end end
def to_binary(%NxRegLoad{n_bits: n_bits, def to_binary(%NxRegLoad{n_bits: n_bits, offset: ofs, dst_field: dst_field, value: value}) do
offset: ofs,
dst_field: dst_field,
value: value}) do
dst_field_bin = Openflow.Match.codec_header(dst_field) dst_field_bin = Openflow.Match.codec_header(dst_field)
value_bin0 = Openflow.Match.Field.codec(value, dst_field) value_bin0 = Openflow.Match.Field.codec(value, dst_field)
tmp_value = :binary.decode_unsigned(value_bin0, :big) tmp_value = :binary.decode_unsigned(value_bin0, :big)
value_bin = <<tmp_value::64>> value_bin = <<tmp_value::64>>
ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) ofs_nbits = ofs <<< 6 ||| n_bits - 1
body = <<ofs_nbits::16, dst_field_bin::4-bytes, value_bin::bytes>> body = <<ofs_nbits::16, dst_field_bin::4-bytes, value_bin::bytes>>
exp_body = <<@experimenter::32, @nxast::16, body::bytes>> exp_body = <<@experimenter::32, @nxast::16, body::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<ofs::10, n_bits::6, dst_field_bin::4-bytes, value_bin::bytes>> = body <<ofs::10, n_bits::6, dst_field_bin::4-bytes, value_bin::bytes>> = body
dst_field = Openflow.Match.codec_header(dst_field_bin) dst_field = Openflow.Match.codec_header(dst_field_bin)
value = Openflow.Match.Field.codec(value_bin, dst_field) value = Openflow.Match.Field.codec(value_bin, dst_field)
%NxRegLoad{n_bits: n_bits + 1, %NxRegLoad{n_bits: n_bits + 1, offset: ofs, dst_field: dst_field, value: value}
offset: ofs,
dst_field: dst_field,
value: value}
end end
end end

View file

@ -18,23 +18,27 @@ defmodule Openflow.Action.NxRegLoad2 do
def to_binary(%NxRegLoad2{dst_field: dst_field, value: value}) do def to_binary(%NxRegLoad2{dst_field: dst_field, value: value}) do
match_bin = match_bin =
[{dst_field, value}] [{dst_field, value}]
|> Openflow.Match.new |> Openflow.Match.new()
|> Openflow.Match.to_binary |> Openflow.Match.to_binary()
<<1::16, _length::16, padded_field::bytes>> = match_bin <<1::16, _length::16, padded_field::bytes>> = match_bin
patial_len = 4 + 4 + 2 + 6 + byte_size(padded_field) patial_len = 4 + 4 + 2 + 6 + byte_size(padded_field)
padding = Openflow.Utils.padding(patial_len, 8) padding = Openflow.Utils.padding(patial_len, 8)
exp_body = <<@experimenter::32, @nxast::16, 0::48, padded_field::bytes, 0::size(padding)-unit(8)>>
exp_body =
<<@experimenter::32, @nxast::16, 0::48, padded_field::bytes, 0::size(padding)-unit(8)>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, _::48, match_field_bin::bytes>>) do def read(<<@experimenter::32, @nxast::16, _::48, match_field_bin::bytes>>) do
<<_class::16, _field::7, _hm::1, flen::8, _rest::bytes>> = match_field_bin <<_class::16, _field::7, _hm::1, flen::8, _rest::bytes>> = match_field_bin
match_len = 4 + 4 + flen match_len = 4 + 4 + flen
match_bin = <<1::16, match_len::16, match_field_bin::bytes, 0::size(4)-unit(8)>> match_bin = <<1::16, match_len::16, match_field_bin::bytes, 0::size(4)-unit(8)>>
{[{dst_field, value}|_], _rest} = Openflow.Match.read(match_bin) {[{dst_field, value} | _], _rest} = Openflow.Match.read(match_bin)
%NxRegLoad2{dst_field: dst_field, value: value} %NxRegLoad2{dst_field: dst_field, value: value}
end end
end end

View file

@ -19,38 +19,49 @@ defmodule Openflow.Action.NxRegMove do
n_bits = Keyword.get(options, :n_bits, default_n_bits) n_bits = Keyword.get(options, :n_bits, default_n_bits)
src_ofs = Keyword.get(options, :src_offset, 0) src_ofs = Keyword.get(options, :src_offset, 0)
dst_ofs = Keyword.get(options, :dst_offset, 0) dst_ofs = Keyword.get(options, :dst_offset, 0)
%NxRegMove{n_bits: n_bits,
%NxRegMove{
n_bits: n_bits,
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs, dst_offset: dst_ofs,
src_field: src_field, src_field: src_field,
dst_field: dst_field} dst_field: dst_field
}
end end
def to_binary(%NxRegMove{n_bits: n_bits, def to_binary(%NxRegMove{
n_bits: n_bits,
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs, dst_offset: dst_ofs,
src_field: src_field, src_field: src_field,
dst_field: dst_field}) do dst_field: dst_field
}) do
src_field_bin = Openflow.Match.codec_header(src_field) src_field_bin = Openflow.Match.codec_header(src_field)
dst_field_bin = Openflow.Match.codec_header(dst_field) dst_field_bin = Openflow.Match.codec_header(dst_field)
body = <<n_bits::16, src_ofs::16, dst_ofs::16,
src_field_bin::4-bytes, dst_field_bin::4-bytes>> body =
<<n_bits::16, src_ofs::16, dst_ofs::16, src_field_bin::4-bytes, dst_field_bin::4-bytes>>
exp_body = <<@experimenter::32, @nxast::16, body::bytes>> exp_body = <<@experimenter::32, @nxast::16, body::bytes>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<n_bits::16, src_ofs::16, dst_ofs::16, <<n_bits::16, src_ofs::16, dst_ofs::16, src_field_bin::4-bytes, dst_field_bin::4-bytes>> =
src_field_bin::4-bytes, dst_field_bin::4-bytes>> = body body
src_field = Openflow.Match.codec_header(src_field_bin) src_field = Openflow.Match.codec_header(src_field_bin)
dst_field = Openflow.Match.codec_header(dst_field_bin) dst_field = Openflow.Match.codec_header(dst_field_bin)
%NxRegMove{n_bits: n_bits,
%NxRegMove{
n_bits: n_bits,
src_offset: src_ofs, src_offset: src_ofs,
dst_offset: dst_ofs, dst_offset: dst_ofs,
src_field: src_field, src_field: src_field,
dst_field: dst_field} dst_field: dst_field
}
end end
end end

View file

@ -1,5 +1,5 @@
defmodule Openflow.Action.NxResubmit do defmodule Openflow.Action.NxResubmit do
defstruct([in_port: :in_port]) defstruct(in_port: :in_port)
@experimenter 0x00002320 @experimenter 0x00002320
@nxast 1 @nxast 1
@ -16,7 +16,7 @@ defmodule Openflow.Action.NxResubmit do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do

View file

@ -1,5 +1,5 @@
defmodule Openflow.Action.NxResubmitTable do defmodule Openflow.Action.NxResubmitTable do
defstruct([in_port: :in_port, table_id: :all]) defstruct(in_port: :in_port, table_id: :all)
@experimenter 0x00002320 @experimenter 0x00002320
@nxast 14 @nxast 14
@ -9,6 +9,7 @@ defmodule Openflow.Action.NxResubmitTable do
def new(table_id) when is_atom(table_id) or is_integer(table_id) do def new(table_id) when is_atom(table_id) or is_integer(table_id) do
new(table_id: table_id) new(table_id: table_id)
end end
def new(options) do def new(options) do
in_port = Keyword.get(options, :in_port, :in_port) in_port = Keyword.get(options, :in_port, :in_port)
table_id = Keyword.get(options, :table_id, :all) table_id = Keyword.get(options, :table_id, :all)
@ -22,10 +23,12 @@ defmodule Openflow.Action.NxResubmitTable do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::size(3)-unit(8)>>) do def read(
<<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::size(3)-unit(8)>>
) do
in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no) in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no)
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
%NxResubmitTable{in_port: in_port, table_id: table_id} %NxResubmitTable{in_port: in_port, table_id: table_id}

View file

@ -19,10 +19,12 @@ defmodule Openflow.Action.NxResubmitTableCt do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::size(3)-unit(8)>>) do def read(
<<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::size(3)-unit(8)>>
) do
in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no) in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no)
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
%NxResubmitTableCt{in_port: in_port, table_id: table_id} %NxResubmitTableCt{in_port: in_port, table_id: table_id}

View file

@ -16,29 +16,40 @@ defmodule Openflow.Action.NxSample do
collector_set_id = Keyword.get(options, :collector_set_id, 0) collector_set_id = Keyword.get(options, :collector_set_id, 0)
obs_domain_id = Keyword.get(options, :obs_domain_id, 0) obs_domain_id = Keyword.get(options, :obs_domain_id, 0)
obs_point_id = Keyword.get(options, :obs_point_id, 0) obs_point_id = Keyword.get(options, :obs_point_id, 0)
%NxSample{probability: probability,
%NxSample{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id} obs_point_id: obs_point_id
}
end end
def to_binary(%NxSample{probability: probability, def to_binary(%NxSample{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id}) do obs_point_id: obs_point_id
exp_body = <<@experimenter::32, @nxast::16, probability::16, }) do
collector_set_id::32, obs_domain_id::32, obs_point_id::32>> exp_body =
<<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32,
obs_point_id::32>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, probability::16, def read(
collector_set_id::32, obs_domain_id::32, obs_point_id::32>>) do <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32,
%NxSample{probability: probability, obs_point_id::32>>
) do
%NxSample{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id} obs_point_id: obs_point_id
}
end end
end end

View file

@ -18,32 +18,43 @@ defmodule Openflow.Action.NxSample2 do
obs_domain_id = Keyword.get(options, :obs_domain_id, 0) obs_domain_id = Keyword.get(options, :obs_domain_id, 0)
obs_point_id = Keyword.get(options, :obs_point_id, 0) obs_point_id = Keyword.get(options, :obs_point_id, 0)
sampling_port = Keyword.get(options, :sampling_port, 0) sampling_port = Keyword.get(options, :sampling_port, 0)
%NxSample2{probability: probability,
%NxSample2{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id, obs_point_id: obs_point_id,
sampling_port: sampling_port} sampling_port: sampling_port
}
end end
def to_binary(%NxSample2{probability: probability, def to_binary(%NxSample2{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id, obs_point_id: obs_point_id,
sampling_port: sampling_port}) do sampling_port: sampling_port
exp_body = <<@experimenter::32, @nxast::16, probability::16, }) do
collector_set_id::32, obs_domain_id::32, obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>> exp_body =
<<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32,
obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, def read(
obs_domain_id::32, obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>>) do <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32,
%NxSample2{probability: probability, obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>>
) do
%NxSample2{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id, obs_point_id: obs_point_id,
sampling_port: sampling_port} sampling_port: sampling_port
}
end end
end end

View file

@ -20,37 +20,50 @@ defmodule Openflow.Action.NxSample3 do
obs_point_id = Keyword.get(options, :obs_point_id, 0) obs_point_id = Keyword.get(options, :obs_point_id, 0)
sampling_port = Keyword.get(options, :sampling_port, 0) sampling_port = Keyword.get(options, :sampling_port, 0)
direction = Keyword.get(options, :direction, :default) direction = Keyword.get(options, :direction, :default)
%NxSample3{probability: probability,
%NxSample3{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id, obs_point_id: obs_point_id,
sampling_port: sampling_port, sampling_port: sampling_port,
direction: direction} direction: direction
}
end end
def to_binary(%NxSample3{probability: probability, def to_binary(%NxSample3{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id, obs_point_id: obs_point_id,
sampling_port: sampling_port, sampling_port: sampling_port,
direction: direction}) do direction: direction
}) do
direction_int = Openflow.Enums.to_int(direction, :nx_action_sample_direction) direction_int = Openflow.Enums.to_int(direction, :nx_action_sample_direction)
exp_body = <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32,
obs_domain_id::32, obs_point_id::32, sampling_port::16, direction_int::8, 0::size(5)-unit(8)>> exp_body =
<<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32,
obs_point_id::32, sampling_port::16, direction_int::8, 0::size(5)-unit(8)>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, def read(
obs_domain_id::32, obs_point_id::32, sampling_port::16, direction_int::8, 0::size(5)-unit(8)>>) do <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32,
obs_point_id::32, sampling_port::16, direction_int::8, 0::size(5)-unit(8)>>
) do
direction = Openflow.Enums.to_atom(direction_int, :nx_action_sample_direction) direction = Openflow.Enums.to_atom(direction_int, :nx_action_sample_direction)
%NxSample3{probability: probability,
%NxSample3{
probability: probability,
collector_set_id: collector_set_id, collector_set_id: collector_set_id,
obs_domain_id: obs_domain_id, obs_domain_id: obs_domain_id,
obs_point_id: obs_point_id, obs_point_id: obs_point_id,
sampling_port: sampling_port, sampling_port: sampling_port,
direction: direction} direction: direction
}
end end
end end

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxSetMplsLabel do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, _::16, label::32>>) do def read(<<@experimenter::32, @nxast::16, _::16, label::32>>) do

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxSetMplsTc do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, tc::8, _::size(5)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, tc::8, _::size(5)-unit(8)>>) do

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxSetMplsTtl do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, ttl::8, _::size(5)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, ttl::8, _::size(5)-unit(8)>>) do

View file

@ -1,5 +1,5 @@
defmodule Openflow.Action.NxSetQueue do defmodule Openflow.Action.NxSetQueue do
defstruct([queue_id: 0]) defstruct(queue_id: 0)
@experimenter 0x00002320 @experimenter 0x00002320
@nxast 4 @nxast 4
@ -15,7 +15,7 @@ defmodule Openflow.Action.NxSetQueue do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, 0::size(2)-unit(8), queue_id::32>>) do def read(<<@experimenter::32, @nxast::16, 0::size(2)-unit(8), queue_id::32>>) do

View file

@ -15,7 +15,7 @@ defmodule Openflow.Action.NxSetTunnel do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do

View file

@ -1,5 +1,5 @@
defmodule Openflow.Action.NxSetTunnel64 do defmodule Openflow.Action.NxSetTunnel64 do
defstruct([tunnel_id: 0]) defstruct(tunnel_id: 0)
@experimenter 0x00002320 @experimenter 0x00002320
@nxast 9 @nxast 9
@ -15,7 +15,7 @@ defmodule Openflow.Action.NxSetTunnel64 do
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>>) do def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>>) do

View file

@ -20,16 +20,21 @@ defmodule Openflow.Action.NxStackPop do
def to_binary(%NxStackPop{n_bits: n_bits, offset: ofs, field: field}) do def to_binary(%NxStackPop{n_bits: n_bits, offset: ofs, field: field}) do
field_bin = Openflow.Match.codec_header(field) field_bin = Openflow.Match.codec_header(field)
exp_body = <<@experimenter::32, @nxast::16, ofs::16,
field_bin::4-bytes, n_bits::16, 0::size(6)-unit(8)>> exp_body =
<<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16,
0::size(6)-unit(8)>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, ofs::16, def read(
field_bin::4-bytes, n_bits::16, _::size(6)-unit(8)>>) do <<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16,
_::size(6)-unit(8)>>
) do
field = Openflow.Match.codec_header(field_bin) field = Openflow.Match.codec_header(field_bin)
%NxStackPop{n_bits: n_bits, offset: ofs, field: field} %NxStackPop{n_bits: n_bits, offset: ofs, field: field}
end end

View file

@ -20,16 +20,21 @@ defmodule Openflow.Action.NxStackPush do
def to_binary(%NxStackPush{n_bits: n_bits, offset: ofs, field: field}) do def to_binary(%NxStackPush{n_bits: n_bits, offset: ofs, field: field}) do
field_bin = Openflow.Match.codec_header(field) field_bin = Openflow.Match.codec_header(field)
exp_body = <<@experimenter::32, @nxast::16, ofs::16,
field_bin::4-bytes, n_bits::16, 0::size(6)-unit(8)>> exp_body =
<<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16,
0::size(6)-unit(8)>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, ofs::16, def read(
field_bin::4-bytes, n_bits::16, _::size(6)-unit(8)>>) do <<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16,
_::size(6)-unit(8)>>
) do
field = Openflow.Match.codec_header(field_bin) field = Openflow.Match.codec_header(field_bin)
%NxStackPush{n_bits: n_bits, offset: ofs, field: field} %NxStackPush{n_bits: n_bits, offset: ofs, field: field}
end end

View file

@ -1,7 +1,7 @@
defmodule Openflow.Action.NxWriteMetadata do defmodule Openflow.Action.NxWriteMetadata do
defstruct( defstruct(
metadata: 0, metadata: 0,
metadata_mask: 0xffffffffffffffff metadata_mask: 0xFFFFFFFFFFFFFFFF
) )
@experimenter 0x00002320 @experimenter 0x00002320
@ -12,18 +12,21 @@ defmodule Openflow.Action.NxWriteMetadata do
def new(metadata) when is_integer(metadata) do def new(metadata) when is_integer(metadata) do
new(metadata: metadata) new(metadata: metadata)
end end
def new(options) when is_list(options) do def new(options) when is_list(options) do
metadata = Keyword.get(options, :metadata, 0) metadata = Keyword.get(options, :metadata, 0)
metadata_mask = Keyword.get(options, :metadata_mask, 0xffffffffffffffff) metadata_mask = Keyword.get(options, :metadata_mask, 0xFFFFFFFFFFFFFFFF)
%NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask} %NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask}
end end
def to_binary(%NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask}) do def to_binary(%NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask}) do
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), metadata::64, metadata_mask::64>> exp_body =
<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), metadata::64, metadata_mask::64>>
exp_body_size = byte_size(exp_body) exp_body_size = byte_size(exp_body)
padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8)
length = 4 + exp_body_size + padding_length length = 4 + exp_body_size + padding_length
<<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>>
end end
def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8), metadata::64, metadata_mask::64>>) do def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8), metadata::64, metadata_mask::64>>) do

View file

@ -11,6 +11,7 @@ defmodule Openflow.Action.Output do
def new(port) when not is_list(port) do def new(port) when not is_list(port) do
new(port_number: port) new(port_number: port)
end end
def new(options) when is_list(options) do def new(options) when is_list(options) do
port_no = Keyword.get(options, :port_number) port_no = Keyword.get(options, :port_number)
max_len = Keyword.get(options, :max_len, :no_buffer) max_len = Keyword.get(options, :max_len, :no_buffer)

View file

@ -1,5 +1,5 @@
defmodule Openflow.Action.PushPbb do defmodule Openflow.Action.PushPbb do
defstruct(ethertype: 0x88e7) defstruct(ethertype: 0x88E7)
alias __MODULE__ alias __MODULE__

View file

@ -14,8 +14,8 @@ defmodule Openflow.Action.SetField do
def to_binary(%SetField{field: {field, value}}) do def to_binary(%SetField{field: {field, value}}) do
match_bin = match_bin =
[{field, value}] [{field, value}]
|> Openflow.Match.new |> Openflow.Match.new()
|> Openflow.Match.to_binary |> Openflow.Match.to_binary()
<<1::16, _length::16, padded_field::bytes>> = match_bin <<1::16, _length::16, padded_field::bytes>> = match_bin
patial_len = @set_field_size - 4 + byte_size(padded_field) patial_len = @set_field_size - 4 + byte_size(padded_field)
@ -28,7 +28,7 @@ defmodule Openflow.Action.SetField do
<<_class::16, _field::7, _hm::1, flen::8, _rest::bytes>> = match_field_bin <<_class::16, _field::7, _hm::1, flen::8, _rest::bytes>> = match_field_bin
match_len = 4 + 4 + flen match_len = 4 + 4 + flen
match_bin = <<1::16, match_len::16, match_field_bin::bytes>> match_bin = <<1::16, match_len::16, match_field_bin::bytes>>
{[field|_], _rest} = Openflow.Match.read(match_bin) {[field | _], _rest} = Openflow.Match.read(match_bin)
%SetField{field: field} %SetField{field: field}
end end
end end

View file

@ -2,8 +2,10 @@ defmodule Openflow.Barrier.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__

View file

@ -2,8 +2,10 @@ defmodule Openflow.Barrier.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__

View file

@ -29,26 +29,43 @@ defmodule Openflow.Bucket do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) 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 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_len = length - @header_size
<<actions_bin::size(actions_len)-bytes, rest::bytes>> = binary <<actions_bin::size(actions_len)-bytes, rest::bytes>> = binary
watch_port = Openflow.Utils.get_enum(watch_port_int, :openflow13_port_no) watch_port = Openflow.Utils.get_enum(watch_port_int, :openflow13_port_no)
watch_group = Openflow.Utils.get_enum(watch_group_int, :group_id) watch_group = Openflow.Utils.get_enum(watch_group_int, :group_id)
actions = Openflow.Action.read(actions_bin) 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) bucket = %Bucket{
weight: weight,
watch_port: watch_port,
watch_group: watch_group,
actions: actions
}
do_read([bucket | acc], rest)
end end
defp to_binary(acc, []), do: acc 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 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_port_int = Openflow.Utils.get_enum(watch_port, :openflow13_port_no)
watch_group_int = Openflow.Utils.get_enum(watch_group, :group_id) watch_group_int = Openflow.Utils.get_enum(watch_group, :group_id)
actions_bin = Openflow.Action.to_binary(actions) actions_bin = Openflow.Action.to_binary(actions)
length = byte_size(actions_bin) + @header_size 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>> 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) to_binary(<<acc::bytes, bucket_bin::bytes>>, rest)
end end
end end

View file

@ -3,8 +3,10 @@ defmodule Openflow.Echo.Reply do
version: 4, version: 4,
xid: 0, xid: 0,
data: "", data: "",
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__

View file

@ -3,8 +3,10 @@ defmodule Openflow.Echo.Request do
version: 4, version: 4,
xid: 0, xid: 0,
data: "", data: "",
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__
@ -23,4 +25,3 @@ defmodule Openflow.Echo.Request do
data data
end end
end end

View file

@ -32,12 +32,10 @@ defmodule Openflow.Enums do
{Openflow.SetAsync, 28}, {Openflow.SetAsync, 28},
{Openflow.MeterMod, 29} {Openflow.MeterMod, 29}
], ],
experimenter_id: [ experimenter_id: [
nicira_ext_message: 0x00002320, nicira_ext_message: 0x00002320,
onf_ext_message: 0x4f4e4600 onf_ext_message: 0x4F4E4600
], ],
nicira_ext_message: [ nicira_ext_message: [
# {Openflow.NxRole.Request, 10}, /* Openflow 1.3 support role request/reply */ # {Openflow.NxRole.Request, 10}, /* Openflow 1.3 support role request/reply */
# {Openflow.NxRole.Reply, 11}, # {Openflow.NxRole.Reply, 11},
@ -61,20 +59,16 @@ defmodule Openflow.Enums do
{Openflow.NxCtFlushZone, 29}, {Openflow.NxCtFlushZone, 29},
{Openflow.NxPacketIn2, 30} {Openflow.NxPacketIn2, 30}
], ],
onf_ext_message: [ onf_ext_message: [
{Openflow.OnfBundleControl, 2300}, {Openflow.OnfBundleControl, 2300},
{Openflow.OnfBundleAddMessage, 2301}, {Openflow.OnfBundleAddMessage, 2301}
], ],
multipart_request_flags: [ multipart_request_flags: [
more: 1 <<< 0 more: 1 <<< 0
], ],
multipart_reply_flags: [ multipart_reply_flags: [
more: 1 <<< 0 more: 1 <<< 0
], ],
multipart_request_codec: [ multipart_request_codec: [
{Openflow.Multipart.Desc.Request, 0}, {Openflow.Multipart.Desc.Request, 0},
{Openflow.Multipart.Flow.Request, 1}, {Openflow.Multipart.Flow.Request, 1},
@ -90,9 +84,8 @@ defmodule Openflow.Enums do
{Openflow.Multipart.MeterFeatures.Request, 11}, {Openflow.Multipart.MeterFeatures.Request, 11},
{Openflow.Multipart.TableFeatures.Request, 12}, {Openflow.Multipart.TableFeatures.Request, 12},
{Openflow.Multipart.PortDesc.Request, 13}, {Openflow.Multipart.PortDesc.Request, 13},
{Openflow.Multipart.Experimenter.Request, 0xffff}, {Openflow.Multipart.Experimenter.Request, 0xFFFF}
], ],
multipart_reply_codec: [ multipart_reply_codec: [
{Openflow.Multipart.Desc.Reply, 0}, {Openflow.Multipart.Desc.Reply, 0},
{Openflow.Multipart.Flow.Reply, 1}, {Openflow.Multipart.Flow.Reply, 1},
@ -108,21 +101,18 @@ defmodule Openflow.Enums do
{Openflow.Multipart.MeterFeatures.Reply, 11}, {Openflow.Multipart.MeterFeatures.Reply, 11},
{Openflow.Multipart.TableFeatures.Reply, 12}, {Openflow.Multipart.TableFeatures.Reply, 12},
{Openflow.Multipart.PortDesc.Reply, 13}, {Openflow.Multipart.PortDesc.Reply, 13},
{Openflow.Multipart.Experimenter.Reply, 0xffff}, {Openflow.Multipart.Experimenter.Reply, 0xFFFF}
], ],
nicira_ext_stats: [ nicira_ext_stats: [
{Openflow.Multipart.NxFlow, 0}, {Openflow.Multipart.NxFlow, 0},
{Openflow.Multipart.NxAggregate, 1}, {Openflow.Multipart.NxAggregate, 1},
{Openflow.Multipart.NxFlowMonitor, 2}, {Openflow.Multipart.NxFlowMonitor, 2},
{Openflow.Multipart.NxIPFIXBridge, 3}, {Openflow.Multipart.NxIPFIXBridge, 3},
{Openflow.Multipart.NxIPFIXFlow, 4}, {Openflow.Multipart.NxIPFIXFlow, 4}
], ],
hello_elem: [ hello_elem: [
versionbitmap: 1 versionbitmap: 1
], ],
error_type: [ error_type: [
hello_failed: 0, hello_failed: 0,
bad_request: 1, bad_request: 1,
@ -138,14 +128,12 @@ defmodule Openflow.Enums do
role_request_failed: 11, role_request_failed: 11,
meter_mod_failed: 12, meter_mod_failed: 12,
table_features_failed: 13, table_features_failed: 13,
experimenter: 0xffff experimenter: 0xFFFF
], ],
hello_failed: [ hello_failed: [
inconpatible: 0, inconpatible: 0,
eperm: 1 eperm: 1
], ],
bad_request: [ bad_request: [
bad_version: 0, bad_version: 0,
bad_type: 1, bad_type: 1,
@ -162,7 +150,6 @@ defmodule Openflow.Enums do
bad_packet: 12, bad_packet: 12,
multipart_buffer_overflow: 13 multipart_buffer_overflow: 13
], ],
bad_action: [ bad_action: [
bad_type: 0, bad_type: 0,
bad_len: 1, bad_len: 1,
@ -181,7 +168,6 @@ defmodule Openflow.Enums do
bad_set_len: 14, bad_set_len: 14,
bad_set_argument: 15 bad_set_argument: 15
], ],
bad_instruction: [ bad_instruction: [
unknown_instruction: 0, unknown_instruction: 0,
unsupported_instruction: 1, unsupported_instruction: 1,
@ -193,7 +179,6 @@ defmodule Openflow.Enums do
bad_len: 7, bad_len: 7,
eperm: 8 eperm: 8
], ],
bad_match: [ bad_match: [
bad_type: 0, bad_type: 0,
bad_len: 1, bad_len: 1,
@ -208,7 +193,6 @@ defmodule Openflow.Enums do
dup_field: 10, dup_field: 10,
eperm: 11 eperm: 11
], ],
flow_mod_failed: [ flow_mod_failed: [
unknown: 0, unknown: 0,
table_full: 1, table_full: 1,
@ -219,7 +203,6 @@ defmodule Openflow.Enums do
bad_command: 6, bad_command: 6,
bad_flags: 7 bad_flags: 7
], ],
group_mod_failed: [ group_mod_failed: [
group_exists: 0, group_exists: 0,
invalid_group: 1, invalid_group: 1,
@ -237,7 +220,6 @@ defmodule Openflow.Enums do
bad_watch: 13, bad_watch: 13,
eperm: 14 eperm: 14
], ],
port_mod_failed: [ port_mod_failed: [
bad_port: 0, bad_port: 0,
bad_hw_addr: 1, bad_hw_addr: 1,
@ -245,31 +227,26 @@ defmodule Openflow.Enums do
bad_advertise: 3, bad_advertise: 3,
eperm: 4 eperm: 4
], ],
table_mod_failed: [ table_mod_failed: [
bad_table: 0, bad_table: 0,
bad_config: 1, bad_config: 1,
eperm: 2 eperm: 2
], ],
queue_op_failed: [ queue_op_failed: [
bad_port: 0, bad_port: 0,
bad_queue: 1, bad_queue: 1,
eperm: 2 eperm: 2
], ],
switch_config_failed: [ switch_config_failed: [
bad_flags: 0, bad_flags: 0,
bad_len: 1, bad_len: 1,
eperm: 2 eperm: 2
], ],
role_request_failed: [ role_request_failed: [
stale: 0, stale: 0,
unsup: 1, unsup: 1,
bad_role: 2 bad_role: 2
], ],
meter_mod_failed: [ meter_mod_failed: [
unknown: 0, unknown: 0,
meter_exists: 1, meter_exists: 1,
@ -284,7 +261,6 @@ defmodule Openflow.Enums do
out_of_meters: 10, out_of_meters: 10,
out_of_bands: 11 out_of_bands: 11
], ],
table_features_failed: [ table_features_failed: [
bad_table: 0, bad_table: 0,
bad_metadata: 1, bad_metadata: 1,
@ -293,7 +269,6 @@ defmodule Openflow.Enums do
bad_argument: 4, bad_argument: 4,
eperm: 5 eperm: 5
], ],
switch_capabilities: [ switch_capabilities: [
flow_stats: 1 <<< 0, flow_stats: 1 <<< 0,
table_stats: 1 <<< 1, table_stats: 1 <<< 1,
@ -304,36 +279,30 @@ defmodule Openflow.Enums do
arp_match_ip: 1 <<< 7, arp_match_ip: 1 <<< 7,
port_blocked: 1 <<< 8 port_blocked: 1 <<< 8
], ],
config_flags: [ config_flags: [
drop: 1 <<< 0, drop: 1 <<< 0,
reasm: 1 <<< 1 reasm: 1 <<< 1
], ],
controller_max_len: [ controller_max_len: [
max: 0xffe5, max: 0xFFE5,
no_buffer: 0xffff no_buffer: 0xFFFF
], ],
experimenter_oxm_vendors: [ experimenter_oxm_vendors: [
nicira_ext_match: 0x00002320, nicira_ext_match: 0x00002320,
hp_ext_match: 0x00002428, hp_ext_match: 0x00002428,
onf_ext_match: 0x4f4e4600 onf_ext_match: 0x4F4E4600
], ],
match_type: [ match_type: [
standard: 0, standard: 0,
oxm: 1 oxm: 1
], ],
oxm_class: [ oxm_class: [
nxm_0: 0x0000, nxm_0: 0x0000,
nxm_1: 0x0001, nxm_1: 0x0001,
openflow_basic: 0x8000, openflow_basic: 0x8000,
packet_register: 0x8001, packet_register: 0x8001,
experimenter: 0xffff experimenter: 0xFFFF
], ],
nxm_0: [ nxm_0: [
nx_in_port: 0, nx_in_port: 0,
nx_eth_dst: 1, nx_eth_dst: 1,
@ -353,9 +322,8 @@ defmodule Openflow.Enums do
nx_arp_op: 15, nx_arp_op: 15,
nx_arp_spa: 16, nx_arp_spa: 16,
nx_arp_tpa: 17, nx_arp_tpa: 17,
nx_tcp_flags: 34, nx_tcp_flags: 34
], ],
nxm_1: [ nxm_1: [
reg0: 0, reg0: 0,
reg1: 1, reg1: 1,
@ -483,7 +451,6 @@ defmodule Openflow.Enums do
ct_tp_src: 124, ct_tp_src: 124,
ct_tp_dst: 125 ct_tp_dst: 125
], ],
openflow_basic: [ openflow_basic: [
in_port: 0, in_port: 0,
in_phy_port: 1, in_phy_port: 1,
@ -555,12 +522,10 @@ defmodule Openflow.Enums do
gtpu_extn_udp_port: 66, gtpu_extn_udp_port: 66,
gtpu_extn_sci: 67 gtpu_extn_sci: 67
], ],
vlan_id: [ vlan_id: [
present: 0x1000, present: 0x1000,
none: 0x0000 none: 0x0000
], ],
ipv6exthdr_flags: [ ipv6exthdr_flags: [
nonext: 1 <<< 0, nonext: 1 <<< 0,
esp: 1 <<< 1, esp: 1 <<< 1,
@ -572,7 +537,6 @@ defmodule Openflow.Enums do
unrep: 1 <<< 7, unrep: 1 <<< 7,
unseq: 1 <<< 8 unseq: 1 <<< 8
], ],
tcp_flags: [ tcp_flags: [
fin: 1 <<< 0, fin: 1 <<< 0,
syn: 1 <<< 1, syn: 1 <<< 1,
@ -584,18 +548,24 @@ defmodule Openflow.Enums do
cwr: 1 <<< 7, cwr: 1 <<< 7,
ns: 1 <<< 8 ns: 1 <<< 8
], ],
ct_state_flags: [ ct_state_flags: [
new: 1 <<< 0, # Beginning of a new connection. # Beginning of a new connection.
est: 1 <<< 1, # Part of an existing connection. new: 1 <<< 0,
rel: 1 <<< 2, # Related to an established connection. # Part of an existing connection.
rep: 1 <<< 3, # Flow is in the reply direction. est: 1 <<< 1,
inv: 1 <<< 4, # Could not track connection. # Related to an established connection.
trk: 1 <<< 5, # Conntrack has occurred. rel: 1 <<< 2,
snat: 1 <<< 6, # Packet's source address/port was mangled by NAT. # Flow is in the reply direction.
dnat: 1 <<< 7 # Packet's destination address/port was mangled by NAT. rep: 1 <<< 3,
# Could not track connection.
inv: 1 <<< 4,
# Conntrack has occurred.
trk: 1 <<< 5,
# Packet's source address/port was mangled by NAT.
snat: 1 <<< 6,
# Packet's destination address/port was mangled by NAT.
dnat: 1 <<< 7
], ],
packet_register: [ packet_register: [
xreg0: 0, xreg0: 0,
xreg1: 1, xreg1: 1,
@ -606,7 +576,6 @@ defmodule Openflow.Enums do
xreg6: 6, xreg6: 6,
xreg7: 7 xreg7: 7
], ],
nicira_ext_match: [ nicira_ext_match: [
nsh_flags: 1, nsh_flags: 1,
nsh_mdtype: 2, nsh_mdtype: 2,
@ -618,7 +587,6 @@ defmodule Openflow.Enums do
nsh_c3: 8, nsh_c3: 8,
nsh_c4: 9 nsh_c4: 9
], ],
hp_ext_match: [ hp_ext_match: [
hp_udp_src_port_range: 0, hp_udp_src_port_range: 0,
hp_udp_dst_port_range: 1, hp_udp_dst_port_range: 1,
@ -630,42 +598,35 @@ defmodule Openflow.Enums do
hp_custom_3: 7, hp_custom_3: 7,
hp_custom_4: 8 hp_custom_4: 8
], ],
hp_custom_match_type: [ hp_custom_match_type: [
l2_start: 1, l2_start: 1,
l3_start: 2, l3_start: 2,
l4_start: 3 l4_start: 3
], ],
onf_ext_match: [ onf_ext_match: [
onf_tcp_flags: 42, onf_tcp_flags: 42,
onf_actset_output: 43, onf_actset_output: 43,
onf_pbb_uca: 2560, onf_pbb_uca: 2560
], ],
packet_in_reason: [ packet_in_reason: [
no_match: 0, no_match: 0,
action: 1, action: 1,
invalid_ttl: 2 invalid_ttl: 2
], ],
buffer_id: [ buffer_id: [
no_buffer: 0xffffffff no_buffer: 0xFFFFFFFF
], ],
port_config: [ port_config: [
port_down: 1 <<< 0, port_down: 1 <<< 0,
no_receive: 1 <<< 2, no_receive: 1 <<< 2,
no_forward: 1 <<< 5, no_forward: 1 <<< 5,
no_packet_in: 1 <<< 6 no_packet_in: 1 <<< 6
], ],
port_state: [ port_state: [
link_down: 1 <<< 0, link_down: 1 <<< 0,
blocked: 1 <<< 1, blocked: 1 <<< 1,
live: 1 <<< 2 live: 1 <<< 2
], ],
port_features: [ port_features: [
{:"10mb_hd", 1 <<< 0}, {:"10mb_hd", 1 <<< 0},
{:"10mb_fd", 1 <<< 1}, {:"10mb_fd", 1 <<< 1},
@ -684,31 +645,28 @@ defmodule Openflow.Enums do
{:pause, 1 <<< 14}, {:pause, 1 <<< 14},
{:pause_asym, 1 <<< 15} {:pause_asym, 1 <<< 15}
], ],
openflow10_port_no: [ openflow10_port_no: [
max: 0xff00, max: 0xFF00,
in_port: 0xfff8, in_port: 0xFFF8,
table: 0xfff9, table: 0xFFF9,
normal: 0xfffa, normal: 0xFFFA,
flood: 0xfffb, flood: 0xFFFB,
all: 0xfffc, all: 0xFFFC,
controller: 0xfffd, controller: 0xFFFD,
local: 0xfffe, local: 0xFFFE,
none: 0xffff none: 0xFFFF
], ],
openflow13_port_no: [ openflow13_port_no: [
max: 0xffffff00, max: 0xFFFFFF00,
in_port: 0xfffffff8, in_port: 0xFFFFFFF8,
table: 0xfffffff9, table: 0xFFFFFFF9,
normal: 0xfffffffa, normal: 0xFFFFFFFA,
flood: 0xfffffffb, flood: 0xFFFFFFFB,
all: 0xfffffffc, all: 0xFFFFFFFC,
controller: 0xfffffffd, controller: 0xFFFFFFFD,
local: 0xfffffffe, local: 0xFFFFFFFE,
any: 0xffffffff any: 0xFFFFFFFF
], ],
packet_in_reason: [ packet_in_reason: [
no_match: 0, no_match: 0,
action: 1, action: 1,
@ -717,7 +675,6 @@ defmodule Openflow.Enums do
group: 4, group: 4,
packet_out: 5 packet_out: 5
], ],
flow_mod_command: [ flow_mod_command: [
add: 0, add: 0,
modify: 1, modify: 1,
@ -725,7 +682,6 @@ defmodule Openflow.Enums do
delete: 3, delete: 3,
delete_strict: 4 delete_strict: 4
], ],
flow_mod_flags: [ flow_mod_flags: [
send_flow_rem: 1 <<< 0, send_flow_rem: 1 <<< 0,
check_overlap: 1 <<< 1, check_overlap: 1 <<< 1,
@ -733,7 +689,6 @@ defmodule Openflow.Enums do
no_packet_counts: 1 <<< 3, no_packet_counts: 1 <<< 3,
no_byte_counts: 1 <<< 4 no_byte_counts: 1 <<< 4
], ],
flow_removed_reason: [ flow_removed_reason: [
idle_timeout: 0, idle_timeout: 0,
hard_timeout: 1, hard_timeout: 1,
@ -742,74 +697,62 @@ defmodule Openflow.Enums do
meter_delete: 4, meter_delete: 4,
eviction: 5 eviction: 5
], ],
port_reason: [ port_reason: [
add: 0, add: 0,
delete: 1, delete: 1,
modify: 2 modify: 2
], ],
group_mod_command: [ group_mod_command: [
add: 0, add: 0,
modify: 1, modify: 1,
delete: 2 delete: 2
], ],
group_type: [ group_type: [
all: 0, all: 0,
select: 1, select: 1,
indirect: 2, indirect: 2,
fast_failover: 3 fast_failover: 3
], ],
group_id: [ group_id: [
max: 0xffffff00, max: 0xFFFFFF00,
all: 0xfffffffc, all: 0xFFFFFFFC,
any: 0xffffffff any: 0xFFFFFFFF
], ],
group_capabilities: [ group_capabilities: [
select_weight: 1 <<< 0, select_weight: 1 <<< 0,
select_liveness: 1 <<< 1, select_liveness: 1 <<< 1,
chaining: 1 <<< 2, chaining: 1 <<< 2,
chaining_checks: 1 <<< 3 chaining_checks: 1 <<< 3
], ],
table_id: [ table_id: [
max: 0xfe, max: 0xFE,
all: 0xff all: 0xFF
], ],
queue_id: [ queue_id: [
all: 0xffffffff all: 0xFFFFFFFF
], ],
meter_mod_command: [ meter_mod_command: [
add: 0, add: 0,
modify: 1, modify: 1,
delete: 2 delete: 2
], ],
meter_id: [ meter_id: [
max: 0xffff0000, max: 0xFFFF0000,
slowpath: 0xfffffffd, slowpath: 0xFFFFFFFD,
controller: 0xfffffffe, controller: 0xFFFFFFFE,
all: 0xffffffff all: 0xFFFFFFFF
], ],
meter_flags: [ meter_flags: [
kbps: 1 <<< 0, kbps: 1 <<< 0,
pktps: 1 <<< 1, pktps: 1 <<< 1,
burst: 1 <<< 2, burst: 1 <<< 2,
stats: 1 <<< 3 stats: 1 <<< 3
], ],
meter_band_type: [ meter_band_type: [
{Openflow.MeterBand.Drop, 1}, {Openflow.MeterBand.Drop, 1},
{Openflow.MeterBand.Remark, 2}, {Openflow.MeterBand.Remark, 2},
{Openflow.MeterBand.Experimenter, 0xffff}, {Openflow.MeterBand.Experimenter, 0xFFFF}
], ],
table_config: [ table_config: [
table_miss_controller: 0 <<< 0, table_miss_controller: 0 <<< 0,
table_miss_continue: 1 <<< 0, table_miss_continue: 1 <<< 0,
@ -818,7 +761,6 @@ defmodule Openflow.Enums do
eviction: 1 <<< 2, eviction: 1 <<< 2,
vacancy_events: 1 <<< 3 vacancy_events: 1 <<< 3
], ],
action_type: [ action_type: [
{Openflow.Action.Output, 0}, {Openflow.Action.Output, 0},
{Openflow.Action.CopyTtlOut, 11}, {Openflow.Action.CopyTtlOut, 11},
@ -840,18 +782,15 @@ defmodule Openflow.Enums do
{Openflow.Action.Decap, 29}, {Openflow.Action.Decap, 29},
{Openflow.Action.SetSequence, 30}, {Openflow.Action.SetSequence, 30},
{Openflow.Action.ValidateSequence, 31}, {Openflow.Action.ValidateSequence, 31},
{Openflow.Action.Experimenter, 0xffff} {Openflow.Action.Experimenter, 0xFFFF}
], ],
action_vendor: [ action_vendor: [
nicira_ext_action: 0x00002320, nicira_ext_action: 0x00002320,
onf_ext_action: 0x4f4e4600 onf_ext_action: 0x4F4E4600
], ],
onf_ext_action: [ onf_ext_action: [
{Openflow.Action.OnfCopyField, 3200} {Openflow.Action.OnfCopyField, 3200}
], ],
nicira_ext_action: [ nicira_ext_action: [
{Openflow.Action.NxResubmit, 1}, {Openflow.Action.NxResubmit, 1},
{Openflow.Action.NxSetTunnel, 2}, {Openflow.Action.NxSetTunnel, 2},
@ -898,41 +837,35 @@ defmodule Openflow.Enums do
{Openflow.Action.NxLearn2, 45}, {Openflow.Action.NxLearn2, 45},
{Openflow.Action.NxEncap, 46}, {Openflow.Action.NxEncap, 46},
{Openflow.Action.NxDecap, 47}, {Openflow.Action.NxDecap, 47},
{Openflow.Action.NxDebugRecirc, 0xff}, {Openflow.Action.NxDebugRecirc, 0xFF}
], ],
nx_mp_algorithm: [ nx_mp_algorithm: [
modulo_n: 0, modulo_n: 0,
hash_threshold: 1, hash_threshold: 1,
highest_random_weight: 2, highest_random_weight: 2,
iterative_hash: 3 iterative_hash: 3
], ],
nx_hash_fields: [ nx_hash_fields: [
eth_src: 0, eth_src: 0,
symmetric_l4: 1, symmetric_l4: 1,
symmetric_l3l4: 2, symmetric_l3l4: 2,
symmetric_l3l4_udp: 3, symmetric_l3l4_udp: 3,
nw_src: 4, nw_src: 4,
nw_dst: 5, nw_dst: 5
], ],
nx_bd_algorithm: [ nx_bd_algorithm: [
active_backup: 0, active_backup: 0,
highest_random_weight: 1 highest_random_weight: 1
], ],
nx_learn_flag: [ nx_learn_flag: [
send_flow_rem: 1 <<< 0, send_flow_rem: 1 <<< 0,
delete_learned: 1 <<< 1, delete_learned: 1 <<< 1,
write_result: 1 <<< 2 write_result: 1 <<< 2
], ],
nx_conntrack_flags: [ nx_conntrack_flags: [
commit: 1 <<< 0, commit: 1 <<< 0,
force: 1 <<< 1 force: 1 <<< 1
], ],
nx_nat_flags: [ nx_nat_flags: [
src: 1 <<< 0, src: 1 <<< 0,
dst: 1 <<< 1, dst: 1 <<< 1,
@ -940,7 +873,6 @@ defmodule Openflow.Enums do
protocol_hash: 1 <<< 3, protocol_hash: 1 <<< 3,
protocol_random: 1 <<< 4 protocol_random: 1 <<< 4
], ],
nx_nat_range: [ nx_nat_range: [
ipv4_min: 1 <<< 0, ipv4_min: 1 <<< 0,
ipv4_max: 1 <<< 1, ipv4_max: 1 <<< 1,
@ -949,7 +881,6 @@ defmodule Openflow.Enums do
proto_min: 1 <<< 4, proto_min: 1 <<< 4,
proto_max: 1 <<< 5 proto_max: 1 <<< 5
], ],
nx_action_controller2_prop_type: [ nx_action_controller2_prop_type: [
max_len: 0, max_len: 0,
controller_id: 1, controller_id: 1,
@ -957,19 +888,16 @@ defmodule Openflow.Enums do
userdata: 3, userdata: 3,
pause: 4 pause: 4
], ],
nx_action_sample_direction: [ nx_action_sample_direction: [
default: 0, default: 0,
ingress: 1, ingress: 1,
egress: 2 egress: 2
], ],
nx_flow_spec_type: [ nx_flow_spec_type: [
{Openflow.Action.NxFlowSpecMatch, 0}, {Openflow.Action.NxFlowSpecMatch, 0},
{Openflow.Action.NxFlowSpecLoad, 1}, {Openflow.Action.NxFlowSpecLoad, 1},
{Openflow.Action.NxFlowSpecOutput, 2} {Openflow.Action.NxFlowSpecOutput, 2}
], ],
instruction_type: [ instruction_type: [
{Openflow.Instruction.GotoTable, 1}, {Openflow.Instruction.GotoTable, 1},
{Openflow.Instruction.WriteMetadata, 2}, {Openflow.Instruction.WriteMetadata, 2},
@ -977,33 +905,28 @@ defmodule Openflow.Enums do
{Openflow.Instruction.ApplyActions, 4}, {Openflow.Instruction.ApplyActions, 4},
{Openflow.Instruction.ClearActions, 5}, {Openflow.Instruction.ClearActions, 5},
{Openflow.Instruction.Meter, 6}, {Openflow.Instruction.Meter, 6},
{Openflow.Instruction.Experimenter, 0xffff} {Openflow.Instruction.Experimenter, 0xFFFF}
], ],
controller_role: [ controller_role: [
nochange: 0, nochange: 0,
equal: 1, equal: 1,
master: 2, master: 2,
slave: 3 slave: 3
], ],
nx_role: [ nx_role: [
other: 0, other: 0,
master: 1, master: 1,
slave: 2 slave: 2
], ],
packet_in_format: [ packet_in_format: [
standard: 0, standard: 0,
nxt_packet_in: 1, nxt_packet_in: 1,
nxt_packet_in2: 2 nxt_packet_in2: 2
], ],
flow_format: [ flow_format: [
openflow10: 0, openflow10: 0,
nxm: 1 nxm: 1
], ],
packet_in2_prop_type: [ packet_in2_prop_type: [
packet: 0, packet: 0,
full_len: 1, full_len: 1,
@ -1015,7 +938,6 @@ defmodule Openflow.Enums do
userdata: 7, userdata: 7,
continuation: 8 continuation: 8
], ],
continuation_prop_type: [ continuation_prop_type: [
bridge: 0x8000, bridge: 0x8000,
stack: 0x8001, stack: 0x8001,
@ -1026,7 +948,6 @@ defmodule Openflow.Enums do
actions: 0x8006, actions: 0x8006,
action_set: 0x8007 action_set: 0x8007
], ],
flow_monitor_flag: [ flow_monitor_flag: [
initial: 1 <<< 0, initial: 1 <<< 0,
add: 1 <<< 1, add: 1 <<< 1,
@ -1035,20 +956,17 @@ defmodule Openflow.Enums do
actions: 1 <<< 4, actions: 1 <<< 4,
own: 1 <<< 5 own: 1 <<< 5
], ],
flow_update_event: [ flow_update_event: [
added: 0, added: 0,
deleted: 1, deleted: 1,
modified: 2, modified: 2,
abbrev: 3 abbrev: 3
], ],
tlv_table_mod_command: [ tlv_table_mod_command: [
add: 0, add: 0,
delete: 1, delete: 1,
clear: 2 clear: 2
], ],
table_feature_prop_type: [ table_feature_prop_type: [
instructions: 0, instructions: 0,
instructions_miss: 1, instructions_miss: 1,
@ -1064,8 +982,8 @@ defmodule Openflow.Enums do
write_setfield_miss: 13, write_setfield_miss: 13,
apply_setfield: 14, apply_setfield: 14,
apply_setfield_miss: 15, apply_setfield_miss: 15,
experimenter: 0xfffe, experimenter: 0xFFFE,
experimenter_miss: 0xffff experimenter_miss: 0xFFFF
] ]
] ]

View file

@ -9,16 +9,19 @@ defmodule Openflow.ErrorMsg do
data: "", data: "",
exp_type: nil, exp_type: nil,
experimenter: nil, experimenter: nil,
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__
def ofp_type, do: 1 def ofp_type, do: 1
def read(<<0xffff::16, exp_type::16, experimenter::32, data::bytes>>) do def read(<<0xFFFF::16, exp_type::16, experimenter::32, data::bytes>>) do
error_type = Openflow.Enums.to_atom(0xffff, :error_type) error_type = Openflow.Enums.to_atom(0xFFFF, :error_type)
%ErrorMsg{ %ErrorMsg{
type: error_type, type: error_type,
exp_type: exp_type, exp_type: exp_type,
@ -26,9 +29,11 @@ defmodule Openflow.ErrorMsg do
data: data data: data
} }
end end
def read(<<type::16, code::16, data::bytes>>) do def read(<<type::16, code::16, data::bytes>>) do
error_type = Openflow.Enums.to_atom(type, :error_type) error_type = Openflow.Enums.to_atom(type, :error_type)
error_code = Openflow.Enums.to_atom(code, error_type) error_code = Openflow.Enums.to_atom(code, error_type)
%ErrorMsg{ %ErrorMsg{
type: error_type, type: error_type,
code: error_code, code: error_code,
@ -36,16 +41,17 @@ defmodule Openflow.ErrorMsg do
} }
end end
def to_binary(%ErrorMsg{type: :experimenter, def to_binary(%ErrorMsg{
type: :experimenter,
exp_type: exp_type, exp_type: exp_type,
experimenter: experimenter, experimenter: experimenter,
data: data}) do data: data
}) do
error_type = Openflow.Enums.to_int(:experimenter, :error_type) error_type = Openflow.Enums.to_int(:experimenter, :error_type)
<<error_type::16, exp_type::16, experimenter::32, data::bytes>> <<error_type::16, exp_type::16, experimenter::32, data::bytes>>
end end
def to_binary(%ErrorMsg{type: type,
code: code, def to_binary(%ErrorMsg{type: type, code: code, data: data}) do
data: data}) do
error_type = Openflow.Enums.to_int(type, :error_type) error_type = Openflow.Enums.to_int(type, :error_type)
error_code = Openflow.Enums.to_int(code, type) error_code = Openflow.Enums.to_int(code, type)
<<error_type::16, error_code::16, data::bytes>> <<error_type::16, error_code::16, data::bytes>>

View file

@ -14,9 +14,11 @@ defmodule Openflow.Experimenter do
def ofp_type, do: 4 def ofp_type, do: 4
def new(options) do def new(options) do
%Experimenter{exp_id: Keyword.get(options, :exp_id, 0), %Experimenter{
exp_id: Keyword.get(options, :exp_id, 0),
exp_type: Keyword.get(options, :exp_type, 0), exp_type: Keyword.get(options, :exp_type, 0),
data: Keyword.get(options, :data, "")} data: Keyword.get(options, :data, "")
}
end end
def to_binary(%Experimenter{exp_id: exp_id, exp_type: exp_type, data: data}) do def to_binary(%Experimenter{exp_id: exp_id, exp_type: exp_type, data: data}) do
@ -27,10 +29,12 @@ defmodule Openflow.Experimenter do
case Openflow.Utils.get_enum(exp_id, :experimenter_id) do case Openflow.Utils.get_enum(exp_id, :experimenter_id) do
^exp_id -> ^exp_id ->
%Experimenter{exp_id: exp_id, exp_type: exp_type, data: data} %Experimenter{exp_id: exp_id, exp_type: exp_type, data: data}
experimenter when is_atom(experimenter) -> experimenter when is_atom(experimenter) ->
case Openflow.Utils.get_enum(exp_type, experimenter) do case Openflow.Utils.get_enum(exp_type, experimenter) do
^exp_type -> ^exp_type ->
%Experimenter{exp_id: exp_id, exp_type: exp_type, data: data} %Experimenter{exp_id: exp_id, exp_type: exp_type, data: data}
codec when is_atom(codec) -> codec when is_atom(codec) ->
codec.read(<<exp_id::32, exp_type::32, data::bytes>>) codec.read(<<exp_id::32, exp_type::32, data::bytes>>)
end end

View file

@ -13,10 +13,12 @@ defmodule Openflow.Features.Reply do
def ofp_type, do: 6 def ofp_type, do: 6
def read(<<datapath_id::64-bits, n_buf::32, n_tab::8, def read(
aux_id::8, _pad::16, caps_int::32, _rsv::32>>) do <<datapath_id::64-bits, n_buf::32, n_tab::8, aux_id::8, _pad::16, caps_int::32, _rsv::32>>
) do
dpid = Openflow.Utils.to_hex_string(datapath_id) dpid = Openflow.Utils.to_hex_string(datapath_id)
flags = Openflow.Enums.int_to_flags(caps_int, :switch_capabilities) flags = Openflow.Enums.int_to_flags(caps_int, :switch_capabilities)
%Reply{ %Reply{
datapath_id: dpid, datapath_id: dpid,
n_buffers: n_buf, n_buffers: n_buf,
@ -31,7 +33,8 @@ defmodule Openflow.Features.Reply do
n_buffers: n_buf, n_buffers: n_buf,
n_tables: n_tab, n_tables: n_tab,
aux_id: aux_id, aux_id: aux_id,
capabilities: flags}) do capabilities: flags
}) do
dpid_int = String.to_integer(datapath_id, 16) dpid_int = String.to_integer(datapath_id, 16)
flags_int = Openflow.Enums.flags_to_int(flags, :switch_capabilities) flags_int = Openflow.Enums.flags_to_int(flags, :switch_capabilities)
<<dpid_int::64, n_buf::32, n_tab::8, aux_id::8, 0::16, flags_int::32, 0::32>> <<dpid_int::64, n_buf::32, n_tab::8, aux_id::8, 0::16, flags_int::32, 0::32>>

View file

@ -2,8 +2,10 @@ defmodule Openflow.Features.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__

View file

@ -35,9 +35,11 @@ defmodule Openflow.FlowMod do
out_port = Keyword.get(options, :out_port, :any) out_port = Keyword.get(options, :out_port, :any)
out_group = Keyword.get(options, :out_group, :any) out_group = Keyword.get(options, :out_group, :any)
flags = Keyword.get(options, :flags, []) flags = Keyword.get(options, :flags, [])
match = Keyword.get(options, :match, Openflow.Match.new) match = Keyword.get(options, :match, Openflow.Match.new())
instructions = Keyword.get(options, :instructions, []) instructions = Keyword.get(options, :instructions, [])
%FlowMod{cookie: cookie,
%FlowMod{
cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
priority: priority, priority: priority,
table_id: table_id, table_id: table_id,
@ -49,12 +51,15 @@ defmodule Openflow.FlowMod do
out_group: out_group, out_group: out_group,
flags: flags, flags: flags,
match: match, match: match,
instructions: instructions} instructions: instructions
}
end end
def read(<<cookie::64, cookie_mask::64, table_id_int::8, command_int::8, def read(
idle::16, hard::16, prio::16, buffer_id_int::32, out_port_int::32, <<cookie::64, cookie_mask::64, table_id_int::8, command_int::8, idle::16, hard::16,
out_group_int::32, flags_int::16, _::size(2)-unit(8), rest::bytes>>) do prio::16, buffer_id_int::32, out_port_int::32, out_group_int::32, flags_int::16,
_::size(2)-unit(8), rest::bytes>>
) do
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
command = Openflow.Utils.get_enum(command_int, :flow_mod_command) command = Openflow.Utils.get_enum(command_int, :flow_mod_command)
buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id) buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id)
@ -64,7 +69,9 @@ defmodule Openflow.FlowMod do
{match_fields, instructions_bin} = Openflow.Match.read(rest) {match_fields, instructions_bin} = Openflow.Match.read(rest)
match = Openflow.Match.new(match_fields) match = Openflow.Match.new(match_fields)
instructions = Openflow.Instruction.read(instructions_bin) instructions = Openflow.Instruction.read(instructions_bin)
%FlowMod{cookie: cookie,
%FlowMod{
cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
priority: prio, priority: prio,
table_id: table_id, table_id: table_id,
@ -76,11 +83,13 @@ defmodule Openflow.FlowMod do
out_group: out_group, out_group: out_group,
flags: flags, flags: flags,
match: match, match: match,
instructions: instructions} instructions: instructions
}
end end
def to_binary(flow_mod) do def to_binary(flow_mod) do
%FlowMod{cookie: cookie, %FlowMod{
cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
priority: prio, priority: prio,
table_id: table_id, table_id: table_id,
@ -92,7 +101,9 @@ defmodule Openflow.FlowMod do
out_group: out_group, out_group: out_group,
flags: flags, flags: flags,
match: match_fields, match: match_fields,
instructions: instructions} = flow_mod instructions: instructions
} = flow_mod
table_id_int = Openflow.Utils.get_enum(table_id, :table_id) table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
command_int = Openflow.Utils.get_enum(command, :flow_mod_command) command_int = Openflow.Utils.get_enum(command, :flow_mod_command)
buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id) buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id)
@ -101,9 +112,9 @@ defmodule Openflow.FlowMod do
flags_int = Openflow.Enums.flags_to_int(flags, :flow_mod_flags) flags_int = Openflow.Enums.flags_to_int(flags, :flow_mod_flags)
match_fields_bin = Openflow.Match.to_binary(match_fields) match_fields_bin = Openflow.Match.to_binary(match_fields)
instructions_bin = Openflow.Instruction.to_binary(instructions) instructions_bin = Openflow.Instruction.to_binary(instructions)
<<cookie::64, cookie_mask::64, table_id_int::8, command_int::8,
idle::16, hard::16, prio::16, buffer_id_int::32, out_port_int::32, <<cookie::64, cookie_mask::64, table_id_int::8, command_int::8, idle::16, hard::16, prio::16,
out_group_int::32, flags_int::16, 0::size(2)-unit(8), buffer_id_int::32, out_port_int::32, out_group_int::32, flags_int::16, 0::size(2)-unit(8),
match_fields_bin::bytes, instructions_bin::bytes>> match_fields_bin::bytes, instructions_bin::bytes>>
end end
end end

View file

@ -21,13 +21,16 @@ defmodule Openflow.FlowRemoved do
def ofp_type, do: 11 def ofp_type, do: 11
def read(<<cookie::64, priority::16, reason_int::8, def read(
table_id_int::8, dsec::32, dnsec::32, <<cookie::64, priority::16, reason_int::8, table_id_int::8, dsec::32, dnsec::32, idle::16,
idle::16, hard::16, pkt::64, byt::64, rest::bytes>>) do hard::16, pkt::64, byt::64, rest::bytes>>
) do
reason = Openflow.Enums.to_atom(reason_int, :flow_removed_reason) reason = Openflow.Enums.to_atom(reason_int, :flow_removed_reason)
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
{match_fields, _rest} = Openflow.Match.read(rest) {match_fields, _rest} = Openflow.Match.read(rest)
%FlowRemoved{cookie: cookie,
%FlowRemoved{
cookie: cookie,
priority: priority, priority: priority,
reason: reason, reason: reason,
table_id: table_id, table_id: table_id,
@ -37,6 +40,7 @@ defmodule Openflow.FlowRemoved do
hard_timeout: hard, hard_timeout: hard,
packet_count: pkt, packet_count: pkt,
byte_count: byt, byte_count: byt,
match: match_fields} match: match_fields
}
end end
end end

View file

@ -2,8 +2,10 @@ defmodule Openflow.GetAsync.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
aux_id: 0, # virtual field datapath_id: nil,
# virtual field
aux_id: 0,
packet_in_mask_master: 0, packet_in_mask_master: 0,
packet_in_mask_slave: 0, packet_in_mask_slave: 0,
port_status_mask_master: 0, port_status_mask_master: 0,
@ -16,25 +18,29 @@ defmodule Openflow.GetAsync.Reply do
def ofp_type, do: 27 def ofp_type, do: 27
def read(<<packet_in_mask_master::32, packet_in_mask_slave::32, def read(
port_status_mask_master::32, port_status_mask_slave::32, <<packet_in_mask_master::32, packet_in_mask_slave::32, port_status_mask_master::32,
flow_removed_mask_master::32, flow_removed_mask_slave::32>>) do port_status_mask_slave::32, flow_removed_mask_master::32, flow_removed_mask_slave::32>>
%Reply{packet_in_mask_master: packet_in_mask_master, ) do
%Reply{
packet_in_mask_master: packet_in_mask_master,
packet_in_mask_slave: packet_in_mask_slave, packet_in_mask_slave: packet_in_mask_slave,
port_status_mask_master: port_status_mask_master, port_status_mask_master: port_status_mask_master,
port_status_mask_slave: port_status_mask_slave, port_status_mask_slave: port_status_mask_slave,
flow_removed_mask_master: flow_removed_mask_master, flow_removed_mask_master: flow_removed_mask_master,
flow_removed_mask_slave: flow_removed_mask_slave} flow_removed_mask_slave: flow_removed_mask_slave
}
end end
def to_binary(%Reply{packet_in_mask_master: packet_in_mask_master, def to_binary(%Reply{
packet_in_mask_master: packet_in_mask_master,
packet_in_mask_slave: packet_in_mask_slave, packet_in_mask_slave: packet_in_mask_slave,
port_status_mask_master: port_status_mask_master, port_status_mask_master: port_status_mask_master,
port_status_mask_slave: port_status_mask_slave, port_status_mask_slave: port_status_mask_slave,
flow_removed_mask_master: flow_removed_mask_master, flow_removed_mask_master: flow_removed_mask_master,
flow_removed_mask_slave: flow_removed_mask_slave}) do flow_removed_mask_slave: flow_removed_mask_slave
<<packet_in_mask_master::32, packet_in_mask_slave::32, }) do
port_status_mask_master::32, port_status_mask_slave::32, <<packet_in_mask_master::32, packet_in_mask_slave::32, port_status_mask_master::32,
flow_removed_mask_master::32, flow_removed_mask_slave::32>> port_status_mask_slave::32, flow_removed_mask_master::32, flow_removed_mask_slave::32>>
end end
end end

View file

@ -2,8 +2,10 @@ defmodule Openflow.GetAsync.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__

View file

@ -4,7 +4,8 @@ defmodule Openflow.GetConfig.Reply do
xid: 0, xid: 0,
datapath_id: "", datapath_id: "",
aux_id: 0, aux_id: 0,
flags: [], # default = "normal" is no special handling # default = "normal" is no special handling
flags: [],
miss_send_len: 128 miss_send_len: 128
) )

View file

@ -2,8 +2,10 @@ defmodule Openflow.GetConfig.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
aux_id: 0 # virtual field datapath_id: nil,
# virtual field
aux_id: 0
) )
alias __MODULE__ alias __MODULE__

View file

@ -19,10 +19,7 @@ defmodule Openflow.GroupMod do
type = Keyword.get(options, :type, :all) type = Keyword.get(options, :type, :all)
group_id = Keyword.get(options, :group_id, 0) group_id = Keyword.get(options, :group_id, 0)
buckets = Keyword.get(options, :buckets, []) buckets = Keyword.get(options, :buckets, [])
%GroupMod{command: command, %GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}
type: type,
group_id: group_id,
buckets: buckets}
end end
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
@ -30,16 +27,10 @@ defmodule Openflow.GroupMod do
type = Openflow.Utils.get_enum(type_int, :group_type) type = Openflow.Utils.get_enum(type_int, :group_type)
group_id = Openflow.Utils.get_enum(group_id_int, :group_id) group_id = Openflow.Utils.get_enum(group_id_int, :group_id)
buckets = Openflow.Bucket.read(buckets_bin) buckets = Openflow.Bucket.read(buckets_bin)
%GroupMod{command: command, %GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}
type: type,
group_id: group_id,
buckets: buckets}
end end
def to_binary(%GroupMod{command: command, def to_binary(%GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}) do
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)
group_id_int = Openflow.Utils.get_enum(group_id, :group_id) group_id_int = Openflow.Utils.get_enum(group_id, :group_id)

View file

@ -9,32 +9,32 @@ defmodule Openflow.Hello do
alias __MODULE__ alias __MODULE__
def ofp_type, def ofp_type, do: 0
do: 0
def new(version) when is_integer(version) do def new(version) when is_integer(version) do
%Hello{elements: [versionbitmap: [version]]} %Hello{elements: [versionbitmap: [version]]}
end end
def new(versions) when is_list(versions) do def new(versions) when is_list(versions) do
%Hello{elements: [versionbitmap: versions]} %Hello{elements: [versionbitmap: versions]}
end end
def supported_version?(%Hello{version: 4, elements: []}), do: true def supported_version?(%Hello{version: 4, elements: []}), do: true
def supported_version?(%Hello{elements: []}), do: false def supported_version?(%Hello{elements: []}), do: false
def supported_version?(%Hello{elements: elements}) do def supported_version?(%Hello{elements: elements}) do
versionbitmaps = for {:versionbitmap, versions} <- elements, do: versions versionbitmaps = for {:versionbitmap, versions} <- elements, do: versions
Enum.any?(versionbitmaps, fn(versions) -> 4 in versions end) Enum.any?(versionbitmaps, fn versions -> 4 in versions end)
end end
def read(binary), def read(binary), do: %Hello{elements: decode([], binary)}
do: %Hello{elements: decode([], binary)}
def to_binary(%Hello{elements: elements}), def to_binary(%Hello{elements: elements}), do: encode([], elements)
do: encode([], elements)
# private functions # private functions
defp decode(acc, <<>>), do: acc defp decode(acc, <<>>), do: acc
defp decode(acc, <<typeint::16, length::16, rest::bytes>>) do defp decode(acc, <<typeint::16, length::16, rest::bytes>>) do
data_len = length - @ofp_hello_size data_len = length - @ofp_hello_size
<<data::bytes-size(data_len), rest2::bytes>> = rest <<data::bytes-size(data_len), rest2::bytes>> = rest
@ -50,15 +50,13 @@ defmodule Openflow.Hello do
end end
end end
defp encode(acc, []), defp encode(acc, []), do: to_string(acc)
do: to_string(acc) defp encode(acc, [h | rest]), do: encode([encode_hello_elem(h) | acc], rest)
defp encode(acc, [h|rest]),
do: encode([encode_hello_elem(h)|acc], rest)
defp decode_hello_elem(:versionbitmap, acc, binary), defp decode_hello_elem(:versionbitmap, acc, binary),
do: [{:versionbitmap, decode_bitmap([], binary, 0)}|acc] do: [{:versionbitmap, decode_bitmap([], binary, 0)} | acc]
defp decode_hello_elem(_, acc, _binary),
do: acc defp decode_hello_elem(_, acc, _binary), do: acc
defp encode_hello_elem({:versionbitmap, versions}) do defp encode_hello_elem({:versionbitmap, versions}) do
bitmap_bin = encode_bitmap(versions) bitmap_bin = encode_bitmap(versions)
@ -66,11 +64,13 @@ defmodule Openflow.Hello do
size_int = @ofp_hello_size + byte_size(bitmap_bin) size_int = @ofp_hello_size + byte_size(bitmap_bin)
<<type_int::16, size_int::16, bitmap_bin::bytes>> <<type_int::16, size_int::16, bitmap_bin::bytes>>
end end
defp encode_hello_elem(_) do defp encode_hello_elem(_) do
<<>> <<>>
end end
defp decode_bitmap(acc, "", _), do: acc defp decode_bitmap(acc, "", _), do: acc
defp decode_bitmap(acc, <<int::32, rest::bytes>>, base) do defp decode_bitmap(acc, <<int::32, rest::bytes>>, base) do
acc acc
|> decode_bitmap(int, 0, base) |> decode_bitmap(int, 0, base)
@ -80,24 +80,27 @@ defmodule Openflow.Hello do
defp encode_bitmap(list) do defp encode_bitmap(list) do
size = size =
list list
|> Enum.max |> Enum.max()
|> div(32) |> div(32)
encode_bitmap(0, list, size) encode_bitmap(0, list, size)
end end
defp decode_bitmap(acc, _, index, _) when index >= 32, defp decode_bitmap(acc, _, index, _) when index >= 32, do: acc
do: acc
defp decode_bitmap(acc, int, index, base) when (int &&& (1 <<< index)) == 0, defp decode_bitmap(acc, int, index, base) when (int &&& 1 <<< index) == 0,
do: decode_bitmap(acc, int, index + 1, base) do: decode_bitmap(acc, int, index + 1, base)
defp decode_bitmap(acc, int, index, base), defp decode_bitmap(acc, int, index, base),
do: decode_bitmap([base + index|acc], int, index + 1, base) do: decode_bitmap([base + index | acc], int, index + 1, base)
defp encode_bitmap(acc, [], size) do defp encode_bitmap(acc, [], size) do
bytes = (size + 1) * 32 bytes = (size + 1) * 32
<<acc::size(bytes)>> <<acc::size(bytes)>>
end end
defp encode_bitmap(acc, [h|rest], size) do
index = (size - div(h, 32) * 32 + rem(h, 32)) defp encode_bitmap(acc, [h | rest], size) do
encode_bitmap(acc ||| (1 <<< index), rest, size) index = size - div(h, 32) * 32 + rem(h, 32)
encode_bitmap(acc ||| 1 <<< index, rest, size)
end end
end end

View file

@ -1,5 +1,4 @@
defmodule Openflow.Instruction do defmodule Openflow.Instruction do
def read(instruction_bin) do def read(instruction_bin) do
do_read([], instruction_bin) do_read([], instruction_bin)
end end
@ -7,6 +6,7 @@ defmodule Openflow.Instruction do
def to_binary(instructions) when is_list(instructions) do def to_binary(instructions) when is_list(instructions) do
to_binary(<<>>, instructions) to_binary(<<>>, instructions)
end end
def to_binary(instruction) do def to_binary(instruction) do
to_binary([instruction]) to_binary([instruction])
end end
@ -14,15 +14,17 @@ defmodule Openflow.Instruction do
# private functions # private functions
defp do_read(acc, <<>>), do: Enum.reverse(acc) defp do_read(acc, <<>>), do: Enum.reverse(acc)
defp do_read(acc, <<type::16, length::16, _::bytes>> = binary) do defp do_read(acc, <<type::16, length::16, _::bytes>> = binary) do
<<instruction_bin::size(length)-bytes, rest::bytes>> = binary <<instruction_bin::size(length)-bytes, rest::bytes>> = binary
codec = Openflow.Enums.to_atom(type, :instruction_type) codec = Openflow.Enums.to_atom(type, :instruction_type)
do_read([codec.read(instruction_bin)|acc], rest) do_read([codec.read(instruction_bin) | acc], rest)
end end
defp to_binary(acc, []), do: acc defp to_binary(acc, []), do: acc
defp to_binary(acc, [instruction|rest]) do
defp to_binary(acc, [instruction | rest]) do
codec = instruction.__struct__ codec = instruction.__struct__
to_binary(<<acc::bytes, (codec.to_binary(instruction))::bytes>>, rest) to_binary(<<acc::bytes, codec.to_binary(instruction)::bytes>>, rest)
end end
end end

View file

@ -9,10 +9,10 @@ defmodule Openflow.Instruction.Experimenter do
def to_binary(%Experimenter{exp_id: exp_id, data: data}) do def to_binary(%Experimenter{exp_id: exp_id, data: data}) do
length = 8 + byte_size(data) length = 8 + byte_size(data)
<<0xffff::16, length::16, exp_id::32, data::bytes>> <<0xFFFF::16, length::16, exp_id::32, data::bytes>>
end end
def read(<<0xffff::16, _::16, exp_id::32, data::bytes>>) do def read(<<0xFFFF::16, _::16, exp_id::32, data::bytes>>) do
%Experimenter{exp_id: exp_id, data: data} %Experimenter{exp_id: exp_id, data: data}
end end
end end

View file

@ -1,11 +1,11 @@
defmodule Openflow.Instruction.WriteMetadata do defmodule Openflow.Instruction.WriteMetadata do
defstruct(metadata: 0, metadata_mask: 0xffffffffffffffff) defstruct(metadata: 0, metadata_mask: 0xFFFFFFFFFFFFFFFF)
alias __MODULE__ alias __MODULE__
def new(options) do def new(options) do
metadata = Keyword.get(options, :metadata, 0) metadata = Keyword.get(options, :metadata, 0)
metadata_mask = Keyword.get(options, :metadata_mask, 0xffffffffffffffff) metadata_mask = Keyword.get(options, :metadata_mask, 0xFFFFFFFFFFFFFFFF)
%WriteMetadata{metadata: metadata, metadata_mask: metadata_mask} %WriteMetadata{metadata: metadata, metadata_mask: metadata_mask}
end end

View file

@ -2,10 +2,10 @@ defmodule Openflow.Match do
@match_size 8 @match_size 8
@header_size 4 @header_size 4
defstruct([ defstruct(
type: :oxm, type: :oxm,
fields: [] fields: []
]) )
alias __MODULE__ alias __MODULE__
@ -13,6 +13,7 @@ defmodule Openflow.Match do
oxm_fields = oxm_fields =
fields fields
|> keyword_to_oxm_fields([]) |> keyword_to_oxm_fields([])
%Match{type: :oxm, fields: oxm_fields} %Match{type: :oxm, fields: oxm_fields}
end end
@ -20,7 +21,10 @@ defmodule Openflow.Match do
<<1::16, no_pad_len::16, binary1::binary>> = binary <<1::16, no_pad_len::16, binary1::binary>> = binary
padding_length = Openflow.Utils.pad_length(no_pad_len, 8) padding_length = Openflow.Utils.pad_length(no_pad_len, 8)
match_field_len = no_pad_len - @header_size match_field_len = no_pad_len - @header_size
<<match_fields::size(match_field_len)-binary, _::size(padding_length)-unit(8), rest::bitstring>> = binary1
<<match_fields::size(match_field_len)-binary, _::size(padding_length)-unit(8),
rest::bitstring>> = binary1
{decode_fields(match_fields, []), rest} {decode_fields(match_fields, []), rest}
end end
@ -33,14 +37,17 @@ defmodule Openflow.Match do
end end
def codec_header(oxm_field0) when is_atom(oxm_field0) do def codec_header(oxm_field0) when is_atom(oxm_field0) do
oxm_field = case has_mask(oxm_field0) do oxm_field =
case has_mask(oxm_field0) do
1 -> 1 ->
string = to_string(oxm_field0) string = to_string(oxm_field0)
"masked_" <> field = string "masked_" <> field = string
String.to_atom(field) String.to_atom(field)
0 -> 0 ->
oxm_field0 oxm_field0
end end
case Openflow.Match.Field.vendor_of(oxm_field) do case Openflow.Match.Field.vendor_of(oxm_field) do
oxm_class when oxm_class in [:nxm_0, :nxm_1, :openflow_basic, :packet_register] -> oxm_class when oxm_class in [:nxm_0, :nxm_1, :openflow_basic, :packet_register] ->
oxm_class_int = Openflow.Enums.to_int(oxm_class, :oxm_class) oxm_class_int = Openflow.Enums.to_int(oxm_class, :oxm_class)
@ -48,8 +55,9 @@ defmodule Openflow.Match do
oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field), 8) oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field), 8)
has_mask = has_mask(oxm_field0) has_mask = has_mask(oxm_field0)
<<oxm_class_int::16, oxm_field_int::7, has_mask::1, oxm_length::8>> <<oxm_class_int::16, oxm_field_int::7, has_mask::1, oxm_length::8>>
experimenter when experimenter in [:nicira_ext_match, :onf_ext_match, :hp_ext_match] -> experimenter when experimenter in [:nicira_ext_match, :onf_ext_match, :hp_ext_match] ->
oxm_class_int = 0xffff oxm_class_int = 0xFFFF
experimenter_int = Openflow.Enums.to_int(experimenter, :experimenter_oxm_vendors) experimenter_int = Openflow.Enums.to_int(experimenter, :experimenter_oxm_vendors)
oxm_field_int = Openflow.Enums.to_int(oxm_field, experimenter) oxm_field_int = Openflow.Enums.to_int(oxm_field, experimenter)
oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field) + 4, 8) oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field) + 4, 8)
@ -57,41 +65,63 @@ defmodule Openflow.Match do
<<oxm_class_int::16, oxm_field_int::7, has_mask::1, oxm_length::8, experimenter_int::32>> <<oxm_class_int::16, oxm_field_int::7, has_mask::1, oxm_length::8, experimenter_int::32>>
end end
end end
def codec_header(<<oxm_class_int::16, oxm_field_int::7, oxm_has_mask::1, _oxm_length::8>>) do def codec_header(<<oxm_class_int::16, oxm_field_int::7, oxm_has_mask::1, _oxm_length::8>>) do
oxm_class = Openflow.Enums.to_atom(oxm_class_int, :oxm_class) oxm_class = Openflow.Enums.to_atom(oxm_class_int, :oxm_class)
case oxm_has_mask do case oxm_has_mask do
0 -> Openflow.Enums.to_atom(oxm_field_int, oxm_class) 0 ->
Openflow.Enums.to_atom(oxm_field_int, oxm_class)
1 -> 1 ->
field_str = field_str =
oxm_field_int oxm_field_int
|> Openflow.Enums.to_atom(oxm_class) |> Openflow.Enums.to_atom(oxm_class)
|> to_string |> to_string
String.to_atom("masked_" <> field_str) String.to_atom("masked_" <> field_str)
end end
end end
def codec_header(<<0xffff::16, oxm_field_int::7, oxm_has_mask::1, _oxm_length::8, experimenter_int::32>>) do
def codec_header(
<<0xFFFF::16, oxm_field_int::7, oxm_has_mask::1, _oxm_length::8, experimenter_int::32>>
) do
experimenter = Openflow.Enums.to_atom(experimenter_int, :experimenter_oxm_vendors) experimenter = Openflow.Enums.to_atom(experimenter_int, :experimenter_oxm_vendors)
Openflow.Enums.to_atom(oxm_field_int, experimenter) Openflow.Enums.to_atom(oxm_field_int, experimenter)
case oxm_has_mask do case oxm_has_mask do
0 -> Openflow.Enums.to_atom(oxm_field_int, experimenter) 0 ->
Openflow.Enums.to_atom(oxm_field_int, experimenter)
1 -> 1 ->
field_str = field_str =
oxm_field_int oxm_field_int
|> Openflow.Enums.to_atom(experimenter) |> Openflow.Enums.to_atom(experimenter)
|> to_string |> to_string
String.to_atom("masked_" <> field_str) String.to_atom("masked_" <> field_str)
end end
end end
def header_size(<<_oxm_class_int::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _::bytes>>), def header_size(
<<_oxm_class_int::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _::bytes>>
),
do: 4 do: 4
def header_size(<<0xffff::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _exp_int::32, _::bytes>>),
def header_size(
<<0xFFFF::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _exp_int::32,
_::bytes>>
),
do: 8 do: 8
# private functions # private functions
defp decode_fields(<<>>, acc), do: Enum.reverse(acc) defp decode_fields(<<>>, acc), do: Enum.reverse(acc)
defp decode_fields(<<0xffff::16, _::7, 1::1, length::8, vendor_int::32, field_int::16, binary::bytes>>, acc) do
defp decode_fields(
<<0xFFFF::16, _::7, 1::1, length::8, vendor_int::32, field_int::16, binary::bytes>>,
acc
) do
length = length - 6 length = length - 6
field_len = div(length, 2) field_len = div(length, 2)
<<value_bin::size(field_len)-bytes, mask_bin::size(field_len)-bytes, rest::bytes>> = binary <<value_bin::size(field_len)-bytes, mask_bin::size(field_len)-bytes, rest::bytes>> = binary
@ -99,16 +129,21 @@ defmodule Openflow.Match do
field_name = Openflow.Enums.to_atom(field_int, experimenter) field_name = Openflow.Enums.to_atom(field_int, experimenter)
value = Openflow.Match.Field.codec(value_bin, field_name) value = Openflow.Match.Field.codec(value_bin, field_name)
mask = Openflow.Match.Field.codec(mask_bin, field_name) mask = Openflow.Match.Field.codec(mask_bin, field_name)
decode_fields(rest, [{field_name, {value, mask}}|acc]) decode_fields(rest, [{field_name, {value, mask}} | acc])
end end
defp decode_fields(<<0xffff::16, _::7, 0::1, length::8, vendor_int::32, field_int::16, binary::bytes>>, acc) do
defp decode_fields(
<<0xFFFF::16, _::7, 0::1, length::8, vendor_int::32, field_int::16, binary::bytes>>,
acc
) do
length = length - 6 length = length - 6
<<value_bin::size(length)-bytes, rest::bytes>> = binary <<value_bin::size(length)-bytes, rest::bytes>> = binary
experimenter = Openflow.Enums.to_atom(vendor_int, :experimenter_oxm_vendors) experimenter = Openflow.Enums.to_atom(vendor_int, :experimenter_oxm_vendors)
field_name = Openflow.Enums.to_atom(field_int, experimenter) field_name = Openflow.Enums.to_atom(field_int, experimenter)
value = Openflow.Match.Field.codec(value_bin, field_name) value = Openflow.Match.Field.codec(value_bin, field_name)
decode_fields(rest, [{field_name, value}|acc]) decode_fields(rest, [{field_name, value} | acc])
end end
defp decode_fields(<<class_int::16, field_int::7, 1::1, length::8, binary::bytes>>, acc) do defp decode_fields(<<class_int::16, field_int::7, 1::1, length::8, binary::bytes>>, acc) do
field_len = div(length, 2) field_len = div(length, 2)
<<value_bin::size(field_len)-bytes, mask_bin::size(field_len)-bytes, rest::bytes>> = binary <<value_bin::size(field_len)-bytes, mask_bin::size(field_len)-bytes, rest::bytes>> = binary
@ -116,19 +151,21 @@ defmodule Openflow.Match do
field_name = Openflow.Enums.to_atom(field_int, class) field_name = Openflow.Enums.to_atom(field_int, class)
value = Openflow.Match.Field.codec(value_bin, field_name) value = Openflow.Match.Field.codec(value_bin, field_name)
mask = Openflow.Match.Field.codec(mask_bin, field_name) mask = Openflow.Match.Field.codec(mask_bin, field_name)
decode_fields(rest, [{field_name, {value, mask}}|acc]) decode_fields(rest, [{field_name, {value, mask}} | acc])
end end
defp decode_fields(<<class_int::16, field_int::7, 0::1, length::8, binary::bytes>>, acc) do defp decode_fields(<<class_int::16, field_int::7, 0::1, length::8, binary::bytes>>, acc) do
<<value_bin::size(length)-bytes, rest::bytes>> = binary <<value_bin::size(length)-bytes, rest::bytes>> = binary
class = Openflow.Enums.to_atom(class_int, :oxm_class) class = Openflow.Enums.to_atom(class_int, :oxm_class)
field_name = Openflow.Enums.to_atom(field_int, class) field_name = Openflow.Enums.to_atom(field_int, class)
value = Openflow.Match.Field.codec(value_bin, field_name) value = Openflow.Match.Field.codec(value_bin, field_name)
decode_fields(rest, [{field_name, value}|acc]) decode_fields(rest, [{field_name, value} | acc])
end end
defp encode_fields([], acc), do: acc defp encode_fields([], acc), do: acc
defp encode_fields([field|fields], acc) do
encode_fields(fields, <<acc::bytes, (encode_field(field))::bytes>>) defp encode_fields([field | fields], acc) do
encode_fields(fields, <<acc::bytes, encode_field(field)::bytes>>)
end end
defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask}) defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask})
@ -136,17 +173,21 @@ defmodule Openflow.Match do
vendor_int = Openflow.Enums.to_int(class, :experimenter_oxm_vendors) vendor_int = Openflow.Enums.to_int(class, :experimenter_oxm_vendors)
field_int = Openflow.Enums.to_int(field, class) field_int = Openflow.Enums.to_int(field, class)
has_mask_int = 1 has_mask_int = 1
length = (byte_size(value) * 2) + 6 length = byte_size(value) * 2 + 6
<<0xffff::16, 0::7, has_mask_int::1, length::8, vendor_int::32, field_int::16, value::bytes, mask::bytes>>
<<0xFFFF::16, 0::7, has_mask_int::1, length::8, vendor_int::32, field_int::16, value::bytes,
mask::bytes>>
end end
defp encode_field(%{class: class, field: field, has_mask: false, value: value}) defp encode_field(%{class: class, field: field, has_mask: false, value: value})
when class == :nicira_ext_match or class == :onf_ext_match do when class == :nicira_ext_match or class == :onf_ext_match do
vendor_int = Openflow.Enums.to_int(class, :experimenter_oxm_vendors) vendor_int = Openflow.Enums.to_int(class, :experimenter_oxm_vendors)
field_int = Openflow.Enums.to_int(field, class) field_int = Openflow.Enums.to_int(field, class)
has_mask_int = 0 has_mask_int = 0
length = byte_size(value) + 6 length = byte_size(value) + 6
<<0xffff::16, 0::7, has_mask_int::1, length::8, vendor_int::32, field_int::16, value::bytes>> <<0xFFFF::16, 0::7, has_mask_int::1, length::8, vendor_int::32, field_int::16, value::bytes>>
end end
defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask}) do defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask}) do
class_int = Openflow.Enums.to_int(class, :oxm_class) class_int = Openflow.Enums.to_int(class, :oxm_class)
field_int = Openflow.Enums.to_int(field, class) field_int = Openflow.Enums.to_int(field, class)
@ -154,6 +195,7 @@ defmodule Openflow.Match do
length = byte_size(value) * 2 length = byte_size(value) * 2
<<class_int::16, field_int::7, has_mask_int::1, length::8, value::bytes, mask::bytes>> <<class_int::16, field_int::7, has_mask_int::1, length::8, value::bytes, mask::bytes>>
end end
defp encode_field(%{class: class, field: field, has_mask: false, value: value}) do defp encode_field(%{class: class, field: field, has_mask: false, value: value}) do
class_int = Openflow.Enums.to_int(class, :oxm_class) class_int = Openflow.Enums.to_int(class, :oxm_class)
field_int = Openflow.Enums.to_int(field, class) field_int = Openflow.Enums.to_int(field, class)
@ -163,8 +205,9 @@ defmodule Openflow.Match do
end end
defp keyword_to_oxm_fields([], acc), do: Enum.reverse(acc) defp keyword_to_oxm_fields([], acc), do: Enum.reverse(acc)
defp keyword_to_oxm_fields([{field_name, field_value}|fields], acc) do
keyword_to_oxm_fields(fields, [oxm_field(field_name, field_value)|acc]) defp keyword_to_oxm_fields([{field_name, field_value} | fields], acc) do
keyword_to_oxm_fields(fields, [oxm_field(field_name, field_value) | acc])
end end
defp oxm_field(field_name, {value, mask}) do defp oxm_field(field_name, {value, mask}) do
@ -173,6 +216,7 @@ defmodule Openflow.Match do
match_class = Openflow.Match.Field.vendor_of(field_name) match_class = Openflow.Match.Field.vendor_of(field_name)
%{class: match_class, field: field_name, has_mask: true, value: value_bin, mask: mask_bin} %{class: match_class, field: field_name, has_mask: true, value: value_bin, mask: mask_bin}
end end
defp oxm_field(field_name, value) do defp oxm_field(field_name, value) do
value_bin = Openflow.Match.Field.codec(value, field_name) value_bin = Openflow.Match.Field.codec(value, field_name)
match_class = Openflow.Match.Field.vendor_of(field_name) match_class = Openflow.Match.Field.vendor_of(field_name)
@ -184,6 +228,7 @@ defmodule Openflow.Match do
oxm_field oxm_field
|> to_string |> to_string
|> String.match?(~r/^masked_/) |> String.match?(~r/^masked_/)
if has_mask? do if has_mask? do
1 1
else else

View file

@ -1,10 +1,11 @@
defmodule Openflow.Match.Field do defmodule Openflow.Match.Field do
def codec(value0, field) when is_binary(value0) do def codec(value0, field) when is_binary(value0) do
{type, format} = format_of(field) {type, format} = format_of(field)
n_bits = n_bits_of(field) n_bits = n_bits_of(field)
bit_size = bit_size(value0) bit_size = bit_size(value0)
value = if bit_size < n_bits do
value =
if bit_size < n_bits do
head_pad_len = n_bits - bit_size head_pad_len = n_bits - bit_size
<<0::size(head_pad_len), value0::bytes>> <<0::size(head_pad_len), value0::bytes>>
else else
@ -16,8 +17,10 @@ defmodule Openflow.Match.Field do
value0 value0
end end
end end
formatting(value, type, format) formatting(value, type, format)
end end
def codec(value, type) do def codec(value, type) do
{type, format} = format_of(type) {type, format} = format_of(type)
formatting(value, type, format) formatting(value, type, format)
@ -577,17 +580,22 @@ defmodule Openflow.Match.Field do
# Formatting = ethernet # Formatting = ethernet
def formatting(<<value::48-bits>>, :mac, :ethernet), do: Openflow.Utils.to_hex_string(value) def formatting(<<value::48-bits>>, :mac, :ethernet), do: Openflow.Utils.to_hex_string(value)
def formatting(value, :mac, :ethernet), do: <<(String.to_integer(value, 16))::48>> def formatting(value, :mac, :ethernet), do: <<String.to_integer(value, 16)::48>>
# Formatting = IPv4 # Formatting = IPv4
def formatting(<<a1, a2, a3, a4>>, :be32, :ipv4), do: {a1, a2, a3, a4} def formatting(<<a1, a2, a3, a4>>, :be32, :ipv4), do: {a1, a2, a3, a4}
def formatting({a1, a2, a3, a4}, :be32, :ipv4), do: <<a1, a2, a3, a4>> def formatting({a1, a2, a3, a4}, :be32, :ipv4), do: <<a1, a2, a3, a4>>
# Formatting = IPv6 # Formatting = IPv6
def formatting(<<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>, :be128, :ipv6) do def formatting(
<<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>,
:be128,
:ipv6
) do
{a1, a2, a3, a4, a5, a6, a7, a8} {a1, a2, a3, a4, a5, a6, a7, a8}
end end
def formatting({a1, a2, a3, a4, a5, a6, a7, a8},:be128, :ipv6) do
def formatting({a1, a2, a3, a4, a5, a6, a7, a8}, :be128, :ipv6) do
<<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>> <<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>
end end
@ -599,6 +607,7 @@ defmodule Openflow.Match.Field do
:bad_enum -> value :bad_enum -> value
end end
end end
def formatting(value, :be16, :openflow10_port) do def formatting(value, :be16, :openflow10_port) do
port_no = port_no =
try do try do
@ -606,6 +615,7 @@ defmodule Openflow.Match.Field do
catch catch
:bad_enum -> value :bad_enum -> value
end end
<<port_no::16>> <<port_no::16>>
end end
@ -617,6 +627,7 @@ defmodule Openflow.Match.Field do
:bad_enum -> value :bad_enum -> value
end end
end end
def formatting(value, :be32, :openflow13_port) do def formatting(value, :be32, :openflow13_port) do
port_no = port_no =
try do try do
@ -624,6 +635,7 @@ defmodule Openflow.Match.Field do
catch catch
:bad_enum -> value :bad_enum -> value
end end
<<port_no::32>> <<port_no::32>>
end end
@ -631,24 +643,27 @@ defmodule Openflow.Match.Field do
def formatting(<<value::16>>, :be16, :tcp_flags) do def formatting(<<value::16>>, :be16, :tcp_flags) do
Openflow.Enums.int_to_flags(value, :tcp_flags) Openflow.Enums.int_to_flags(value, :tcp_flags)
end end
def formatting(value, :be16, :tcp_flags) do def formatting(value, :be16, :tcp_flags) do
<<(Openflow.Enums.flags_to_int(value, :tcp_flags))::16>> <<Openflow.Enums.flags_to_int(value, :tcp_flags)::16>>
end end
# CT State # CT State
def formatting(<<value::32>>, :be32, :ct_state) do def formatting(<<value::32>>, :be32, :ct_state) do
Openflow.Enums.int_to_flags(value, :ct_state_flags) Openflow.Enums.int_to_flags(value, :ct_state_flags)
end end
def formatting(value, :be32, :ct_state) do def formatting(value, :be32, :ct_state) do
<<(Openflow.Enums.flags_to_int(value, :ct_state_flags))::32>> <<Openflow.Enums.flags_to_int(value, :ct_state_flags)::32>>
end end
# CT State # CT State
def formatting(<<value::16>>, :be16, :ipv6exthdr_flags) do def formatting(<<value::16>>, :be16, :ipv6exthdr_flags) do
Openflow.Enums.int_to_flags(value, :ipv6exthdr_flags) Openflow.Enums.int_to_flags(value, :ipv6exthdr_flags)
end end
def formatting(value, :be16, :ipv6exthdr_flags) do def formatting(value, :be16, :ipv6exthdr_flags) do
<<(Openflow.Enums.flags_to_int(value, :ipv6exthdr_flags))::16>> <<Openflow.Enums.flags_to_int(value, :ipv6exthdr_flags)::16>>
end end
# Other # Other

View file

@ -1,5 +1,4 @@
defmodule Openflow.MeterBand do defmodule Openflow.MeterBand do
def read(meter_band_bin) do def read(meter_band_bin) do
do_read([], meter_band_bin) do_read([], meter_band_bin)
end end
@ -7,6 +6,7 @@ defmodule Openflow.MeterBand do
def to_binary(meter_bands) when is_list(meter_bands) do def to_binary(meter_bands) when is_list(meter_bands) do
to_binary(<<>>, meter_bands) to_binary(<<>>, meter_bands)
end end
def to_binary(meter_band) do def to_binary(meter_band) do
to_binary([meter_band]) to_binary([meter_band])
end end
@ -14,15 +14,17 @@ defmodule Openflow.MeterBand do
# private functions # private functions
defp do_read(acc, <<>>), do: Enum.reverse(acc) defp do_read(acc, <<>>), do: Enum.reverse(acc)
defp do_read(acc, <<type::16, length::16, _::bytes>> = binary) do defp do_read(acc, <<type::16, length::16, _::bytes>> = binary) do
<<meter_band_bin::size(length)-bytes, rest::bytes>> = binary <<meter_band_bin::size(length)-bytes, rest::bytes>> = binary
codec = Openflow.Enums.to_atom(type, :meter_band_type) codec = Openflow.Enums.to_atom(type, :meter_band_type)
do_read([codec.read(meter_band_bin)|acc], rest) do_read([codec.read(meter_band_bin) | acc], rest)
end end
defp to_binary(acc, []), do: acc defp to_binary(acc, []), do: acc
defp to_binary(acc, [meter_band|rest]) do
defp to_binary(acc, [meter_band | rest]) do
codec = meter_band.__struct__ codec = meter_band.__struct__
to_binary(<<acc::bytes, (codec.to_binary(meter_band))::bytes>>, rest) to_binary(<<acc::bytes, codec.to_binary(meter_band)::bytes>>, rest)
end end
end end

View file

@ -14,11 +14,11 @@ defmodule Openflow.MeterBand.Experimenter do
%Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter} %Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter}
end end
def read(<<0xffff::16, _::16, rate::32, burst_size::32, experimenter::32>>) do def read(<<0xFFFF::16, _::16, rate::32, burst_size::32, experimenter::32>>) do
%Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter} %Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter}
end end
def to_binary(%Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter}) do def to_binary(%Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter}) do
<<0xffff::16, 16::16, rate::32, burst_size::32, experimenter::32>> <<0xFFFF::16, 16::16, rate::32, burst_size::32, experimenter::32>>
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Aggregate.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
packet_count: 0, packet_count: 0,

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Aggregate.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
table_id: :all, table_id: :all,
out_port: :any, out_port: :any,
@ -23,44 +24,55 @@ defmodule Openflow.Multipart.Aggregate.Request do
cookie = Keyword.get(options, :cookie, 0) cookie = Keyword.get(options, :cookie, 0)
cookie_mask = Keyword.get(options, :cookie, 0) cookie_mask = Keyword.get(options, :cookie, 0)
match = Keyword.get(options, :match, []) match = Keyword.get(options, :match, [])
%Request{table_id: table_id,
%Request{
table_id: table_id,
out_port: out_port, out_port: out_port,
out_group: out_group, out_group: out_group,
cookie: cookie, cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
match: match} match: match
}
end end
def read(<<table_id_int::8, _::size(3)-unit(8), def read(
out_port_int::32, out_group_int::32, <<table_id_int::8, _::size(3)-unit(8), out_port_int::32, out_group_int::32,
_::size(4)-unit(8), cookie::64, _::size(4)-unit(8), cookie::64, cookie_mask::64, match_bin::bytes>>
cookie_mask::64, match_bin::bytes>>) do ) do
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no)
out_group = Openflow.Utils.get_enum(out_group_int, :group_id) out_group = Openflow.Utils.get_enum(out_group_int, :group_id)
{match, _rest} = Openflow.Match.read(match_bin) {match, _rest} = Openflow.Match.read(match_bin)
%Request{table_id: table_id,
%Request{
table_id: table_id,
out_port: out_port, out_port: out_port,
out_group: out_group, out_group: out_group,
cookie: cookie, cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
match: match} match: match
}
end end
def to_binary(%Request{table_id: table_id, def to_binary(
%Request{
table_id: table_id,
out_port: out_port, out_port: out_port,
out_group: out_group, out_group: out_group,
cookie: cookie, cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
match: match} = msg) do match: match
} = msg
) do
table_id_int = Openflow.Utils.get_enum(table_id, :table_id) table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no)
out_group_int = Openflow.Utils.get_enum(out_group, :group_id) out_group_int = Openflow.Utils.get_enum(out_group, :group_id)
match_bin = Openflow.Match.to_binary(match) match_bin = Openflow.Match.to_binary(match)
body_bin = <<table_id_int::8, 0::size(3)-unit(8),
out_port_int::32, out_group_int::32, body_bin =
0::size(4)-unit(8), cookie::64, <<table_id_int::8, 0::size(3)-unit(8), out_port_int::32, out_group_int::32,
cookie_mask::64, match_bin::bytes>> 0::size(4)-unit(8), cookie::64, cookie_mask::64, match_bin::bytes>>
header_bin = Openflow.Multipart.Request.header(msg) header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>> <<header_bin::bytes, body_bin::bytes>>
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Desc.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
mfr_desc: "", mfr_desc: "",
@ -19,13 +20,17 @@ defmodule Openflow.Multipart.Desc.Reply do
def ofp_type, do: 19 def ofp_type, do: 19
def read(<<mfr_desc::size(@desc_str_len)-bytes, hw_desc::size(@desc_str_len)-bytes, def read(
<<mfr_desc::size(@desc_str_len)-bytes, hw_desc::size(@desc_str_len)-bytes,
sw_desc::size(@desc_str_len)-bytes, serial_num::size(@serial_num_len)-bytes, sw_desc::size(@desc_str_len)-bytes, serial_num::size(@serial_num_len)-bytes,
dp_desc::size(@desc_str_len)-bytes>>) do dp_desc::size(@desc_str_len)-bytes>>
%Reply{mfr_desc: Openflow.Utils.decode_string(mfr_desc), ) do
%Reply{
mfr_desc: Openflow.Utils.decode_string(mfr_desc),
hw_desc: Openflow.Utils.decode_string(hw_desc), hw_desc: Openflow.Utils.decode_string(hw_desc),
sw_desc: Openflow.Utils.decode_string(sw_desc), sw_desc: Openflow.Utils.decode_string(sw_desc),
serial_num: Openflow.Utils.decode_string(serial_num), serial_num: Openflow.Utils.decode_string(serial_num),
dp_desc: Openflow.Utils.decode_string(dp_desc)} dp_desc: Openflow.Utils.decode_string(dp_desc)
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Desc.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [] flags: []
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Flow.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
flows: [] flows: []
@ -22,13 +23,16 @@ defmodule Openflow.Multipart.Flow.Reply do
end end
def append_body(%Reply{flows: flows} = message, %Reply{flags: [:more], flows: continue}) do def append_body(%Reply{flows: flows} = message, %Reply{flags: [:more], flows: continue}) do
%{message|flows: [continue|flows]} %{message | flows: [continue | flows]}
end end
def append_body(%Reply{flows: flows} = message, %Reply{flags: [], flows: continue}) do def append_body(%Reply{flows: flows} = message, %Reply{flags: [], flows: continue}) do
new_flows = [continue|flows] new_flows =
|> Enum.reverse [continue | flows]
|> List.flatten |> Enum.reverse()
%{message|flows: new_flows} |> List.flatten()
%{message | flows: new_flows}
end end
end end
@ -57,20 +61,24 @@ defmodule Openflow.Multipart.FlowStats do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<length::16, _tail::bytes>> = binary) do defp do_read(acc, <<length::16, _tail::bytes>> = binary) do
<<flow_stats_bin::size(length)-bytes, rest::bytes>> = binary <<flow_stats_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(flow_stats_bin)|acc], rest) do_read([codec(flow_stats_bin) | acc], rest)
end end
defp codec(<<_length::16, table_id_int::8, 0::8, duration_sec::32, defp codec(
duration_nsec::32, priority::16, idle::16, hard::16, <<_length::16, table_id_int::8, 0::8, duration_sec::32, duration_nsec::32, priority::16,
flags_int::16, _::size(4)-unit(8), cookie::64, idle::16, hard::16, flags_int::16, _::size(4)-unit(8), cookie::64, packet_count::64,
packet_count::64, byte_count::64, tail::bytes>>) do byte_count::64, tail::bytes>>
) do
{match, instructions_bin} = Openflow.Match.read(tail) {match, instructions_bin} = Openflow.Match.read(tail)
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
flags = Openflow.Enums.int_to_flags(flags_int, :flow_mod_flags) flags = Openflow.Enums.int_to_flags(flags_int, :flow_mod_flags)
instructions = Openflow.Instruction.read(instructions_bin) instructions = Openflow.Instruction.read(instructions_bin)
%FlowStats{table_id: table_id,
%FlowStats{
table_id: table_id,
duration_sec: duration_sec, duration_sec: duration_sec,
duration_nsec: duration_nsec, duration_nsec: duration_nsec,
priority: priority, priority: priority,
@ -81,6 +89,7 @@ defmodule Openflow.Multipart.FlowStats do
packet_count: packet_count, packet_count: packet_count,
byte_count: byte_count, byte_count: byte_count,
match: match, match: match,
instructions: instructions} instructions: instructions
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Flow.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
table_id: :all, table_id: :all,
out_port: :any, out_port: :any,
@ -22,45 +23,56 @@ defmodule Openflow.Multipart.Flow.Request do
out_group = Keyword.get(options, :out_group, :any) out_group = Keyword.get(options, :out_group, :any)
cookie = Keyword.get(options, :cookie, 0) cookie = Keyword.get(options, :cookie, 0)
cookie_mask = Keyword.get(options, :cookie, 0) cookie_mask = Keyword.get(options, :cookie, 0)
match = Keyword.get(options, :match, Openflow.Match.new) match = Keyword.get(options, :match, Openflow.Match.new())
%Request{table_id: table_id,
%Request{
table_id: table_id,
out_port: out_port, out_port: out_port,
out_group: out_group, out_group: out_group,
cookie: cookie, cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
match: match} match: match
}
end end
def read(<<table_id_int::8, _::size(3)-unit(8), def read(
out_port_int::32, out_group_int::32, <<table_id_int::8, _::size(3)-unit(8), out_port_int::32, out_group_int::32,
_::size(4)-unit(8), cookie::64, _::size(4)-unit(8), cookie::64, cookie_mask::64, match_bin::bytes>>
cookie_mask::64, match_bin::bytes>>) do ) do
table_id = Openflow.Utils.get_enum(table_id_int, :table_id) table_id = Openflow.Utils.get_enum(table_id_int, :table_id)
out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no)
out_group = Openflow.Utils.get_enum(out_group_int, :group_id) out_group = Openflow.Utils.get_enum(out_group_int, :group_id)
{match, _rest} = Openflow.Match.read(match_bin) {match, _rest} = Openflow.Match.read(match_bin)
%Request{table_id: table_id,
%Request{
table_id: table_id,
out_port: out_port, out_port: out_port,
out_group: out_group, out_group: out_group,
cookie: cookie, cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
match: match} match: match
}
end end
def to_binary(%Request{table_id: table_id, def to_binary(
%Request{
table_id: table_id,
out_port: out_port, out_port: out_port,
out_group: out_group, out_group: out_group,
cookie: cookie, cookie: cookie,
cookie_mask: cookie_mask, cookie_mask: cookie_mask,
match: match} = msg) do match: match
} = msg
) do
table_id_int = Openflow.Utils.get_enum(table_id, :table_id) table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no)
out_group_int = Openflow.Utils.get_enum(out_group, :group_id) out_group_int = Openflow.Utils.get_enum(out_group, :group_id)
match_bin = Openflow.Match.to_binary(match) match_bin = Openflow.Match.to_binary(match)
body_bin = <<table_id_int::8, 0::size(3)-unit(8),
out_port_int::32, out_group_int::32, body_bin =
0::size(4)-unit(8), cookie::64, <<table_id_int::8, 0::size(3)-unit(8), out_port_int::32, out_group_int::32,
cookie_mask::64, match_bin::bytes>> 0::size(4)-unit(8), cookie::64, cookie_mask::64, match_bin::bytes>>
header_bin = Openflow.Multipart.Request.header(msg) header_bin = Openflow.Multipart.Request.header(msg)
<<header_bin::bytes, body_bin::bytes>> <<header_bin::bytes, body_bin::bytes>>
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Group.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
groups: [] groups: []
@ -22,13 +23,16 @@ defmodule Openflow.Multipart.Group.Reply do
end end
def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do
%{message|groups: [continue|groups]} %{message | groups: [continue | groups]}
end end
def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do
new_groups = [continue|groups] new_groups =
|> Enum.reverse [continue | groups]
|> List.flatten |> Enum.reverse()
%{message|groups: new_groups} |> List.flatten()
%{message | groups: new_groups}
end end
end end
@ -54,27 +58,32 @@ defmodule Openflow.Multipart.Group do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<length::16, _binary::bytes>> = binary) do defp do_read(acc, <<length::16, _binary::bytes>> = binary) do
<<group_bin::size(length)-bytes, rest::bytes>> = binary <<group_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(group_bin)|acc], rest) do_read([codec(group_bin) | acc], rest)
end end
defp codec(<<length::16, _::size(2)-unit(8), defp codec(
group_id::32, ref_count::32, <<length::16, _::size(2)-unit(8), group_id::32, ref_count::32, _::size(4)-unit(8),
_::size(4)-unit(8), packet_count::64, packet_count::64, byte_count::64, duration_sec::32, duration_nsec::32, tail::bytes>>
byte_count::64, duration_sec::32, ) do
duration_nsec::32, tail::bytes>>) do
bucket_stats_size = length - @ofp_group_stats_size bucket_stats_size = length - @ofp_group_stats_size
<<bucket_stats_bin::size(bucket_stats_size)-bytes, _rest::bytes>> = tail <<bucket_stats_bin::size(bucket_stats_size)-bytes, _rest::bytes>> = tail
bucket_stats = for <<packet_count::64, byte_count::64 <- bucket_stats_bin>> do
bucket_stats =
for <<packet_count::64, byte_count::64 <- bucket_stats_bin>> do
%{packet_count: packet_count, byte_count: byte_count} %{packet_count: packet_count, byte_count: byte_count}
end end
%Group{group_id: group_id,
%Group{
group_id: group_id,
ref_count: ref_count, ref_count: ref_count,
packet_count: packet_count, packet_count: packet_count,
byte_count: byte_count, byte_count: byte_count,
duration_sec: duration_sec, duration_sec: duration_sec,
duration_nsec: duration_nsec, duration_nsec: duration_nsec,
bucket_stats: bucket_stats} bucket_stats: bucket_stats
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Group.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
group_id: :all group_id: :all
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.GroupDesc.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
groups: [] groups: []
) )
@ -21,13 +22,16 @@ defmodule Openflow.Multipart.GroupDesc.Reply do
end end
def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do
%{message|groups: [continue|groups]} %{message | groups: [continue | groups]}
end end
def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do
new_groups = [continue|groups] new_groups =
|> Enum.reverse [continue | groups]
|> List.flatten |> Enum.reverse()
%{message|groups: new_groups} |> List.flatten()
%{message | groups: new_groups}
end end
end end
@ -49,9 +53,10 @@ defmodule Openflow.Multipart.GroupDescStats do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<length::16, _tail::bytes>> = binary) do defp do_read(acc, <<length::16, _tail::bytes>> = binary) do
<<group_stats_bin::size(length)-bytes, rest::bytes>> = binary <<group_stats_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(group_stats_bin)|acc], rest) do_read([codec(group_stats_bin) | acc], rest)
end end
defp codec(<<length::16, type_int::8, _::8, group_id::32, tail::bytes>>) do defp codec(<<length::16, type_int::8, _::8, group_id::32, tail::bytes>>) do

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.GroupDesc.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [] flags: []
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.GroupFeatures.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
types: 0, types: 0,
@ -21,17 +22,17 @@ defmodule Openflow.Multipart.GroupFeatures.Reply do
def ofp_type, do: 18 def ofp_type, do: 18
def read(<<types_int::32, capabilities_int::32, def read(
max_groups_for_all_int::32, <<types_int::32, capabilities_int::32, max_groups_for_all_int::32,
max_groups_for_select_int::32, max_groups_for_select_int::32, max_groups_for_indirect_int::32,
max_groups_for_indirect_int::32, max_groups_for_fast_failover_int::32, actions_for_all_int::32,
max_groups_for_fast_failover_int::32, actions_for_select_int::32, actions_for_indirect_int::32,
actions_for_all_int::32, actions_for_fast_failover_int::32>>
actions_for_select_int::32, ) do
actions_for_indirect_int::32,
actions_for_fast_failover_int::32>>) do
capabilities = Openflow.Enums.int_to_flags(capabilities_int, :group_capabilities) capabilities = Openflow.Enums.int_to_flags(capabilities_int, :group_capabilities)
%Reply{types: types_int,
%Reply{
types: types_int,
capabilities: capabilities, capabilities: capabilities,
max_groups_for_all: max_groups_for_all_int, max_groups_for_all: max_groups_for_all_int,
max_groups_for_select: max_groups_for_select_int, max_groups_for_select: max_groups_for_select_int,
@ -40,6 +41,7 @@ defmodule Openflow.Multipart.GroupFeatures.Reply do
actions_for_all: actions_for_all_int, actions_for_all: actions_for_all_int,
actions_for_select: actions_for_select_int, actions_for_select: actions_for_select_int,
actions_for_indirect: actions_for_indirect_int, actions_for_indirect: actions_for_indirect_int,
actions_for_fast_failover: actions_for_fast_failover_int} actions_for_fast_failover: actions_for_fast_failover_int
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.GroupFeatures.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [] flags: []
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Meter.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
meters: [] meters: []
@ -18,13 +19,16 @@ defmodule Openflow.Multipart.Meter.Reply do
end end
def append_body(%Reply{meters: meters} = message, %Reply{flags: [:more], meters: continue}) do def append_body(%Reply{meters: meters} = message, %Reply{flags: [:more], meters: continue}) do
%{message|meters: [continue|meters]} %{message | meters: [continue | meters]}
end end
def append_body(%Reply{meters: meters} = message, %Reply{flags: [], meters: continue}) do def append_body(%Reply{meters: meters} = message, %Reply{flags: [], meters: continue}) do
new_meters = [continue|meters] new_meters =
|> Enum.reverse [continue | meters]
|> List.flatten |> Enum.reverse()
%{message|meters: new_meters} |> List.flatten()
%{message | meters: new_meters}
end end
end end
@ -50,25 +54,32 @@ defmodule Openflow.Multipart.Meter do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<_::32, length::16, _binary::bytes>> = binary) do defp do_read(acc, <<_::32, length::16, _binary::bytes>> = binary) do
<<meter_bin::size(length)-bytes, rest::bytes>> = binary <<meter_bin::size(length)-bytes, rest::bytes>> = binary
do_read([codec(meter_bin)|acc], rest) do_read([codec(meter_bin) | acc], rest)
end end
defp codec(<<meter_id::32, length::16, _::size(6)-unit(8), defp codec(
flow_count::32, packet_in_count::64, byte_in_count::64, <<meter_id::32, length::16, _::size(6)-unit(8), flow_count::32, packet_in_count::64,
duration_sec::32, duration_nsec::32, tail::bytes>>) do byte_in_count::64, duration_sec::32, duration_nsec::32, tail::bytes>>
) do
band_stats_size = length - @ofp_meter_stats_size band_stats_size = length - @ofp_meter_stats_size
<<band_stats_bin::size(band_stats_size)-bytes, _rest::bytes>> = tail <<band_stats_bin::size(band_stats_size)-bytes, _rest::bytes>> = tail
band_stats = for <<packet_band_count::64, byte_band_count::64 <- band_stats_bin>> do
%{packet_band_count: packet_band_count,byte_band_count: byte_band_count} band_stats =
for <<packet_band_count::64, byte_band_count::64 <- band_stats_bin>> do
%{packet_band_count: packet_band_count, byte_band_count: byte_band_count}
end end
%Meter{meter_id: meter_id,
%Meter{
meter_id: meter_id,
flow_count: flow_count, flow_count: flow_count,
packet_in_count: packet_in_count, packet_in_count: packet_in_count,
byte_in_count: byte_in_count, byte_in_count: byte_in_count,
duration_sec: duration_sec, duration_sec: duration_sec,
duration_nsec: duration_nsec, duration_nsec: duration_nsec,
band_stats: band_stats} band_stats: band_stats
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Meter.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
meter_id: :all meter_id: :all
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.MeterConfig.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
meter_id: :all meter_id: :all
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.PortDesc.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
ports: [] ports: []
@ -17,17 +18,20 @@ defmodule Openflow.Multipart.PortDesc.Reply do
end end
def read(<<ports_bin::bytes>>) do def read(<<ports_bin::bytes>>) do
ports = for (<<port_bin::64-bytes <- ports_bin>>), do: Openflow.Port.read(port_bin) ports = for <<port_bin::64-bytes <- ports_bin>>, do: Openflow.Port.read(port_bin)
%Reply{ports: Enum.reverse(ports)} %Reply{ports: Enum.reverse(ports)}
end end
def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do
%{message|ports: [continue|ports]} %{message | ports: [continue | ports]}
end end
def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do
new_ports = [continue|ports] new_ports =
|> Enum.reverse [continue | ports]
|> List.flatten |> Enum.reverse()
%{message|ports: new_ports} |> List.flatten()
%{message | ports: new_ports}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.PortDesc.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [] flags: []
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.PortStats.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
ports: [] ports: []
@ -22,13 +23,16 @@ defmodule Openflow.Multipart.PortStats.Reply do
end end
def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do
%{message|ports: [continue|ports]} %{message | ports: [continue | ports]}
end end
def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do
new_ports = [continue|ports] new_ports =
|> Enum.reverse [continue | ports]
|> List.flatten |> Enum.reverse()
%{message|ports: new_ports} |> List.flatten()
%{message | ports: new_ports}
end end
end end
@ -60,17 +64,19 @@ defmodule Openflow.Multipart.PortStats do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<port_stats_bin::112-bytes, rest::bytes>>) do defp do_read(acc, <<port_stats_bin::112-bytes, rest::bytes>>) do
do_read([codec(port_stats_bin)|acc], rest) do_read([codec(port_stats_bin) | acc], rest)
end end
defp codec(<<port_no::32, _::size(4)-unit(8), rx_packets::64, defp codec(
tx_packets::64, rx_bytes::64, tx_bytes::64, <<port_no::32, _::size(4)-unit(8), rx_packets::64, tx_packets::64, rx_bytes::64,
rx_dropped::64, tx_dropped::64, rx_errors::64, tx_bytes::64, rx_dropped::64, tx_dropped::64, rx_errors::64, tx_errors::64,
tx_errors::64, rx_frame_err::64, rx_over_err::64, rx_frame_err::64, rx_over_err::64, rx_crc_err::64, collisions::64, duration_sec::32,
rx_crc_err::64, collisions::64, duration_nsec::32>>
duration_sec::32, duration_nsec::32>>) do ) do
%PortStats{port_number: port_no, %PortStats{
port_number: port_no,
rx_packets: rx_packets, rx_packets: rx_packets,
tx_packets: tx_packets, tx_packets: tx_packets,
rx_bytes: rx_bytes, rx_bytes: rx_bytes,
@ -84,6 +90,7 @@ defmodule Openflow.Multipart.PortStats do
rx_crc_err: rx_crc_err, rx_crc_err: rx_crc_err,
collisions: collisions, collisions: collisions,
duration_sec: duration_sec, duration_sec: duration_sec,
duration_nsec: duration_nsec} duration_nsec: duration_nsec
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.PortStats.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
port_number: :any port_number: :any
) )

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Queue.Reply do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
aux_id: nil, aux_id: nil,
flags: [], flags: [],
queues: [] queues: []
@ -22,13 +23,16 @@ defmodule Openflow.Multipart.Queue.Reply do
end end
def append_body(%Reply{queues: queues} = message, %Reply{flags: [:more], queues: continue}) do def append_body(%Reply{queues: queues} = message, %Reply{flags: [:more], queues: continue}) do
%{message|queues: [continue|queues]} %{message | queues: [continue | queues]}
end end
def append_body(%Reply{queues: queues} = message, %Reply{flags: [], queues: continue}) do def append_body(%Reply{queues: queues} = message, %Reply{flags: [], queues: continue}) do
new_queues = [continue|queues] new_queues =
|> Enum.reverse [continue | queues]
|> List.flatten |> Enum.reverse()
%{message|queues: new_queues} |> List.flatten()
%{message | queues: new_queues}
end end
end end
@ -52,19 +56,23 @@ defmodule Openflow.Multipart.Queue do
# private functions # private functions
defp do_read(acc, ""), do: Enum.reverse(acc) defp do_read(acc, ""), do: Enum.reverse(acc)
defp do_read(acc, <<queue_bin::40-bytes, rest::bytes>>) do defp do_read(acc, <<queue_bin::40-bytes, rest::bytes>>) do
do_read([codec(queue_bin)|acc], rest) do_read([codec(queue_bin) | acc], rest)
end end
defp codec(<<port_no::32, queue_id::32, tx_bytes::64, defp codec(
tx_packets::64, tx_errors::64, <<port_no::32, queue_id::32, tx_bytes::64, tx_packets::64, tx_errors::64,
duration_sec::32, duration_nsec::32>>) do duration_sec::32, duration_nsec::32>>
%Queue{port_number: port_no, ) do
%Queue{
port_number: port_no,
queue_id: queue_id, queue_id: queue_id,
tx_bytes: tx_bytes, tx_bytes: tx_bytes,
tx_packets: tx_packets, tx_packets: tx_packets,
tx_errors: tx_errors, tx_errors: tx_errors,
duration_sec: duration_sec, duration_sec: duration_sec,
duration_nsec: duration_nsec} duration_nsec: duration_nsec
}
end end
end end

View file

@ -2,7 +2,8 @@ defmodule Openflow.Multipart.Queue.Request do
defstruct( defstruct(
version: 4, version: 4,
xid: 0, xid: 0,
datapath_id: nil, # virtual field # virtual field
datapath_id: nil,
flags: [], flags: [],
port_number: :any, port_number: :any,
queue_id: :all queue_id: :all

View file

@ -5,15 +5,17 @@ defmodule Openflow.Multipart.Reply do
codec = Openflow.Enums.to_atom(type_int, :multipart_reply_codec) codec = Openflow.Enums.to_atom(type_int, :multipart_reply_codec)
flags = Openflow.Enums.int_to_flags(flags_int, :multipart_reply_flags) flags = Openflow.Enums.int_to_flags(flags_int, :multipart_reply_flags)
reply = codec.read(reply_bin) reply = codec.read(reply_bin)
%{reply|flags: flags} %{reply | flags: flags}
end end
def to_binary(%{__struct__: codec, flags: flags} = msg) do def to_binary(%{__struct__: codec, flags: flags} = msg) do
flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags) flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags)
type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec) type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec)
case codec.to_binary(msg) do case codec.to_binary(msg) do
reply_bin when is_binary(reply_bin) -> reply_bin when is_binary(reply_bin) ->
<<type_int::16, flags_int::16, 0::size(4)-unit(8), reply_bin::bytes>> <<type_int::16, flags_int::16, 0::size(4)-unit(8), reply_bin::bytes>>
{:error, reason} -> {:error, reason} ->
{:error, reason} {:error, reason}
end end

Some files were not shown because too many files have changed in this diff Show more