Formatted
This commit is contained in:
parent
5fc01a9bec
commit
7635272fbd
150 changed files with 5055 additions and 4032 deletions
18
.formatter.exs
Normal file
18
.formatter.exs
Normal 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
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
use Mix.Config
|
use Mix.Config
|
||||||
|
|
||||||
config :tres,
|
config :tres,
|
||||||
protocol: :tcp,
|
protocol: :tcp,
|
||||||
port: 6653,
|
port: 6653,
|
||||||
max_connections: 10,
|
max_connections: 10,
|
||||||
num_acceptors: 10,
|
num_acceptors: 10,
|
||||||
callback_module: Tres.ExampleHandler,
|
callback_module: Tres.ExampleHandler,
|
||||||
callback_args: []
|
callback_args: []
|
||||||
|
|
||||||
config :logger,
|
config :logger,
|
||||||
level: :info,
|
level: :info,
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,26 @@ defmodule Openflow do
|
||||||
|
|
||||||
@spec read(binary()) :: {:ok, map()} | {:error, :binary_too_small}
|
@spec read(binary()) :: {:ok, map()} | {:error, :binary_too_small}
|
||||||
def read(binary)
|
def read(binary)
|
||||||
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 =
|
||||||
|> Openflow.Enums.to_atom(:openflow_codec)
|
type
|
||||||
|> do_read(body_bin)
|
|> Openflow.Enums.to_atom(:openflow_codec)
|
||||||
|
|> 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}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule Openflow.Action.NxBundle do
|
defmodule Openflow.Action.NxBundle do
|
||||||
defstruct(
|
defstruct(
|
||||||
algorithm: :active_backup,
|
algorithm: :active_backup,
|
||||||
hash_field: :eth_src,
|
hash_field: :eth_src,
|
||||||
basis: 0,
|
basis: 0,
|
||||||
slave_type: :nx_in_port,
|
slave_type: :nx_in_port,
|
||||||
n_slaves: 0,
|
n_slaves: 0,
|
||||||
slaves: []
|
slaves: []
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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,
|
|
||||||
hash_field: options[:hash_field] || :eth_src,
|
%NxBundle{
|
||||||
basis: options[:basis] || 0,
|
algorithm: options[:algorithm] || :active_backup,
|
||||||
n_slaves: length(slaves),
|
hash_field: options[:hash_field] || :eth_src,
|
||||||
slaves: slaves}
|
basis: options[:basis] || 0,
|
||||||
|
n_slaves: length(slaves),
|
||||||
|
slaves: slaves
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxBundle{algorithm: alg,
|
def to_binary(%NxBundle{
|
||||||
hash_field: hash_field,
|
algorithm: alg,
|
||||||
basis: basis,
|
hash_field: hash_field,
|
||||||
slave_type: slave_type,
|
basis: basis,
|
||||||
n_slaves: n_slaves,
|
slave_type: slave_type,
|
||||||
slaves: slaves}) do
|
n_slaves: n_slaves,
|
||||||
|
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,
|
|
||||||
hash_field: hash_field,
|
%NxBundle{
|
||||||
basis: basis,
|
algorithm: alg,
|
||||||
slave_type: slave_type,
|
hash_field: hash_field,
|
||||||
n_slaves: n_slaves,
|
basis: basis,
|
||||||
slaves: slaves}
|
slave_type: slave_type,
|
||||||
|
n_slaves: n_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 =
|
||||||
slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no)
|
for slave <- slaves do
|
||||||
<<slave_int::16>>
|
slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no)
|
||||||
end
|
<<slave_int::16>>
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@ defmodule Openflow.Action.NxBundleLoad do
|
||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
algorithm: :active_backup,
|
algorithm: :active_backup,
|
||||||
hash_field: :eth_src,
|
hash_field: :eth_src,
|
||||||
basis: 0,
|
basis: 0,
|
||||||
slave_type: :nx_in_port,
|
slave_type: :nx_in_port,
|
||||||
n_slaves: 0,
|
n_slaves: 0,
|
||||||
slaves: [],
|
slaves: [],
|
||||||
offset: 0,
|
offset: 0,
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
dst_field: nil
|
dst_field: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -22,45 +22,52 @@ 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,
|
|
||||||
hash_field: options[:hash_field] || :eth_src,
|
%NxBundleLoad{
|
||||||
basis: options[:basis] || 0,
|
algorithm: options[:algorithm] || :active_backup,
|
||||||
n_slaves: length(slaves),
|
hash_field: options[:hash_field] || :eth_src,
|
||||||
slaves: slaves,
|
basis: options[:basis] || 0,
|
||||||
offset: options[:offset] || 0,
|
n_slaves: length(slaves),
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
slaves: slaves,
|
||||||
dst_field: options[:dst_field]}
|
offset: options[:offset] || 0,
|
||||||
|
n_bits: options[:n_bits] || default_n_bits,
|
||||||
|
dst_field: options[:dst_field]
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxBundleLoad{algorithm: alg,
|
def to_binary(%NxBundleLoad{
|
||||||
hash_field: hash_field,
|
algorithm: alg,
|
||||||
basis: basis,
|
hash_field: hash_field,
|
||||||
slave_type: slave_type,
|
basis: basis,
|
||||||
n_slaves: n_slaves,
|
slave_type: slave_type,
|
||||||
slaves: slaves,
|
n_slaves: n_slaves,
|
||||||
offset: ofs,
|
slaves: slaves,
|
||||||
n_bits: n_bits,
|
offset: ofs,
|
||||||
dst_field: dst_field}) do
|
n_bits: n_bits,
|
||||||
|
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,26 +76,32 @@ 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,
|
|
||||||
hash_field: hash_field,
|
%NxBundleLoad{
|
||||||
basis: basis,
|
algorithm: alg,
|
||||||
slave_type: slave_type,
|
hash_field: hash_field,
|
||||||
n_slaves: n_slaves,
|
basis: basis,
|
||||||
slaves: slaves,
|
slave_type: slave_type,
|
||||||
offset: ofs,
|
n_slaves: n_slaves,
|
||||||
n_bits: n_bits + 1,
|
slaves: slaves,
|
||||||
dst_field: dst_field}
|
offset: ofs,
|
||||||
|
n_bits: n_bits + 1,
|
||||||
|
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 =
|
||||||
slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no)
|
for slave <- slaves do
|
||||||
<<slave_int::16>>
|
slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no)
|
||||||
end
|
<<slave_int::16>>
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -15,10 +13,10 @@ defmodule Openflow.Action.NxClone do
|
||||||
def to_binary(%NxClone{actions: actions}) do
|
def to_binary(%NxClone{actions: actions}) do
|
||||||
actions_bin = Openflow.Action.to_binary(actions)
|
actions_bin = Openflow.Action.to_binary(actions)
|
||||||
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>>
|
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_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, 0::size(6)-unit(8), actions_bin::bytes>>) do
|
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>>) do
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule Openflow.Action.NxConjunction do
|
defmodule Openflow.Action.NxConjunction do
|
||||||
defstruct(
|
defstruct(
|
||||||
clause: 0,
|
clause: 0,
|
||||||
n_clauses: 0,
|
n_clauses: 0,
|
||||||
id: 0
|
id: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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{
|
||||||
n_clauses: options[:n_clauses] || 0,
|
clause: options[:clause] || 0,
|
||||||
id: options[:id] || 0}
|
n_clauses: options[:n_clauses] || 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
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@ defmodule Openflow.Action.NxConntrack do
|
||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
flags: [],
|
flags: [],
|
||||||
zone_src: nil,
|
zone_src: nil,
|
||||||
zone_imm: 0,
|
zone_imm: 0,
|
||||||
zone_offset: nil,
|
zone_offset: nil,
|
||||||
zone_n_bits: nil,
|
zone_n_bits: nil,
|
||||||
recirc_table: 255,
|
recirc_table: 255,
|
||||||
alg: 0,
|
alg: 0,
|
||||||
exec: []
|
exec: []
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -18,61 +18,73 @@ defmodule Openflow.Action.NxConntrack do
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
def new(options \\ []) do
|
def new(options \\ []) do
|
||||||
%NxConntrack{flags: options[:flags] || [],
|
%NxConntrack{
|
||||||
zone_src: options[:zone_src],
|
flags: options[:flags] || [],
|
||||||
zone_imm: options[:zone_imm] || 0,
|
zone_src: options[:zone_src],
|
||||||
zone_offset: options[:zone_offset],
|
zone_imm: options[:zone_imm] || 0,
|
||||||
zone_n_bits: options[:zone_n_bits],
|
zone_offset: options[:zone_offset],
|
||||||
recirc_table: options[:recirc_table] || 255,
|
zone_n_bits: options[:zone_n_bits],
|
||||||
alg: options[:alg] || 0,
|
recirc_table: options[:recirc_table] || 255,
|
||||||
exec: options[:exec] || []}
|
alg: options[:alg] || 0,
|
||||||
|
exec: options[:exec] || []
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxConntrack{
|
def to_binary(%NxConntrack{
|
||||||
flags: flags,
|
flags: flags,
|
||||||
zone_src: zone_src,
|
zone_src: zone_src,
|
||||||
zone_offset: zone_ofs,
|
zone_offset: zone_ofs,
|
||||||
zone_n_bits: zone_n_bits,
|
zone_n_bits: zone_n_bits,
|
||||||
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
|
|
||||||
zone_src_bin = Openflow.Match.codec_header(zone_src)
|
{src_bin, ofs_nbits} =
|
||||||
{zone_src_bin, (zone_ofs <<< 6) ||| (zone_n_bits - 1)}
|
if not is_nil(zone_src) do
|
||||||
else
|
zone_src_bin = Openflow.Match.codec_header(zone_src)
|
||||||
{<<0::32>>, zone_imm}
|
{zone_src_bin, zone_ofs <<< 6 ||| zone_n_bits - 1}
|
||||||
end
|
else
|
||||||
|
{<<0::32>>, zone_imm}
|
||||||
|
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,
|
||||||
exp_body_size = byte_size(exp_body)
|
recirc_table::8, 0::size(3)-unit(8), alg::16, exec_bin::bytes>>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
id: options[:id] || 0,
|
max_len: options[:max_len] || :no_buffer,
|
||||||
reason: options[:reason] || :action}
|
id: options[:id] || 0,
|
||||||
|
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}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
defmodule Openflow.Action.NxController2 do
|
defmodule Openflow.Action.NxController2 do
|
||||||
defstruct(
|
defstruct(
|
||||||
max_len: :no_buffer,
|
max_len: :no_buffer,
|
||||||
id: 0,
|
id: 0,
|
||||||
reason: :action,
|
reason: :action,
|
||||||
userdata: "",
|
userdata: "",
|
||||||
pause: false
|
pause: false
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -12,20 +12,22 @@ defmodule Openflow.Action.NxController2 do
|
||||||
|
|
||||||
@prop_header_size 4
|
@prop_header_size 4
|
||||||
|
|
||||||
@prop_max_len 0
|
@prop_max_len 0
|
||||||
@prop_ctl_id 1
|
@prop_ctl_id 1
|
||||||
@prop_reason 2
|
@prop_reason 2
|
||||||
@prop_userdata 3
|
@prop_userdata 3
|
||||||
@prop_pause 4
|
@prop_pause 4
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
def new(options) do
|
def new(options) do
|
||||||
%NxController2{max_len: options[:max_len] || :no_buffer,
|
%NxController2{
|
||||||
id: options[:id] || 0,
|
max_len: options[:max_len] || :no_buffer,
|
||||||
reason: options[:reason] || :action,
|
id: options[:id] || 0,
|
||||||
userdata: options[:userdata],
|
reason: options[:reason] || :action,
|
||||||
pause: options[:pause] || false}
|
userdata: options[:userdata],
|
||||||
|
pause: options[:pause] || false
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxController2{} = ctl) do
|
def to_binary(%NxController2{} = ctl) do
|
||||||
|
|
@ -33,10 +35,10 @@ defmodule Openflow.Action.NxController2 do
|
||||||
prop_keys = get_prop_key(ctl)
|
prop_keys = get_prop_key(ctl)
|
||||||
props_bin = encode_prop("", prop_keys, ctl)
|
props_bin = encode_prop("", prop_keys, ctl)
|
||||||
exp_body = <<ext_header::bytes, props_bin::bytes>>
|
exp_body = <<ext_header::bytes, props_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>>
|
<<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 =
|
||||||
padding_length = 2
|
cond do
|
||||||
prop_length = @prop_header_size + 2 + padding_length
|
prop == :max_len and (value != :no_buffer or value < 0xFFFF) ->
|
||||||
max_len_int = Openflow.Utils.get_enum(value, :controller_max_len)
|
padding_length = 2
|
||||||
<<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>>
|
prop_length = @prop_header_size + 2 + padding_length
|
||||||
prop == :id ->
|
max_len_int = Openflow.Utils.get_enum(value, :controller_max_len)
|
||||||
padding_length = 2
|
<<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>>
|
||||||
prop_length = @prop_header_size + 2 + padding_length
|
|
||||||
<<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>>
|
prop == :id ->
|
||||||
prop == :reason and value != :action ->
|
padding_length = 2
|
||||||
padding_length = 3
|
prop_length = @prop_header_size + 2 + padding_length
|
||||||
prop_length = @prop_header_size + 1 + padding_length
|
<<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>>
|
||||||
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 and value != :action ->
|
||||||
prop == :userdata and byte_size(value) > 0 ->
|
padding_length = 3
|
||||||
prop_length = @prop_header_size + byte_size(value)
|
prop_length = @prop_header_size + 1 + padding_length
|
||||||
padding_length = Openflow.Utils.padding(prop_length, 8)
|
reason_int = Openflow.Utils.get_enum(value, :packet_in_reason)
|
||||||
<<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>>
|
<<@prop_reason::16, prop_length::16, reason_int::8, 0::size(padding_length)-unit(8)>>
|
||||||
prop == :pause and value == true ->
|
|
||||||
padding_length = 4
|
prop == :userdata and byte_size(value) > 0 ->
|
||||||
prop_length = @prop_header_size + padding_length
|
prop_length = @prop_header_size + byte_size(value)
|
||||||
<<@prop_pause::16, prop_length::16, 0::size(padding_length)-unit(8)>>
|
padding_length = Openflow.Utils.padding(prop_length, 8)
|
||||||
true ->
|
<<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>>
|
||||||
""
|
|
||||||
end
|
prop == :pause and value == true ->
|
||||||
|
padding_length = 4
|
||||||
|
prop_length = @prop_header_size + padding_length
|
||||||
|
<<@prop_pause::16, prop_length::16, 0::size(padding_length)-unit(8)>>
|
||||||
|
|
||||||
|
true ->
|
||||||
|
""
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
exp_body_size = byte_size(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)
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -2,67 +2,80 @@ defmodule Openflow.Action.NxFlowSpecLoad do
|
||||||
defstruct(
|
defstruct(
|
||||||
src: nil,
|
src: nil,
|
||||||
dst: nil,
|
dst: nil,
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
src_offset: 0,
|
src_offset: 0,
|
||||||
dst_offset: 0
|
dst_offset: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@learn_src_field 0
|
@learn_src_field 0
|
||||||
@learn_src_immediate 1
|
@learn_src_immediate 1
|
||||||
@learn_dst 1
|
@learn_dst 1
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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],
|
|
||||||
dst: dst,
|
%NxFlowSpecLoad{
|
||||||
n_bits: n_bits,
|
src: options[:src],
|
||||||
src_offset: options[:src_offset] || 0,
|
dst: dst,
|
||||||
dst_offset: options[:dst_offset] || 0}
|
n_bits: n_bits,
|
||||||
|
src_offset: options[:src_offset] || 0,
|
||||||
|
dst_offset: options[:dst_offset] || 0
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxFlowSpecLoad{} = fsm) do
|
def to_binary(%NxFlowSpecLoad{} = fsm) do
|
||||||
%NxFlowSpecLoad{
|
%NxFlowSpecLoad{
|
||||||
dst: dst_field,
|
dst: dst_field,
|
||||||
n_bits: n_bits,
|
n_bits: n_bits,
|
||||||
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,
|
|
||||||
dst: dst,
|
flow_spec = %NxFlowSpecLoad{
|
||||||
n_bits: n_bits,
|
src: src,
|
||||||
src_offset: src_ofs,
|
dst: dst,
|
||||||
dst_offset: dst_ofs}
|
n_bits: n_bits,
|
||||||
|
src_offset: src_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}
|
||||||
|
|
|
||||||
|
|
@ -2,67 +2,80 @@ defmodule Openflow.Action.NxFlowSpecMatch do
|
||||||
defstruct(
|
defstruct(
|
||||||
src: nil,
|
src: nil,
|
||||||
dst: nil,
|
dst: nil,
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
src_offset: 0,
|
src_offset: 0,
|
||||||
dst_offset: 0
|
dst_offset: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@learn_src_field 0
|
@learn_src_field 0
|
||||||
@learn_src_immediate 1
|
@learn_src_immediate 1
|
||||||
@learn_dst 0
|
@learn_dst 0
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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],
|
|
||||||
dst: dst,
|
%NxFlowSpecMatch{
|
||||||
n_bits: n_bits,
|
src: options[:src],
|
||||||
src_offset: options[:src_offset] || 0,
|
dst: dst,
|
||||||
dst_offset: options[:dst_offset] || 0}
|
n_bits: n_bits,
|
||||||
|
src_offset: options[:src_offset] || 0,
|
||||||
|
dst_offset: options[:dst_offset] || 0
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxFlowSpecMatch{} = fsm) do
|
def to_binary(%NxFlowSpecMatch{} = fsm) do
|
||||||
%NxFlowSpecMatch{
|
%NxFlowSpecMatch{
|
||||||
dst: dst_field,
|
dst: dst_field,
|
||||||
n_bits: n_bits,
|
n_bits: n_bits,
|
||||||
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,
|
|
||||||
dst: dst,
|
flow_spec = %NxFlowSpecMatch{
|
||||||
n_bits: n_bits,
|
src: src,
|
||||||
src_offset: src_ofs,
|
dst: dst,
|
||||||
dst_offset: dst_ofs}
|
n_bits: n_bits,
|
||||||
|
src_offset: src_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}
|
||||||
|
|
|
||||||
|
|
@ -5,32 +5,28 @@ defmodule Openflow.Action.NxFlowSpecOutput do
|
||||||
src_offset: 0
|
src_offset: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@learn_src_field 0
|
@learn_src_field 0
|
||||||
@learn_dst 2
|
@learn_dst 2
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -17,53 +17,60 @@ 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{
|
||||||
hard_timeout: options[:hard_timeout] || 0,
|
idle_timeout: options[:idle_timeout] || 0,
|
||||||
priority: options[:priority] || 0,
|
hard_timeout: options[:hard_timeout] || 0,
|
||||||
cookie: options[:cookie] || 0,
|
priority: options[:priority] || 0,
|
||||||
flags: options[:flags] || [],
|
cookie: options[:cookie] || 0,
|
||||||
table_id: options[:table_id] || 0xff,
|
flags: options[:flags] || [],
|
||||||
fin_idle_timeout: options[:fin_idle_timeout] || 0,
|
table_id: options[:table_id] || 0xFF,
|
||||||
fin_hard_timeout: options[:fin_hard_timeout] || 0,
|
fin_idle_timeout: options[:fin_idle_timeout] || 0,
|
||||||
flow_specs: options[:flow_specs] || []}
|
fin_hard_timeout: options[:fin_hard_timeout] || 0,
|
||||||
|
flow_specs: options[:flow_specs] || []
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxLearn{idle_timeout: idle,
|
def to_binary(%NxLearn{
|
||||||
hard_timeout: hard,
|
idle_timeout: idle,
|
||||||
priority: prio,
|
hard_timeout: hard,
|
||||||
cookie: cookie,
|
priority: prio,
|
||||||
flags: flags,
|
cookie: cookie,
|
||||||
table_id: table_id,
|
flags: flags,
|
||||||
fin_idle_timeout: fin_idle,
|
table_id: table_id,
|
||||||
fin_hard_timeout: fin_hard,
|
fin_idle_timeout: fin_idle,
|
||||||
flow_specs: flow_specs}) do
|
fin_hard_timeout: fin_hard,
|
||||||
|
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,
|
|
||||||
hard_timeout: hard,
|
%NxLearn{
|
||||||
priority: prio,
|
idle_timeout: idle,
|
||||||
cookie: cookie,
|
hard_timeout: hard,
|
||||||
flags: flags,
|
priority: prio,
|
||||||
table_id: table_id,
|
cookie: cookie,
|
||||||
fin_idle_timeout: fin_idle,
|
flags: flags,
|
||||||
fin_hard_timeout: fin_hard,
|
table_id: table_id,
|
||||||
flow_specs: flow_specs}
|
fin_idle_timeout: fin_idle,
|
||||||
|
fin_hard_timeout: fin_hard,
|
||||||
|
flow_specs: flow_specs
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -20,65 +20,77 @@ 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{
|
||||||
hard_timeout: options[:hard_timeout] || 0,
|
idle_timeout: options[:idle_timeout] || 0,
|
||||||
priority: options[:priority] || 0,
|
hard_timeout: options[:hard_timeout] || 0,
|
||||||
cookie: options[:cookie] || 0,
|
priority: options[:priority] || 0,
|
||||||
flags: options[:flags] || [],
|
cookie: options[:cookie] || 0,
|
||||||
table_id: options[:table_id] || 0xff,
|
flags: options[:flags] || [],
|
||||||
fin_idle_timeout: options[:fin_idle_timeout] || 0,
|
table_id: options[:table_id] || 0xFF,
|
||||||
fin_hard_timeout: options[:fin_hard_timeout] || 0,
|
fin_idle_timeout: options[:fin_idle_timeout] || 0,
|
||||||
limit: options[:limit] || 0,
|
fin_hard_timeout: options[:fin_hard_timeout] || 0,
|
||||||
result_dst_offset: options[:result_dst_offset] || 0,
|
limit: options[:limit] || 0,
|
||||||
result_dst: options[:result_dst],
|
result_dst_offset: options[:result_dst_offset] || 0,
|
||||||
flow_specs: options[:flow_specs] || []}
|
result_dst: options[:result_dst],
|
||||||
|
flow_specs: options[:flow_specs] || []
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxLearn2{idle_timeout: idle,
|
def to_binary(%NxLearn2{
|
||||||
hard_timeout: hard,
|
idle_timeout: idle,
|
||||||
priority: prio,
|
hard_timeout: hard,
|
||||||
cookie: cookie,
|
priority: prio,
|
||||||
flags: flags,
|
cookie: cookie,
|
||||||
table_id: table_id,
|
flags: flags,
|
||||||
fin_idle_timeout: fin_idle,
|
table_id: table_id,
|
||||||
fin_hard_timeout: fin_hard,
|
fin_idle_timeout: fin_idle,
|
||||||
limit: limit,
|
fin_hard_timeout: fin_hard,
|
||||||
result_dst_offset: result_dst_ofs,
|
limit: limit,
|
||||||
result_dst: result_dst,
|
result_dst_offset: result_dst_ofs,
|
||||||
flow_specs: flow_specs}) do
|
result_dst: result_dst,
|
||||||
|
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
|
|
||||||
Openflow.Match.codec_header(result_dst)
|
result_dst_bin =
|
||||||
else
|
if :write_result in flags do
|
||||||
""
|
Openflow.Match.codec_header(result_dst)
|
||||||
end
|
else
|
||||||
|
""
|
||||||
|
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,
|
|
||||||
hard_timeout: hard,
|
learn = %NxLearn2{
|
||||||
priority: prio,
|
idle_timeout: idle,
|
||||||
cookie: cookie,
|
hard_timeout: hard,
|
||||||
flags: flags,
|
priority: prio,
|
||||||
table_id: table_id,
|
cookie: cookie,
|
||||||
fin_idle_timeout: fin_idle,
|
flags: flags,
|
||||||
fin_hard_timeout: fin_hard,
|
table_id: table_id,
|
||||||
limit: limit,
|
fin_idle_timeout: fin_idle,
|
||||||
result_dst_offset: result_dst_ofs}
|
fin_hard_timeout: fin_hard,
|
||||||
|
limit: limit,
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ defmodule Openflow.Action.NxMultipath do
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
hash_field: :eth_src,
|
hash_field: :eth_src,
|
||||||
basis: 0,
|
basis: 0,
|
||||||
algorithm: :modulo_n,
|
algorithm: :modulo_n,
|
||||||
max_link: 0,
|
max_link: 0,
|
||||||
argument: 0,
|
argument: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
dst_field: nil
|
dst_field: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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,
|
|
||||||
basis: basis,
|
%NxMultipath{
|
||||||
algorithm: alg,
|
hash_field: hash_field,
|
||||||
max_link: max_link,
|
basis: basis,
|
||||||
offset: ofs,
|
algorithm: alg,
|
||||||
n_bits: n_bits,
|
max_link: max_link,
|
||||||
argument: arg,
|
offset: ofs,
|
||||||
dst_field: dst_field}
|
n_bits: n_bits,
|
||||||
|
argument: arg,
|
||||||
|
dst_field: dst_field
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxMultipath{hash_field: hash_field,
|
def to_binary(%NxMultipath{
|
||||||
basis: basis,
|
hash_field: hash_field,
|
||||||
algorithm: alg,
|
basis: basis,
|
||||||
max_link: max_link,
|
algorithm: alg,
|
||||||
argument: arg,
|
max_link: max_link,
|
||||||
offset: ofs,
|
argument: arg,
|
||||||
n_bits: n_bits,
|
offset: ofs,
|
||||||
dst_field: dst_field}) do
|
n_bits: n_bits,
|
||||||
|
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,
|
|
||||||
basis: basis,
|
%NxMultipath{
|
||||||
algorithm: alg,
|
hash_field: hash_field,
|
||||||
max_link: max_link,
|
basis: basis,
|
||||||
argument: arg,
|
algorithm: alg,
|
||||||
offset: ofs,
|
max_link: max_link,
|
||||||
n_bits: n_bits + 1,
|
argument: arg,
|
||||||
dst_field: dst_field}
|
offset: ofs,
|
||||||
|
n_bits: n_bits + 1,
|
||||||
|
dst_field: dst_field
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
defmodule Openflow.Action.NxNat do
|
defmodule Openflow.Action.NxNat do
|
||||||
defstruct(
|
defstruct(
|
||||||
flags: [],
|
flags: [],
|
||||||
ipv4_min: nil,
|
ipv4_min: nil,
|
||||||
ipv4_max: nil,
|
ipv4_max: nil,
|
||||||
ipv6_min: nil,
|
ipv6_min: nil,
|
||||||
ipv6_max: nil,
|
ipv6_max: nil,
|
||||||
proto_min: nil,
|
proto_min: nil,
|
||||||
proto_max: nil
|
proto_max: nil
|
||||||
)
|
)
|
||||||
|
|
@ -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,
|
|
||||||
ipv4_min: ipv4_min,
|
%NxNat{
|
||||||
ipv4_max: ipv4_max,
|
flags: flags,
|
||||||
ipv6_min: ipv6_min,
|
ipv4_min: ipv4_min,
|
||||||
ipv6_max: ipv6_max,
|
ipv4_max: ipv4_max,
|
||||||
proto_min: proto_min,
|
ipv6_min: ipv6_min,
|
||||||
proto_max: proto_max}
|
ipv6_max: ipv6_max,
|
||||||
|
proto_min: proto_min,
|
||||||
|
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 =
|
||||||
exp_body_size = byte_size(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)
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ defmodule Openflow.Action.NxNote do
|
||||||
def to_binary(%NxNote{note: note}) do
|
def to_binary(%NxNote{note: note}) do
|
||||||
padding = Openflow.Utils.padding(byte_size(note) + 2, 8)
|
padding = Openflow.Utils.padding(byte_size(note) + 2, 8)
|
||||||
exp_body = <<@experimenter::32, @nxast::16, note::bytes, 0::size(padding)-unit(8)>>
|
exp_body = <<@experimenter::32, @nxast::16, note::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, note_bin::bytes>>) do
|
def read(<<@experimenter::32, @nxast::16, note_bin::bytes>>) do
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ defmodule Openflow.Action.NxOutputReg do
|
||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
src_field: nil,
|
src_field: nil,
|
||||||
max_len: :no_buffer
|
max_len: :no_buffer
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ defmodule Openflow.Action.NxOutputReg2 do
|
||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
src_field: nil,
|
src_field: nil,
|
||||||
max_len: :no_buffer
|
max_len: :no_buffer
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -24,28 +24,31 @@ 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)>>
|
||||||
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, 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
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ defmodule Openflow.Action.NxOutputTrunc do
|
||||||
def to_binary(%NxOutputTrunc{port_number: port_no, max_len: max_len}) do
|
def to_binary(%NxOutputTrunc{port_number: port_no, max_len: max_len}) do
|
||||||
port_no_int = Openflow.Utils.get_enum(port_no, :openflow10_port_no)
|
port_no_int = Openflow.Utils.get_enum(port_no, :openflow10_port_no)
|
||||||
exp_body = <<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>>
|
exp_body = <<@experimenter::32, @nxast::16, port_no_int::16, max_len::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, port_no_int::16, max_len::32>>) do
|
def read(<<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>>) do
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxPopMpls do
|
||||||
|
|
||||||
def to_binary(%NxPopMpls{ethertype: ethertype}) do
|
def to_binary(%NxPopMpls{ethertype: ethertype}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, ethertype::16, 0::size(4)-unit(8)>>
|
exp_body = <<@experimenter::32, @nxast::16, ethertype::16, 0::size(4)-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, ethertype::16, _::size(4)-unit(8)>>) do
|
def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ defmodule Openflow.Action.NxPopQueue do
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
@nxast 5
|
@nxast 5
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
def new do
|
def new do
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxPopQueue do
|
||||||
|
|
||||||
def to_binary(%NxPopQueue{}) do
|
def to_binary(%NxPopQueue{}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, 0::48>>
|
exp_body = <<@experimenter::32, @nxast::16, 0::48>>
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxPushMpls do
|
||||||
|
|
||||||
def to_binary(%NxPushMpls{ethertype: ethertype}) do
|
def to_binary(%NxPushMpls{ethertype: ethertype}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, ethertype::16, 0::size(4)-unit(8)>>
|
exp_body = <<@experimenter::32, @nxast::16, ethertype::16, 0::size(4)-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, ethertype::16, _::size(4)-unit(8)>>) do
|
def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ defmodule Openflow.Action.NxRegLoad do
|
||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
dst_field: nil,
|
dst_field: nil,
|
||||||
value: nil
|
value: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Openflow.Action.NxRegLoad2 do
|
defmodule Openflow.Action.NxRegLoad2 do
|
||||||
defstruct(
|
defstruct(
|
||||||
dst_field: nil,
|
dst_field: nil,
|
||||||
value: nil
|
value: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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_size = byte_size(exp_body)
|
exp_body =
|
||||||
|
<<@experimenter::32, @nxast::16, 0::48, padded_field::bytes, 0::size(padding)-unit(8)>>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
defmodule Openflow.Action.NxRegMove do
|
defmodule Openflow.Action.NxRegMove do
|
||||||
defstruct(
|
defstruct(
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
src_offset: 0,
|
src_offset: 0,
|
||||||
dst_offset: 0,
|
dst_offset: 0,
|
||||||
src_field: nil,
|
src_field: nil,
|
||||||
dst_field: nil
|
dst_field: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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,
|
|
||||||
src_offset: src_ofs,
|
%NxRegMove{
|
||||||
dst_offset: dst_ofs,
|
n_bits: n_bits,
|
||||||
src_field: src_field,
|
src_offset: src_ofs,
|
||||||
dst_field: dst_field}
|
dst_offset: dst_ofs,
|
||||||
|
src_field: src_field,
|
||||||
|
dst_field: dst_field
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxRegMove{n_bits: n_bits,
|
def to_binary(%NxRegMove{
|
||||||
src_offset: src_ofs,
|
n_bits: n_bits,
|
||||||
dst_offset: dst_ofs,
|
src_offset: src_ofs,
|
||||||
src_field: src_field,
|
dst_offset: dst_ofs,
|
||||||
dst_field: dst_field}) do
|
src_field: src_field,
|
||||||
|
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,
|
|
||||||
src_offset: src_ofs,
|
%NxRegMove{
|
||||||
dst_offset: dst_ofs,
|
n_bits: n_bits,
|
||||||
src_field: src_field,
|
src_offset: src_ofs,
|
||||||
dst_field: dst_field}
|
dst_offset: dst_ofs,
|
||||||
|
src_field: src_field,
|
||||||
|
dst_field: dst_field
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -13,10 +13,10 @@ defmodule Openflow.Action.NxResubmit do
|
||||||
def to_binary(%NxResubmit{in_port: in_port}) do
|
def to_binary(%NxResubmit{in_port: in_port}) do
|
||||||
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
|
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
|
||||||
exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, 0::size(4)-unit(8)>>
|
exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, 0::size(4)-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, in_port_int::16, _::size(4)-unit(8)>>) do
|
def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -19,13 +20,15 @@ defmodule Openflow.Action.NxResubmitTable do
|
||||||
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
|
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
|
||||||
table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
|
table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
|
||||||
exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::24>>
|
exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::24>>
|
||||||
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}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,15 @@ defmodule Openflow.Action.NxResubmitTableCt do
|
||||||
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
|
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
|
||||||
table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
|
table_id_int = Openflow.Utils.get_enum(table_id, :table_id)
|
||||||
exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::24>>
|
exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::24>>
|
||||||
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}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule Openflow.Action.NxSample do
|
defmodule Openflow.Action.NxSample do
|
||||||
defstruct(
|
defstruct(
|
||||||
probability: 0,
|
probability: 0,
|
||||||
collector_set_id: 0,
|
collector_set_id: 0,
|
||||||
obs_domain_id: 0,
|
obs_domain_id: 0,
|
||||||
obs_point_id: 0
|
obs_point_id: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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,
|
|
||||||
collector_set_id: collector_set_id,
|
%NxSample{
|
||||||
obs_domain_id: obs_domain_id,
|
probability: probability,
|
||||||
obs_point_id: obs_point_id}
|
collector_set_id: collector_set_id,
|
||||||
|
obs_domain_id: obs_domain_id,
|
||||||
|
obs_point_id: obs_point_id
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxSample{probability: probability,
|
def to_binary(%NxSample{
|
||||||
collector_set_id: collector_set_id,
|
probability: probability,
|
||||||
obs_domain_id: obs_domain_id,
|
collector_set_id: collector_set_id,
|
||||||
obs_point_id: obs_point_id}) do
|
obs_domain_id: obs_domain_id,
|
||||||
exp_body = <<@experimenter::32, @nxast::16, probability::16,
|
obs_point_id: obs_point_id
|
||||||
collector_set_id::32, obs_domain_id::32, obs_point_id::32>>
|
}) do
|
||||||
exp_body_size = byte_size(exp_body)
|
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)
|
||||||
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>>
|
||||||
collector_set_id: collector_set_id,
|
) do
|
||||||
obs_domain_id: obs_domain_id,
|
%NxSample{
|
||||||
obs_point_id: obs_point_id}
|
probability: probability,
|
||||||
|
collector_set_id: collector_set_id,
|
||||||
|
obs_domain_id: obs_domain_id,
|
||||||
|
obs_point_id: obs_point_id
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
defmodule Openflow.Action.NxSample2 do
|
defmodule Openflow.Action.NxSample2 do
|
||||||
defstruct(
|
defstruct(
|
||||||
probability: 0,
|
probability: 0,
|
||||||
collector_set_id: 0,
|
collector_set_id: 0,
|
||||||
obs_domain_id: 0,
|
obs_domain_id: 0,
|
||||||
obs_point_id: 0,
|
obs_point_id: 0,
|
||||||
sampling_port: 0
|
sampling_port: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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,
|
|
||||||
collector_set_id: collector_set_id,
|
%NxSample2{
|
||||||
obs_domain_id: obs_domain_id,
|
probability: probability,
|
||||||
obs_point_id: obs_point_id,
|
collector_set_id: collector_set_id,
|
||||||
sampling_port: sampling_port}
|
obs_domain_id: obs_domain_id,
|
||||||
|
obs_point_id: obs_point_id,
|
||||||
|
sampling_port: sampling_port
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxSample2{probability: probability,
|
def to_binary(%NxSample2{
|
||||||
collector_set_id: collector_set_id,
|
probability: probability,
|
||||||
obs_domain_id: obs_domain_id,
|
collector_set_id: collector_set_id,
|
||||||
obs_point_id: obs_point_id,
|
obs_domain_id: obs_domain_id,
|
||||||
sampling_port: sampling_port}) do
|
obs_point_id: obs_point_id,
|
||||||
exp_body = <<@experimenter::32, @nxast::16, probability::16,
|
sampling_port: sampling_port
|
||||||
collector_set_id::32, obs_domain_id::32, obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>>
|
}) do
|
||||||
exp_body_size = byte_size(exp_body)
|
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)
|
||||||
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)>>
|
||||||
collector_set_id: collector_set_id,
|
) do
|
||||||
obs_domain_id: obs_domain_id,
|
%NxSample2{
|
||||||
obs_point_id: obs_point_id,
|
probability: probability,
|
||||||
sampling_port: sampling_port}
|
collector_set_id: collector_set_id,
|
||||||
|
obs_domain_id: obs_domain_id,
|
||||||
|
obs_point_id: obs_point_id,
|
||||||
|
sampling_port: sampling_port
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule Openflow.Action.NxSample3 do
|
defmodule Openflow.Action.NxSample3 do
|
||||||
defstruct(
|
defstruct(
|
||||||
probability: 0,
|
probability: 0,
|
||||||
collector_set_id: 0,
|
collector_set_id: 0,
|
||||||
obs_domain_id: 0,
|
obs_domain_id: 0,
|
||||||
obs_point_id: 0,
|
obs_point_id: 0,
|
||||||
sampling_port: 0,
|
sampling_port: 0,
|
||||||
direction: :default
|
direction: :default
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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,
|
|
||||||
collector_set_id: collector_set_id,
|
%NxSample3{
|
||||||
obs_domain_id: obs_domain_id,
|
probability: probability,
|
||||||
obs_point_id: obs_point_id,
|
collector_set_id: collector_set_id,
|
||||||
sampling_port: sampling_port,
|
obs_domain_id: obs_domain_id,
|
||||||
direction: direction}
|
obs_point_id: obs_point_id,
|
||||||
|
sampling_port: sampling_port,
|
||||||
|
direction: direction
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%NxSample3{probability: probability,
|
def to_binary(%NxSample3{
|
||||||
collector_set_id: collector_set_id,
|
probability: probability,
|
||||||
obs_domain_id: obs_domain_id,
|
collector_set_id: collector_set_id,
|
||||||
obs_point_id: obs_point_id,
|
obs_domain_id: obs_domain_id,
|
||||||
sampling_port: sampling_port,
|
obs_point_id: obs_point_id,
|
||||||
direction: direction}) do
|
sampling_port: sampling_port,
|
||||||
|
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 =
|
||||||
exp_body_size = byte_size(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)
|
||||||
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,
|
|
||||||
collector_set_id: collector_set_id,
|
%NxSample3{
|
||||||
obs_domain_id: obs_domain_id,
|
probability: probability,
|
||||||
obs_point_id: obs_point_id,
|
collector_set_id: collector_set_id,
|
||||||
sampling_port: sampling_port,
|
obs_domain_id: obs_domain_id,
|
||||||
direction: direction}
|
obs_point_id: obs_point_id,
|
||||||
|
sampling_port: sampling_port,
|
||||||
|
direction: direction
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetMplsLabel do
|
||||||
|
|
||||||
def to_binary(%NxSetMplsLabel{label: label}) do
|
def to_binary(%NxSetMplsLabel{label: label}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, 0::16, label::32>>
|
exp_body = <<@experimenter::32, @nxast::16, 0::16, label::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, _::16, label::32>>) do
|
def read(<<@experimenter::32, @nxast::16, _::16, label::32>>) do
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetMplsTc do
|
||||||
|
|
||||||
def to_binary(%NxSetMplsTc{tc: tc}) do
|
def to_binary(%NxSetMplsTc{tc: tc}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, tc::8, 0::size(5)-unit(8)>>
|
exp_body = <<@experimenter::32, @nxast::16, tc::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, tc::8, _::size(5)-unit(8)>>) do
|
def read(<<@experimenter::32, @nxast::16, tc::8, _::size(5)-unit(8)>>) do
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetMplsTtl do
|
||||||
|
|
||||||
def to_binary(%NxSetMplsTtl{ttl: ttl}) do
|
def to_binary(%NxSetMplsTtl{ttl: ttl}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, ttl::8, 0::size(5)-unit(8)>>
|
exp_body = <<@experimenter::32, @nxast::16, ttl::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, ttl::8, _::size(5)-unit(8)>>) do
|
def read(<<@experimenter::32, @nxast::16, ttl::8, _::size(5)-unit(8)>>) do
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetQueue do
|
||||||
|
|
||||||
def to_binary(%NxSetQueue{queue_id: queue_id}) do
|
def to_binary(%NxSetQueue{queue_id: queue_id}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, 0::16, queue_id::32>>
|
exp_body = <<@experimenter::32, @nxast::16, 0::16, queue_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, 0::size(2)-unit(8), queue_id::32>>) do
|
def read(<<@experimenter::32, @nxast::16, 0::size(2)-unit(8), queue_id::32>>) do
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetTunnel do
|
||||||
|
|
||||||
def to_binary(%NxSetTunnel{tunnel_id: tunnel_id}) do
|
def to_binary(%NxSetTunnel{tunnel_id: tunnel_id}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, 0::16, tunnel_id::32>>
|
exp_body = <<@experimenter::32, @nxast::16, 0::16, tunnel_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, _::16, tunnel_id::32>>) do
|
def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetTunnel64 do
|
||||||
|
|
||||||
def to_binary(%NxSetTunnel64{tunnel_id: tunnel_id}) do
|
def to_binary(%NxSetTunnel64{tunnel_id: tunnel_id}) do
|
||||||
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>>
|
exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::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, 0::size(6)-unit(8), tunnel_id::64>>) do
|
def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>>) do
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule Openflow.Action.NxStackPop do
|
defmodule Openflow.Action.NxStackPop do
|
||||||
defstruct(
|
defstruct(
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
field: nil
|
field: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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 =
|
||||||
exp_body_size = byte_size(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)
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
defmodule Openflow.Action.NxStackPush do
|
defmodule Openflow.Action.NxStackPush do
|
||||||
defstruct(
|
defstruct(
|
||||||
n_bits: 0,
|
n_bits: 0,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
field: nil
|
field: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
@experimenter 0x00002320
|
@experimenter 0x00002320
|
||||||
|
|
@ -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 =
|
||||||
exp_body_size = byte_size(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)
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
exp_body_size = byte_size(exp_body)
|
<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), metadata::64, metadata_mask::64>>
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule Openflow.Action.PushPbb do
|
defmodule Openflow.Action.PushPbb do
|
||||||
defstruct(ethertype: 0x88e7)
|
defstruct(ethertype: 0x88E7)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule Openflow.Barrier.Reply do
|
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__
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule Openflow.Barrier.Request do
|
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__
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
defmodule Openflow.Bucket do
|
defmodule Openflow.Bucket do
|
||||||
defstruct(
|
defstruct(
|
||||||
weight: 0,
|
weight: 0,
|
||||||
watch_port: 0,
|
watch_port: 0,
|
||||||
watch_group: 0,
|
watch_group: 0,
|
||||||
actions: []
|
actions: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
defmodule Openflow.Echo.Reply do
|
defmodule Openflow.Echo.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
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__
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
defmodule Openflow.Echo.Request do
|
defmodule Openflow.Echo.Request do
|
||||||
defstruct(
|
defstruct(
|
||||||
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
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -2,33 +2,38 @@ defmodule Openflow.ErrorMsg do
|
||||||
@moduledoc "OpenFlow Error codec module"
|
@moduledoc "OpenFlow Error codec module"
|
||||||
|
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
type: nil,
|
type: nil,
|
||||||
code: nil,
|
code: nil,
|
||||||
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,
|
||||||
experimenter: experimenter,
|
experimenter: experimenter,
|
||||||
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{
|
||||||
exp_type: exp_type,
|
type: :experimenter,
|
||||||
experimenter: experimenter,
|
exp_type: exp_type,
|
||||||
data: data}) do
|
experimenter: experimenter,
|
||||||
|
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>>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
defmodule Openflow.Experimenter do
|
defmodule Openflow.Experimenter do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: "",
|
datapath_id: "",
|
||||||
aux_id: 0,
|
aux_id: 0,
|
||||||
exp_id: 0,
|
exp_id: 0,
|
||||||
exp_type: 0,
|
exp_type: 0,
|
||||||
data: ""
|
data: ""
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -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_type: Keyword.get(options, :exp_type, 0),
|
exp_id: Keyword.get(options, :exp_id, 0),
|
||||||
data: Keyword.get(options, :data, "")}
|
exp_type: Keyword.get(options, :exp_type, 0),
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
defmodule Openflow.Features.Reply do
|
defmodule Openflow.Features.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: "",
|
datapath_id: "",
|
||||||
n_buffers: 0,
|
n_buffers: 0,
|
||||||
n_tables: 0,
|
n_tables: 0,
|
||||||
aux_id: 0,
|
aux_id: 0,
|
||||||
capabilities: []
|
capabilities: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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>>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule Openflow.Features.Request do
|
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__
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ defmodule Openflow.FlowMod do
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: "",
|
datapath_id: "",
|
||||||
aux_id: 0,
|
aux_id: 0,
|
||||||
cookie: 0,
|
cookie: 0,
|
||||||
cookie_mask: 0,
|
cookie_mask: 0,
|
||||||
table_id: 0,
|
table_id: 0,
|
||||||
|
|
@ -35,26 +35,31 @@ 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,
|
|
||||||
cookie_mask: cookie_mask,
|
%FlowMod{
|
||||||
priority: priority,
|
cookie: cookie,
|
||||||
table_id: table_id,
|
cookie_mask: cookie_mask,
|
||||||
command: command,
|
priority: priority,
|
||||||
idle_timeout: idle,
|
table_id: table_id,
|
||||||
hard_timeout: hard,
|
command: command,
|
||||||
buffer_id: buffer_id,
|
idle_timeout: idle,
|
||||||
out_port: out_port,
|
hard_timeout: hard,
|
||||||
out_group: out_group,
|
buffer_id: buffer_id,
|
||||||
flags: flags,
|
out_port: out_port,
|
||||||
match: match,
|
out_group: out_group,
|
||||||
instructions: instructions}
|
flags: flags,
|
||||||
|
match: match,
|
||||||
|
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,35 +69,41 @@ 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,
|
|
||||||
cookie_mask: cookie_mask,
|
%FlowMod{
|
||||||
priority: prio,
|
cookie: cookie,
|
||||||
table_id: table_id,
|
cookie_mask: cookie_mask,
|
||||||
command: command,
|
priority: prio,
|
||||||
idle_timeout: idle,
|
table_id: table_id,
|
||||||
hard_timeout: hard,
|
command: command,
|
||||||
buffer_id: buffer_id,
|
idle_timeout: idle,
|
||||||
out_port: out_port,
|
hard_timeout: hard,
|
||||||
out_group: out_group,
|
buffer_id: buffer_id,
|
||||||
flags: flags,
|
out_port: out_port,
|
||||||
match: match,
|
out_group: out_group,
|
||||||
instructions: instructions}
|
flags: flags,
|
||||||
|
match: match,
|
||||||
|
instructions: instructions
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(flow_mod) do
|
def to_binary(flow_mod) do
|
||||||
%FlowMod{cookie: cookie,
|
%FlowMod{
|
||||||
cookie_mask: cookie_mask,
|
cookie: cookie,
|
||||||
priority: prio,
|
cookie_mask: cookie_mask,
|
||||||
table_id: table_id,
|
priority: prio,
|
||||||
command: command,
|
table_id: table_id,
|
||||||
idle_timeout: idle,
|
command: command,
|
||||||
hard_timeout: hard,
|
idle_timeout: idle,
|
||||||
buffer_id: buffer_id,
|
hard_timeout: hard,
|
||||||
out_port: out_port,
|
buffer_id: buffer_id,
|
||||||
out_group: out_group,
|
out_port: out_port,
|
||||||
flags: flags,
|
out_group: out_group,
|
||||||
match: match_fields,
|
flags: flags,
|
||||||
instructions: instructions} = flow_mod
|
match: match_fields,
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,46 @@
|
||||||
defmodule Openflow.FlowRemoved do
|
defmodule Openflow.FlowRemoved do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: "",
|
datapath_id: "",
|
||||||
aux_id: 0,
|
aux_id: 0,
|
||||||
cookie: 0,
|
cookie: 0,
|
||||||
priority: 0,
|
priority: 0,
|
||||||
reason: :idle_timeout,
|
reason: :idle_timeout,
|
||||||
table_id: 0,
|
table_id: 0,
|
||||||
duration_sec: 0,
|
duration_sec: 0,
|
||||||
duration_nsec: 0,
|
duration_nsec: 0,
|
||||||
idle_timeout: 0,
|
idle_timeout: 0,
|
||||||
hard_timeout: 0,
|
hard_timeout: 0,
|
||||||
packet_count: 0,
|
packet_count: 0,
|
||||||
byte_count: 0,
|
byte_count: 0,
|
||||||
match: []
|
match: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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,
|
|
||||||
priority: priority,
|
%FlowRemoved{
|
||||||
reason: reason,
|
cookie: cookie,
|
||||||
table_id: table_id,
|
priority: priority,
|
||||||
duration_sec: dsec,
|
reason: reason,
|
||||||
duration_nsec: dnsec,
|
table_id: table_id,
|
||||||
idle_timeout: idle,
|
duration_sec: dsec,
|
||||||
hard_timeout: hard,
|
duration_nsec: dnsec,
|
||||||
packet_count: pkt,
|
idle_timeout: idle,
|
||||||
byte_count: byt,
|
hard_timeout: hard,
|
||||||
match: match_fields}
|
packet_count: pkt,
|
||||||
|
byte_count: byt,
|
||||||
|
match: match_fields
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,46 @@
|
||||||
defmodule Openflow.GetAsync.Reply do
|
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,
|
||||||
packet_in_mask_master: 0,
|
# virtual field
|
||||||
packet_in_mask_slave: 0,
|
aux_id: 0,
|
||||||
port_status_mask_master: 0,
|
packet_in_mask_master: 0,
|
||||||
port_status_mask_slave: 0,
|
packet_in_mask_slave: 0,
|
||||||
|
port_status_mask_master: 0,
|
||||||
|
port_status_mask_slave: 0,
|
||||||
flow_removed_mask_master: 0,
|
flow_removed_mask_master: 0,
|
||||||
flow_removed_mask_slave: 0
|
flow_removed_mask_slave: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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
|
||||||
packet_in_mask_slave: packet_in_mask_slave,
|
%Reply{
|
||||||
port_status_mask_master: port_status_mask_master,
|
packet_in_mask_master: packet_in_mask_master,
|
||||||
port_status_mask_slave: port_status_mask_slave,
|
packet_in_mask_slave: packet_in_mask_slave,
|
||||||
flow_removed_mask_master: flow_removed_mask_master,
|
port_status_mask_master: port_status_mask_master,
|
||||||
flow_removed_mask_slave: flow_removed_mask_slave}
|
port_status_mask_slave: port_status_mask_slave,
|
||||||
|
flow_removed_mask_master: flow_removed_mask_master,
|
||||||
|
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_slave: packet_in_mask_slave,
|
packet_in_mask_master: packet_in_mask_master,
|
||||||
port_status_mask_master: port_status_mask_master,
|
packet_in_mask_slave: packet_in_mask_slave,
|
||||||
port_status_mask_slave: port_status_mask_slave,
|
port_status_mask_master: port_status_mask_master,
|
||||||
flow_removed_mask_master: flow_removed_mask_master,
|
port_status_mask_slave: port_status_mask_slave,
|
||||||
flow_removed_mask_slave: flow_removed_mask_slave}) do
|
flow_removed_mask_master: flow_removed_mask_master,
|
||||||
<<packet_in_mask_master::32, packet_in_mask_slave::32,
|
flow_removed_mask_slave: flow_removed_mask_slave
|
||||||
port_status_mask_master::32, port_status_mask_slave::32,
|
}) do
|
||||||
flow_removed_mask_master::32, flow_removed_mask_slave::32>>
|
<<packet_in_mask_master::32, packet_in_mask_slave::32, port_status_mask_master::32,
|
||||||
|
port_status_mask_slave::32, flow_removed_mask_master::32, flow_removed_mask_slave::32>>
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule Openflow.GetAsync.Request do
|
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__
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
defmodule Openflow.GetConfig.Reply do
|
defmodule Openflow.GetConfig.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
defmodule Openflow.GetConfig.Request do
|
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__
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ defmodule Openflow.GroupMod do
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: "",
|
datapath_id: "",
|
||||||
aux_id: 0,
|
aux_id: 0,
|
||||||
command: :add,
|
command: :add,
|
||||||
type: :all,
|
type: :all,
|
||||||
group_id: 0,
|
group_id: 0,
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
defmodule Openflow.Match do
|
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 =
|
||||||
1 ->
|
case has_mask(oxm_field0) do
|
||||||
string = to_string(oxm_field0)
|
1 ->
|
||||||
"masked_" <> field = string
|
string = to_string(oxm_field0)
|
||||||
String.to_atom(field)
|
"masked_" <> field = string
|
||||||
0 ->
|
String.to_atom(field)
|
||||||
oxm_field0
|
|
||||||
end
|
0 ->
|
||||||
|
oxm_field0
|
||||||
|
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(
|
||||||
do: 4
|
<<_oxm_class_int::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _::bytes>>
|
||||||
def header_size(<<0xffff::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _exp_int::32, _::bytes>>),
|
),
|
||||||
do: 8
|
do: 4
|
||||||
|
|
||||||
|
def header_size(
|
||||||
|
<<0xFFFF::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _exp_int::32,
|
||||||
|
_::bytes>>
|
||||||
|
),
|
||||||
|
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,37 +151,43 @@ 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})
|
||||||
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 = 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
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule Openflow.MeterBand.Drop do
|
defmodule Openflow.MeterBand.Drop do
|
||||||
defstruct(
|
defstruct(
|
||||||
rate: 0,
|
rate: 0,
|
||||||
burst_size: 0
|
burst_size: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule Openflow.MeterBand.Experimenter do
|
defmodule Openflow.MeterBand.Experimenter do
|
||||||
defstruct(
|
defstruct(
|
||||||
rate: 0,
|
rate: 0,
|
||||||
burst_size: 0,
|
burst_size: 0,
|
||||||
experimenter: 0
|
experimenter: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule Openflow.MeterBand.Remark do
|
defmodule Openflow.MeterBand.Remark do
|
||||||
defstruct(
|
defstruct(
|
||||||
rate: 0,
|
rate: 0,
|
||||||
burst_size: 0,
|
burst_size: 0,
|
||||||
prec_level: 0
|
prec_level: 0
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ defmodule Openflow.MeterMod do
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: "",
|
datapath_id: "",
|
||||||
aux_id: 0,
|
aux_id: 0,
|
||||||
command: :add,
|
command: :add,
|
||||||
flags: [],
|
flags: [],
|
||||||
meter_id: 0,
|
meter_id: 0,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
defmodule Openflow.Multipart.Aggregate.Reply do
|
defmodule Openflow.Multipart.Aggregate.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
|
flags: [],
|
||||||
packet_count: 0,
|
packet_count: 0,
|
||||||
byte_count: 0,
|
byte_count: 0,
|
||||||
flow_count: 0
|
flow_count: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
defmodule Openflow.Multipart.Aggregate.Request do
|
defmodule Openflow.Multipart.Aggregate.Request do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
flags: [],
|
datapath_id: nil,
|
||||||
table_id: :all,
|
flags: [],
|
||||||
out_port: :any,
|
table_id: :all,
|
||||||
out_group: :any,
|
out_port: :any,
|
||||||
cookie: 0,
|
out_group: :any,
|
||||||
cookie_mask: 0,
|
cookie: 0,
|
||||||
match: []
|
cookie_mask: 0,
|
||||||
|
match: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -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,
|
|
||||||
out_port: out_port,
|
%Request{
|
||||||
out_group: out_group,
|
table_id: table_id,
|
||||||
cookie: cookie,
|
out_port: out_port,
|
||||||
cookie_mask: cookie_mask,
|
out_group: out_group,
|
||||||
match: match}
|
cookie: cookie,
|
||||||
|
cookie_mask: cookie_mask,
|
||||||
|
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,
|
|
||||||
out_port: out_port,
|
%Request{
|
||||||
out_group: out_group,
|
table_id: table_id,
|
||||||
cookie: cookie,
|
out_port: out_port,
|
||||||
cookie_mask: cookie_mask,
|
out_group: out_group,
|
||||||
match: match}
|
cookie: cookie,
|
||||||
|
cookie_mask: cookie_mask,
|
||||||
|
match: match
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%Request{table_id: table_id,
|
def to_binary(
|
||||||
out_port: out_port,
|
%Request{
|
||||||
out_group: out_group,
|
table_id: table_id,
|
||||||
cookie: cookie,
|
out_port: out_port,
|
||||||
cookie_mask: cookie_mask,
|
out_group: out_group,
|
||||||
match: match} = msg) do
|
cookie: cookie,
|
||||||
|
cookie_mask: cookie_mask,
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,36 @@
|
||||||
defmodule Openflow.Multipart.Desc.Reply do
|
defmodule Openflow.Multipart.Desc.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
mfr_desc: "",
|
flags: [],
|
||||||
hw_desc: "",
|
mfr_desc: "",
|
||||||
sw_desc: "",
|
hw_desc: "",
|
||||||
serial_num: "",
|
sw_desc: "",
|
||||||
dp_desc: ""
|
serial_num: "",
|
||||||
|
dp_desc: ""
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
@desc_str_len 256
|
@desc_str_len 256
|
||||||
@serial_num_len 32
|
@serial_num_len 32
|
||||||
|
|
||||||
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(
|
||||||
sw_desc::size(@desc_str_len)-bytes, serial_num::size(@serial_num_len)-bytes,
|
<<mfr_desc::size(@desc_str_len)-bytes, hw_desc::size(@desc_str_len)-bytes,
|
||||||
dp_desc::size(@desc_str_len)-bytes>>) do
|
sw_desc::size(@desc_str_len)-bytes, serial_num::size(@serial_num_len)-bytes,
|
||||||
%Reply{mfr_desc: Openflow.Utils.decode_string(mfr_desc),
|
dp_desc::size(@desc_str_len)-bytes>>
|
||||||
hw_desc: Openflow.Utils.decode_string(hw_desc),
|
) do
|
||||||
sw_desc: Openflow.Utils.decode_string(sw_desc),
|
%Reply{
|
||||||
serial_num: Openflow.Utils.decode_string(serial_num),
|
mfr_desc: Openflow.Utils.decode_string(mfr_desc),
|
||||||
dp_desc: Openflow.Utils.decode_string(dp_desc)}
|
hw_desc: Openflow.Utils.decode_string(hw_desc),
|
||||||
|
sw_desc: Openflow.Utils.decode_string(sw_desc),
|
||||||
|
serial_num: Openflow.Utils.decode_string(serial_num),
|
||||||
|
dp_desc: Openflow.Utils.decode_string(dp_desc)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
defmodule Openflow.Multipart.Desc.Request do
|
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: []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
defmodule Openflow.Multipart.Flow.Reply do
|
defmodule Openflow.Multipart.Flow.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
flows: []
|
flags: [],
|
||||||
|
flows: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -22,29 +23,32 @@ 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
|
||||||
|
|
||||||
defmodule Openflow.Multipart.FlowStats do
|
defmodule Openflow.Multipart.FlowStats do
|
||||||
defstruct(
|
defstruct(
|
||||||
table_id: 0,
|
table_id: 0,
|
||||||
duration_sec: 0,
|
duration_sec: 0,
|
||||||
duration_nsec: 0,
|
duration_nsec: 0,
|
||||||
priority: 0,
|
priority: 0,
|
||||||
idle_timeout: 0,
|
idle_timeout: 0,
|
||||||
hard_timeout: 0,
|
hard_timeout: 0,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
cookie: 0,
|
cookie: 0,
|
||||||
packet_count: 0,
|
packet_count: 0,
|
||||||
byte_count: 0,
|
byte_count: 0,
|
||||||
match: [],
|
match: [],
|
||||||
instructions: []
|
instructions: []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -57,30 +61,35 @@ 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,
|
|
||||||
duration_sec: duration_sec,
|
%FlowStats{
|
||||||
duration_nsec: duration_nsec,
|
table_id: table_id,
|
||||||
priority: priority,
|
duration_sec: duration_sec,
|
||||||
idle_timeout: idle,
|
duration_nsec: duration_nsec,
|
||||||
hard_timeout: hard,
|
priority: priority,
|
||||||
flags: flags,
|
idle_timeout: idle,
|
||||||
cookie: cookie,
|
hard_timeout: hard,
|
||||||
packet_count: packet_count,
|
flags: flags,
|
||||||
byte_count: byte_count,
|
cookie: cookie,
|
||||||
match: match,
|
packet_count: packet_count,
|
||||||
instructions: instructions}
|
byte_count: byte_count,
|
||||||
|
match: match,
|
||||||
|
instructions: instructions
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
defmodule Openflow.Multipart.Flow.Request do
|
defmodule Openflow.Multipart.Flow.Request do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
flags: [],
|
datapath_id: nil,
|
||||||
table_id: :all,
|
flags: [],
|
||||||
out_port: :any,
|
table_id: :all,
|
||||||
out_group: :any,
|
out_port: :any,
|
||||||
cookie: 0,
|
out_group: :any,
|
||||||
cookie_mask: 0,
|
cookie: 0,
|
||||||
match: []
|
cookie_mask: 0,
|
||||||
|
match: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -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,
|
|
||||||
out_port: out_port,
|
%Request{
|
||||||
out_group: out_group,
|
table_id: table_id,
|
||||||
cookie: cookie,
|
out_port: out_port,
|
||||||
cookie_mask: cookie_mask,
|
out_group: out_group,
|
||||||
match: match}
|
cookie: cookie,
|
||||||
|
cookie_mask: cookie_mask,
|
||||||
|
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,
|
|
||||||
out_port: out_port,
|
%Request{
|
||||||
out_group: out_group,
|
table_id: table_id,
|
||||||
cookie: cookie,
|
out_port: out_port,
|
||||||
cookie_mask: cookie_mask,
|
out_group: out_group,
|
||||||
match: match}
|
cookie: cookie,
|
||||||
|
cookie_mask: cookie_mask,
|
||||||
|
match: match
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_binary(%Request{table_id: table_id,
|
def to_binary(
|
||||||
out_port: out_port,
|
%Request{
|
||||||
out_group: out_group,
|
table_id: table_id,
|
||||||
cookie: cookie,
|
out_port: out_port,
|
||||||
cookie_mask: cookie_mask,
|
out_group: out_group,
|
||||||
match: match} = msg) do
|
cookie: cookie,
|
||||||
|
cookie_mask: cookie_mask,
|
||||||
|
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
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
defmodule Openflow.Multipart.Group.Reply do
|
defmodule Openflow.Multipart.Group.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
groups: []
|
flags: [],
|
||||||
|
groups: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -22,25 +23,28 @@ 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
|
||||||
|
|
||||||
defmodule Openflow.Multipart.Group do
|
defmodule Openflow.Multipart.Group do
|
||||||
defstruct(
|
defstruct(
|
||||||
group_id: 0,
|
group_id: 0,
|
||||||
ref_count: 0,
|
ref_count: 0,
|
||||||
packet_count: 0,
|
packet_count: 0,
|
||||||
byte_count: 0,
|
byte_count: 0,
|
||||||
duration_sec: 0,
|
duration_sec: 0,
|
||||||
duration_nsec: 0,
|
duration_nsec: 0,
|
||||||
bucket_stats: []
|
bucket_stats: []
|
||||||
)
|
)
|
||||||
|
|
||||||
@ofp_group_stats_size 40
|
@ofp_group_stats_size 40
|
||||||
|
|
@ -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
|
|
||||||
%{packet_count: packet_count, byte_count: byte_count}
|
bucket_stats =
|
||||||
end
|
for <<packet_count::64, byte_count::64 <- bucket_stats_bin>> do
|
||||||
%Group{group_id: group_id,
|
%{packet_count: packet_count, byte_count: byte_count}
|
||||||
ref_count: ref_count,
|
end
|
||||||
packet_count: packet_count,
|
|
||||||
byte_count: byte_count,
|
%Group{
|
||||||
duration_sec: duration_sec,
|
group_id: group_id,
|
||||||
duration_nsec: duration_nsec,
|
ref_count: ref_count,
|
||||||
bucket_stats: bucket_stats}
|
packet_count: packet_count,
|
||||||
|
byte_count: byte_count,
|
||||||
|
duration_sec: duration_sec,
|
||||||
|
duration_nsec: duration_nsec,
|
||||||
|
bucket_stats: bucket_stats
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
defmodule Openflow.Multipart.Group.Request do
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
defmodule Openflow.Multipart.GroupDesc.Reply do
|
defmodule Openflow.Multipart.GroupDesc.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
flags: [],
|
datapath_id: nil,
|
||||||
groups: []
|
flags: [],
|
||||||
|
groups: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -21,21 +22,24 @@ 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
|
||||||
|
|
||||||
defmodule Openflow.Multipart.GroupDescStats do
|
defmodule Openflow.Multipart.GroupDescStats do
|
||||||
defstruct(
|
defstruct(
|
||||||
type: :all,
|
type: :all,
|
||||||
group_id: 0,
|
group_id: 0,
|
||||||
buckets: []
|
buckets: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
defmodule Openflow.Multipart.GroupDesc.Request do
|
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: []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,47 @@
|
||||||
defmodule Openflow.Multipart.GroupFeatures.Reply do
|
defmodule Openflow.Multipart.GroupFeatures.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
types: 0,
|
flags: [],
|
||||||
|
types: 0,
|
||||||
capabilities: [],
|
capabilities: [],
|
||||||
max_groups_for_all: 0,
|
max_groups_for_all: 0,
|
||||||
max_groups_for_select: 0,
|
max_groups_for_select: 0,
|
||||||
max_groups_for_indirect: 0,
|
max_groups_for_indirect: 0,
|
||||||
max_groups_for_fast_failover: 0,
|
max_groups_for_fast_failover: 0,
|
||||||
actions_for_all: 0,
|
actions_for_all: 0,
|
||||||
actions_for_select: 0,
|
actions_for_select: 0,
|
||||||
actions_for_indirect: 0,
|
actions_for_indirect: 0,
|
||||||
actions_for_fast_failover: 0
|
actions_for_fast_failover: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
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,
|
|
||||||
capabilities: capabilities,
|
%Reply{
|
||||||
max_groups_for_all: max_groups_for_all_int,
|
types: types_int,
|
||||||
max_groups_for_select: max_groups_for_select_int,
|
capabilities: capabilities,
|
||||||
max_groups_for_indirect: max_groups_for_indirect_int,
|
max_groups_for_all: max_groups_for_all_int,
|
||||||
max_groups_for_fast_failover: max_groups_for_fast_failover_int,
|
max_groups_for_select: max_groups_for_select_int,
|
||||||
actions_for_all: actions_for_all_int,
|
max_groups_for_indirect: max_groups_for_indirect_int,
|
||||||
actions_for_select: actions_for_select_int,
|
max_groups_for_fast_failover: max_groups_for_fast_failover_int,
|
||||||
actions_for_indirect: actions_for_indirect_int,
|
actions_for_all: actions_for_all_int,
|
||||||
actions_for_fast_failover: actions_for_fast_failover_int}
|
actions_for_select: actions_for_select_int,
|
||||||
|
actions_for_indirect: actions_for_indirect_int,
|
||||||
|
actions_for_fast_failover: actions_for_fast_failover_int
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
defmodule Openflow.Multipart.GroupFeatures.Request do
|
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: []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
defmodule Openflow.Multipart.Meter.Reply do
|
defmodule Openflow.Multipart.Meter.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
meters: []
|
flags: [],
|
||||||
|
meters: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -18,25 +19,28 @@ 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
|
||||||
|
|
||||||
defmodule Openflow.Multipart.Meter do
|
defmodule Openflow.Multipart.Meter do
|
||||||
defstruct(
|
defstruct(
|
||||||
meter_id: 0,
|
meter_id: 0,
|
||||||
flow_count: 0,
|
flow_count: 0,
|
||||||
packet_in_count: 0,
|
packet_in_count: 0,
|
||||||
byte_in_count: 0,
|
byte_in_count: 0,
|
||||||
duration_sec: 0,
|
duration_sec: 0,
|
||||||
duration_nsec: 0,
|
duration_nsec: 0,
|
||||||
band_stats: []
|
band_stats: []
|
||||||
)
|
)
|
||||||
|
|
||||||
@ofp_meter_stats_size 40
|
@ofp_meter_stats_size 40
|
||||||
|
|
@ -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 =
|
||||||
end
|
for <<packet_band_count::64, byte_band_count::64 <- band_stats_bin>> do
|
||||||
%Meter{meter_id: meter_id,
|
%{packet_band_count: packet_band_count, byte_band_count: byte_band_count}
|
||||||
flow_count: flow_count,
|
end
|
||||||
packet_in_count: packet_in_count,
|
|
||||||
byte_in_count: byte_in_count,
|
%Meter{
|
||||||
duration_sec: duration_sec,
|
meter_id: meter_id,
|
||||||
duration_nsec: duration_nsec,
|
flow_count: flow_count,
|
||||||
band_stats: band_stats}
|
packet_in_count: packet_in_count,
|
||||||
|
byte_in_count: byte_in_count,
|
||||||
|
duration_sec: duration_sec,
|
||||||
|
duration_nsec: duration_nsec,
|
||||||
|
band_stats: band_stats
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
defmodule Openflow.Multipart.Meter.Request do
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
defmodule Openflow.Multipart.MeterConfig.Request do
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
defmodule Openflow.Multipart.PortDesc.Reply do
|
defmodule Openflow.Multipart.PortDesc.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
ports: []
|
flags: [],
|
||||||
|
ports: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
defmodule Openflow.Multipart.PortDesc.Request do
|
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: []
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
defmodule Openflow.Multipart.PortStats.Reply do
|
defmodule Openflow.Multipart.PortStats.Reply do
|
||||||
defstruct(
|
defstruct(
|
||||||
version: 4,
|
version: 4,
|
||||||
xid: 0,
|
xid: 0,
|
||||||
datapath_id: nil, # virtual field
|
# virtual field
|
||||||
aux_id: nil,
|
datapath_id: nil,
|
||||||
flags: [],
|
aux_id: nil,
|
||||||
ports: []
|
flags: [],
|
||||||
|
ports: []
|
||||||
)
|
)
|
||||||
|
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
@ -22,32 +23,35 @@ 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
|
||||||
|
|
||||||
defmodule Openflow.Multipart.PortStats do
|
defmodule Openflow.Multipart.PortStats do
|
||||||
defstruct(
|
defstruct(
|
||||||
port_number: 0,
|
port_number: 0,
|
||||||
rx_packets: 0,
|
rx_packets: 0,
|
||||||
tx_packets: 0,
|
tx_packets: 0,
|
||||||
rx_bytes: 0,
|
rx_bytes: 0,
|
||||||
tx_bytes: 0,
|
tx_bytes: 0,
|
||||||
rx_dropped: 0,
|
rx_dropped: 0,
|
||||||
tx_dropped: 0,
|
tx_dropped: 0,
|
||||||
rx_errors: 0,
|
rx_errors: 0,
|
||||||
tx_errors: 0,
|
tx_errors: 0,
|
||||||
rx_frame_err: 0,
|
rx_frame_err: 0,
|
||||||
rx_over_err: 0,
|
rx_over_err: 0,
|
||||||
rx_crc_err: 0,
|
rx_crc_err: 0,
|
||||||
collisions: 0,
|
collisions: 0,
|
||||||
duration_sec: 0,
|
duration_sec: 0,
|
||||||
duration_nsec: 0
|
duration_nsec: 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -60,30 +64,33 @@ 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{
|
||||||
rx_packets: rx_packets,
|
port_number: port_no,
|
||||||
tx_packets: tx_packets,
|
rx_packets: rx_packets,
|
||||||
rx_bytes: rx_bytes,
|
tx_packets: tx_packets,
|
||||||
tx_bytes: tx_bytes,
|
rx_bytes: rx_bytes,
|
||||||
rx_dropped: rx_dropped,
|
tx_bytes: tx_bytes,
|
||||||
tx_dropped: tx_dropped,
|
rx_dropped: rx_dropped,
|
||||||
rx_errors: rx_errors,
|
tx_dropped: tx_dropped,
|
||||||
tx_errors: tx_errors,
|
rx_errors: rx_errors,
|
||||||
rx_frame_err: rx_frame_err,
|
tx_errors: tx_errors,
|
||||||
rx_over_err: rx_over_err,
|
rx_frame_err: rx_frame_err,
|
||||||
rx_crc_err: rx_crc_err,
|
rx_over_err: rx_over_err,
|
||||||
collisions: collisions,
|
rx_crc_err: rx_crc_err,
|
||||||
duration_sec: duration_sec,
|
collisions: collisions,
|
||||||
duration_nsec: duration_nsec}
|
duration_sec: duration_sec,
|
||||||
|
duration_nsec: duration_nsec
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue