diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..b874ba3 --- /dev/null +++ b/.formatter.exs @@ -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 + ] +] diff --git a/config/config.exs b/config/config.exs index e8565e6..40896b3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -3,12 +3,12 @@ use Mix.Config config :tres, - protocol: :tcp, - port: 6653, + protocol: :tcp, + port: 6653, max_connections: 10, - num_acceptors: 10, + num_acceptors: 10, callback_module: Tres.ExampleHandler, - callback_args: [] + callback_args: [] config :logger, level: :info, diff --git a/lib/openflow.ex b/lib/openflow.ex index a0e5f0d..ac30ab8 100644 --- a/lib/openflow.ex +++ b/lib/openflow.ex @@ -5,23 +5,26 @@ defmodule Openflow do @spec read(binary()) :: {:ok, map()} | {:error, :binary_too_small} def read(binary) - when byte_size(binary) < @ofp_header_size do + when byte_size(binary) < @ofp_header_size do {:error, :binary_too_small} end + 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} end + def read(<>) do body_len = len - @ofp_header_size <> = binary2 - result = type - |> Openflow.Enums.to_atom(:openflow_codec) - |> do_read(body_bin) + result = + type + |> Openflow.Enums.to_atom(:openflow_codec) + |> do_read(body_bin) 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} end end @@ -30,19 +33,23 @@ defmodule Openflow do binaries = for message <- messages, do: to_binary(message) Enum.join(binaries, "") end + def to_binary(%{__struct__: encoder, version: version, xid: xid} = msg) do case encoder.to_binary(msg) do body_bin when is_binary(body_bin) -> length = @ofp_header_size + byte_size(body_bin) - <> + <> + {:error, reason} -> {:error, reason} end end def append_body(nil, message), do: message + def append_body(message, continue) do mod = message.__struct__ + if function_exported?(mod, :append_body, 2) do mod.append_body(message, continue) else @@ -55,6 +62,7 @@ defmodule Openflow do defp do_read({:error, reason}, _) do {:error, reason} end + defp do_read(decoder, body_bin) do case decoder.read(body_bin) do {:error, reason} -> {:error, reason} diff --git a/lib/openflow/action.ex b/lib/openflow/action.ex index 2bccd6d..6ffbe57 100644 --- a/lib/openflow/action.ex +++ b/lib/openflow/action.ex @@ -1,5 +1,4 @@ defmodule Openflow.Action do - def read(action_bin) do do_read([], action_bin) end @@ -7,6 +6,7 @@ defmodule Openflow.Action do def to_binary(actions) when is_list(actions) do to_binary(<<>>, actions) end + def to_binary(action) do to_binary([action]) end @@ -15,15 +15,17 @@ defmodule Openflow.Action do defp do_read(acc, <<>>), do: Enum.reverse(acc) defp do_read(acc, <<0::32, _::bytes>>), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary 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 defp to_binary(acc, []), do: acc - defp to_binary(acc, [action|rest]) do + + defp to_binary(acc, [action | rest]) do codec = action.__struct__ - to_binary(<>, rest) + to_binary(<>, rest) end end diff --git a/lib/openflow/actions/experimenter.ex b/lib/openflow/actions/experimenter.ex index 8390026..b2b7e99 100644 --- a/lib/openflow/actions/experimenter.ex +++ b/lib/openflow/actions/experimenter.ex @@ -5,7 +5,7 @@ defmodule Openflow.Action.Experimenter do @experimter_size 8 - def ofpat, do: 0xffff + def ofpat, do: 0xFFFF def new(exp_id, data \\ "") do %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 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 - 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 vendor_id when is_integer(vendor_id) -> %Experimenter{exp_id: exp_id, data: <>} + vendor when is_atom(vendor) -> case Openflow.Utils.get_enum(exp_type, vendor) do codec when is_atom(codec) -> codec.read(<>) + exp_type when is_integer(exp_type) -> %Experimenter{exp_id: exp_id, data: <>} end diff --git a/lib/openflow/actions/nx_bundle.ex b/lib/openflow/actions/nx_bundle.ex index 8fcd5f0..da16230 100644 --- a/lib/openflow/actions/nx_bundle.ex +++ b/lib/openflow/actions/nx_bundle.ex @@ -1,11 +1,11 @@ defmodule Openflow.Action.NxBundle do defstruct( - algorithm: :active_backup, + algorithm: :active_backup, hash_field: :eth_src, - basis: 0, + basis: 0, slave_type: :nx_in_port, - n_slaves: 0, - slaves: [] + n_slaves: 0, + slaves: [] ) @experimenter 0x00002320 @@ -15,36 +15,44 @@ defmodule Openflow.Action.NxBundle do def new(options) do slaves = options[:slaves] || [] - %NxBundle{algorithm: options[:algorithm] || :active_backup, - hash_field: options[:hash_field] || :eth_src, - basis: options[:basis] || 0, - n_slaves: length(slaves), - slaves: slaves} + + %NxBundle{ + algorithm: options[:algorithm] || :active_backup, + hash_field: options[:hash_field] || :eth_src, + basis: options[:basis] || 0, + n_slaves: length(slaves), + slaves: slaves + } end - def to_binary(%NxBundle{algorithm: alg, - hash_field: hash_field, - basis: basis, - slave_type: slave_type, - n_slaves: n_slaves, - slaves: slaves}) do + def to_binary(%NxBundle{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves + }) do hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm) slave_type_bin = Openflow.Match.codec_header(slave_type) slaves_bin = codec_slaves(slaves) - body = <> + + body = + <> + 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do - <> = body + <> = body + slave_len = n_slaves * 2 <> = rest 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) slaves = codec_slaves(slaves_bin) n_slaves = length(slaves) - %NxBundle{algorithm: alg, - hash_field: hash_field, - basis: basis, - slave_type: slave_type, - n_slaves: n_slaves, - slaves: slaves} + + %NxBundle{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves + } end # private functions defp codec_slaves(slaves) when is_list(slaves) do - slaves1 = for slave <- slaves do - slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) - <> - end + slaves1 = + for slave <- slaves do + slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) + <> + end + Enum.join(slaves1, "") end + defp codec_slaves(slaves) when is_binary(slaves) do for <> do Openflow.Utils.get_enum(slave_int, :openflow10_port_no) diff --git a/lib/openflow/actions/nx_bundle_load.ex b/lib/openflow/actions/nx_bundle_load.ex index b9c4ef1..f213fe0 100644 --- a/lib/openflow/actions/nx_bundle_load.ex +++ b/lib/openflow/actions/nx_bundle_load.ex @@ -2,15 +2,15 @@ defmodule Openflow.Action.NxBundleLoad do import Bitwise defstruct( - algorithm: :active_backup, + algorithm: :active_backup, hash_field: :eth_src, - basis: 0, + basis: 0, slave_type: :nx_in_port, - n_slaves: 0, - slaves: [], - offset: 0, - n_bits: 0, - dst_field: nil + n_slaves: 0, + slaves: [], + offset: 0, + n_bits: 0, + dst_field: nil ) @experimenter 0x00002320 @@ -22,45 +22,52 @@ defmodule Openflow.Action.NxBundleLoad do dst_field = options[:dst_field] default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) slaves = options[:slaves] || [] - %NxBundleLoad{algorithm: options[:algorithm] || :active_backup, - hash_field: options[:hash_field] || :eth_src, - basis: options[:basis] || 0, - n_slaves: length(slaves), - slaves: slaves, - offset: options[:offset] || 0, - n_bits: options[:n_bits] || default_n_bits, - dst_field: options[:dst_field]} + + %NxBundleLoad{ + algorithm: options[:algorithm] || :active_backup, + hash_field: options[:hash_field] || :eth_src, + basis: options[:basis] || 0, + n_slaves: length(slaves), + slaves: slaves, + offset: options[:offset] || 0, + n_bits: options[:n_bits] || default_n_bits, + dst_field: options[:dst_field] + } end - def to_binary(%NxBundleLoad{algorithm: alg, - hash_field: hash_field, - basis: basis, - slave_type: slave_type, - n_slaves: n_slaves, - slaves: slaves, - offset: ofs, - n_bits: n_bits, - dst_field: dst_field}) do + def to_binary(%NxBundleLoad{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves, + offset: ofs, + n_bits: n_bits, + dst_field: dst_field + }) do hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm) slave_type_bin = Openflow.Match.codec_header(slave_type) 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) - body = <> + + body = + <> + 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do - <> = body + <> = body + slave_len = n_slaves * 2 <> = rest alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm) @@ -69,26 +76,32 @@ defmodule Openflow.Action.NxBundleLoad do slaves = codec_slaves(slaves_bin) n_slaves = length(slaves) dst_field = Openflow.Match.codec_header(dst_field_bin) - %NxBundleLoad{algorithm: alg, - hash_field: hash_field, - basis: basis, - slave_type: slave_type, - n_slaves: n_slaves, - slaves: slaves, - offset: ofs, - n_bits: n_bits + 1, - dst_field: dst_field} + + %NxBundleLoad{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves, + offset: ofs, + n_bits: n_bits + 1, + dst_field: dst_field + } end # private functions defp codec_slaves(slaves) when is_list(slaves) do - slaves1 = for slave <- slaves do - slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) - <> - end + slaves1 = + for slave <- slaves do + slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) + <> + end + Enum.join(slaves1, "") end + defp codec_slaves(slaves) when is_binary(slaves) do for <> do Openflow.Utils.get_enum(slave_int, :openflow10_port_no) diff --git a/lib/openflow/actions/nx_clone.ex b/lib/openflow/actions/nx_clone.ex index afa8618..971721b 100644 --- a/lib/openflow/actions/nx_clone.ex +++ b/lib/openflow/actions/nx_clone.ex @@ -1,7 +1,5 @@ defmodule Openflow.Action.NxClone do - defstruct( - actions: [] - ) + defstruct(actions: []) @experimenter 0x00002320 @nxast 42 @@ -15,10 +13,10 @@ defmodule Openflow.Action.NxClone do def to_binary(%NxClone{actions: actions}) do actions_bin = Openflow.Action.to_binary(actions) 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) 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 def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>>) do diff --git a/lib/openflow/actions/nx_conjunction.ex b/lib/openflow/actions/nx_conjunction.ex index b9818d6..be33f2a 100644 --- a/lib/openflow/actions/nx_conjunction.ex +++ b/lib/openflow/actions/nx_conjunction.ex @@ -1,8 +1,8 @@ defmodule Openflow.Action.NxConjunction do defstruct( - clause: 0, + clause: 0, n_clauses: 0, - id: 0 + id: 0 ) @experimenter 0x00002320 @@ -11,14 +11,16 @@ defmodule Openflow.Action.NxConjunction do alias __MODULE__ def new(options) do - %NxConjunction{clause: options[:clause] || 0, - n_clauses: options[:n_clauses] || 0, - id: options[:id] || 0} + %NxConjunction{ + clause: options[:clause] || 0, + n_clauses: options[:n_clauses] || 0, + id: options[:id] || 0 + } end 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>> - <<0xffff::16, 16::16, exp_body::bytes>> + <<0xFFFF::16, 16::16, exp_body::bytes>> end def read(<<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>>) do diff --git a/lib/openflow/actions/nx_conntrack.ex b/lib/openflow/actions/nx_conntrack.ex index 4c4dafc..7844221 100644 --- a/lib/openflow/actions/nx_conntrack.ex +++ b/lib/openflow/actions/nx_conntrack.ex @@ -2,14 +2,14 @@ defmodule Openflow.Action.NxConntrack do import Bitwise defstruct( - flags: [], - zone_src: nil, - zone_imm: 0, - zone_offset: nil, - zone_n_bits: nil, + flags: [], + zone_src: nil, + zone_imm: 0, + zone_offset: nil, + zone_n_bits: nil, recirc_table: 255, - alg: 0, - exec: [] + alg: 0, + exec: [] ) @experimenter 0x00002320 @@ -18,61 +18,73 @@ defmodule Openflow.Action.NxConntrack do alias __MODULE__ def new(options \\ []) do - %NxConntrack{flags: options[:flags] || [], - zone_src: options[:zone_src], - zone_imm: options[:zone_imm] || 0, - zone_offset: options[:zone_offset], - zone_n_bits: options[:zone_n_bits], - recirc_table: options[:recirc_table] || 255, - alg: options[:alg] || 0, - exec: options[:exec] || []} + %NxConntrack{ + flags: options[:flags] || [], + zone_src: options[:zone_src], + zone_imm: options[:zone_imm] || 0, + zone_offset: options[:zone_offset], + zone_n_bits: options[:zone_n_bits], + recirc_table: options[:recirc_table] || 255, + alg: options[:alg] || 0, + exec: options[:exec] || [] + } end def to_binary(%NxConntrack{ - flags: flags, - zone_src: zone_src, - zone_offset: zone_ofs, - zone_n_bits: zone_n_bits, - zone_imm: zone_imm, + flags: flags, + zone_src: zone_src, + zone_offset: zone_ofs, + zone_n_bits: zone_n_bits, + zone_imm: zone_imm, recirc_table: recirc_table, - alg: alg, - exec: exec}) do + alg: alg, + exec: exec + }) do 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) - {zone_src_bin, (zone_ofs <<< 6) ||| (zone_n_bits - 1)} - else - {<<0::32>>, zone_imm} - end + + {src_bin, ofs_nbits} = + if not is_nil(zone_src) do + zone_src_bin = Openflow.Match.codec_header(zone_src) + {zone_src_bin, zone_ofs <<< 6 ||| zone_n_bits - 1} + else + {<<0::32>>, zone_imm} + end + 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, - 0::size(3)-unit(8), alg::16, exec_bin::bytes>> - exp_body_size = byte_size(exp_body) + + exp_body = + <<@experimenter::32, @nxast::16, flags_int::16, src_bin::bytes, ofs_nbits::16, + recirc_table::8, 0::size(3)-unit(8), alg::16, exec_bin::bytes>> + + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) 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 - def read(<<@experimenter::32, @nxast::16, flags_int::16, - src_bin::4-bytes, ofs_nbits::16-bits, recirc_table::8, - _::size(3)-unit(8), alg::16, exec_bin::bytes>>) do + def read( + <<@experimenter::32, @nxast::16, flags_int::16, src_bin::4-bytes, ofs_nbits::16-bits, + recirc_table::8, _::size(3)-unit(8), alg::16, exec_bin::bytes>> + ) do flags = Openflow.Enums.int_to_flags(flags_int, :nx_conntrack_flags) exec = Openflow.Action.read(exec_bin) + ct = %NxConntrack{ - flags: flags, + flags: flags, recirc_table: recirc_table, - alg: alg, - exec: exec + alg: alg, + exec: exec } + case src_bin do <<0::32>> -> <> = ofs_nbits - %{ct|zone_imm: zone_imm} + %{ct | zone_imm: zone_imm} + binary when is_binary(binary) -> zone_src = Openflow.Match.codec_header(binary) <> = 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 diff --git a/lib/openflow/actions/nx_controller.ex b/lib/openflow/actions/nx_controller.ex index 4faf769..2f2d1fc 100644 --- a/lib/openflow/actions/nx_controller.ex +++ b/lib/openflow/actions/nx_controller.ex @@ -11,19 +11,27 @@ defmodule Openflow.Action.NxController do alias __MODULE__ def new(options) do - %NxController{max_len: options[:max_len] || :no_buffer, - id: options[:id] || 0, - reason: options[:reason] || :action} + %NxController{ + max_len: options[:max_len] || :no_buffer, + id: options[:id] || 0, + reason: options[:reason] || :action + } end 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) 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 - 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) reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason) %NxController{max_len: max_len, id: controller_id, reason: reason} diff --git a/lib/openflow/actions/nx_controller2.ex b/lib/openflow/actions/nx_controller2.ex index 5b932e7..78fb9d5 100644 --- a/lib/openflow/actions/nx_controller2.ex +++ b/lib/openflow/actions/nx_controller2.ex @@ -1,10 +1,10 @@ defmodule Openflow.Action.NxController2 do defstruct( - max_len: :no_buffer, - id: 0, - reason: :action, + max_len: :no_buffer, + id: 0, + reason: :action, userdata: "", - pause: false + pause: false ) @experimenter 0x00002320 @@ -12,20 +12,22 @@ defmodule Openflow.Action.NxController2 do @prop_header_size 4 - @prop_max_len 0 - @prop_ctl_id 1 - @prop_reason 2 + @prop_max_len 0 + @prop_ctl_id 1 + @prop_reason 2 @prop_userdata 3 - @prop_pause 4 + @prop_pause 4 alias __MODULE__ def new(options) do - %NxController2{max_len: options[:max_len] || :no_buffer, - id: options[:id] || 0, - reason: options[:reason] || :action, - userdata: options[:userdata], - pause: options[:pause] || false} + %NxController2{ + max_len: options[:max_len] || :no_buffer, + id: options[:id] || 0, + reason: options[:reason] || :action, + userdata: options[:userdata], + pause: options[:pause] || false + } end def to_binary(%NxController2{} = ctl) do @@ -33,10 +35,10 @@ defmodule Openflow.Action.NxController2 do prop_keys = get_prop_key(ctl) props_bin = encode_prop("", prop_keys, ctl) exp_body = <> - exp_body_size = byte_size(exp_body) + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) length = 4 + exp_body_size + padding_length - <<0xffff::16, length::16, exp_body::bytes>> + <<0xFFFF::16, length::16, exp_body::bytes>> end 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 ctl - |> Map.from_struct - |> Enum.map(fn({k, v}) -> if(not is_nil(v), do: k, else: nil) end) - |> Enum.filter(fn(v) -> not is_nil(v) end) + |> Map.from_struct() + |> Enum.map(fn {k, v} -> if(not is_nil(v), do: k, else: nil) end) + |> Enum.filter(fn v -> not is_nil(v) end) end 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) - prop_bin = cond do - prop == :max_len and (value != :no_buffer or value < 0xffff) -> - padding_length = 2 - prop_length = @prop_header_size + 2 + padding_length - max_len_int = Openflow.Utils.get_enum(value, :controller_max_len) - <<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>> - prop == :id -> - padding_length = 2 - prop_length = @prop_header_size + 2 + padding_length - <<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>> - prop == :reason and value != :action -> - padding_length = 3 - prop_length = @prop_header_size + 1 + padding_length - reason_int = Openflow.Utils.get_enum(value, :packet_in_reason) - <<@prop_reason::16, prop_length::16, reason_int::8, 0::size(padding_length)-unit(8)>> - prop == :userdata and byte_size(value) > 0 -> - prop_length = @prop_header_size + byte_size(value) - padding_length = Openflow.Utils.padding(prop_length, 8) - <<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>> - 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 + + prop_bin = + cond do + prop == :max_len and (value != :no_buffer or value < 0xFFFF) -> + padding_length = 2 + prop_length = @prop_header_size + 2 + padding_length + max_len_int = Openflow.Utils.get_enum(value, :controller_max_len) + <<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>> + + prop == :id -> + padding_length = 2 + prop_length = @prop_header_size + 2 + padding_length + <<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>> + + prop == :reason and value != :action -> + padding_length = 3 + prop_length = @prop_header_size + 1 + padding_length + reason_int = Openflow.Utils.get_enum(value, :packet_in_reason) + <<@prop_reason::16, prop_length::16, reason_int::8, 0::size(padding_length)-unit(8)>> + + prop == :userdata and byte_size(value) > 0 -> + prop_length = @prop_header_size + byte_size(value) + padding_length = Openflow.Utils.padding(prop_length, 8) + <<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>> + + 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(<>, rest, ctl) end defp decode_prop(ctl, ""), do: ctl + defp decode_prop(ctl, <> = bin) do prop_type = Openflow.Enums.to_atom(prop_type_int, :nx_action_controller2_prop_type) + case prop_type do :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) decode_prop(struct(ctl, %{max_len: max_len}), rest) + :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) + :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) decode_prop(struct(ctl, %{reason: reason}), rest) + :userdata -> <<@prop_userdata::16, prop_length::16, remains::bytes>> = bin userdata_len = prop_length - 4 padding_length = Openflow.Utils.padding(prop_length, 8) - <> = remains + + <> = + remains + decode_prop(struct(ctl, %{userdata: userdata}), rest) + :pause -> <<@prop_pause::16, _::16, 0::size(4)-unit(8), rest::bytes>> = bin decode_prop(struct(ctl, %{pause: true}), rest) diff --git a/lib/openflow/actions/nx_ct_clear.ex b/lib/openflow/actions/nx_ct_clear.ex index 32f0810..f58d3b3 100644 --- a/lib/openflow/actions/nx_ct_clear.ex +++ b/lib/openflow/actions/nx_ct_clear.ex @@ -12,7 +12,7 @@ defmodule Openflow.Action.NxCtClear do def to_binary(%NxCtClear{}) do 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 def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_dec_mpls_ttl.ex b/lib/openflow/actions/nx_dec_mpls_ttl.ex index 8b2c0f1..6b5744d 100644 --- a/lib/openflow/actions/nx_dec_mpls_ttl.ex +++ b/lib/openflow/actions/nx_dec_mpls_ttl.ex @@ -12,7 +12,7 @@ defmodule Openflow.Action.NxDecMplsTtl do def to_binary(%NxDecMplsTtl{}) do 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 def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_dec_ttl.ex b/lib/openflow/actions/nx_dec_ttl.ex index 7d949b8..de6b088 100644 --- a/lib/openflow/actions/nx_dec_ttl.ex +++ b/lib/openflow/actions/nx_dec_ttl.ex @@ -12,7 +12,7 @@ defmodule Openflow.Action.NxDecTtl do def to_binary(%NxDecTtl{}) do 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 def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex b/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex index 6704e75..729b705 100644 --- a/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex +++ b/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex @@ -12,14 +12,17 @@ defmodule Openflow.Action.NxDecTtlCntIds do def to_binary(%NxDecTtlCntIds{ids: ids}) do n_controllers = length(ids) - ids_bin = Enum.join((for id <- ids, do: <>), "") + ids_bin = Enum.join(for(id <- ids, do: <>), "") 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_size = byte_size(exp_body) + + 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) 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 def read(<<@experimenter::32, @nxast::16, n_controllers::16, body::bitstring>>) do diff --git a/lib/openflow/actions/nx_exit.ex b/lib/openflow/actions/nx_exit.ex index 842dd77..cc9786b 100644 --- a/lib/openflow/actions/nx_exit.ex +++ b/lib/openflow/actions/nx_exit.ex @@ -12,7 +12,7 @@ defmodule Openflow.Action.NxExit do def to_binary(%NxExit{}) do exp_body = <<@experimenter::32, @nxast::16, 0::48>> - <<0xffff::16, 16::16, exp_body::bytes>> + <<0xFFFF::16, 16::16, exp_body::bytes>> end def read(<<@experimenter::32, @nxast::16, 0::48>>) do diff --git a/lib/openflow/actions/nx_fin_timeout.ex b/lib/openflow/actions/nx_fin_timeout.ex index a94a4dd..8f8e005 100644 --- a/lib/openflow/actions/nx_fin_timeout.ex +++ b/lib/openflow/actions/nx_fin_timeout.ex @@ -10,13 +10,15 @@ defmodule Openflow.Action.NxFinTimeout do alias __MODULE__ def new(options) do - %NxFinTimeout{idle_timeout: options[:idle_timeout] || 0, - hard_timeout: options[:hard_timeout] || 0} + %NxFinTimeout{ + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0 + } end 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>> - <<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 def read(<<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16, _::size(2)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_flow_spec.ex b/lib/openflow/actions/nx_flow_spec.ex index 62a56b3..b865cc7 100644 --- a/lib/openflow/actions/nx_flow_spec.ex +++ b/lib/openflow/actions/nx_flow_spec.ex @@ -1,5 +1,4 @@ defmodule Openflow.Action.NxFlowSpec do - def read(flow_spec_bin) do do_read([], flow_spec_bin) end @@ -7,6 +6,7 @@ defmodule Openflow.Action.NxFlowSpec do def to_binary(flow_specs) when is_list(flow_specs) do to_binary(<<>>, flow_specs) end + def to_binary(flow_spec) do to_binary([flow_spec]) end @@ -15,15 +15,17 @@ defmodule Openflow.Action.NxFlowSpec do defp do_read(acc, <<>>), 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 codec = Openflow.Enums.to_atom(type, :nx_flow_spec_type) {flow_spec, rest} = codec.read(binary) - do_read([flow_spec|acc], rest) + do_read([flow_spec | acc], rest) end 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__ - to_binary(<>, rest) + to_binary(<>, rest) end end diff --git a/lib/openflow/actions/nx_flow_spec_load.ex b/lib/openflow/actions/nx_flow_spec_load.ex index 5b35f20..dcdbf86 100644 --- a/lib/openflow/actions/nx_flow_spec_load.ex +++ b/lib/openflow/actions/nx_flow_spec_load.ex @@ -2,67 +2,80 @@ defmodule Openflow.Action.NxFlowSpecLoad do defstruct( src: nil, dst: nil, - n_bits: 0, + n_bits: 0, src_offset: 0, dst_offset: 0 ) - @learn_src_field 0 + @learn_src_field 0 @learn_src_immediate 1 - @learn_dst 1 + @learn_dst 1 alias __MODULE__ def new(options) do dst = options[:dst] n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) - %NxFlowSpecLoad{src: options[:src], - dst: dst, - n_bits: n_bits, - src_offset: options[:src_offset] || 0, - dst_offset: options[:dst_offset] || 0} + + %NxFlowSpecLoad{ + src: options[:src], + dst: dst, + n_bits: n_bits, + src_offset: options[:src_offset] || 0, + dst_offset: options[:dst_offset] || 0 + } end def to_binary(%NxFlowSpecLoad{} = fsm) do %NxFlowSpecLoad{ - dst: dst_field, - n_bits: n_bits, + dst: dst_field, + n_bits: n_bits, src_offset: src_ofs, dst_offset: dst_ofs } = fsm + {src_code, src_bin} = codec_src(fsm) dst_bin = Openflow.Match.codec_header(dst_field) + case src_code do @learn_src_immediate -> - <<0::2, src_code::1, @learn_dst::2, n_bits::11, - src_bin::bytes, dst_bin::4-bytes, dst_ofs::16>> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, dst_bin::4-bytes, + dst_ofs::16>> + @learn_src_field -> - <<0::2, src_code::1, @learn_dst::2, n_bits::11, - src_bin::4-bytes, src_ofs::16, dst_bin::4-bytes, dst_ofs::16>> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, + dst_bin::4-bytes, dst_ofs::16>> end end - def read(<<_::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 + def read( + <<_::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) dst = Openflow.Match.codec_header(dst_bin) - flow_spec = %NxFlowSpecLoad{src: src, - dst: dst, - n_bits: n_bits, - src_offset: src_ofs, - dst_offset: dst_ofs} + + flow_spec = %NxFlowSpecLoad{ + src: src, + dst: dst, + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs + } + {flow_spec, rest} end + 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_nbits = n_bits + rounded_up_len - <> = binary + + <> = + binary + dst = Openflow.Match.codec_header(dst_bin) src = Openflow.Match.Field.codec(src_bin, dst) - flow_spec = %NxFlowSpecLoad{src: src, - dst: dst, - n_bits: n_bits, - dst_offset: dst_ofs} + flow_spec = %NxFlowSpecLoad{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs} {flow_spec, rest} end @@ -72,6 +85,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do src_bin = Openflow.Match.codec_header(src_field) {@learn_src_field, src_bin} end + defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do src_bin = Openflow.Match.Field.codec(src, dst_field) {@learn_src_immediate, src_bin} diff --git a/lib/openflow/actions/nx_flow_spec_match.ex b/lib/openflow/actions/nx_flow_spec_match.ex index c8e2e1c..feae23d 100644 --- a/lib/openflow/actions/nx_flow_spec_match.ex +++ b/lib/openflow/actions/nx_flow_spec_match.ex @@ -2,67 +2,80 @@ defmodule Openflow.Action.NxFlowSpecMatch do defstruct( src: nil, dst: nil, - n_bits: 0, + n_bits: 0, src_offset: 0, dst_offset: 0 ) - @learn_src_field 0 + @learn_src_field 0 @learn_src_immediate 1 - @learn_dst 0 + @learn_dst 0 alias __MODULE__ def new(options) do dst = options[:dst] n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) - %NxFlowSpecMatch{src: options[:src], - dst: dst, - n_bits: n_bits, - src_offset: options[:src_offset] || 0, - dst_offset: options[:dst_offset] || 0} + + %NxFlowSpecMatch{ + src: options[:src], + dst: dst, + n_bits: n_bits, + src_offset: options[:src_offset] || 0, + dst_offset: options[:dst_offset] || 0 + } end def to_binary(%NxFlowSpecMatch{} = fsm) do %NxFlowSpecMatch{ - dst: dst_field, - n_bits: n_bits, + dst: dst_field, + n_bits: n_bits, src_offset: src_ofs, dst_offset: dst_ofs } = fsm + {src_code, src_bin} = codec_src(fsm) dst_bin = Openflow.Match.codec_header(dst_field) + case src_code do @learn_src_immediate -> - <<0::2, src_code::1, @learn_dst::2, n_bits::11, - src_bin::bytes, dst_bin::4-bytes, dst_ofs::16>> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, dst_bin::4-bytes, + dst_ofs::16>> + @learn_src_field -> - <<0::2, src_code::1, @learn_dst::2, n_bits::11, - src_bin::bytes, src_ofs::16, dst_bin::4-bytes, dst_ofs::16>> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, src_ofs::16, + dst_bin::4-bytes, dst_ofs::16>> end end - def read(<<_::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 + def read( + <<_::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) dst = Openflow.Match.codec_header(dst_bin) - flow_spec = %NxFlowSpecMatch{src: src, - dst: dst, - n_bits: n_bits, - src_offset: src_ofs, - dst_offset: dst_ofs} + + flow_spec = %NxFlowSpecMatch{ + src: src, + dst: dst, + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs + } + {flow_spec, rest} end + 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_nbits = n_bits + rounded_up_len - <> = binary + + <> = + binary + dst = Openflow.Match.codec_header(dst_bin) src = Openflow.Match.Field.codec(src_bin, dst) - flow_spec = %NxFlowSpecMatch{src: src, - dst: dst, - n_bits: n_bits, - dst_offset: dst_ofs} + flow_spec = %NxFlowSpecMatch{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs} {flow_spec, rest} end @@ -72,6 +85,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do src_bin = Openflow.Match.codec_header(src_field) {@learn_src_field, src_bin} end + defp codec_src(%NxFlowSpecMatch{src: src, dst: dst_field}) do src_bin = Openflow.Match.Field.codec(src, dst_field) {@learn_src_immediate, src_bin} diff --git a/lib/openflow/actions/nx_flow_spec_output.ex b/lib/openflow/actions/nx_flow_spec_output.ex index 75ad422..7f0500b 100644 --- a/lib/openflow/actions/nx_flow_spec_output.ex +++ b/lib/openflow/actions/nx_flow_spec_output.ex @@ -5,32 +5,28 @@ defmodule Openflow.Action.NxFlowSpecOutput do src_offset: 0 ) - @learn_src_field 0 - @learn_dst 2 + @learn_src_field 0 + @learn_dst 2 alias __MODULE__ def new(options) do src = options[:src] n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(src) - %NxFlowSpecOutput{n_bits: n_bits, - src: src, - src_offset: options[:src_offset] || 0} + %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: options[:src_offset] || 0} end - def to_binary(%NxFlowSpecOutput{n_bits: n_bits, - src: src, - src_offset: src_ofs}) do + def to_binary(%NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs}) do 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>> end - def read(<<0::2, @learn_src_field::1, @learn_dst::2, - n_bits::11, src_bin::4-bytes, src_ofs::16, rest::bitstring>>) do + def read( + <<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) - flow_spec = %NxFlowSpecOutput{n_bits: n_bits, - src: src, - src_offset: src_ofs} + flow_spec = %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs} {flow_spec, rest} end end diff --git a/lib/openflow/actions/nx_learn.ex b/lib/openflow/actions/nx_learn.ex index b57f380..04b6cf3 100644 --- a/lib/openflow/actions/nx_learn.ex +++ b/lib/openflow/actions/nx_learn.ex @@ -17,53 +17,60 @@ defmodule Openflow.Action.NxLearn do alias __MODULE__ def new(options) do - %NxLearn{idle_timeout: options[:idle_timeout] || 0, - hard_timeout: options[:hard_timeout] || 0, - priority: options[:priority] || 0, - cookie: options[:cookie] || 0, - flags: options[:flags] || [], - table_id: options[:table_id] || 0xff, - fin_idle_timeout: options[:fin_idle_timeout] || 0, - fin_hard_timeout: options[:fin_hard_timeout] || 0, - flow_specs: options[:flow_specs] || []} + %NxLearn{ + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0, + priority: options[:priority] || 0, + cookie: options[:cookie] || 0, + flags: options[:flags] || [], + table_id: options[:table_id] || 0xFF, + fin_idle_timeout: options[:fin_idle_timeout] || 0, + fin_hard_timeout: options[:fin_hard_timeout] || 0, + flow_specs: options[:flow_specs] || [] + } end - def to_binary(%NxLearn{idle_timeout: idle, - hard_timeout: hard, - priority: prio, - cookie: cookie, - flags: flags, - table_id: table_id, - fin_idle_timeout: fin_idle, - fin_hard_timeout: fin_hard, - flow_specs: flow_specs}) do + def to_binary(%NxLearn{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + flow_specs: flow_specs + }) do flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag) 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, - 0::size(1)-unit(8), fin_idle::16, fin_hard::16, - flow_specs_bin::bitstring>> - exp_body_size = byte_size(exp_body) + + exp_body = + <<@experimenter::32, @nxast::16, idle::16, hard::16, prio::16, cookie::64, flags_int::16, + 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) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) 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 def read(<<@experimenter::32, @nxast::16, body::bitstring>>) do - <> = body + <> = body + flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag) flow_specs = Openflow.Action.NxFlowSpec.read(flow_specs_bin) - %NxLearn{idle_timeout: idle, - hard_timeout: hard, - priority: prio, - cookie: cookie, - flags: flags, - table_id: table_id, - fin_idle_timeout: fin_idle, - fin_hard_timeout: fin_hard, - flow_specs: flow_specs} + + %NxLearn{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + flow_specs: flow_specs + } end end diff --git a/lib/openflow/actions/nx_learn2.ex b/lib/openflow/actions/nx_learn2.ex index fac6e77..ea3a49d 100644 --- a/lib/openflow/actions/nx_learn2.ex +++ b/lib/openflow/actions/nx_learn2.ex @@ -20,65 +20,77 @@ defmodule Openflow.Action.NxLearn2 do alias __MODULE__ def new(options) do - %NxLearn2{idle_timeout: options[:idle_timeout] || 0, - hard_timeout: options[:hard_timeout] || 0, - priority: options[:priority] || 0, - cookie: options[:cookie] || 0, - flags: options[:flags] || [], - table_id: options[:table_id] || 0xff, - fin_idle_timeout: options[:fin_idle_timeout] || 0, - fin_hard_timeout: options[:fin_hard_timeout] || 0, - limit: options[:limit] || 0, - result_dst_offset: options[:result_dst_offset] || 0, - result_dst: options[:result_dst], - flow_specs: options[:flow_specs] || []} + %NxLearn2{ + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0, + priority: options[:priority] || 0, + cookie: options[:cookie] || 0, + flags: options[:flags] || [], + table_id: options[:table_id] || 0xFF, + fin_idle_timeout: options[:fin_idle_timeout] || 0, + fin_hard_timeout: options[:fin_hard_timeout] || 0, + limit: options[:limit] || 0, + result_dst_offset: options[:result_dst_offset] || 0, + result_dst: options[:result_dst], + flow_specs: options[:flow_specs] || [] + } end - def to_binary(%NxLearn2{idle_timeout: idle, - hard_timeout: hard, - priority: prio, - cookie: cookie, - flags: flags, - table_id: table_id, - fin_idle_timeout: fin_idle, - fin_hard_timeout: fin_hard, - limit: limit, - result_dst_offset: result_dst_ofs, - result_dst: result_dst, - flow_specs: flow_specs}) do + def to_binary(%NxLearn2{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + limit: limit, + result_dst_offset: result_dst_ofs, + result_dst: result_dst, + flow_specs: flow_specs + }) do 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) - else - "" - end + + result_dst_bin = + if :write_result in flags do + Openflow.Match.codec_header(result_dst) + else + "" + end + 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, - 0::size(1)-unit(8), fin_idle::16, fin_hard::16, - limit::32, 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 = + <<@experimenter::32, @nxast::16, idle::16, hard::16, prio::16, cookie::64, flags_int::16, + table_id::8, 0::size(1)-unit(8), fin_idle::16, fin_hard::16, limit::32, + result_dst_ofs::16, 0::size(2)-unit(8), result_dst_bin::bytes, flow_specs_bin::bitstring>> + + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) length = 4 + exp_body_size + padding_length - <<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> end def read(<<@experimenter::32, @nxast::16, body::bytes>>) do - <> = body + <> = body + flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag) - learn = %NxLearn2{idle_timeout: idle, - hard_timeout: hard, - priority: prio, - cookie: cookie, - flags: flags, - table_id: table_id, - fin_idle_timeout: fin_idle, - fin_hard_timeout: fin_hard, - limit: limit, - result_dst_offset: result_dst_ofs} + + learn = %NxLearn2{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + limit: limit, + result_dst_offset: result_dst_ofs + } + if :write_result in flags do header_size = Openflow.Match.header_size(rest) <> = rest diff --git a/lib/openflow/actions/nx_multipath.ex b/lib/openflow/actions/nx_multipath.ex index 86c45c9..72975e0 100644 --- a/lib/openflow/actions/nx_multipath.ex +++ b/lib/openflow/actions/nx_multipath.ex @@ -3,13 +3,13 @@ defmodule Openflow.Action.NxMultipath do defstruct( hash_field: :eth_src, - basis: 0, - algorithm: :modulo_n, - max_link: 0, - argument: 0, - offset: 0, - n_bits: 0, - dst_field: nil + basis: 0, + algorithm: :modulo_n, + max_link: 0, + argument: 0, + offset: 0, + n_bits: 0, + dst_field: nil ) @experimenter 0x00002320 @@ -27,52 +27,62 @@ defmodule Openflow.Action.NxMultipath do default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) n_bits = Keyword.get(options, :n_bits, default_n_bits) ofs = Keyword.get(options, :offset, 0) - %NxMultipath{hash_field: hash_field, - basis: basis, - algorithm: alg, - max_link: max_link, - offset: ofs, - n_bits: n_bits, - argument: arg, - dst_field: dst_field} + + %NxMultipath{ + hash_field: hash_field, + basis: basis, + algorithm: alg, + max_link: max_link, + offset: ofs, + n_bits: n_bits, + argument: arg, + dst_field: dst_field + } end - def to_binary(%NxMultipath{hash_field: hash_field, - basis: basis, - algorithm: alg, - max_link: max_link, - argument: arg, - offset: ofs, - n_bits: n_bits, - dst_field: dst_field}) do + def to_binary(%NxMultipath{ + hash_field: hash_field, + basis: basis, + algorithm: alg, + max_link: max_link, + argument: arg, + offset: ofs, + n_bits: n_bits, + dst_field: dst_field + }) do hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) alg_int = Openflow.Enums.to_int(alg, :nx_mp_algorithm) dst_field_bin = Openflow.Match.codec_header(dst_field) - ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) - body = <> + ofs_nbits = ofs <<< 6 ||| n_bits - 1 + + body = + <> + 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do - <> = body + <> = body + hash_field = Openflow.Enums.to_atom(hash_field_int, :nx_hash_fields) alg = Openflow.Enums.to_atom(alg_int, :nx_mp_algorithm) dst_field = Openflow.Match.codec_header(dst_field_bin) - %NxMultipath{hash_field: hash_field, - basis: basis, - algorithm: alg, - max_link: max_link, - argument: arg, - offset: ofs, - n_bits: n_bits + 1, - dst_field: dst_field} + + %NxMultipath{ + hash_field: hash_field, + basis: basis, + algorithm: alg, + max_link: max_link, + argument: arg, + offset: ofs, + n_bits: n_bits + 1, + dst_field: dst_field + } end end diff --git a/lib/openflow/actions/nx_nat.ex b/lib/openflow/actions/nx_nat.ex index a8af26d..921d5f1 100644 --- a/lib/openflow/actions/nx_nat.ex +++ b/lib/openflow/actions/nx_nat.ex @@ -1,10 +1,10 @@ defmodule Openflow.Action.NxNat do defstruct( - flags: [], - ipv4_min: nil, - ipv4_max: nil, - ipv6_min: nil, - ipv6_max: nil, + flags: [], + ipv4_min: nil, + ipv4_max: nil, + ipv6_min: nil, + ipv6_max: nil, proto_min: nil, proto_max: nil ) @@ -22,30 +22,38 @@ defmodule Openflow.Action.NxNat do ipv6_max = Keyword.get(options, :ipv6_max) proto_min = Keyword.get(options, :proto_min) proto_max = Keyword.get(options, :proto_max) - %NxNat{flags: flags, - ipv4_min: ipv4_min, - ipv4_max: ipv4_max, - ipv6_min: ipv6_min, - ipv6_max: ipv6_max, - proto_min: proto_min, - proto_max: proto_max} + + %NxNat{ + flags: flags, + ipv4_min: ipv4_min, + ipv4_max: ipv4_max, + ipv6_min: ipv6_min, + ipv6_max: ipv6_max, + proto_min: proto_min, + proto_max: proto_max + } end def to_binary(%NxNat{flags: flags} = nat) do flags_int = Openflow.Enums.flags_to_int(flags, :nx_nat_flags) + range_flags = nat |> get_ranges |> Openflow.Enums.flags_to_int(:nx_nat_range) |> Openflow.Enums.int_to_flags(:nx_nat_range) + ranges_bin = encode_ranges("", range_flags, nat) 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_size = byte_size(exp_body) + + 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do @@ -59,33 +67,43 @@ defmodule Openflow.Action.NxNat do defp get_ranges(nat) do nat - |> Map.from_struct + |> Map.from_struct() |> Map.delete(:flags) - |> 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.map(fn {k, v} -> if(not is_nil(v), do: k, else: nil) end) + |> Enum.filter(fn v -> not is_nil(v) end) end 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 range == :ipv4_min or range == :ipv4_max -> case Map.get(nat, range) do - {a1, a2, a3, a4} -> + {a1, a2, a3, a4} -> encode_ranges(<>, rest, nat) + "" -> encode_ranges(<>, rest, nat) end + range == :ipv6_min or range == :ipv6_max -> case Map.get(nat, range) do {a1, a2, a3, a4, a5, a6, a7, a8} -> - encode_ranges(<>, rest, nat) + encode_ranges( + <>, + rest, + nat + ) + "" -> encode_ranges(<>, rest, nat) end + range == :proto_min or range == :proto_max -> 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(<>, rest, nat) + _ -> encode_ranges(<>, rest, nat) end @@ -93,26 +111,32 @@ defmodule Openflow.Action.NxNat do end defp decode_ranges(nat, [], _), do: nat - defp decode_ranges(nat, [range|ranges], bin) do + + defp decode_ranges(nat, [range | ranges], bin) do cond do range == :ipv4_min or range == :ipv4_max -> case bin do <> -> decode_ranges(struct(nat, %{range => {a1, a2, a3, a4}}), ranges, rest) + rest -> decode_ranges(struct(nat, %{range => ""}), ranges, rest) end + range == :ipv6_min or range == :ipv6_max -> case bin do <> -> decode_ranges(struct(nat, %{range => {a1, a2, a3, a4, a5, a6, a7, a8}}), ranges, rest) + rest -> decode_ranges(struct(nat, %{range => ""}), ranges, rest) end + range == :proto_min or range == :proto_max -> case bin do - <> when proto in (1..0xffff) -> + <> when proto in 1..0xFFFF -> decode_ranges(struct(nat, %{range => proto}), ranges, rest) + rest -> decode_ranges(struct(nat, %{range => ""}), ranges, rest) end diff --git a/lib/openflow/actions/nx_note.ex b/lib/openflow/actions/nx_note.ex index 2e281fe..b96847d 100644 --- a/lib/openflow/actions/nx_note.ex +++ b/lib/openflow/actions/nx_note.ex @@ -13,10 +13,10 @@ defmodule Openflow.Action.NxNote do def to_binary(%NxNote{note: note}) do padding = Openflow.Utils.padding(byte_size(note) + 2, 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) 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 def read(<<@experimenter::32, @nxast::16, note_bin::bytes>>) do diff --git a/lib/openflow/actions/nx_output_reg.ex b/lib/openflow/actions/nx_output_reg.ex index f94c130..852358a 100644 --- a/lib/openflow/actions/nx_output_reg.ex +++ b/lib/openflow/actions/nx_output_reg.ex @@ -2,10 +2,10 @@ defmodule Openflow.Action.NxOutputReg do import Bitwise defstruct( - n_bits: 0, - offset: 0, - src_field: nil, - max_len: :no_buffer + n_bits: 0, + offset: 0, + src_field: nil, + max_len: :no_buffer ) @experimenter 0x00002320 @@ -19,34 +19,25 @@ defmodule Openflow.Action.NxOutputReg do n_bits = Keyword.get(options, :n_bits, default_n_bits) ofs = Keyword.get(options, :offset, 0) max_len = Keyword.get(options, :max_len, :no_buffer) - %NxOutputReg{n_bits: n_bits, - offset: ofs, - src_field: src_field, - max_len: max_len} + %NxOutputReg{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len} end - def to_binary(%NxOutputReg{n_bits: n_bits, - offset: ofs, - src_field: src_field, - max_len: max_len}) do + def to_binary(%NxOutputReg{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}) do 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) body = <> 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do <> = body src_field = Openflow.Match.codec_header(src_field_bin) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) - %NxOutputReg{n_bits: n_bits + 1, - offset: ofs, - src_field: src_field, - max_len: max_len} + %NxOutputReg{n_bits: n_bits + 1, offset: ofs, src_field: src_field, max_len: max_len} end end diff --git a/lib/openflow/actions/nx_output_reg2.ex b/lib/openflow/actions/nx_output_reg2.ex index d5c88c7..e254cf3 100644 --- a/lib/openflow/actions/nx_output_reg2.ex +++ b/lib/openflow/actions/nx_output_reg2.ex @@ -2,10 +2,10 @@ defmodule Openflow.Action.NxOutputReg2 do import Bitwise defstruct( - n_bits: 0, - offset: 0, - src_field: nil, - max_len: :no_buffer + n_bits: 0, + offset: 0, + src_field: nil, + max_len: :no_buffer ) @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 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) padding = Openflow.Utils.padding(byte_size(src_field_bin), 10) body = <> 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do <> = body exp_size = match_header_size(oxm_header) - 4 <> = rest - src_field = Openflow.Match.codec_header(<>) + + src_field = + Openflow.Match.codec_header(<>) + 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} end # private functions - defp match_header_size(<<0xffff::16, _::bytes>>), do: 8 - defp match_header_size(<<_::16, _::bytes>>), do: 4 + defp match_header_size(<<0xFFFF::16, _::bytes>>), do: 8 + defp match_header_size(<<_::16, _::bytes>>), do: 4 end diff --git a/lib/openflow/actions/nx_output_trunc.ex b/lib/openflow/actions/nx_output_trunc.ex index d8289b2..98b3c6e 100644 --- a/lib/openflow/actions/nx_output_trunc.ex +++ b/lib/openflow/actions/nx_output_trunc.ex @@ -18,10 +18,10 @@ defmodule Openflow.Action.NxOutputTrunc 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) 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) 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 def read(<<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>>) do diff --git a/lib/openflow/actions/nx_pop_mpls.ex b/lib/openflow/actions/nx_pop_mpls.ex index 7aef5b0..f14f863 100644 --- a/lib/openflow/actions/nx_pop_mpls.ex +++ b/lib/openflow/actions/nx_pop_mpls.ex @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxPopMpls do def to_binary(%NxPopMpls{ethertype: ethertype}) do 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) 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 def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_pop_queue.ex b/lib/openflow/actions/nx_pop_queue.ex index bda8339..4821cd3 100644 --- a/lib/openflow/actions/nx_pop_queue.ex +++ b/lib/openflow/actions/nx_pop_queue.ex @@ -3,7 +3,7 @@ defmodule Openflow.Action.NxPopQueue do @experimenter 0x00002320 @nxast 5 - + alias __MODULE__ def new do @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxPopQueue do def to_binary(%NxPopQueue{}) do 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) 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 def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_push_mpls.ex b/lib/openflow/actions/nx_push_mpls.ex index 241d6b3..4db52b0 100644 --- a/lib/openflow/actions/nx_push_mpls.ex +++ b/lib/openflow/actions/nx_push_mpls.ex @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxPushMpls do def to_binary(%NxPushMpls{ethertype: ethertype}) do 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) 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 def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_reg_load.ex b/lib/openflow/actions/nx_reg_load.ex index ae5a6ac..1ee7da5 100644 --- a/lib/openflow/actions/nx_reg_load.ex +++ b/lib/openflow/actions/nx_reg_load.ex @@ -2,10 +2,10 @@ defmodule Openflow.Action.NxRegLoad do import Bitwise defstruct( - n_bits: 0, - offset: 0, - dst_field: nil, - value: nil + n_bits: 0, + offset: 0, + dst_field: nil, + value: nil ) @experimenter 0x00002320 @@ -19,36 +19,27 @@ defmodule Openflow.Action.NxRegLoad do n_bits = Keyword.get(options, :n_bits, default_n_bits) ofs = Keyword.get(options, :offset, 0) value = Keyword.get(options, :value) - %NxRegLoad{n_bits: n_bits, - offset: ofs, - dst_field: dst_field, - value: value} + %NxRegLoad{n_bits: n_bits, offset: ofs, dst_field: dst_field, value: value} end - def to_binary(%NxRegLoad{n_bits: n_bits, - offset: ofs, - dst_field: dst_field, - value: value}) do + def to_binary(%NxRegLoad{n_bits: n_bits, offset: ofs, dst_field: dst_field, value: value}) do dst_field_bin = Openflow.Match.codec_header(dst_field) value_bin0 = Openflow.Match.Field.codec(value, dst_field) tmp_value = :binary.decode_unsigned(value_bin0, :big) value_bin = <> - ofs_nbits = (ofs <<< 6) ||| (n_bits - 1) + ofs_nbits = ofs <<< 6 ||| n_bits - 1 body = <> 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do <> = body dst_field = Openflow.Match.codec_header(dst_field_bin) value = Openflow.Match.Field.codec(value_bin, dst_field) - %NxRegLoad{n_bits: n_bits + 1, - offset: ofs, - dst_field: dst_field, - value: value} + %NxRegLoad{n_bits: n_bits + 1, offset: ofs, dst_field: dst_field, value: value} end end diff --git a/lib/openflow/actions/nx_reg_load2.ex b/lib/openflow/actions/nx_reg_load2.ex index 00d4cf6..0c1510e 100644 --- a/lib/openflow/actions/nx_reg_load2.ex +++ b/lib/openflow/actions/nx_reg_load2.ex @@ -1,7 +1,7 @@ defmodule Openflow.Action.NxRegLoad2 do defstruct( - dst_field: nil, - value: nil + dst_field: nil, + value: nil ) @experimenter 0x00002320 @@ -18,23 +18,27 @@ defmodule Openflow.Action.NxRegLoad2 do def to_binary(%NxRegLoad2{dst_field: dst_field, value: value}) do match_bin = [{dst_field, value}] - |> Openflow.Match.new - |> Openflow.Match.to_binary + |> Openflow.Match.new() + |> Openflow.Match.to_binary() + <<1::16, _length::16, padded_field::bytes>> = match_bin patial_len = 4 + 4 + 2 + 6 + byte_size(padded_field) 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) 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 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 match_len = 4 + 4 + flen 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} end end diff --git a/lib/openflow/actions/nx_reg_move.ex b/lib/openflow/actions/nx_reg_move.ex index f50a3f7..309fd38 100644 --- a/lib/openflow/actions/nx_reg_move.ex +++ b/lib/openflow/actions/nx_reg_move.ex @@ -1,10 +1,10 @@ defmodule Openflow.Action.NxRegMove do defstruct( - n_bits: 0, + n_bits: 0, src_offset: 0, dst_offset: 0, - src_field: nil, - dst_field: nil + src_field: nil, + dst_field: nil ) @experimenter 0x00002320 @@ -19,38 +19,49 @@ defmodule Openflow.Action.NxRegMove do n_bits = Keyword.get(options, :n_bits, default_n_bits) src_ofs = Keyword.get(options, :src_offset, 0) dst_ofs = Keyword.get(options, :dst_offset, 0) - %NxRegMove{n_bits: n_bits, - src_offset: src_ofs, - dst_offset: dst_ofs, - src_field: src_field, - dst_field: dst_field} + + %NxRegMove{ + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs, + src_field: src_field, + dst_field: dst_field + } end - def to_binary(%NxRegMove{n_bits: n_bits, - src_offset: src_ofs, - dst_offset: dst_ofs, - src_field: src_field, - dst_field: dst_field}) do + def to_binary(%NxRegMove{ + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs, + src_field: src_field, + dst_field: dst_field + }) do src_field_bin = Openflow.Match.codec_header(src_field) dst_field_bin = Openflow.Match.codec_header(dst_field) - body = <> + + body = + <> + 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) 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 def read(<<@experimenter::32, @nxast::16, body::bytes>>) do - <> = body + <> = + body + src_field = Openflow.Match.codec_header(src_field_bin) dst_field = Openflow.Match.codec_header(dst_field_bin) - %NxRegMove{n_bits: n_bits, - src_offset: src_ofs, - dst_offset: dst_ofs, - src_field: src_field, - dst_field: dst_field} + + %NxRegMove{ + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs, + src_field: src_field, + dst_field: dst_field + } end end diff --git a/lib/openflow/actions/nx_resubmit.ex b/lib/openflow/actions/nx_resubmit.ex index 4167a19..9ed1623 100644 --- a/lib/openflow/actions/nx_resubmit.ex +++ b/lib/openflow/actions/nx_resubmit.ex @@ -1,5 +1,5 @@ defmodule Openflow.Action.NxResubmit do - defstruct([in_port: :in_port]) + defstruct(in_port: :in_port) @experimenter 0x00002320 @nxast 1 @@ -13,10 +13,10 @@ defmodule Openflow.Action.NxResubmit do def to_binary(%NxResubmit{in_port: in_port}) do 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_size = byte_size(exp_body) + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) length = 4 + exp_body_size + padding_length - <<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> end def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_resubmit_table.ex b/lib/openflow/actions/nx_resubmit_table.ex index 663ad28..04bbba8 100644 --- a/lib/openflow/actions/nx_resubmit_table.ex +++ b/lib/openflow/actions/nx_resubmit_table.ex @@ -1,5 +1,5 @@ defmodule Openflow.Action.NxResubmitTable do - defstruct([in_port: :in_port, table_id: :all]) + defstruct(in_port: :in_port, table_id: :all) @experimenter 0x00002320 @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 new(table_id: table_id) end + def new(options) do in_port = Keyword.get(options, :in_port, :in_port) 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) 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_size = byte_size(exp_body) + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) length = 4 + exp_body_size + padding_length - <<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> 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) table_id = Openflow.Utils.get_enum(table_id_int, :table_id) %NxResubmitTable{in_port: in_port, table_id: table_id} diff --git a/lib/openflow/actions/nx_resubmit_table_ct.ex b/lib/openflow/actions/nx_resubmit_table_ct.ex index 01398e1..849640e 100644 --- a/lib/openflow/actions/nx_resubmit_table_ct.ex +++ b/lib/openflow/actions/nx_resubmit_table_ct.ex @@ -16,13 +16,15 @@ defmodule Openflow.Action.NxResubmitTableCt do in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no) 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_size = byte_size(exp_body) + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) length = 4 + exp_body_size + padding_length - <<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> -end + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + 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) table_id = Openflow.Utils.get_enum(table_id_int, :table_id) %NxResubmitTableCt{in_port: in_port, table_id: table_id} diff --git a/lib/openflow/actions/nx_sample.ex b/lib/openflow/actions/nx_sample.ex index b133e38..206c0ed 100644 --- a/lib/openflow/actions/nx_sample.ex +++ b/lib/openflow/actions/nx_sample.ex @@ -1,9 +1,9 @@ defmodule Openflow.Action.NxSample do defstruct( - probability: 0, + probability: 0, collector_set_id: 0, - obs_domain_id: 0, - obs_point_id: 0 + obs_domain_id: 0, + obs_point_id: 0 ) @experimenter 0x00002320 @@ -16,29 +16,40 @@ defmodule Openflow.Action.NxSample do collector_set_id = Keyword.get(options, :collector_set_id, 0) obs_domain_id = Keyword.get(options, :obs_domain_id, 0) obs_point_id = Keyword.get(options, :obs_point_id, 0) - %NxSample{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id} + + %NxSample{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id + } end - def to_binary(%NxSample{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id}) do - 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) + def to_binary(%NxSample{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id + }) do + 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) 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 - def read(<<@experimenter::32, @nxast::16, probability::16, - collector_set_id::32, obs_domain_id::32, obs_point_id::32>>) do - %NxSample{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id} + def read( + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32>> + ) do + %NxSample{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id + } end end diff --git a/lib/openflow/actions/nx_sample2.ex b/lib/openflow/actions/nx_sample2.ex index fd15c5b..271a3c6 100644 --- a/lib/openflow/actions/nx_sample2.ex +++ b/lib/openflow/actions/nx_sample2.ex @@ -1,10 +1,10 @@ defmodule Openflow.Action.NxSample2 do defstruct( - probability: 0, + probability: 0, collector_set_id: 0, - obs_domain_id: 0, - obs_point_id: 0, - sampling_port: 0 + obs_domain_id: 0, + obs_point_id: 0, + sampling_port: 0 ) @experimenter 0x00002320 @@ -18,32 +18,43 @@ defmodule Openflow.Action.NxSample2 do obs_domain_id = Keyword.get(options, :obs_domain_id, 0) obs_point_id = Keyword.get(options, :obs_point_id, 0) sampling_port = Keyword.get(options, :sampling_port, 0) - %NxSample2{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id, - sampling_port: sampling_port} + + %NxSample2{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port + } end - def to_binary(%NxSample2{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id, - sampling_port: sampling_port}) do - 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) + def to_binary(%NxSample2{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port + }) do + 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) 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 - def read(<<@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)>>) do - %NxSample2{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id, - sampling_port: sampling_port} + def read( + <<@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)>> + ) do + %NxSample2{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port + } end end diff --git a/lib/openflow/actions/nx_sample3.ex b/lib/openflow/actions/nx_sample3.ex index f7e10ac..bb1c531 100644 --- a/lib/openflow/actions/nx_sample3.ex +++ b/lib/openflow/actions/nx_sample3.ex @@ -1,11 +1,11 @@ defmodule Openflow.Action.NxSample3 do defstruct( - probability: 0, + probability: 0, collector_set_id: 0, - obs_domain_id: 0, - obs_point_id: 0, - sampling_port: 0, - direction: :default + obs_domain_id: 0, + obs_point_id: 0, + sampling_port: 0, + direction: :default ) @experimenter 0x00002320 @@ -20,37 +20,50 @@ defmodule Openflow.Action.NxSample3 do obs_point_id = Keyword.get(options, :obs_point_id, 0) sampling_port = Keyword.get(options, :sampling_port, 0) direction = Keyword.get(options, :direction, :default) - %NxSample3{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id, - sampling_port: sampling_port, - direction: direction} + + %NxSample3{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port, + direction: direction + } end - def to_binary(%NxSample3{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id, - sampling_port: sampling_port, - direction: direction}) do + def to_binary(%NxSample3{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port, + direction: direction + }) do 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_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, 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) 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 - def read(<<@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 + def read( + <<@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) - %NxSample3{probability: probability, - collector_set_id: collector_set_id, - obs_domain_id: obs_domain_id, - obs_point_id: obs_point_id, - sampling_port: sampling_port, - direction: direction} + + %NxSample3{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port, + direction: direction + } end end diff --git a/lib/openflow/actions/nx_set_mpls_label.ex b/lib/openflow/actions/nx_set_mpls_label.ex index 99436da..9fdcf04 100644 --- a/lib/openflow/actions/nx_set_mpls_label.ex +++ b/lib/openflow/actions/nx_set_mpls_label.ex @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetMplsLabel do def to_binary(%NxSetMplsLabel{label: label}) do 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) 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 def read(<<@experimenter::32, @nxast::16, _::16, label::32>>) do diff --git a/lib/openflow/actions/nx_set_mpls_tc.ex b/lib/openflow/actions/nx_set_mpls_tc.ex index 16414f2..9392558 100644 --- a/lib/openflow/actions/nx_set_mpls_tc.ex +++ b/lib/openflow/actions/nx_set_mpls_tc.ex @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetMplsTc do def to_binary(%NxSetMplsTc{tc: tc}) do 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) 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 def read(<<@experimenter::32, @nxast::16, tc::8, _::size(5)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_set_mpls_ttl.ex b/lib/openflow/actions/nx_set_mpls_ttl.ex index 929398f..cd932af 100644 --- a/lib/openflow/actions/nx_set_mpls_ttl.ex +++ b/lib/openflow/actions/nx_set_mpls_ttl.ex @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetMplsTtl do def to_binary(%NxSetMplsTtl{ttl: ttl}) do 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) 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 def read(<<@experimenter::32, @nxast::16, ttl::8, _::size(5)-unit(8)>>) do diff --git a/lib/openflow/actions/nx_set_queue.ex b/lib/openflow/actions/nx_set_queue.ex index d133276..845c494 100644 --- a/lib/openflow/actions/nx_set_queue.ex +++ b/lib/openflow/actions/nx_set_queue.ex @@ -1,5 +1,5 @@ defmodule Openflow.Action.NxSetQueue do - defstruct([queue_id: 0]) + defstruct(queue_id: 0) @experimenter 0x00002320 @nxast 4 @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetQueue do def to_binary(%NxSetQueue{queue_id: queue_id}) do 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) 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 def read(<<@experimenter::32, @nxast::16, 0::size(2)-unit(8), queue_id::32>>) do diff --git a/lib/openflow/actions/nx_set_tunnel.ex b/lib/openflow/actions/nx_set_tunnel.ex index 0ed3d14..661114b 100644 --- a/lib/openflow/actions/nx_set_tunnel.ex +++ b/lib/openflow/actions/nx_set_tunnel.ex @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetTunnel do def to_binary(%NxSetTunnel{tunnel_id: tunnel_id}) do 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) 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 def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do diff --git a/lib/openflow/actions/nx_set_tunnel64.ex b/lib/openflow/actions/nx_set_tunnel64.ex index c70b230..d729689 100644 --- a/lib/openflow/actions/nx_set_tunnel64.ex +++ b/lib/openflow/actions/nx_set_tunnel64.ex @@ -1,5 +1,5 @@ defmodule Openflow.Action.NxSetTunnel64 do - defstruct([tunnel_id: 0]) + defstruct(tunnel_id: 0) @experimenter 0x00002320 @nxast 9 @@ -12,10 +12,10 @@ defmodule Openflow.Action.NxSetTunnel64 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_size = byte_size(exp_body) + exp_body_size = byte_size(exp_body) padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) length = 4 + exp_body_size + padding_length - <<0xffff::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> end def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>>) do diff --git a/lib/openflow/actions/nx_stack_pop.ex b/lib/openflow/actions/nx_stack_pop.ex index c106678..479932c 100644 --- a/lib/openflow/actions/nx_stack_pop.ex +++ b/lib/openflow/actions/nx_stack_pop.ex @@ -1,8 +1,8 @@ defmodule Openflow.Action.NxStackPop do defstruct( - n_bits: 0, - offset: 0, - field: nil + n_bits: 0, + offset: 0, + field: nil ) @experimenter 0x00002320 @@ -20,16 +20,21 @@ defmodule Openflow.Action.NxStackPop do def to_binary(%NxStackPop{n_bits: n_bits, offset: ofs, field: field}) do 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_size = byte_size(exp_body) + + 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) 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 - def read(<<@experimenter::32, @nxast::16, ofs::16, - field_bin::4-bytes, n_bits::16, _::size(6)-unit(8)>>) do + def read( + <<@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) %NxStackPop{n_bits: n_bits, offset: ofs, field: field} end diff --git a/lib/openflow/actions/nx_stack_push.ex b/lib/openflow/actions/nx_stack_push.ex index 21dc9c0..aa33e71 100644 --- a/lib/openflow/actions/nx_stack_push.ex +++ b/lib/openflow/actions/nx_stack_push.ex @@ -1,8 +1,8 @@ defmodule Openflow.Action.NxStackPush do defstruct( - n_bits: 0, - offset: 0, - field: nil + n_bits: 0, + offset: 0, + field: nil ) @experimenter 0x00002320 @@ -20,16 +20,21 @@ defmodule Openflow.Action.NxStackPush do def to_binary(%NxStackPush{n_bits: n_bits, offset: ofs, field: field}) do 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_size = byte_size(exp_body) + + 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) 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 - def read(<<@experimenter::32, @nxast::16, ofs::16, - field_bin::4-bytes, n_bits::16, _::size(6)-unit(8)>>) do + def read( + <<@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) %NxStackPush{n_bits: n_bits, offset: ofs, field: field} end diff --git a/lib/openflow/actions/nx_write_metadata.ex b/lib/openflow/actions/nx_write_metadata.ex index 5450257..4396d6a 100644 --- a/lib/openflow/actions/nx_write_metadata.ex +++ b/lib/openflow/actions/nx_write_metadata.ex @@ -1,7 +1,7 @@ defmodule Openflow.Action.NxWriteMetadata do defstruct( metadata: 0, - metadata_mask: 0xffffffffffffffff + metadata_mask: 0xFFFFFFFFFFFFFFFF ) @experimenter 0x00002320 @@ -12,18 +12,21 @@ defmodule Openflow.Action.NxWriteMetadata do def new(metadata) when is_integer(metadata) do new(metadata: metadata) end + def new(options) when is_list(options) do 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} end 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_size = byte_size(exp_body) + 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) 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 def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8), metadata::64, metadata_mask::64>>) do diff --git a/lib/openflow/actions/output.ex b/lib/openflow/actions/output.ex index 116dc96..070b123 100644 --- a/lib/openflow/actions/output.ex +++ b/lib/openflow/actions/output.ex @@ -11,6 +11,7 @@ defmodule Openflow.Action.Output do def new(port) when not is_list(port) do new(port_number: port) end + def new(options) when is_list(options) do port_no = Keyword.get(options, :port_number) max_len = Keyword.get(options, :max_len, :no_buffer) diff --git a/lib/openflow/actions/push_pbb.ex b/lib/openflow/actions/push_pbb.ex index f509b70..4a7d0ae 100644 --- a/lib/openflow/actions/push_pbb.ex +++ b/lib/openflow/actions/push_pbb.ex @@ -1,5 +1,5 @@ defmodule Openflow.Action.PushPbb do - defstruct(ethertype: 0x88e7) + defstruct(ethertype: 0x88E7) alias __MODULE__ diff --git a/lib/openflow/actions/set_field.ex b/lib/openflow/actions/set_field.ex index a1b0c1d..79b4070 100644 --- a/lib/openflow/actions/set_field.ex +++ b/lib/openflow/actions/set_field.ex @@ -14,8 +14,8 @@ defmodule Openflow.Action.SetField do def to_binary(%SetField{field: {field, value}}) do match_bin = [{field, value}] - |> Openflow.Match.new - |> Openflow.Match.to_binary + |> Openflow.Match.new() + |> Openflow.Match.to_binary() <<1::16, _length::16, padded_field::bytes>> = match_bin 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 match_len = 4 + 4 + flen 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} end end diff --git a/lib/openflow/barrier/reply.ex b/lib/openflow/barrier/reply.ex index a392f3d..59f7f68 100644 --- a/lib/openflow/barrier/reply.ex +++ b/lib/openflow/barrier/reply.ex @@ -1,9 +1,11 @@ defmodule Openflow.Barrier.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ diff --git a/lib/openflow/barrier/request.ex b/lib/openflow/barrier/request.ex index 6ca6437..399e533 100644 --- a/lib/openflow/barrier/request.ex +++ b/lib/openflow/barrier/request.ex @@ -1,9 +1,11 @@ defmodule Openflow.Barrier.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ diff --git a/lib/openflow/buckets.ex b/lib/openflow/buckets.ex index 806f3b6..005db35 100644 --- a/lib/openflow/buckets.ex +++ b/lib/openflow/buckets.ex @@ -1,9 +1,9 @@ defmodule Openflow.Bucket do defstruct( - weight: 0, - watch_port: 0, + weight: 0, + watch_port: 0, watch_group: 0, - actions: [] + actions: [] ) alias __MODULE__ @@ -29,26 +29,43 @@ defmodule Openflow.Bucket do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) - defp do_read(acc, <>) do + + defp do_read( + acc, + <> + ) do actions_len = length - @header_size <> = binary watch_port = Openflow.Utils.get_enum(watch_port_int, :openflow13_port_no) watch_group = Openflow.Utils.get_enum(watch_group_int, :group_id) actions = Openflow.Action.read(actions_bin) - bucket = %Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} - do_read([bucket|acc], rest) + + bucket = %Bucket{ + weight: weight, + watch_port: watch_port, + watch_group: watch_group, + actions: actions + } + + do_read([bucket | acc], rest) end defp to_binary(acc, []), do: acc - defp to_binary(acc, [bucket|rest]) do - %Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} = bucket + + defp to_binary(acc, [bucket | rest]) do + %Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} = + bucket + watch_port_int = Openflow.Utils.get_enum(watch_port, :openflow13_port_no) watch_group_int = Openflow.Utils.get_enum(watch_group, :group_id) actions_bin = Openflow.Action.to_binary(actions) length = byte_size(actions_bin) + @header_size - bucket_bin = <> + + bucket_bin = + <> + to_binary(<>, rest) end end diff --git a/lib/openflow/echo/reply.ex b/lib/openflow/echo/reply.ex index 5955bf3..455ef64 100644 --- a/lib/openflow/echo/reply.ex +++ b/lib/openflow/echo/reply.ex @@ -1,10 +1,12 @@ defmodule Openflow.Echo.Reply do defstruct( - version: 4, - xid: 0, - data: "", - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + data: "", + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ diff --git a/lib/openflow/echo/request.ex b/lib/openflow/echo/request.ex index 248dede..f3a6af3 100644 --- a/lib/openflow/echo/request.ex +++ b/lib/openflow/echo/request.ex @@ -1,10 +1,12 @@ defmodule Openflow.Echo.Request do defstruct( - version: 4, - xid: 0, - data: "", - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + data: "", + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ @@ -23,4 +25,3 @@ defmodule Openflow.Echo.Request do data end end - diff --git a/lib/openflow/enums.ex b/lib/openflow/enums.ex index b29f59d..7ea33b5 100644 --- a/lib/openflow/enums.ex +++ b/lib/openflow/enums.ex @@ -3,41 +3,39 @@ defmodule Openflow.Enums do @enums [ openflow_codec: [ - {Openflow.Hello, 0}, - {Openflow.ErrorMsg, 1}, - {Openflow.Echo.Request, 2}, - {Openflow.Echo.Reply, 3}, - {Openflow.Experimenter, 4}, - {Openflow.Features.Request, 5}, - {Openflow.Features.Reply, 6}, + {Openflow.Hello, 0}, + {Openflow.ErrorMsg, 1}, + {Openflow.Echo.Request, 2}, + {Openflow.Echo.Reply, 3}, + {Openflow.Experimenter, 4}, + {Openflow.Features.Request, 5}, + {Openflow.Features.Reply, 6}, {Openflow.GetConfig.Request, 7}, - {Openflow.GetConfig.Reply, 8}, - {Openflow.SetConfig, 9}, - {Openflow.PacketIn, 10}, - {Openflow.FlowRemoved, 11}, - {Openflow.PortStatus, 12}, - {Openflow.PacketOut, 13}, - {Openflow.FlowMod, 14}, - {Openflow.GroupMod, 15}, - {Openflow.PortMod, 16}, - {Openflow.TableMod, 17}, + {Openflow.GetConfig.Reply, 8}, + {Openflow.SetConfig, 9}, + {Openflow.PacketIn, 10}, + {Openflow.FlowRemoved, 11}, + {Openflow.PortStatus, 12}, + {Openflow.PacketOut, 13}, + {Openflow.FlowMod, 14}, + {Openflow.GroupMod, 15}, + {Openflow.PortMod, 16}, + {Openflow.TableMod, 17}, {Openflow.Multipart.Request, 18}, - {Openflow.Multipart.Reply, 19}, - {Openflow.Barrier.Request, 20}, - {Openflow.Barrier.Reply, 21}, - {Openflow.Role.Request, 24}, - {Openflow.Role.Reply, 25}, - {Openflow.GetAsync.Request, 26}, - {Openflow.GetAsync.Reply, 27}, - {Openflow.SetAsync, 28}, - {Openflow.MeterMod, 29} + {Openflow.Multipart.Reply, 19}, + {Openflow.Barrier.Request, 20}, + {Openflow.Barrier.Reply, 21}, + {Openflow.Role.Request, 24}, + {Openflow.Role.Reply, 25}, + {Openflow.GetAsync.Request, 26}, + {Openflow.GetAsync.Reply, 27}, + {Openflow.SetAsync, 28}, + {Openflow.MeterMod, 29} ], - experimenter_id: [ nicira_ext_message: 0x00002320, - onf_ext_message: 0x4f4e4600 + onf_ext_message: 0x4F4E4600 ], - nicira_ext_message: [ # {Openflow.NxRole.Request, 10}, /* Openflow 1.3 support role request/reply */ # {Openflow.NxRole.Reply, 11}, @@ -45,534 +43,500 @@ defmodule Openflow.Enums do # {Openflow.NxFlowMod, 13}, /* Prefer use ofp_flow_mod to nx_flow_mod */ # {Openflow.NxFlowRemoved, 14}, /* Prefer use ofp_flow_removed to nx_flow_removed */ # {Openflow.NxSetFlowModTableId, 15}, /* OpenFlow 1.3 support multiple flow table. */ - {Openflow.NxSetPacketInFormat, 16}, + {Openflow.NxSetPacketInFormat, 16}, # {Openflow.NxPacketIn, 17}, /* No special reason for implement this struct codec. */ # {Openflow.NxFlowAge, 18}, /* No special reason for implement this struct codec. */ # {Openflow.NxSetAsyncConfig, 19}, /* Openflow 1.3 support async config. */ - {Openflow.NxSetControllerId, 20}, - {Openflow.NxFlowMonitor.Cancel, 21}, - {Openflow.NxFlowMonitor.Paused, 22}, + {Openflow.NxSetControllerId, 20}, + {Openflow.NxFlowMonitor.Cancel, 21}, + {Openflow.NxFlowMonitor.Paused, 22}, {Openflow.NxFlowMonitor.Resumed, 23}, - {Openflow.NxTLVTableMod, 24}, - {Openflow.NxTLVTable.Request, 25}, - {Openflow.NxTLVTable.Reply, 26}, - {Openflow.NxSetAsyncConfig2, 27}, - {Openflow.NxResume, 28}, - {Openflow.NxCtFlushZone, 29}, - {Openflow.NxPacketIn2, 30} + {Openflow.NxTLVTableMod, 24}, + {Openflow.NxTLVTable.Request, 25}, + {Openflow.NxTLVTable.Reply, 26}, + {Openflow.NxSetAsyncConfig2, 27}, + {Openflow.NxResume, 28}, + {Openflow.NxCtFlushZone, 29}, + {Openflow.NxPacketIn2, 30} ], - onf_ext_message: [ - {Openflow.OnfBundleControl, 2300}, - {Openflow.OnfBundleAddMessage, 2301}, + {Openflow.OnfBundleControl, 2300}, + {Openflow.OnfBundleAddMessage, 2301} ], - multipart_request_flags: [ more: 1 <<< 0 ], - multipart_reply_flags: [ more: 1 <<< 0 ], - multipart_request_codec: [ - {Openflow.Multipart.Desc.Request, 0}, - {Openflow.Multipart.Flow.Request, 1}, - {Openflow.Multipart.Aggregate.Request, 2}, - {Openflow.Multipart.Table.Request, 3}, - {Openflow.Multipart.PortStats.Request, 4}, - {Openflow.Multipart.Queue.Request, 5}, - {Openflow.Multipart.Group.Request, 6}, - {Openflow.Multipart.GroupDesc.Request, 7}, - {Openflow.Multipart.GroupFeatures.Request, 8}, - {Openflow.Multipart.Meter.Request, 9}, - {Openflow.Multipart.MeterConfig.Request, 10}, - {Openflow.Multipart.MeterFeatures.Request, 11}, - {Openflow.Multipart.TableFeatures.Request, 12}, - {Openflow.Multipart.PortDesc.Request, 13}, - {Openflow.Multipart.Experimenter.Request, 0xffff}, + {Openflow.Multipart.Desc.Request, 0}, + {Openflow.Multipart.Flow.Request, 1}, + {Openflow.Multipart.Aggregate.Request, 2}, + {Openflow.Multipart.Table.Request, 3}, + {Openflow.Multipart.PortStats.Request, 4}, + {Openflow.Multipart.Queue.Request, 5}, + {Openflow.Multipart.Group.Request, 6}, + {Openflow.Multipart.GroupDesc.Request, 7}, + {Openflow.Multipart.GroupFeatures.Request, 8}, + {Openflow.Multipart.Meter.Request, 9}, + {Openflow.Multipart.MeterConfig.Request, 10}, + {Openflow.Multipart.MeterFeatures.Request, 11}, + {Openflow.Multipart.TableFeatures.Request, 12}, + {Openflow.Multipart.PortDesc.Request, 13}, + {Openflow.Multipart.Experimenter.Request, 0xFFFF} ], - multipart_reply_codec: [ - {Openflow.Multipart.Desc.Reply, 0}, - {Openflow.Multipart.Flow.Reply, 1}, - {Openflow.Multipart.Aggregate.Reply, 2}, - {Openflow.Multipart.Table.Reply, 3}, - {Openflow.Multipart.PortStats.Reply, 4}, - {Openflow.Multipart.Queue.Reply, 5}, - {Openflow.Multipart.Group.Reply, 6}, - {Openflow.Multipart.GroupDesc.Reply, 7}, - {Openflow.Multipart.GroupFeatures.Reply, 8}, - {Openflow.Multipart.Meter.Reply, 9}, - {Openflow.Multipart.MeterConfig.Reply, 10}, - {Openflow.Multipart.MeterFeatures.Reply, 11}, - {Openflow.Multipart.TableFeatures.Reply, 12}, - {Openflow.Multipart.PortDesc.Reply, 13}, - {Openflow.Multipart.Experimenter.Reply, 0xffff}, + {Openflow.Multipart.Desc.Reply, 0}, + {Openflow.Multipart.Flow.Reply, 1}, + {Openflow.Multipart.Aggregate.Reply, 2}, + {Openflow.Multipart.Table.Reply, 3}, + {Openflow.Multipart.PortStats.Reply, 4}, + {Openflow.Multipart.Queue.Reply, 5}, + {Openflow.Multipart.Group.Reply, 6}, + {Openflow.Multipart.GroupDesc.Reply, 7}, + {Openflow.Multipart.GroupFeatures.Reply, 8}, + {Openflow.Multipart.Meter.Reply, 9}, + {Openflow.Multipart.MeterConfig.Reply, 10}, + {Openflow.Multipart.MeterFeatures.Reply, 11}, + {Openflow.Multipart.TableFeatures.Reply, 12}, + {Openflow.Multipart.PortDesc.Reply, 13}, + {Openflow.Multipart.Experimenter.Reply, 0xFFFF} ], - nicira_ext_stats: [ - {Openflow.Multipart.NxFlow, 0}, - {Openflow.Multipart.NxAggregate, 1}, + {Openflow.Multipart.NxFlow, 0}, + {Openflow.Multipart.NxAggregate, 1}, {Openflow.Multipart.NxFlowMonitor, 2}, {Openflow.Multipart.NxIPFIXBridge, 3}, - {Openflow.Multipart.NxIPFIXFlow, 4}, + {Openflow.Multipart.NxIPFIXFlow, 4} ], - hello_elem: [ - versionbitmap: 1 + versionbitmap: 1 ], - error_type: [ - hello_failed: 0, - bad_request: 1, - bad_action: 2, - bad_instruction: 3, - bad_match: 4, - flow_mod_failed: 5, - group_mod_failed: 6, - port_mod_failed: 7, - table_mod_failed: 8, - queue_op_failed: 9, - switch_config_failed: 10, - role_request_failed: 11, - meter_mod_failed: 12, + hello_failed: 0, + bad_request: 1, + bad_action: 2, + bad_instruction: 3, + bad_match: 4, + flow_mod_failed: 5, + group_mod_failed: 6, + port_mod_failed: 7, + table_mod_failed: 8, + queue_op_failed: 9, + switch_config_failed: 10, + role_request_failed: 11, + meter_mod_failed: 12, table_features_failed: 13, - experimenter: 0xffff + experimenter: 0xFFFF ], - hello_failed: [ inconpatible: 0, - eperm: 1 + eperm: 1 ], - bad_request: [ - bad_version: 0, - bad_type: 1, - bad_multipart: 2, - bad_experimeter: 3, - bad_exp_type: 4, - eperm: 5, - bad_len: 6, - buffer_empty: 7, - buffer_unknown: 8, - bad_table_id: 9, - is_slave: 10, - bad_port: 11, - bad_packet: 12, + bad_version: 0, + bad_type: 1, + bad_multipart: 2, + bad_experimeter: 3, + bad_exp_type: 4, + eperm: 5, + bad_len: 6, + buffer_empty: 7, + buffer_unknown: 8, + bad_table_id: 9, + is_slave: 10, + bad_port: 11, + bad_packet: 12, multipart_buffer_overflow: 13 ], - bad_action: [ - bad_type: 0, - bad_len: 1, - bad_experimeter: 2, - bad_exp_type: 3, - bad_out_port: 4, - bad_argument: 5, - eperm: 6, - too_many: 7, - bad_queue: 8, - bad_out_group: 9, + bad_type: 0, + bad_len: 1, + bad_experimeter: 2, + bad_exp_type: 3, + bad_out_port: 4, + bad_argument: 5, + eperm: 6, + too_many: 7, + bad_queue: 8, + bad_out_group: 9, match_inconsistent: 10, - unsupported_order: 11, - bad_tag: 12, - bad_set_type: 13, - bad_set_len: 14, - bad_set_argument: 15 + unsupported_order: 11, + bad_tag: 12, + bad_set_type: 13, + bad_set_len: 14, + bad_set_argument: 15 ], - bad_instruction: [ - unknown_instruction: 0, - unsupported_instruction: 1, - bad_table_id: 2, - unsupported_metadata: 3, + unknown_instruction: 0, + unsupported_instruction: 1, + bad_table_id: 2, + unsupported_metadata: 3, unsupported_metadata_mask: 4, - bad_experimeter: 5, - bad_exp_type: 6, - bad_len: 7, - eperm: 8 + bad_experimeter: 5, + bad_exp_type: 6, + bad_len: 7, + eperm: 8 ], - bad_match: [ - bad_type: 0, - bad_len: 1, - bad_tag: 2, + bad_type: 0, + bad_len: 1, + bad_tag: 2, bad_dl_addr_mask: 3, bad_nw_addr_mask: 4, - bad_wildcards: 5, - bad_field: 6, - bad_value: 7, - bad_mask: 8, - bad_prereq: 9, - dup_field: 10, - eperm: 11 + bad_wildcards: 5, + bad_field: 6, + bad_value: 7, + bad_mask: 8, + bad_prereq: 9, + dup_field: 10, + eperm: 11 ], - flow_mod_failed: [ - unknown: 0, - table_full: 1, + unknown: 0, + table_full: 1, bad_table_id: 2, - overlap: 3, - eperm: 4, - bad_timeout: 5, - bad_command: 6, - bad_flags: 7 + overlap: 3, + eperm: 4, + bad_timeout: 5, + bad_command: 6, + bad_flags: 7 ], - group_mod_failed: [ - group_exists: 0, - invalid_group: 1, - weight_unsupported: 2, - out_of_groups: 3, - ouf_of_buckets: 4, + group_exists: 0, + invalid_group: 1, + weight_unsupported: 2, + out_of_groups: 3, + ouf_of_buckets: 4, chaining_unsupported: 5, - watch_unsupported: 6, - loop: 7, - unknown_group: 8, - chained_group: 9, - bad_type: 10, - bad_command: 11, - bad_bucket: 12, - bad_watch: 13, - eperm: 14 + watch_unsupported: 6, + loop: 7, + unknown_group: 8, + chained_group: 9, + bad_type: 10, + bad_command: 11, + bad_bucket: 12, + bad_watch: 13, + eperm: 14 ], - port_mod_failed: [ - bad_port: 0, - bad_hw_addr: 1, - bad_config: 2, + bad_port: 0, + bad_hw_addr: 1, + bad_config: 2, bad_advertise: 3, - eperm: 4 + eperm: 4 ], - table_mod_failed: [ - bad_table: 0, + bad_table: 0, bad_config: 1, - eperm: 2 + eperm: 2 ], - queue_op_failed: [ - bad_port: 0, + bad_port: 0, bad_queue: 1, - eperm: 2 + eperm: 2 ], - switch_config_failed: [ bad_flags: 0, - bad_len: 1, - eperm: 2 + bad_len: 1, + eperm: 2 ], - role_request_failed: [ - stale: 0, - unsup: 1, + stale: 0, + unsup: 1, bad_role: 2 ], - meter_mod_failed: [ - unknown: 0, - meter_exists: 1, - invalid_meter: 2, - unknown_meter: 3, - bad_command: 4, - bad_flags: 5, - bad_rate: 6, - bad_burst: 7, - bad_band: 8, + unknown: 0, + meter_exists: 1, + invalid_meter: 2, + unknown_meter: 3, + bad_command: 4, + bad_flags: 5, + bad_rate: 6, + bad_burst: 7, + bad_band: 8, bad_band_value: 9, out_of_meters: 10, - out_of_bands: 11 + out_of_bands: 11 ], - table_features_failed: [ - bad_table: 0, + bad_table: 0, bad_metadata: 1, - bad_type: 2, - bad_len: 3, + bad_type: 2, + bad_len: 3, bad_argument: 4, - eperm: 5 + eperm: 5 ], - switch_capabilities: [ - flow_stats: 1 <<< 0, - table_stats: 1 <<< 1, - port_stats: 1 <<< 2, - group_stats: 1 <<< 3, - ip_reasm: 1 <<< 5, - queue_stats: 1 <<< 6, + flow_stats: 1 <<< 0, + table_stats: 1 <<< 1, + port_stats: 1 <<< 2, + group_stats: 1 <<< 3, + ip_reasm: 1 <<< 5, + queue_stats: 1 <<< 6, arp_match_ip: 1 <<< 7, port_blocked: 1 <<< 8 ], - config_flags: [ - drop: 1 <<< 0, + drop: 1 <<< 0, reasm: 1 <<< 1 ], - controller_max_len: [ - max: 0xffe5, - no_buffer: 0xffff + max: 0xFFE5, + no_buffer: 0xFFFF ], - experimenter_oxm_vendors: [ nicira_ext_match: 0x00002320, - hp_ext_match: 0x00002428, - onf_ext_match: 0x4f4e4600 + hp_ext_match: 0x00002428, + onf_ext_match: 0x4F4E4600 ], - match_type: [ standard: 0, - oxm: 1 + oxm: 1 ], - oxm_class: [ - nxm_0: 0x0000, - nxm_1: 0x0001, - openflow_basic: 0x8000, + nxm_0: 0x0000, + nxm_1: 0x0001, + openflow_basic: 0x8000, packet_register: 0x8001, - experimenter: 0xffff + experimenter: 0xFFFF ], - nxm_0: [ - nx_in_port: 0, - nx_eth_dst: 1, - nx_eth_src: 2, - nx_eth_type: 3, - nx_vlan_tci: 4, - nx_ip_tos: 5, - nx_ip_proto: 6, - nx_ipv4_src: 7, - nx_ipv4_dst: 8, - nx_tcp_src: 9, - nx_tcp_dst: 10, - nx_udp_src: 11, - nx_udp_dst: 12, + nx_in_port: 0, + nx_eth_dst: 1, + nx_eth_src: 2, + nx_eth_type: 3, + nx_vlan_tci: 4, + nx_ip_tos: 5, + nx_ip_proto: 6, + nx_ipv4_src: 7, + nx_ipv4_dst: 8, + nx_tcp_src: 9, + nx_tcp_dst: 10, + nx_udp_src: 11, + nx_udp_dst: 12, nx_icmpv4_type: 13, nx_icmpv4_code: 14, - nx_arp_op: 15, - nx_arp_spa: 16, - nx_arp_tpa: 17, - nx_tcp_flags: 34, + nx_arp_op: 15, + nx_arp_spa: 16, + nx_arp_tpa: 17, + nx_tcp_flags: 34 ], - nxm_1: [ - reg0: 0, - reg1: 1, - reg2: 2, - reg3: 3, - reg4: 4, - reg5: 5, - reg6: 6, - reg7: 7, - reg8: 8, - reg9: 9, - reg10: 10, - reg11: 11, - reg12: 12, - reg13: 13, - reg14: 14, - reg15: 15, - tun_id: 16, - nx_arp_sha: 17, - nx_arp_tha: 18, - nx_ipv6_src: 19, - nx_ipv6_dst: 20, - nx_icmpv6_type: 21, - nx_icmpv6_code: 22, + reg0: 0, + reg1: 1, + reg2: 2, + reg3: 3, + reg4: 4, + reg5: 5, + reg6: 6, + reg7: 7, + reg8: 8, + reg9: 9, + reg10: 10, + reg11: 11, + reg12: 12, + reg13: 13, + reg14: 14, + reg15: 15, + tun_id: 16, + nx_arp_sha: 17, + nx_arp_tha: 18, + nx_ipv6_src: 19, + nx_ipv6_dst: 20, + nx_icmpv6_type: 21, + nx_icmpv6_code: 22, nx_ipv6_nd_target: 23, - nx_ipv6_nd_sll: 24, - nx_ipv6_nd_tll: 25, - nx_ip_frag: 26, - nx_ipv6_label: 27, - nx_ip_ecn: 28, - nx_ip_ttl: 29, - nx_mpls_ttl: 30, - tun_src: 31, - tun_dst: 32, - pkt_mark: 33, - dp_hash: 35, - recirc_id: 36, - conj_id: 37, - tun_gbp_id: 38, - tun_gbp_flags: 39, - tun_metadata0: 40, - tun_metadata1: 41, - tun_metadata2: 42, - tun_metadata3: 43, - tun_metadata4: 44, - tun_metadata5: 45, - tun_metadata6: 46, - tun_metadata7: 47, - tun_metadata8: 48, - tun_metadata9: 49, - tun_metadata10: 50, - tun_metadata11: 51, - tun_metadata12: 52, - tun_metadata13: 53, - tun_metadata14: 54, - tun_metadata15: 55, - tun_metadata16: 56, - tun_metadata17: 57, - tun_metadata18: 58, - tun_metadata19: 59, - tun_metadata20: 60, - tun_metadata21: 61, - tun_metadata22: 62, - tun_metadata23: 63, - tun_metadata24: 64, - tun_metadata25: 65, - tun_metadata26: 66, - tun_metadata27: 67, - tun_metadata28: 68, - tun_metadata29: 69, - tun_metadata30: 70, - tun_metadata31: 71, - tun_metadata32: 72, - tun_metadata33: 73, - tun_metadata34: 74, - tun_metadata35: 75, - tun_metadata36: 76, - tun_metadata37: 77, - tun_metadata38: 78, - tun_metadata39: 79, - tun_metadata40: 80, - tun_metadata41: 81, - tun_metadata42: 82, - tun_metadata43: 83, - tun_metadata44: 84, - tun_metadata45: 85, - tun_metadata46: 86, - tun_metadata47: 87, - tun_metadata48: 88, - tun_metadata49: 89, - tun_metadata50: 90, - tun_metadata51: 91, - tun_metadata52: 92, - tun_metadata53: 93, - tun_metadata54: 94, - tun_metadata55: 95, - tun_metadata56: 96, - tun_metadata57: 97, - tun_metadata58: 98, - tun_metadata59: 99, - tun_metadata60: 100, - tun_metadata61: 101, - tun_metadata62: 102, - tun_metadata63: 103, - tun_flags: 104, - ct_state: 105, - ct_zone: 106, - ct_mark: 107, - ct_label: 108, - tun_ipv6_src: 109, - tun_ipv6_dst: 110, - xxreg0: 111, - xxreg1: 112, - xxreg2: 113, - xxreg3: 114, - xxreg4: 115, - xxreg5: 116, - xxreg6: 117, - xxreg7: 118, - ct_nw_proto: 119, - ct_nw_src: 120, - ct_nw_dst: 121, - ct_ipv6_src: 122, - ct_ipv6_dst: 123, - ct_tp_src: 124, - ct_tp_dst: 125 + nx_ipv6_nd_sll: 24, + nx_ipv6_nd_tll: 25, + nx_ip_frag: 26, + nx_ipv6_label: 27, + nx_ip_ecn: 28, + nx_ip_ttl: 29, + nx_mpls_ttl: 30, + tun_src: 31, + tun_dst: 32, + pkt_mark: 33, + dp_hash: 35, + recirc_id: 36, + conj_id: 37, + tun_gbp_id: 38, + tun_gbp_flags: 39, + tun_metadata0: 40, + tun_metadata1: 41, + tun_metadata2: 42, + tun_metadata3: 43, + tun_metadata4: 44, + tun_metadata5: 45, + tun_metadata6: 46, + tun_metadata7: 47, + tun_metadata8: 48, + tun_metadata9: 49, + tun_metadata10: 50, + tun_metadata11: 51, + tun_metadata12: 52, + tun_metadata13: 53, + tun_metadata14: 54, + tun_metadata15: 55, + tun_metadata16: 56, + tun_metadata17: 57, + tun_metadata18: 58, + tun_metadata19: 59, + tun_metadata20: 60, + tun_metadata21: 61, + tun_metadata22: 62, + tun_metadata23: 63, + tun_metadata24: 64, + tun_metadata25: 65, + tun_metadata26: 66, + tun_metadata27: 67, + tun_metadata28: 68, + tun_metadata29: 69, + tun_metadata30: 70, + tun_metadata31: 71, + tun_metadata32: 72, + tun_metadata33: 73, + tun_metadata34: 74, + tun_metadata35: 75, + tun_metadata36: 76, + tun_metadata37: 77, + tun_metadata38: 78, + tun_metadata39: 79, + tun_metadata40: 80, + tun_metadata41: 81, + tun_metadata42: 82, + tun_metadata43: 83, + tun_metadata44: 84, + tun_metadata45: 85, + tun_metadata46: 86, + tun_metadata47: 87, + tun_metadata48: 88, + tun_metadata49: 89, + tun_metadata50: 90, + tun_metadata51: 91, + tun_metadata52: 92, + tun_metadata53: 93, + tun_metadata54: 94, + tun_metadata55: 95, + tun_metadata56: 96, + tun_metadata57: 97, + tun_metadata58: 98, + tun_metadata59: 99, + tun_metadata60: 100, + tun_metadata61: 101, + tun_metadata62: 102, + tun_metadata63: 103, + tun_flags: 104, + ct_state: 105, + ct_zone: 106, + ct_mark: 107, + ct_label: 108, + tun_ipv6_src: 109, + tun_ipv6_dst: 110, + xxreg0: 111, + xxreg1: 112, + xxreg2: 113, + xxreg3: 114, + xxreg4: 115, + xxreg5: 116, + xxreg6: 117, + xxreg7: 118, + ct_nw_proto: 119, + ct_nw_src: 120, + ct_nw_dst: 121, + ct_ipv6_src: 122, + ct_ipv6_dst: 123, + ct_tp_src: 124, + ct_tp_dst: 125 ], - openflow_basic: [ - in_port: 0, - in_phy_port: 1, - metadata: 2, - eth_dst: 3, - eth_src: 4, - eth_type: 5, - vlan_vid: 6, - vlan_pcp: 7, - ip_dscp: 8, - ip_ecn: 9, - ip_proto: 10, - ipv4_src: 11, - ipv4_dst: 12, - tcp_src: 13, - tcp_dst: 14, - udp_src: 15, - udp_dst: 16, - sctp_src: 17, - sctp_dst: 18, - icmpv4_type: 19, - icmpv4_code: 20, - arp_op: 21, - arp_spa: 22, - arp_tpa: 23, - arp_sha: 24, - arp_tha: 25, - ipv6_src: 26, - ipv6_dst: 27, - ipv6_flabel: 28, - icmpv6_type: 29, - icmpv6_code: 30, + in_port: 0, + in_phy_port: 1, + metadata: 2, + eth_dst: 3, + eth_src: 4, + eth_type: 5, + vlan_vid: 6, + vlan_pcp: 7, + ip_dscp: 8, + ip_ecn: 9, + ip_proto: 10, + ipv4_src: 11, + ipv4_dst: 12, + tcp_src: 13, + tcp_dst: 14, + udp_src: 15, + udp_dst: 16, + sctp_src: 17, + sctp_dst: 18, + icmpv4_type: 19, + icmpv4_code: 20, + arp_op: 21, + arp_spa: 22, + arp_tpa: 23, + arp_sha: 24, + arp_tha: 25, + ipv6_src: 26, + ipv6_dst: 27, + ipv6_flabel: 28, + icmpv6_type: 29, + icmpv6_code: 30, ipv6_nd_target: 31, - ipv6_nd_sll: 32, - ipv6_nd_tll: 33, - mpls_label: 34, - mpls_tc: 35, - mpls_bos: 36, - pbb_isid: 37, - tunnel_id: 38, - ipv6_exthdr: 39, + ipv6_nd_sll: 32, + ipv6_nd_tll: 33, + mpls_label: 34, + mpls_tc: 35, + mpls_bos: 36, + pbb_isid: 37, + tunnel_id: 38, + ipv6_exthdr: 39, # Lagopus extended match fields - pbb_uca: 41, - packet_type: 42, - gre_flags: 43, - gre_ver: 44, - gre_protocol: 45, - gre_key: 46, - gre_seqnum: 47, - lisp_flags: 48, - lisp_nonce: 49, - lisp_id: 50, - vxlan_flags: 51, - vxlan_vni: 52, + pbb_uca: 41, + packet_type: 42, + gre_flags: 43, + gre_ver: 44, + gre_protocol: 45, + gre_key: 46, + gre_seqnum: 47, + lisp_flags: 48, + lisp_nonce: 49, + lisp_id: 50, + vxlan_flags: 51, + vxlan_vni: 52, mpls_data_first_nibble: 53, - mpls_ach_version: 54, - mpls_ach_channel: 55, - mpls_pw_metadata: 56, - mpls_cw_flags: 57, - mpls_cw_fragment: 58, - mpls_cw_len: 59, - mpls_cw_seq_num: 60, - gtpu_flags: 61, - gtpu_ver: 62, - gtpu_msg_type: 63, - gtpu_teid: 64, - gtpu_extn_hdr: 65, - gtpu_extn_udp_port: 66, - gtpu_extn_sci: 67 + mpls_ach_version: 54, + mpls_ach_channel: 55, + mpls_pw_metadata: 56, + mpls_cw_flags: 57, + mpls_cw_fragment: 58, + mpls_cw_len: 59, + mpls_cw_seq_num: 60, + gtpu_flags: 61, + gtpu_ver: 62, + gtpu_msg_type: 63, + gtpu_teid: 64, + gtpu_extn_hdr: 65, + gtpu_extn_udp_port: 66, + gtpu_extn_sci: 67 ], - vlan_id: [ present: 0x1000, - none: 0x0000 + none: 0x0000 ], - ipv6exthdr_flags: [ nonext: 1 <<< 0, - esp: 1 <<< 1, - auth: 1 <<< 2, - dest: 1 <<< 3, - frag: 1 <<< 4, + esp: 1 <<< 1, + auth: 1 <<< 2, + dest: 1 <<< 3, + frag: 1 <<< 4, router: 1 <<< 5, - hop: 1 <<< 6, - unrep: 1 <<< 7, - unseq: 1 <<< 8 + hop: 1 <<< 6, + unrep: 1 <<< 7, + unseq: 1 <<< 8 ], - tcp_flags: [ fin: 1 <<< 0, syn: 1 <<< 1, @@ -582,20 +546,26 @@ defmodule Openflow.Enums do urg: 1 <<< 5, ece: 1 <<< 6, cwr: 1 <<< 7, - ns: 1 <<< 8 + ns: 1 <<< 8 ], - ct_state_flags: [ - new: 1 <<< 0, # Beginning of a new connection. - est: 1 <<< 1, # Part of an existing connection. - rel: 1 <<< 2, # Related to an established connection. - rep: 1 <<< 3, # Flow is in the reply direction. - inv: 1 <<< 4, # Could not track connection. - trk: 1 <<< 5, # Conntrack has occurred. - snat: 1 <<< 6, # Packet's source address/port was mangled by NAT. - dnat: 1 <<< 7 # Packet's destination address/port was mangled by NAT. + # Beginning of a new connection. + new: 1 <<< 0, + # Part of an existing connection. + est: 1 <<< 1, + # Related to an established connection. + rel: 1 <<< 2, + # Flow is in the reply direction. + rep: 1 <<< 3, + # Could not track connection. + inv: 1 <<< 4, + # Conntrack has occurred. + trk: 1 <<< 5, + # Packet's source address/port was mangled by NAT. + snat: 1 <<< 6, + # Packet's destination address/port was mangled by NAT. + dnat: 1 <<< 7 ], - packet_register: [ xreg0: 0, xreg1: 1, @@ -606,466 +576,414 @@ defmodule Openflow.Enums do xreg6: 6, xreg7: 7 ], - nicira_ext_match: [ - nsh_flags: 1, + nsh_flags: 1, nsh_mdtype: 2, - nsh_np: 3, - nsh_spi: 4, - nsh_si: 5, - nsh_c1: 6, - nsh_c2: 7, - nsh_c3: 8, - nsh_c4: 9 + nsh_np: 3, + nsh_spi: 4, + nsh_si: 5, + nsh_c1: 6, + nsh_c2: 7, + nsh_c3: 8, + nsh_c4: 9 ], - hp_ext_match: [ hp_udp_src_port_range: 0, hp_udp_dst_port_range: 1, hp_tcp_src_port_range: 2, hp_tcp_dst_port_range: 3, - hp_tcp_flags: 4, - hp_custom_1: 5, - hp_custom_2: 6, - hp_custom_3: 7, - hp_custom_4: 8 + hp_tcp_flags: 4, + hp_custom_1: 5, + hp_custom_2: 6, + hp_custom_3: 7, + hp_custom_4: 8 ], - hp_custom_match_type: [ l2_start: 1, l3_start: 2, l4_start: 3 ], - onf_ext_match: [ - onf_tcp_flags: 42, + onf_tcp_flags: 42, onf_actset_output: 43, - onf_pbb_uca: 2560, + onf_pbb_uca: 2560 ], - packet_in_reason: [ - no_match: 0, - action: 1, + no_match: 0, + action: 1, invalid_ttl: 2 ], - buffer_id: [ - no_buffer: 0xffffffff + no_buffer: 0xFFFFFFFF ], - port_config: [ - port_down: 1 <<< 0, - no_receive: 1 <<< 2, - no_forward: 1 <<< 5, + port_down: 1 <<< 0, + no_receive: 1 <<< 2, + no_forward: 1 <<< 5, no_packet_in: 1 <<< 6 ], - port_state: [ link_down: 1 <<< 0, - blocked: 1 <<< 1, - live: 1 <<< 2 + blocked: 1 <<< 1, + live: 1 <<< 2 ], - port_features: [ - {:"10mb_hd", 1 <<< 0}, - {:"10mb_fd", 1 <<< 1}, + {:"10mb_hd", 1 <<< 0}, + {:"10mb_fd", 1 <<< 1}, {:"100mb_hd", 1 <<< 2}, {:"100mb_fd", 1 <<< 3}, - {:"1gb_hd", 1 <<< 4}, - {:"1gb_fd", 1 <<< 5}, - {:"10gb_fd", 1 <<< 6}, - {:"40gb_fd", 1 <<< 7}, + {:"1gb_hd", 1 <<< 4}, + {:"1gb_fd", 1 <<< 5}, + {:"10gb_fd", 1 <<< 6}, + {:"40gb_fd", 1 <<< 7}, {:"100gb_fd", 1 <<< 8}, - {:"1tb_fd", 1 <<< 9}, - {:other, 1 <<< 10}, - {:copper, 1 <<< 11}, - {:fiber, 1 <<< 12}, - {:autoneg, 1 <<< 13}, - {:pause, 1 <<< 14}, + {:"1tb_fd", 1 <<< 9}, + {:other, 1 <<< 10}, + {:copper, 1 <<< 11}, + {:fiber, 1 <<< 12}, + {:autoneg, 1 <<< 13}, + {:pause, 1 <<< 14}, {:pause_asym, 1 <<< 15} ], - openflow10_port_no: [ - max: 0xff00, - in_port: 0xfff8, - table: 0xfff9, - normal: 0xfffa, - flood: 0xfffb, - all: 0xfffc, - controller: 0xfffd, - local: 0xfffe, - none: 0xffff + max: 0xFF00, + in_port: 0xFFF8, + table: 0xFFF9, + normal: 0xFFFA, + flood: 0xFFFB, + all: 0xFFFC, + controller: 0xFFFD, + local: 0xFFFE, + none: 0xFFFF ], - openflow13_port_no: [ - max: 0xffffff00, - in_port: 0xfffffff8, - table: 0xfffffff9, - normal: 0xfffffffa, - flood: 0xfffffffb, - all: 0xfffffffc, - controller: 0xfffffffd, - local: 0xfffffffe, - any: 0xffffffff + max: 0xFFFFFF00, + in_port: 0xFFFFFFF8, + table: 0xFFFFFFF9, + normal: 0xFFFFFFFA, + flood: 0xFFFFFFFB, + all: 0xFFFFFFFC, + controller: 0xFFFFFFFD, + local: 0xFFFFFFFE, + any: 0xFFFFFFFF ], - packet_in_reason: [ - no_match: 0, - action: 1, + no_match: 0, + action: 1, invalid_ttl: 2, - action_set: 3, - group: 4, - packet_out: 5 + action_set: 3, + group: 4, + packet_out: 5 ], - flow_mod_command: [ - add: 0, - modify: 1, + add: 0, + modify: 1, modify_strict: 2, - delete: 3, + delete: 3, delete_strict: 4 ], - flow_mod_flags: [ - send_flow_rem: 1 <<< 0, - check_overlap: 1 <<< 1, - reset_counts: 1 <<< 2, + send_flow_rem: 1 <<< 0, + check_overlap: 1 <<< 1, + reset_counts: 1 <<< 2, no_packet_counts: 1 <<< 3, - no_byte_counts: 1 <<< 4 + no_byte_counts: 1 <<< 4 ], - flow_removed_reason: [ idle_timeout: 0, hard_timeout: 1, - delete: 2, + delete: 2, group_delete: 3, meter_delete: 4, - eviction: 5 + eviction: 5 ], - port_reason: [ - add: 0, + add: 0, delete: 1, modify: 2 ], - group_mod_command: [ - add: 0, - modify: 1, - delete: 2 - ], - - group_type: [ - all: 0, - select: 1, - indirect: 2, - fast_failover: 3 - ], - - group_id: [ - max: 0xffffff00, - all: 0xfffffffc, - any: 0xffffffff - ], - - group_capabilities: [ - select_weight: 1 <<< 0, - select_liveness: 1 <<< 1, - chaining: 1 <<< 2, - chaining_checks: 1 <<< 3 - ], - - table_id: [ - max: 0xfe, - all: 0xff - ], - - queue_id: [ - all: 0xffffffff - ], - - meter_mod_command: [ - add: 0, + add: 0, modify: 1, delete: 2 ], - - meter_id: [ - max: 0xffff0000, - slowpath: 0xfffffffd, - controller: 0xfffffffe, - all: 0xffffffff + group_type: [ + all: 0, + select: 1, + indirect: 2, + fast_failover: 3 + ], + group_id: [ + max: 0xFFFFFF00, + all: 0xFFFFFFFC, + any: 0xFFFFFFFF + ], + group_capabilities: [ + select_weight: 1 <<< 0, + select_liveness: 1 <<< 1, + chaining: 1 <<< 2, + chaining_checks: 1 <<< 3 + ], + table_id: [ + max: 0xFE, + all: 0xFF + ], + queue_id: [ + all: 0xFFFFFFFF + ], + meter_mod_command: [ + add: 0, + modify: 1, + delete: 2 + ], + meter_id: [ + max: 0xFFFF0000, + slowpath: 0xFFFFFFFD, + controller: 0xFFFFFFFE, + all: 0xFFFFFFFF ], - meter_flags: [ - kbps: 1 <<< 0, + kbps: 1 <<< 0, pktps: 1 <<< 1, burst: 1 <<< 2, stats: 1 <<< 3 ], - meter_band_type: [ - {Openflow.MeterBand.Drop, 1}, - {Openflow.MeterBand.Remark, 2}, - {Openflow.MeterBand.Experimenter, 0xffff}, + {Openflow.MeterBand.Drop, 1}, + {Openflow.MeterBand.Remark, 2}, + {Openflow.MeterBand.Experimenter, 0xFFFF} ], - table_config: [ table_miss_controller: 0 <<< 0, - table_miss_continue: 1 <<< 0, - table_miss_drop: 2 <<< 0, - table_miss_mask: 3 <<< 0, - eviction: 1 <<< 2, - vacancy_events: 1 <<< 3 + table_miss_continue: 1 <<< 0, + table_miss_drop: 2 <<< 0, + table_miss_mask: 3 <<< 0, + eviction: 1 <<< 2, + vacancy_events: 1 <<< 3 ], - action_type: [ - {Openflow.Action.Output, 0}, - {Openflow.Action.CopyTtlOut, 11}, - {Openflow.Action.CopyTtlIn, 12}, - {Openflow.Action.SetMplsTtl, 15}, - {Openflow.Action.DecMplsTtl, 16}, - {Openflow.Action.PushVlan, 17}, - {Openflow.Action.PopVlan, 18}, - {Openflow.Action.PushMpls, 19}, - {Openflow.Action.PopMpls, 20}, - {Openflow.Action.SetQueue, 21}, - {Openflow.Action.Group, 22}, - {Openflow.Action.SetNwTtl, 23}, - {Openflow.Action.DecNwTtl, 24}, - {Openflow.Action.SetField, 25}, - {Openflow.Action.PushPbb, 26}, - {Openflow.Action.PopPbb, 27}, - {Openflow.Action.Encap, 28}, - {Openflow.Action.Decap, 29}, - {Openflow.Action.SetSequence, 30}, + {Openflow.Action.Output, 0}, + {Openflow.Action.CopyTtlOut, 11}, + {Openflow.Action.CopyTtlIn, 12}, + {Openflow.Action.SetMplsTtl, 15}, + {Openflow.Action.DecMplsTtl, 16}, + {Openflow.Action.PushVlan, 17}, + {Openflow.Action.PopVlan, 18}, + {Openflow.Action.PushMpls, 19}, + {Openflow.Action.PopMpls, 20}, + {Openflow.Action.SetQueue, 21}, + {Openflow.Action.Group, 22}, + {Openflow.Action.SetNwTtl, 23}, + {Openflow.Action.DecNwTtl, 24}, + {Openflow.Action.SetField, 25}, + {Openflow.Action.PushPbb, 26}, + {Openflow.Action.PopPbb, 27}, + {Openflow.Action.Encap, 28}, + {Openflow.Action.Decap, 29}, + {Openflow.Action.SetSequence, 30}, {Openflow.Action.ValidateSequence, 31}, - {Openflow.Action.Experimenter, 0xffff} + {Openflow.Action.Experimenter, 0xFFFF} ], - action_vendor: [ nicira_ext_action: 0x00002320, - onf_ext_action: 0x4f4e4600 + onf_ext_action: 0x4F4E4600 ], - onf_ext_action: [ {Openflow.Action.OnfCopyField, 3200} ], - nicira_ext_action: [ - {Openflow.Action.NxResubmit, 1}, - {Openflow.Action.NxSetTunnel, 2}, - {Openflow.Action.NxSetQueue, 4}, - {Openflow.Action.NxPopQueue, 5}, - {Openflow.Action.NxRegMove, 6}, - {Openflow.Action.NxRegLoad, 7}, - {Openflow.Action.NxNote, 8}, - {Openflow.Action.NxSetTunnel64, 9}, - {Openflow.Action.NxMultipath, 10}, - {Openflow.Action.NxBundle, 12}, - {Openflow.Action.NxBundleLoad, 13}, - {Openflow.Action.NxResubmitTable, 14}, - {Openflow.Action.NxOutputReg, 15}, - {Openflow.Action.NxLearn, 16}, - {Openflow.Action.NxExit, 17}, - {Openflow.Action.NxDecTtl, 18}, - {Openflow.Action.NxFinTimeout, 19}, - {Openflow.Action.NxController, 20}, - {Openflow.Action.NxDecTtlCntIds, 21}, - {Openflow.Action.NxWriteMetadata, 22}, - {Openflow.Action.NxPushMpls, 23}, - {Openflow.Action.NxPopMpls, 24}, - {Openflow.Action.NxSetMplsTtl, 25}, - {Openflow.Action.NxDecMplsTtl, 26}, - {Openflow.Action.NxStackPush, 27}, - {Openflow.Action.NxStackPop, 28}, - {Openflow.Action.NxSample, 29}, - {Openflow.Action.NxSetMplsLabel, 30}, - {Openflow.Action.NxSetMplsTc, 31}, - {Openflow.Action.NxOutputReg2, 32}, - {Openflow.Action.NxRegLoad2, 33}, - {Openflow.Action.NxConjunction, 34}, - {Openflow.Action.NxConntrack, 35}, - {Openflow.Action.NxNat, 36}, - {Openflow.Action.NxController2, 37}, - {Openflow.Action.NxSample2, 38}, - {Openflow.Action.NxOutputTrunc, 39}, - {Openflow.Action.NxGroup, 40}, - {Openflow.Action.NxSample3, 41}, - {Openflow.Action.NxClone, 42}, - {Openflow.Action.NxCtClear, 43}, + {Openflow.Action.NxResubmit, 1}, + {Openflow.Action.NxSetTunnel, 2}, + {Openflow.Action.NxSetQueue, 4}, + {Openflow.Action.NxPopQueue, 5}, + {Openflow.Action.NxRegMove, 6}, + {Openflow.Action.NxRegLoad, 7}, + {Openflow.Action.NxNote, 8}, + {Openflow.Action.NxSetTunnel64, 9}, + {Openflow.Action.NxMultipath, 10}, + {Openflow.Action.NxBundle, 12}, + {Openflow.Action.NxBundleLoad, 13}, + {Openflow.Action.NxResubmitTable, 14}, + {Openflow.Action.NxOutputReg, 15}, + {Openflow.Action.NxLearn, 16}, + {Openflow.Action.NxExit, 17}, + {Openflow.Action.NxDecTtl, 18}, + {Openflow.Action.NxFinTimeout, 19}, + {Openflow.Action.NxController, 20}, + {Openflow.Action.NxDecTtlCntIds, 21}, + {Openflow.Action.NxWriteMetadata, 22}, + {Openflow.Action.NxPushMpls, 23}, + {Openflow.Action.NxPopMpls, 24}, + {Openflow.Action.NxSetMplsTtl, 25}, + {Openflow.Action.NxDecMplsTtl, 26}, + {Openflow.Action.NxStackPush, 27}, + {Openflow.Action.NxStackPop, 28}, + {Openflow.Action.NxSample, 29}, + {Openflow.Action.NxSetMplsLabel, 30}, + {Openflow.Action.NxSetMplsTc, 31}, + {Openflow.Action.NxOutputReg2, 32}, + {Openflow.Action.NxRegLoad2, 33}, + {Openflow.Action.NxConjunction, 34}, + {Openflow.Action.NxConntrack, 35}, + {Openflow.Action.NxNat, 36}, + {Openflow.Action.NxController2, 37}, + {Openflow.Action.NxSample2, 38}, + {Openflow.Action.NxOutputTrunc, 39}, + {Openflow.Action.NxGroup, 40}, + {Openflow.Action.NxSample3, 41}, + {Openflow.Action.NxClone, 42}, + {Openflow.Action.NxCtClear, 43}, {Openflow.Action.NxResubmitTableCt, 44}, - {Openflow.Action.NxLearn2, 45}, - {Openflow.Action.NxEncap, 46}, - {Openflow.Action.NxDecap, 47}, - {Openflow.Action.NxDebugRecirc, 0xff}, + {Openflow.Action.NxLearn2, 45}, + {Openflow.Action.NxEncap, 46}, + {Openflow.Action.NxDecap, 47}, + {Openflow.Action.NxDebugRecirc, 0xFF} ], - nx_mp_algorithm: [ - modulo_n: 0, - hash_threshold: 1, + modulo_n: 0, + hash_threshold: 1, highest_random_weight: 2, - iterative_hash: 3 + iterative_hash: 3 ], - nx_hash_fields: [ - eth_src: 0, - symmetric_l4: 1, - symmetric_l3l4: 2, + eth_src: 0, + symmetric_l4: 1, + symmetric_l3l4: 2, symmetric_l3l4_udp: 3, - nw_src: 4, - nw_dst: 5, + nw_src: 4, + nw_dst: 5 ], - nx_bd_algorithm: [ - active_backup: 0, + active_backup: 0, highest_random_weight: 1 ], - nx_learn_flag: [ - send_flow_rem: 1 <<< 0, + send_flow_rem: 1 <<< 0, delete_learned: 1 <<< 1, - write_result: 1 <<< 2 + write_result: 1 <<< 2 ], - nx_conntrack_flags: [ commit: 1 <<< 0, - force: 1 <<< 1 + force: 1 <<< 1 ], - nx_nat_flags: [ - src: 1 <<< 0, - dst: 1 <<< 1, - persistent: 1 <<< 2, - protocol_hash: 1 <<< 3, + src: 1 <<< 0, + dst: 1 <<< 1, + persistent: 1 <<< 2, + protocol_hash: 1 <<< 3, protocol_random: 1 <<< 4 ], - nx_nat_range: [ - ipv4_min: 1 <<< 0, - ipv4_max: 1 <<< 1, - ipv6_min: 1 <<< 2, - ipv6_max: 1 <<< 3, + ipv4_min: 1 <<< 0, + ipv4_max: 1 <<< 1, + ipv6_min: 1 <<< 2, + ipv6_max: 1 <<< 3, proto_min: 1 <<< 4, proto_max: 1 <<< 5 ], - nx_action_controller2_prop_type: [ - max_len: 0, + max_len: 0, controller_id: 1, - reason: 2, - userdata: 3, - pause: 4 + reason: 2, + userdata: 3, + pause: 4 ], - nx_action_sample_direction: [ default: 0, ingress: 1, - egress: 2 + egress: 2 ], - nx_flow_spec_type: [ - {Openflow.Action.NxFlowSpecMatch, 0}, - {Openflow.Action.NxFlowSpecLoad, 1}, + {Openflow.Action.NxFlowSpecMatch, 0}, + {Openflow.Action.NxFlowSpecLoad, 1}, {Openflow.Action.NxFlowSpecOutput, 2} ], - instruction_type: [ - {Openflow.Instruction.GotoTable, 1}, - {Openflow.Instruction.WriteMetadata, 2}, - {Openflow.Instruction.WriteActions, 3}, - {Openflow.Instruction.ApplyActions, 4}, - {Openflow.Instruction.ClearActions, 5}, - {Openflow.Instruction.Meter, 6}, - {Openflow.Instruction.Experimenter, 0xffff} + {Openflow.Instruction.GotoTable, 1}, + {Openflow.Instruction.WriteMetadata, 2}, + {Openflow.Instruction.WriteActions, 3}, + {Openflow.Instruction.ApplyActions, 4}, + {Openflow.Instruction.ClearActions, 5}, + {Openflow.Instruction.Meter, 6}, + {Openflow.Instruction.Experimenter, 0xFFFF} ], - controller_role: [ nochange: 0, - equal: 1, - master: 2, - slave: 3 + equal: 1, + master: 2, + slave: 3 ], - nx_role: [ - other: 0, + other: 0, master: 1, - slave: 2 + slave: 2 ], - packet_in_format: [ - standard: 0, - nxt_packet_in: 1, + standard: 0, + nxt_packet_in: 1, nxt_packet_in2: 2 ], - flow_format: [ openflow10: 0, - nxm: 1 + nxm: 1 ], - packet_in2_prop_type: [ - packet: 0, - full_len: 1, - buffer_id: 2, - table_id: 3, - cookie: 4, - reason: 5, - metadata: 6, - userdata: 7, + packet: 0, + full_len: 1, + buffer_id: 2, + table_id: 3, + cookie: 4, + reason: 5, + metadata: 6, + userdata: 7, continuation: 8 ], - continuation_prop_type: [ - bridge: 0x8000, - stack: 0x8001, - mirrors: 0x8002, + bridge: 0x8000, + stack: 0x8001, + mirrors: 0x8002, conntracked: 0x8003, - table_id: 0x8004, - cookie: 0x8005, - actions: 0x8006, - action_set: 0x8007 + table_id: 0x8004, + cookie: 0x8005, + actions: 0x8006, + action_set: 0x8007 ], - flow_monitor_flag: [ initial: 1 <<< 0, - add: 1 <<< 1, - delete: 1 <<< 2, - modify: 1 <<< 3, + add: 1 <<< 1, + delete: 1 <<< 2, + modify: 1 <<< 3, actions: 1 <<< 4, - own: 1 <<< 5 + own: 1 <<< 5 ], - flow_update_event: [ - added: 0, - deleted: 1, + added: 0, + deleted: 1, modified: 2, - abbrev: 3 + abbrev: 3 ], - tlv_table_mod_command: [ - add: 0, + add: 0, delete: 1, - clear: 2 + clear: 2 ], - table_feature_prop_type: [ - instructions: 0, - instructions_miss: 1, - next_tables: 2, - next_tables_miss: 3, - write_actions: 4, - write_actions_miss: 5, - apply_actions: 6, - apply_actions_miss: 7, - match: 8, - wildcards: 10, - write_setfield: 12, + instructions: 0, + instructions_miss: 1, + next_tables: 2, + next_tables_miss: 3, + write_actions: 4, + write_actions_miss: 5, + apply_actions: 6, + apply_actions_miss: 7, + match: 8, + wildcards: 10, + write_setfield: 12, write_setfield_miss: 13, - apply_setfield: 14, + apply_setfield: 14, apply_setfield_miss: 15, - experimenter: 0xfffe, - experimenter_miss: 0xffff + experimenter: 0xFFFE, + experimenter_miss: 0xFFFF ] ] @@ -1105,7 +1023,7 @@ defmodule Openflow.Enums do def unquote(to_int_fn_name)(unquote(key)), do: unquote(value) end - def unquote(to_int_fn_name)(_), do: throw(:bad_enum) + def unquote(to_int_fn_name)(_), do: throw(:bad_enum) for {key, value} <- enum_def do def unquote(to_atom_fn_name)(unquote(value)), do: unquote(key) diff --git a/lib/openflow/error_msg.ex b/lib/openflow/error_msg.ex index 4a6f354..2279230 100644 --- a/lib/openflow/error_msg.ex +++ b/lib/openflow/error_msg.ex @@ -2,33 +2,38 @@ defmodule Openflow.ErrorMsg do @moduledoc "OpenFlow Error codec module" defstruct( - version: 4, - xid: 0, - type: nil, - code: nil, - data: "", - exp_type: nil, + version: 4, + xid: 0, + type: nil, + code: nil, + data: "", + exp_type: nil, experimenter: nil, - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ def ofp_type, do: 1 - def read(<<0xffff::16, exp_type::16, experimenter::32, data::bytes>>) do - error_type = Openflow.Enums.to_atom(0xffff, :error_type) + def read(<<0xFFFF::16, exp_type::16, experimenter::32, data::bytes>>) do + error_type = Openflow.Enums.to_atom(0xFFFF, :error_type) + %ErrorMsg{ - type: error_type, - exp_type: exp_type, + type: error_type, + exp_type: exp_type, experimenter: experimenter, - data: data + data: data } end + def read(<>) do error_type = Openflow.Enums.to_atom(type, :error_type) error_code = Openflow.Enums.to_atom(code, error_type) + %ErrorMsg{ type: error_type, code: error_code, @@ -36,16 +41,17 @@ defmodule Openflow.ErrorMsg do } end - def to_binary(%ErrorMsg{type: :experimenter, - exp_type: exp_type, - experimenter: experimenter, - data: data}) do + def to_binary(%ErrorMsg{ + type: :experimenter, + exp_type: exp_type, + experimenter: experimenter, + data: data + }) do error_type = Openflow.Enums.to_int(:experimenter, :error_type) <> end - def to_binary(%ErrorMsg{type: type, - code: code, - data: data}) do + + def to_binary(%ErrorMsg{type: type, code: code, data: data}) do error_type = Openflow.Enums.to_int(type, :error_type) error_code = Openflow.Enums.to_int(code, type) <> diff --git a/lib/openflow/experimenter.ex b/lib/openflow/experimenter.ex index bfead7a..1d540f0 100644 --- a/lib/openflow/experimenter.ex +++ b/lib/openflow/experimenter.ex @@ -1,12 +1,12 @@ defmodule Openflow.Experimenter do defstruct( - version: 4, - xid: 0, + version: 4, + xid: 0, datapath_id: "", - aux_id: 0, - exp_id: 0, - exp_type: 0, - data: "" + aux_id: 0, + exp_id: 0, + exp_type: 0, + data: "" ) alias __MODULE__ @@ -14,9 +14,11 @@ defmodule Openflow.Experimenter do def ofp_type, do: 4 def new(options) do - %Experimenter{exp_id: Keyword.get(options, :exp_id, 0), - exp_type: Keyword.get(options, :exp_type, 0), - data: Keyword.get(options, :data, "")} + %Experimenter{ + exp_id: Keyword.get(options, :exp_id, 0), + exp_type: Keyword.get(options, :exp_type, 0), + data: Keyword.get(options, :data, "") + } end 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 ^exp_id -> %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 ^exp_type -> %Experimenter{exp_id: exp_id, exp_type: exp_type, data: data} + codec when is_atom(codec) -> codec.read(<>) end diff --git a/lib/openflow/features/reply.ex b/lib/openflow/features/reply.ex index b22b384..e104ba8 100644 --- a/lib/openflow/features/reply.ex +++ b/lib/openflow/features/reply.ex @@ -1,22 +1,24 @@ defmodule Openflow.Features.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: "", - n_buffers: 0, - n_tables: 0, - aux_id: 0, - capabilities: [] + version: 4, + xid: 0, + datapath_id: "", + n_buffers: 0, + n_tables: 0, + aux_id: 0, + capabilities: [] ) alias __MODULE__ def ofp_type, do: 6 - def read(<>) do + def read( + <> + ) do dpid = Openflow.Utils.to_hex_string(datapath_id) flags = Openflow.Enums.int_to_flags(caps_int, :switch_capabilities) + %Reply{ datapath_id: dpid, n_buffers: n_buf, @@ -31,7 +33,8 @@ defmodule Openflow.Features.Reply do n_buffers: n_buf, n_tables: n_tab, aux_id: aux_id, - capabilities: flags}) do + capabilities: flags + }) do dpid_int = String.to_integer(datapath_id, 16) flags_int = Openflow.Enums.flags_to_int(flags, :switch_capabilities) <> diff --git a/lib/openflow/features/request.ex b/lib/openflow/features/request.ex index d23aee1..83aadbb 100644 --- a/lib/openflow/features/request.ex +++ b/lib/openflow/features/request.ex @@ -1,9 +1,11 @@ defmodule Openflow.Features.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ diff --git a/lib/openflow/flow_mod.ex b/lib/openflow/flow_mod.ex index 338b0c7..1c1d972 100644 --- a/lib/openflow/flow_mod.ex +++ b/lib/openflow/flow_mod.ex @@ -3,7 +3,7 @@ defmodule Openflow.FlowMod do version: 4, xid: 0, datapath_id: "", - aux_id: 0, + aux_id: 0, cookie: 0, cookie_mask: 0, table_id: 0, @@ -35,26 +35,31 @@ defmodule Openflow.FlowMod do out_port = Keyword.get(options, :out_port, :any) out_group = Keyword.get(options, :out_group, :any) 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, []) - %FlowMod{cookie: cookie, - cookie_mask: cookie_mask, - priority: priority, - table_id: table_id, - command: command, - idle_timeout: idle, - hard_timeout: hard, - buffer_id: buffer_id, - out_port: out_port, - out_group: out_group, - flags: flags, - match: match, - instructions: instructions} + + %FlowMod{ + cookie: cookie, + cookie_mask: cookie_mask, + priority: priority, + table_id: table_id, + command: command, + idle_timeout: idle, + hard_timeout: hard, + buffer_id: buffer_id, + out_port: out_port, + out_group: out_group, + flags: flags, + match: match, + instructions: instructions + } end - def read(<>) do + def read( + <> + ) do table_id = Openflow.Utils.get_enum(table_id_int, :table_id) command = Openflow.Utils.get_enum(command_int, :flow_mod_command) 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 = Openflow.Match.new(match_fields) instructions = Openflow.Instruction.read(instructions_bin) - %FlowMod{cookie: cookie, - cookie_mask: cookie_mask, - priority: prio, - table_id: table_id, - command: command, - idle_timeout: idle, - hard_timeout: hard, - buffer_id: buffer_id, - out_port: out_port, - out_group: out_group, - flags: flags, - match: match, - instructions: instructions} + + %FlowMod{ + cookie: cookie, + cookie_mask: cookie_mask, + priority: prio, + table_id: table_id, + command: command, + idle_timeout: idle, + hard_timeout: hard, + buffer_id: buffer_id, + out_port: out_port, + out_group: out_group, + flags: flags, + match: match, + instructions: instructions + } end def to_binary(flow_mod) do - %FlowMod{cookie: cookie, - cookie_mask: cookie_mask, - priority: prio, - table_id: table_id, - command: command, - idle_timeout: idle, - hard_timeout: hard, - buffer_id: buffer_id, - out_port: out_port, - out_group: out_group, - flags: flags, - match: match_fields, - instructions: instructions} = flow_mod + %FlowMod{ + cookie: cookie, + cookie_mask: cookie_mask, + priority: prio, + table_id: table_id, + command: command, + idle_timeout: idle, + hard_timeout: hard, + buffer_id: buffer_id, + out_port: out_port, + out_group: out_group, + flags: flags, + match: match_fields, + instructions: instructions + } = flow_mod + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) command_int = Openflow.Utils.get_enum(command, :flow_mod_command) 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) match_fields_bin = Openflow.Match.to_binary(match_fields) instructions_bin = Openflow.Instruction.to_binary(instructions) - <> end end diff --git a/lib/openflow/flow_removed.ex b/lib/openflow/flow_removed.ex index 3b3fe68..eea87d3 100644 --- a/lib/openflow/flow_removed.ex +++ b/lib/openflow/flow_removed.ex @@ -1,42 +1,46 @@ defmodule Openflow.FlowRemoved do defstruct( - version: 4, - xid: 0, - datapath_id: "", - aux_id: 0, - cookie: 0, - priority: 0, - reason: :idle_timeout, - table_id: 0, - duration_sec: 0, + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + cookie: 0, + priority: 0, + reason: :idle_timeout, + table_id: 0, + duration_sec: 0, duration_nsec: 0, - idle_timeout: 0, - hard_timeout: 0, - packet_count: 0, - byte_count: 0, - match: [] + idle_timeout: 0, + hard_timeout: 0, + packet_count: 0, + byte_count: 0, + match: [] ) alias __MODULE__ def ofp_type, do: 11 - def read(<>) do + def read( + <> + ) do reason = Openflow.Enums.to_atom(reason_int, :flow_removed_reason) table_id = Openflow.Utils.get_enum(table_id_int, :table_id) {match_fields, _rest} = Openflow.Match.read(rest) - %FlowRemoved{cookie: cookie, - priority: priority, - reason: reason, - table_id: table_id, - duration_sec: dsec, - duration_nsec: dnsec, - idle_timeout: idle, - hard_timeout: hard, - packet_count: pkt, - byte_count: byt, - match: match_fields} + + %FlowRemoved{ + cookie: cookie, + priority: priority, + reason: reason, + table_id: table_id, + duration_sec: dsec, + duration_nsec: dnsec, + idle_timeout: idle, + hard_timeout: hard, + packet_count: pkt, + byte_count: byt, + match: match_fields + } end end diff --git a/lib/openflow/get_async/reply.ex b/lib/openflow/get_async/reply.ex index 58b8f45..2f2e1a7 100644 --- a/lib/openflow/get_async/reply.ex +++ b/lib/openflow/get_async/reply.ex @@ -1,40 +1,46 @@ defmodule Openflow.GetAsync.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0, # virtual field - packet_in_mask_master: 0, - packet_in_mask_slave: 0, - port_status_mask_master: 0, - port_status_mask_slave: 0, + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, + packet_in_mask_master: 0, + packet_in_mask_slave: 0, + port_status_mask_master: 0, + port_status_mask_slave: 0, flow_removed_mask_master: 0, - flow_removed_mask_slave: 0 + flow_removed_mask_slave: 0 ) alias __MODULE__ def ofp_type, do: 27 - def read(<>) do - %Reply{packet_in_mask_master: packet_in_mask_master, - packet_in_mask_slave: packet_in_mask_slave, - port_status_mask_master: port_status_mask_master, - port_status_mask_slave: port_status_mask_slave, - flow_removed_mask_master: flow_removed_mask_master, - flow_removed_mask_slave: flow_removed_mask_slave} + def read( + <> + ) do + %Reply{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + 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 - def to_binary(%Reply{packet_in_mask_master: packet_in_mask_master, - packet_in_mask_slave: packet_in_mask_slave, - port_status_mask_master: port_status_mask_master, - port_status_mask_slave: port_status_mask_slave, - flow_removed_mask_master: flow_removed_mask_master, - flow_removed_mask_slave: flow_removed_mask_slave}) do - <> + def to_binary(%Reply{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + port_status_mask_slave: port_status_mask_slave, + flow_removed_mask_master: flow_removed_mask_master, + flow_removed_mask_slave: flow_removed_mask_slave + }) do + <> end end diff --git a/lib/openflow/get_async/request.ex b/lib/openflow/get_async/request.ex index 7433daf..3be0048 100644 --- a/lib/openflow/get_async/request.ex +++ b/lib/openflow/get_async/request.ex @@ -1,9 +1,11 @@ defmodule Openflow.GetAsync.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ diff --git a/lib/openflow/get_config/reply.ex b/lib/openflow/get_config/reply.ex index db1870d..55f08ff 100644 --- a/lib/openflow/get_config/reply.ex +++ b/lib/openflow/get_config/reply.ex @@ -1,10 +1,11 @@ defmodule Openflow.GetConfig.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: "", - aux_id: 0, - flags: [], # default = "normal" is no special handling + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # default = "normal" is no special handling + flags: [], miss_send_len: 128 ) diff --git a/lib/openflow/get_config/request.ex b/lib/openflow/get_config/request.ex index c1ec4d9..e9e0af4 100644 --- a/lib/openflow/get_config/request.ex +++ b/lib/openflow/get_config/request.ex @@ -1,9 +1,11 @@ defmodule Openflow.GetConfig.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0 # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 ) alias __MODULE__ diff --git a/lib/openflow/group_mod.ex b/lib/openflow/group_mod.ex index 276e9af..f8f2a54 100644 --- a/lib/openflow/group_mod.ex +++ b/lib/openflow/group_mod.ex @@ -3,7 +3,7 @@ defmodule Openflow.GroupMod do version: 4, xid: 0, datapath_id: "", - aux_id: 0, + aux_id: 0, command: :add, type: :all, group_id: 0, @@ -19,10 +19,7 @@ defmodule Openflow.GroupMod do type = Keyword.get(options, :type, :all) group_id = Keyword.get(options, :group_id, 0) buckets = Keyword.get(options, :buckets, []) - %GroupMod{command: command, - type: type, - group_id: group_id, - buckets: buckets} + %GroupMod{command: command, type: type, group_id: group_id, buckets: buckets} end def read(<>) do @@ -30,16 +27,10 @@ defmodule Openflow.GroupMod do type = Openflow.Utils.get_enum(type_int, :group_type) group_id = Openflow.Utils.get_enum(group_id_int, :group_id) buckets = Openflow.Bucket.read(buckets_bin) - %GroupMod{command: command, - type: type, - group_id: group_id, - buckets: buckets} + %GroupMod{command: command, type: type, group_id: group_id, buckets: buckets} end - def to_binary(%GroupMod{command: command, - type: type, - group_id: group_id, - buckets: buckets}) do + def to_binary(%GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}) do command_int = Openflow.Utils.get_enum(command, :group_mod_command) type_int = Openflow.Utils.get_enum(type, :group_type) group_id_int = Openflow.Utils.get_enum(group_id, :group_id) diff --git a/lib/openflow/hello.ex b/lib/openflow/hello.ex index a3f4a75..463e32e 100644 --- a/lib/openflow/hello.ex +++ b/lib/openflow/hello.ex @@ -9,32 +9,32 @@ defmodule Openflow.Hello do alias __MODULE__ - def ofp_type, - do: 0 + def ofp_type, do: 0 def new(version) when is_integer(version) do %Hello{elements: [versionbitmap: [version]]} end + def new(versions) when is_list(versions) do %Hello{elements: [versionbitmap: versions]} end def supported_version?(%Hello{version: 4, elements: []}), do: true def supported_version?(%Hello{elements: []}), do: false + def supported_version?(%Hello{elements: elements}) do 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 - def read(binary), - do: %Hello{elements: decode([], binary)} + def read(binary), do: %Hello{elements: decode([], binary)} - def to_binary(%Hello{elements: elements}), - do: encode([], elements) + def to_binary(%Hello{elements: elements}), do: encode([], elements) # private functions defp decode(acc, <<>>), do: acc + defp decode(acc, <>) do data_len = length - @ofp_hello_size <> = rest @@ -50,15 +50,13 @@ defmodule Openflow.Hello do end end - defp encode(acc, []), - do: to_string(acc) - defp encode(acc, [h|rest]), - do: encode([encode_hello_elem(h)|acc], rest) + defp encode(acc, []), do: to_string(acc) + defp encode(acc, [h | rest]), do: encode([encode_hello_elem(h) | acc], rest) defp decode_hello_elem(:versionbitmap, acc, binary), - do: [{:versionbitmap, decode_bitmap([], binary, 0)}|acc] - defp decode_hello_elem(_, acc, _binary), - do: acc + do: [{:versionbitmap, decode_bitmap([], binary, 0)} | acc] + + defp decode_hello_elem(_, acc, _binary), do: acc defp encode_hello_elem({:versionbitmap, versions}) do bitmap_bin = encode_bitmap(versions) @@ -66,11 +64,13 @@ defmodule Openflow.Hello do size_int = @ofp_hello_size + byte_size(bitmap_bin) <> end + defp encode_hello_elem(_) do <<>> end defp decode_bitmap(acc, "", _), do: acc + defp decode_bitmap(acc, <>, base) do acc |> decode_bitmap(int, 0, base) @@ -80,24 +80,27 @@ defmodule Openflow.Hello do defp encode_bitmap(list) do size = list - |> Enum.max + |> Enum.max() |> div(32) + encode_bitmap(0, list, size) end - defp decode_bitmap(acc, _, index, _) when index >= 32, - do: acc - defp decode_bitmap(acc, int, index, base) when (int &&& (1 <<< index)) == 0, + defp decode_bitmap(acc, _, index, _) when index >= 32, do: acc + + defp decode_bitmap(acc, int, index, base) when (int &&& 1 <<< index) == 0, do: decode_bitmap(acc, int, index + 1, 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 bytes = (size + 1) * 32 <> end - defp encode_bitmap(acc, [h|rest], size) do - index = (size - div(h, 32) * 32 + rem(h, 32)) - encode_bitmap(acc ||| (1 <<< index), rest, size) + + defp encode_bitmap(acc, [h | rest], size) do + index = size - div(h, 32) * 32 + rem(h, 32) + encode_bitmap(acc ||| 1 <<< index, rest, size) end end diff --git a/lib/openflow/instruction.ex b/lib/openflow/instruction.ex index c33d631..b64b1c7 100644 --- a/lib/openflow/instruction.ex +++ b/lib/openflow/instruction.ex @@ -1,5 +1,4 @@ defmodule Openflow.Instruction do - def read(instruction_bin) do do_read([], instruction_bin) end @@ -7,6 +6,7 @@ defmodule Openflow.Instruction do def to_binary(instructions) when is_list(instructions) do to_binary(<<>>, instructions) end + def to_binary(instruction) do to_binary([instruction]) end @@ -14,15 +14,17 @@ defmodule Openflow.Instruction do # private functions defp do_read(acc, <<>>), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary 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 defp to_binary(acc, []), do: acc - defp to_binary(acc, [instruction|rest]) do + + defp to_binary(acc, [instruction | rest]) do codec = instruction.__struct__ - to_binary(<>, rest) + to_binary(<>, rest) end end diff --git a/lib/openflow/instructions/experimenter.ex b/lib/openflow/instructions/experimenter.ex index c0c624d..f4cc3f2 100644 --- a/lib/openflow/instructions/experimenter.ex +++ b/lib/openflow/instructions/experimenter.ex @@ -9,10 +9,10 @@ defmodule Openflow.Instruction.Experimenter do def to_binary(%Experimenter{exp_id: exp_id, data: data}) do length = 8 + byte_size(data) - <<0xffff::16, length::16, exp_id::32, data::bytes>> + <<0xFFFF::16, length::16, exp_id::32, data::bytes>> 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} end end diff --git a/lib/openflow/instructions/write_metadata.ex b/lib/openflow/instructions/write_metadata.ex index 034e8d7..5b0df98 100644 --- a/lib/openflow/instructions/write_metadata.ex +++ b/lib/openflow/instructions/write_metadata.ex @@ -1,11 +1,11 @@ defmodule Openflow.Instruction.WriteMetadata do - defstruct(metadata: 0, metadata_mask: 0xffffffffffffffff) + defstruct(metadata: 0, metadata_mask: 0xFFFFFFFFFFFFFFFF) alias __MODULE__ def new(options) do 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} end diff --git a/lib/openflow/match.ex b/lib/openflow/match.ex index 0ca8f98..3cbf258 100644 --- a/lib/openflow/match.ex +++ b/lib/openflow/match.ex @@ -1,11 +1,11 @@ defmodule Openflow.Match do - @match_size 8 + @match_size 8 @header_size 4 - defstruct([ - type: :oxm, + defstruct( + type: :oxm, fields: [] - ]) + ) alias __MODULE__ @@ -13,6 +13,7 @@ defmodule Openflow.Match do oxm_fields = fields |> keyword_to_oxm_fields([]) + %Match{type: :oxm, fields: oxm_fields} end @@ -20,7 +21,10 @@ defmodule Openflow.Match do <<1::16, no_pad_len::16, binary1::binary>> = binary padding_length = Openflow.Utils.pad_length(no_pad_len, 8) match_field_len = no_pad_len - @header_size - <> = binary1 + + <> = binary1 + {decode_fields(match_fields, []), rest} end @@ -33,14 +37,17 @@ defmodule Openflow.Match do end def codec_header(oxm_field0) when is_atom(oxm_field0) do - oxm_field = case has_mask(oxm_field0) do - 1 -> - string = to_string(oxm_field0) - "masked_" <> field = string - String.to_atom(field) - 0 -> - oxm_field0 - end + oxm_field = + case has_mask(oxm_field0) do + 1 -> + string = to_string(oxm_field0) + "masked_" <> field = string + String.to_atom(field) + + 0 -> + oxm_field0 + end + 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_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) has_mask = has_mask(oxm_field0) <> + 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) oxm_field_int = Openflow.Enums.to_int(oxm_field, experimenter) oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field) + 4, 8) @@ -57,41 +65,63 @@ defmodule Openflow.Match do <> end end + def codec_header(<>) do oxm_class = Openflow.Enums.to_atom(oxm_class_int, :oxm_class) + 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 -> field_str = oxm_field_int |> Openflow.Enums.to_atom(oxm_class) |> to_string + String.to_atom("masked_" <> field_str) 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) Openflow.Enums.to_atom(oxm_field_int, experimenter) + case oxm_has_mask do - 0 -> Openflow.Enums.to_atom(oxm_field_int, experimenter) + 0 -> + Openflow.Enums.to_atom(oxm_field_int, experimenter) + 1 -> field_str = oxm_field_int |> Openflow.Enums.to_atom(experimenter) |> to_string + String.to_atom("masked_" <> field_str) end end - def header_size(<<_oxm_class_int::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _::bytes>>), - do: 4 - def header_size(<<0xffff::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _exp_int::32, _::bytes>>), - do: 8 + def header_size( + <<_oxm_class_int::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _::bytes>> + ), + 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 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 field_len = div(length, 2) <> = binary @@ -99,16 +129,21 @@ defmodule Openflow.Match do field_name = Openflow.Enums.to_atom(field_int, experimenter) value = Openflow.Match.Field.codec(value_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 - 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 <> = binary experimenter = Openflow.Enums.to_atom(vendor_int, :experimenter_oxm_vendors) field_name = Openflow.Enums.to_atom(field_int, experimenter) value = Openflow.Match.Field.codec(value_bin, field_name) - decode_fields(rest, [{field_name, value}|acc]) + decode_fields(rest, [{field_name, value} | acc]) end + defp decode_fields(<>, acc) do field_len = div(length, 2) <> = binary @@ -116,37 +151,43 @@ defmodule Openflow.Match do field_name = Openflow.Enums.to_atom(field_int, class) value = Openflow.Match.Field.codec(value_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 + defp decode_fields(<>, acc) do <> = binary class = Openflow.Enums.to_atom(class_int, :oxm_class) field_name = Openflow.Enums.to_atom(field_int, class) value = Openflow.Match.Field.codec(value_bin, field_name) - decode_fields(rest, [{field_name, value}|acc]) + decode_fields(rest, [{field_name, value} | acc]) end defp encode_fields([], acc), do: acc - defp encode_fields([field|fields], acc) do - encode_fields(fields, <>) + + defp encode_fields([field | fields], acc) do + encode_fields(fields, <>) end 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) field_int = Openflow.Enums.to_int(field, class) has_mask_int = 1 - 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>> + 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>> end + 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) field_int = Openflow.Enums.to_int(field, class) has_mask_int = 0 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 + defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask}) do class_int = Openflow.Enums.to_int(class, :oxm_class) field_int = Openflow.Enums.to_int(field, class) @@ -154,6 +195,7 @@ defmodule Openflow.Match do length = byte_size(value) * 2 <> end + defp encode_field(%{class: class, field: field, has_mask: false, value: value}) do class_int = Openflow.Enums.to_int(class, :oxm_class) field_int = Openflow.Enums.to_int(field, class) @@ -163,8 +205,9 @@ defmodule Openflow.Match do end 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 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) %{class: match_class, field: field_name, has_mask: true, value: value_bin, mask: mask_bin} end + defp oxm_field(field_name, value) do value_bin = Openflow.Match.Field.codec(value, field_name) match_class = Openflow.Match.Field.vendor_of(field_name) @@ -184,6 +228,7 @@ defmodule Openflow.Match do oxm_field |> to_string |> String.match?(~r/^masked_/) + if has_mask? do 1 else diff --git a/lib/openflow/match/field.ex b/lib/openflow/match/field.ex index 8a6e411..3cabbd4 100644 --- a/lib/openflow/match/field.ex +++ b/lib/openflow/match/field.ex @@ -1,23 +1,26 @@ defmodule Openflow.Match.Field do - def codec(value0, field) when is_binary(value0) do {type, format} = format_of(field) n_bits = n_bits_of(field) bit_size = bit_size(value0) - value = if bit_size < n_bits do - head_pad_len = n_bits - bit_size - <<0::size(head_pad_len), value0::bytes>> - else - if bit_size > n_bits and type != :mac do - head_pad_len = bit_size - n_bits - <<_::size(head_pad_len), value::size(n_bits)-bits>> = value0 - value + + value = + if bit_size < n_bits do + head_pad_len = n_bits - bit_size + <<0::size(head_pad_len), value0::bytes>> else - value0 + if bit_size > n_bits and type != :mac do + head_pad_len = bit_size - n_bits + <<_::size(head_pad_len), value::size(n_bits)-bits>> = value0 + value + else + value0 + end end - end + formatting(value, type, format) end + def codec(value, type) do {type, format} = format_of(type) formatting(value, type, format) @@ -29,251 +32,251 @@ defmodule Openflow.Match.Field do |> bit_size_of end - def bit_size_of({:u8, _}), do: 8 - def bit_size_of({:u24, _}), do: 24 - def bit_size_of({:be16, _}), do: 16 - def bit_size_of({:be32, _}), do: 32 - def bit_size_of({:be64, _}), do: 64 + def bit_size_of({:u8, _}), do: 8 + def bit_size_of({:u24, _}), do: 24 + def bit_size_of({:be16, _}), do: 16 + def bit_size_of({:be32, _}), do: 32 + def bit_size_of({:be64, _}), do: 64 def bit_size_of({:be128, _}), do: 128 - def bit_size_of({:mac, _}), do: 48 + def bit_size_of({:mac, _}), do: 48 # NXM0 - def vendor_of(:nx_in_port), do: :nxm_0 - def vendor_of(:nx_eth_dst), do: :nxm_0 - def vendor_of(:nx_eth_src), do: :nxm_0 - def vendor_of(:nx_eth_type), do: :nxm_0 - def vendor_of(:nx_vlan_tci), do: :nxm_0 - def vendor_of(:nx_ip_tos), do: :nxm_0 - def vendor_of(:nx_ip_proto), do: :nxm_0 - def vendor_of(:nx_ipv4_src), do: :nxm_0 - def vendor_of(:nx_ipv4_dst), do: :nxm_0 - def vendor_of(:nx_tcp_src), do: :nxm_0 - def vendor_of(:nx_tcp_dst), do: :nxm_0 - def vendor_of(:nx_udp_src), do: :nxm_0 - def vendor_of(:nx_udp_dst), do: :nxm_0 + def vendor_of(:nx_in_port), do: :nxm_0 + def vendor_of(:nx_eth_dst), do: :nxm_0 + def vendor_of(:nx_eth_src), do: :nxm_0 + def vendor_of(:nx_eth_type), do: :nxm_0 + def vendor_of(:nx_vlan_tci), do: :nxm_0 + def vendor_of(:nx_ip_tos), do: :nxm_0 + def vendor_of(:nx_ip_proto), do: :nxm_0 + def vendor_of(:nx_ipv4_src), do: :nxm_0 + def vendor_of(:nx_ipv4_dst), do: :nxm_0 + def vendor_of(:nx_tcp_src), do: :nxm_0 + def vendor_of(:nx_tcp_dst), do: :nxm_0 + def vendor_of(:nx_udp_src), do: :nxm_0 + def vendor_of(:nx_udp_dst), do: :nxm_0 def vendor_of(:nx_icmpv4_type), do: :nxm_0 def vendor_of(:nx_icmpv4_code), do: :nxm_0 - def vendor_of(:nx_arp_op), do: :nxm_0 - def vendor_of(:nx_arp_spa), do: :nxm_0 - def vendor_of(:nx_arp_tpa), do: :nxm_0 - def vendor_of(:nx_tcp_flags), do: :nxm_0 + def vendor_of(:nx_arp_op), do: :nxm_0 + def vendor_of(:nx_arp_spa), do: :nxm_0 + def vendor_of(:nx_arp_tpa), do: :nxm_0 + def vendor_of(:nx_tcp_flags), do: :nxm_0 # NXM1 - def vendor_of(:reg0), do: :nxm_1 - def vendor_of(:reg1), do: :nxm_1 - def vendor_of(:reg2), do: :nxm_1 - def vendor_of(:reg3), do: :nxm_1 - def vendor_of(:reg4), do: :nxm_1 - def vendor_of(:reg5), do: :nxm_1 - def vendor_of(:reg6), do: :nxm_1 - def vendor_of(:reg7), do: :nxm_1 - def vendor_of(:reg8), do: :nxm_1 - def vendor_of(:reg9), do: :nxm_1 - def vendor_of(:reg10), do: :nxm_1 - def vendor_of(:reg11), do: :nxm_1 - def vendor_of(:reg12), do: :nxm_1 - def vendor_of(:reg13), do: :nxm_1 - def vendor_of(:reg14), do: :nxm_1 - def vendor_of(:reg15), do: :nxm_1 - def vendor_of(:tun_id), do: :nxm_1 - def vendor_of(:nx_arp_sha), do: :nxm_1 - def vendor_of(:nx_arp_tha), do: :nxm_1 - def vendor_of(:nx_ipv6_src), do: :nxm_1 - def vendor_of(:nx_ipv6_dst), do: :nxm_1 - def vendor_of(:nx_icmpv6_type), do: :nxm_1 - def vendor_of(:nx_icmpv6_code), do: :nxm_1 + def vendor_of(:reg0), do: :nxm_1 + def vendor_of(:reg1), do: :nxm_1 + def vendor_of(:reg2), do: :nxm_1 + def vendor_of(:reg3), do: :nxm_1 + def vendor_of(:reg4), do: :nxm_1 + def vendor_of(:reg5), do: :nxm_1 + def vendor_of(:reg6), do: :nxm_1 + def vendor_of(:reg7), do: :nxm_1 + def vendor_of(:reg8), do: :nxm_1 + def vendor_of(:reg9), do: :nxm_1 + def vendor_of(:reg10), do: :nxm_1 + def vendor_of(:reg11), do: :nxm_1 + def vendor_of(:reg12), do: :nxm_1 + def vendor_of(:reg13), do: :nxm_1 + def vendor_of(:reg14), do: :nxm_1 + def vendor_of(:reg15), do: :nxm_1 + def vendor_of(:tun_id), do: :nxm_1 + def vendor_of(:nx_arp_sha), do: :nxm_1 + def vendor_of(:nx_arp_tha), do: :nxm_1 + def vendor_of(:nx_ipv6_src), do: :nxm_1 + def vendor_of(:nx_ipv6_dst), do: :nxm_1 + def vendor_of(:nx_icmpv6_type), do: :nxm_1 + def vendor_of(:nx_icmpv6_code), do: :nxm_1 def vendor_of(:nx_ipv6_nd_target), do: :nxm_1 - def vendor_of(:nx_ipv6_nd_sll), do: :nxm_1 - def vendor_of(:nx_ipv6_nd_tll), do: :nxm_1 - def vendor_of(:nx_ip_frag), do: :nxm_1 - def vendor_of(:nx_ipv6_label), do: :nxm_1 - def vendor_of(:nx_ip_ecn), do: :nxm_1 - def vendor_of(:nx_ip_ttl), do: :nxm_1 - def vendor_of(:nx_mpls_ttl), do: :nxm_1 - def vendor_of(:tun_src), do: :nxm_1 - def vendor_of(:tun_dst), do: :nxm_1 - def vendor_of(:pkt_mark), do: :nxm_1 - def vendor_of(:dp_hash), do: :nxm_1 - def vendor_of(:recirc_id), do: :nxm_1 - def vendor_of(:conj_id), do: :nxm_1 - def vendor_of(:nx_tun_gbp_id), do: :nxm_1 - def vendor_of(:nx_tun_gbp_flags), do: :nxm_1 - def vendor_of(:tun_metadata0), do: :nxm_1 - def vendor_of(:tun_metadata1), do: :nxm_1 - def vendor_of(:tun_metadata2), do: :nxm_1 - def vendor_of(:tun_metadata3), do: :nxm_1 - def vendor_of(:tun_metadata4), do: :nxm_1 - def vendor_of(:tun_metadata5), do: :nxm_1 - def vendor_of(:tun_metadata6), do: :nxm_1 - def vendor_of(:tun_metadata7), do: :nxm_1 - def vendor_of(:tun_metadata8), do: :nxm_1 - def vendor_of(:tun_metadata9), do: :nxm_1 - def vendor_of(:tun_metadata10), do: :nxm_1 - def vendor_of(:tun_metadata11), do: :nxm_1 - def vendor_of(:tun_metadata12), do: :nxm_1 - def vendor_of(:tun_metadata13), do: :nxm_1 - def vendor_of(:tun_metadata14), do: :nxm_1 - def vendor_of(:tun_metadata15), do: :nxm_1 - def vendor_of(:tun_metadata16), do: :nxm_1 - def vendor_of(:tun_metadata17), do: :nxm_1 - def vendor_of(:tun_metadata18), do: :nxm_1 - def vendor_of(:tun_metadata19), do: :nxm_1 - def vendor_of(:tun_metadata20), do: :nxm_1 - def vendor_of(:tun_metadata21), do: :nxm_1 - def vendor_of(:tun_metadata22), do: :nxm_1 - def vendor_of(:tun_metadata23), do: :nxm_1 - def vendor_of(:tun_metadata24), do: :nxm_1 - def vendor_of(:tun_metadata25), do: :nxm_1 - def vendor_of(:tun_metadata26), do: :nxm_1 - def vendor_of(:tun_metadata27), do: :nxm_1 - def vendor_of(:tun_metadata28), do: :nxm_1 - def vendor_of(:tun_metadata29), do: :nxm_1 - def vendor_of(:tun_metadata30), do: :nxm_1 - def vendor_of(:tun_metadata31), do: :nxm_1 - def vendor_of(:tun_metadata32), do: :nxm_1 - def vendor_of(:tun_metadata33), do: :nxm_1 - def vendor_of(:tun_metadata34), do: :nxm_1 - def vendor_of(:tun_metadata35), do: :nxm_1 - def vendor_of(:tun_metadata36), do: :nxm_1 - def vendor_of(:tun_metadata37), do: :nxm_1 - def vendor_of(:tun_metadata38), do: :nxm_1 - def vendor_of(:tun_metadata39), do: :nxm_1 - def vendor_of(:tun_metadata40), do: :nxm_1 - def vendor_of(:tun_metadata41), do: :nxm_1 - def vendor_of(:tun_metadata42), do: :nxm_1 - def vendor_of(:tun_metadata43), do: :nxm_1 - def vendor_of(:tun_metadata44), do: :nxm_1 - def vendor_of(:tun_metadata45), do: :nxm_1 - def vendor_of(:tun_metadata46), do: :nxm_1 - def vendor_of(:tun_metadata47), do: :nxm_1 - def vendor_of(:tun_metadata48), do: :nxm_1 - def vendor_of(:tun_metadata49), do: :nxm_1 - def vendor_of(:tun_metadata50), do: :nxm_1 - def vendor_of(:tun_metadata51), do: :nxm_1 - def vendor_of(:tun_metadata52), do: :nxm_1 - def vendor_of(:tun_metadata53), do: :nxm_1 - def vendor_of(:tun_metadata54), do: :nxm_1 - def vendor_of(:tun_metadata55), do: :nxm_1 - def vendor_of(:tun_metadata56), do: :nxm_1 - def vendor_of(:tun_metadata57), do: :nxm_1 - def vendor_of(:tun_metadata58), do: :nxm_1 - def vendor_of(:tun_metadata59), do: :nxm_1 - def vendor_of(:tun_metadata60), do: :nxm_1 - def vendor_of(:tun_metadata61), do: :nxm_1 - def vendor_of(:tun_metadata62), do: :nxm_1 - def vendor_of(:tun_metadata63), do: :nxm_1 - def vendor_of(:tun_flags), do: :nxm_1 - def vendor_of(:ct_state), do: :nxm_1 - def vendor_of(:ct_zone), do: :nxm_1 - def vendor_of(:ct_mark), do: :nxm_1 - def vendor_of(:ct_label), do: :nxm_1 - def vendor_of(:tun_ipv6_src), do: :nxm_1 - def vendor_of(:tun_ipv6_dst), do: :nxm_1 - def vendor_of(:xxreg0), do: :nxm_1 - def vendor_of(:xxreg1), do: :nxm_1 - def vendor_of(:xxreg2), do: :nxm_1 - def vendor_of(:xxreg3), do: :nxm_1 - def vendor_of(:xxreg4), do: :nxm_1 - def vendor_of(:xxreg5), do: :nxm_1 - def vendor_of(:xxreg6), do: :nxm_1 - def vendor_of(:xxreg7), do: :nxm_1 - def vendor_of(:ct_ip_proto), do: :nxm_1 - def vendor_of(:ct_ipv4_src), do: :nxm_1 - def vendor_of(:ct_ipv4_dst), do: :nxm_1 - def vendor_of(:ct_ipv6_src), do: :nxm_1 - def vendor_of(:ct_ipv6_dst), do: :nxm_1 - def vendor_of(:ct_tp_src), do: :nxm_1 - def vendor_of(:ct_tp_dst), do: :nxm_1 + def vendor_of(:nx_ipv6_nd_sll), do: :nxm_1 + def vendor_of(:nx_ipv6_nd_tll), do: :nxm_1 + def vendor_of(:nx_ip_frag), do: :nxm_1 + def vendor_of(:nx_ipv6_label), do: :nxm_1 + def vendor_of(:nx_ip_ecn), do: :nxm_1 + def vendor_of(:nx_ip_ttl), do: :nxm_1 + def vendor_of(:nx_mpls_ttl), do: :nxm_1 + def vendor_of(:tun_src), do: :nxm_1 + def vendor_of(:tun_dst), do: :nxm_1 + def vendor_of(:pkt_mark), do: :nxm_1 + def vendor_of(:dp_hash), do: :nxm_1 + def vendor_of(:recirc_id), do: :nxm_1 + def vendor_of(:conj_id), do: :nxm_1 + def vendor_of(:nx_tun_gbp_id), do: :nxm_1 + def vendor_of(:nx_tun_gbp_flags), do: :nxm_1 + def vendor_of(:tun_metadata0), do: :nxm_1 + def vendor_of(:tun_metadata1), do: :nxm_1 + def vendor_of(:tun_metadata2), do: :nxm_1 + def vendor_of(:tun_metadata3), do: :nxm_1 + def vendor_of(:tun_metadata4), do: :nxm_1 + def vendor_of(:tun_metadata5), do: :nxm_1 + def vendor_of(:tun_metadata6), do: :nxm_1 + def vendor_of(:tun_metadata7), do: :nxm_1 + def vendor_of(:tun_metadata8), do: :nxm_1 + def vendor_of(:tun_metadata9), do: :nxm_1 + def vendor_of(:tun_metadata10), do: :nxm_1 + def vendor_of(:tun_metadata11), do: :nxm_1 + def vendor_of(:tun_metadata12), do: :nxm_1 + def vendor_of(:tun_metadata13), do: :nxm_1 + def vendor_of(:tun_metadata14), do: :nxm_1 + def vendor_of(:tun_metadata15), do: :nxm_1 + def vendor_of(:tun_metadata16), do: :nxm_1 + def vendor_of(:tun_metadata17), do: :nxm_1 + def vendor_of(:tun_metadata18), do: :nxm_1 + def vendor_of(:tun_metadata19), do: :nxm_1 + def vendor_of(:tun_metadata20), do: :nxm_1 + def vendor_of(:tun_metadata21), do: :nxm_1 + def vendor_of(:tun_metadata22), do: :nxm_1 + def vendor_of(:tun_metadata23), do: :nxm_1 + def vendor_of(:tun_metadata24), do: :nxm_1 + def vendor_of(:tun_metadata25), do: :nxm_1 + def vendor_of(:tun_metadata26), do: :nxm_1 + def vendor_of(:tun_metadata27), do: :nxm_1 + def vendor_of(:tun_metadata28), do: :nxm_1 + def vendor_of(:tun_metadata29), do: :nxm_1 + def vendor_of(:tun_metadata30), do: :nxm_1 + def vendor_of(:tun_metadata31), do: :nxm_1 + def vendor_of(:tun_metadata32), do: :nxm_1 + def vendor_of(:tun_metadata33), do: :nxm_1 + def vendor_of(:tun_metadata34), do: :nxm_1 + def vendor_of(:tun_metadata35), do: :nxm_1 + def vendor_of(:tun_metadata36), do: :nxm_1 + def vendor_of(:tun_metadata37), do: :nxm_1 + def vendor_of(:tun_metadata38), do: :nxm_1 + def vendor_of(:tun_metadata39), do: :nxm_1 + def vendor_of(:tun_metadata40), do: :nxm_1 + def vendor_of(:tun_metadata41), do: :nxm_1 + def vendor_of(:tun_metadata42), do: :nxm_1 + def vendor_of(:tun_metadata43), do: :nxm_1 + def vendor_of(:tun_metadata44), do: :nxm_1 + def vendor_of(:tun_metadata45), do: :nxm_1 + def vendor_of(:tun_metadata46), do: :nxm_1 + def vendor_of(:tun_metadata47), do: :nxm_1 + def vendor_of(:tun_metadata48), do: :nxm_1 + def vendor_of(:tun_metadata49), do: :nxm_1 + def vendor_of(:tun_metadata50), do: :nxm_1 + def vendor_of(:tun_metadata51), do: :nxm_1 + def vendor_of(:tun_metadata52), do: :nxm_1 + def vendor_of(:tun_metadata53), do: :nxm_1 + def vendor_of(:tun_metadata54), do: :nxm_1 + def vendor_of(:tun_metadata55), do: :nxm_1 + def vendor_of(:tun_metadata56), do: :nxm_1 + def vendor_of(:tun_metadata57), do: :nxm_1 + def vendor_of(:tun_metadata58), do: :nxm_1 + def vendor_of(:tun_metadata59), do: :nxm_1 + def vendor_of(:tun_metadata60), do: :nxm_1 + def vendor_of(:tun_metadata61), do: :nxm_1 + def vendor_of(:tun_metadata62), do: :nxm_1 + def vendor_of(:tun_metadata63), do: :nxm_1 + def vendor_of(:tun_flags), do: :nxm_1 + def vendor_of(:ct_state), do: :nxm_1 + def vendor_of(:ct_zone), do: :nxm_1 + def vendor_of(:ct_mark), do: :nxm_1 + def vendor_of(:ct_label), do: :nxm_1 + def vendor_of(:tun_ipv6_src), do: :nxm_1 + def vendor_of(:tun_ipv6_dst), do: :nxm_1 + def vendor_of(:xxreg0), do: :nxm_1 + def vendor_of(:xxreg1), do: :nxm_1 + def vendor_of(:xxreg2), do: :nxm_1 + def vendor_of(:xxreg3), do: :nxm_1 + def vendor_of(:xxreg4), do: :nxm_1 + def vendor_of(:xxreg5), do: :nxm_1 + def vendor_of(:xxreg6), do: :nxm_1 + def vendor_of(:xxreg7), do: :nxm_1 + def vendor_of(:ct_ip_proto), do: :nxm_1 + def vendor_of(:ct_ipv4_src), do: :nxm_1 + def vendor_of(:ct_ipv4_dst), do: :nxm_1 + def vendor_of(:ct_ipv6_src), do: :nxm_1 + def vendor_of(:ct_ipv6_dst), do: :nxm_1 + def vendor_of(:ct_tp_src), do: :nxm_1 + def vendor_of(:ct_tp_dst), do: :nxm_1 # OpenFlow Basic - def vendor_of(:in_port), do: :openflow_basic - def vendor_of(:in_phy_port), do: :openflow_basic - def vendor_of(:metadata), do: :openflow_basic - def vendor_of(:eth_dst), do: :openflow_basic - def vendor_of(:eth_src), do: :openflow_basic - def vendor_of(:eth_type), do: :openflow_basic - def vendor_of(:vlan_vid), do: :openflow_basic - def vendor_of(:vlan_pcp), do: :openflow_basic - def vendor_of(:ip_dscp), do: :openflow_basic - def vendor_of(:ip_ecn), do: :openflow_basic - def vendor_of(:ip_proto), do: :openflow_basic - def vendor_of(:ipv4_src), do: :openflow_basic - def vendor_of(:ipv4_dst), do: :openflow_basic - def vendor_of(:tcp_src), do: :openflow_basic - def vendor_of(:tcp_dst), do: :openflow_basic - def vendor_of(:udp_src), do: :openflow_basic - def vendor_of(:udp_dst), do: :openflow_basic - def vendor_of(:sctp_src), do: :openflow_basic - def vendor_of(:sctp_dst), do: :openflow_basic - def vendor_of(:icmpv4_type), do: :openflow_basic - def vendor_of(:icmpv4_code), do: :openflow_basic - def vendor_of(:arp_op), do: :openflow_basic - def vendor_of(:arp_spa), do: :openflow_basic - def vendor_of(:arp_tpa), do: :openflow_basic - def vendor_of(:arp_sha), do: :openflow_basic - def vendor_of(:arp_tha), do: :openflow_basic - def vendor_of(:ipv6_src), do: :openflow_basic - def vendor_of(:ipv6_dst), do: :openflow_basic - def vendor_of(:ipv6_flabel), do: :openflow_basic - def vendor_of(:icmpv6_type), do: :openflow_basic - def vendor_of(:icmpv6_code), do: :openflow_basic - def vendor_of(:ipv6_nd_target), do: :openflow_basic - def vendor_of(:ipv6_nd_sll), do: :openflow_basic - def vendor_of(:ipv6_nd_tll), do: :openflow_basic - def vendor_of(:mpls_label), do: :openflow_basic - def vendor_of(:mpls_tc), do: :openflow_basic - def vendor_of(:mpls_bos), do: :openflow_basic - def vendor_of(:pbb_isid), do: :openflow_basic - def vendor_of(:tunnel_id), do: :openflow_basic - def vendor_of(:ipv6_exthdr), do: :openflow_basic - def vendor_of(:pbb_uca), do: :openflow_basic - def vendor_of(:packet_type), do: :openflow_basic - def vendor_of(:gre_flags), do: :openflow_basic - def vendor_of(:gre_ver), do: :openflow_basic - def vendor_of(:gre_protocol), do: :openflow_basic - def vendor_of(:gre_key), do: :openflow_basic - def vendor_of(:gre_seqnum), do: :openflow_basic - def vendor_of(:lisp_flags), do: :openflow_basic - def vendor_of(:lisp_nonce), do: :openflow_basic - def vendor_of(:lisp_id), do: :openflow_basic - def vendor_of(:vxlan_flags), do: :openflow_basic - def vendor_of(:vxlan_vni), do: :openflow_basic + def vendor_of(:in_port), do: :openflow_basic + def vendor_of(:in_phy_port), do: :openflow_basic + def vendor_of(:metadata), do: :openflow_basic + def vendor_of(:eth_dst), do: :openflow_basic + def vendor_of(:eth_src), do: :openflow_basic + def vendor_of(:eth_type), do: :openflow_basic + def vendor_of(:vlan_vid), do: :openflow_basic + def vendor_of(:vlan_pcp), do: :openflow_basic + def vendor_of(:ip_dscp), do: :openflow_basic + def vendor_of(:ip_ecn), do: :openflow_basic + def vendor_of(:ip_proto), do: :openflow_basic + def vendor_of(:ipv4_src), do: :openflow_basic + def vendor_of(:ipv4_dst), do: :openflow_basic + def vendor_of(:tcp_src), do: :openflow_basic + def vendor_of(:tcp_dst), do: :openflow_basic + def vendor_of(:udp_src), do: :openflow_basic + def vendor_of(:udp_dst), do: :openflow_basic + def vendor_of(:sctp_src), do: :openflow_basic + def vendor_of(:sctp_dst), do: :openflow_basic + def vendor_of(:icmpv4_type), do: :openflow_basic + def vendor_of(:icmpv4_code), do: :openflow_basic + def vendor_of(:arp_op), do: :openflow_basic + def vendor_of(:arp_spa), do: :openflow_basic + def vendor_of(:arp_tpa), do: :openflow_basic + def vendor_of(:arp_sha), do: :openflow_basic + def vendor_of(:arp_tha), do: :openflow_basic + def vendor_of(:ipv6_src), do: :openflow_basic + def vendor_of(:ipv6_dst), do: :openflow_basic + def vendor_of(:ipv6_flabel), do: :openflow_basic + def vendor_of(:icmpv6_type), do: :openflow_basic + def vendor_of(:icmpv6_code), do: :openflow_basic + def vendor_of(:ipv6_nd_target), do: :openflow_basic + def vendor_of(:ipv6_nd_sll), do: :openflow_basic + def vendor_of(:ipv6_nd_tll), do: :openflow_basic + def vendor_of(:mpls_label), do: :openflow_basic + def vendor_of(:mpls_tc), do: :openflow_basic + def vendor_of(:mpls_bos), do: :openflow_basic + def vendor_of(:pbb_isid), do: :openflow_basic + def vendor_of(:tunnel_id), do: :openflow_basic + def vendor_of(:ipv6_exthdr), do: :openflow_basic + def vendor_of(:pbb_uca), do: :openflow_basic + def vendor_of(:packet_type), do: :openflow_basic + def vendor_of(:gre_flags), do: :openflow_basic + def vendor_of(:gre_ver), do: :openflow_basic + def vendor_of(:gre_protocol), do: :openflow_basic + def vendor_of(:gre_key), do: :openflow_basic + def vendor_of(:gre_seqnum), do: :openflow_basic + def vendor_of(:lisp_flags), do: :openflow_basic + def vendor_of(:lisp_nonce), do: :openflow_basic + def vendor_of(:lisp_id), do: :openflow_basic + def vendor_of(:vxlan_flags), do: :openflow_basic + def vendor_of(:vxlan_vni), do: :openflow_basic def vendor_of(:mpls_data_first_nibble), do: :openflow_basic - def vendor_of(:mpls_ach_version), do: :openflow_basic - def vendor_of(:mpls_ach_channel), do: :openflow_basic - def vendor_of(:mpls_pw_metadata), do: :openflow_basic - def vendor_of(:mpls_cw_flags), do: :openflow_basic - def vendor_of(:mpls_cw_fragment), do: :openflow_basic - def vendor_of(:mpls_cw_len), do: :openflow_basic - def vendor_of(:mpls_cw_seq_num), do: :openflow_basic - def vendor_of(:gtpu_flags), do: :openflow_basic - def vendor_of(:gtpu_ver), do: :openflow_basic - def vendor_of(:gtpu_msg_type), do: :openflow_basic - def vendor_of(:gtpu_teid), do: :openflow_basic - def vendor_of(:gtpu_extn_hdr), do: :openflow_basic - def vendor_of(:gtpu_extn_udp_port), do: :openflow_basic - def vendor_of(:gtpu_extn_sci), do: :openflow_basic + def vendor_of(:mpls_ach_version), do: :openflow_basic + def vendor_of(:mpls_ach_channel), do: :openflow_basic + def vendor_of(:mpls_pw_metadata), do: :openflow_basic + def vendor_of(:mpls_cw_flags), do: :openflow_basic + def vendor_of(:mpls_cw_fragment), do: :openflow_basic + def vendor_of(:mpls_cw_len), do: :openflow_basic + def vendor_of(:mpls_cw_seq_num), do: :openflow_basic + def vendor_of(:gtpu_flags), do: :openflow_basic + def vendor_of(:gtpu_ver), do: :openflow_basic + def vendor_of(:gtpu_msg_type), do: :openflow_basic + def vendor_of(:gtpu_teid), do: :openflow_basic + def vendor_of(:gtpu_extn_hdr), do: :openflow_basic + def vendor_of(:gtpu_extn_udp_port), do: :openflow_basic + def vendor_of(:gtpu_extn_sci), do: :openflow_basic # Packet Register - def vendor_of(:xreg0), do: :packet_register - def vendor_of(:xreg1), do: :packet_register - def vendor_of(:xreg2), do: :packet_register - def vendor_of(:xreg3), do: :packet_register - def vendor_of(:xreg4), do: :packet_register - def vendor_of(:xreg5), do: :packet_register - def vendor_of(:xreg6), do: :packet_register - def vendor_of(:xreg7), do: :packet_register + def vendor_of(:xreg0), do: :packet_register + def vendor_of(:xreg1), do: :packet_register + def vendor_of(:xreg2), do: :packet_register + def vendor_of(:xreg3), do: :packet_register + def vendor_of(:xreg4), do: :packet_register + def vendor_of(:xreg5), do: :packet_register + def vendor_of(:xreg6), do: :packet_register + def vendor_of(:xreg7), do: :packet_register # Nicira Ext Match - def vendor_of(:nsh_flags), do: :nicira_ext_match + def vendor_of(:nsh_flags), do: :nicira_ext_match def vendor_of(:nsh_mdtype), do: :nicira_ext_match - def vendor_of(:nsh_np), do: :nicira_ext_match - def vendor_of(:nsh_spi), do: :nicira_ext_match - def vendor_of(:nsh_si), do: :nicira_ext_match - def vendor_of(:nsh_c1), do: :nicira_ext_match - def vendor_of(:nsh_c2), do: :nicira_ext_match - def vendor_of(:nsh_c3), do: :nicira_ext_match - def vendor_of(:nsh_c4), do: :nicira_ext_match + def vendor_of(:nsh_np), do: :nicira_ext_match + def vendor_of(:nsh_spi), do: :nicira_ext_match + def vendor_of(:nsh_si), do: :nicira_ext_match + def vendor_of(:nsh_c1), do: :nicira_ext_match + def vendor_of(:nsh_c2), do: :nicira_ext_match + def vendor_of(:nsh_c3), do: :nicira_ext_match + def vendor_of(:nsh_c4), do: :nicira_ext_match # HP Ext Match def vendor_of(:hp_udp_src_port_range), do: :hp_ext_match @@ -281,269 +284,269 @@ defmodule Openflow.Match.Field do def vendor_of(:hp_tcp_src_port_range), do: :hp_ext_match def vendor_of(:hp_tcp_dst_port_range), do: :hp_ext_match def vendor_of(:hp_tcp_flags), do: :hp_ext_match - def vendor_of(:hp_custom_1), do: :hp_ext_match - def vendor_of(:hp_custom_2), do: :hp_ext_match - def vendor_of(:hp_custom_3), do: :hp_ext_match - def vendor_of(:hp_custom_4), do: :hp_ext_match + def vendor_of(:hp_custom_1), do: :hp_ext_match + def vendor_of(:hp_custom_2), do: :hp_ext_match + def vendor_of(:hp_custom_3), do: :hp_ext_match + def vendor_of(:hp_custom_4), do: :hp_ext_match # ONF Ext Match - def vendor_of(:onf_tcp_flags), do: :onf_ext_match + def vendor_of(:onf_tcp_flags), do: :onf_ext_match def vendor_of(:onf_actset_output), do: :onf_ext_match - def vendor_of(:onf_pbb_uca), do: :onf_ext_match + def vendor_of(:onf_pbb_uca), do: :onf_ext_match # NXM0 - def format_of(:nx_in_port), do: {:be16, :openflow10_port} - def format_of(:nx_eth_dst), do: {:mac, :ethernet} - def format_of(:nx_eth_src), do: {:mac, :ethernet} - def format_of(:nx_eth_type), do: {:be16, :hexadecimal} - def format_of(:nx_vlan_tci), do: {:be16, :hexadecimal} - def format_of(:nx_ip_tos), do: {:u8, :decimal} - def format_of(:nx_ip_proto), do: {:u8, :decimal} - def format_of(:nx_ipv4_src), do: {:be32, :ipv4} - def format_of(:nx_ipv4_dst), do: {:be32, :ipv4} - def format_of(:nx_tcp_src), do: {:be16, :decimal} - def format_of(:nx_tcp_dst), do: {:be16, :decimal} - def format_of(:nx_udp_src), do: {:be16, :decimal} - def format_of(:nx_udp_dst), do: {:be16, :decimal} - def format_of(:nx_icmpv4_type), do: {:u8, :decimal} - def format_of(:nx_icmpv4_code), do: {:u8, :decimal} - def format_of(:nx_arp_op), do: {:be16, :decimal} - def format_of(:nx_arp_spa), do: {:be32, :ipv4} - def format_of(:nx_arp_tpa), do: {:be32, :ipv4} - def format_of(:nx_tcp_flags), do: {:be16, :tcp_flags} + def format_of(:nx_in_port), do: {:be16, :openflow10_port} + def format_of(:nx_eth_dst), do: {:mac, :ethernet} + def format_of(:nx_eth_src), do: {:mac, :ethernet} + def format_of(:nx_eth_type), do: {:be16, :hexadecimal} + def format_of(:nx_vlan_tci), do: {:be16, :hexadecimal} + def format_of(:nx_ip_tos), do: {:u8, :decimal} + def format_of(:nx_ip_proto), do: {:u8, :decimal} + def format_of(:nx_ipv4_src), do: {:be32, :ipv4} + def format_of(:nx_ipv4_dst), do: {:be32, :ipv4} + def format_of(:nx_tcp_src), do: {:be16, :decimal} + def format_of(:nx_tcp_dst), do: {:be16, :decimal} + def format_of(:nx_udp_src), do: {:be16, :decimal} + def format_of(:nx_udp_dst), do: {:be16, :decimal} + def format_of(:nx_icmpv4_type), do: {:u8, :decimal} + def format_of(:nx_icmpv4_code), do: {:u8, :decimal} + def format_of(:nx_arp_op), do: {:be16, :decimal} + def format_of(:nx_arp_spa), do: {:be32, :ipv4} + def format_of(:nx_arp_tpa), do: {:be32, :ipv4} + def format_of(:nx_tcp_flags), do: {:be16, :tcp_flags} # NXM1 - def format_of(:reg0), do: {:be32, :hexadecimal} - def format_of(:reg1), do: {:be32, :hexadecimal} - def format_of(:reg2), do: {:be32, :hexadecimal} - def format_of(:reg3), do: {:be32, :hexadecimal} - def format_of(:reg4), do: {:be32, :hexadecimal} - def format_of(:reg5), do: {:be32, :hexadecimal} - def format_of(:reg6), do: {:be32, :hexadecimal} - def format_of(:reg7), do: {:be32, :hexadecimal} - def format_of(:reg8), do: {:be32, :hexadecimal} - def format_of(:reg9), do: {:be32, :hexadecimal} - def format_of(:reg10), do: {:be32, :hexadecimal} - def format_of(:reg11), do: {:be32, :hexadecimal} - def format_of(:reg12), do: {:be32, :hexadecimal} - def format_of(:reg13), do: {:be32, :hexadecimal} - def format_of(:reg14), do: {:be32, :hexadecimal} - def format_of(:reg15), do: {:be32, :hexadecimal} - def format_of(:tun_id), do: {:be64, :hexadecimal} - def format_of(:nx_arp_sha), do: {:mac, :ethernet} - def format_of(:nx_arp_tha), do: {:mac, :ethernet} - def format_of(:nx_ipv6_src), do: {:be128, :ipv6} - def format_of(:nx_ipv6_dst), do: {:be128, :ipv6} - def format_of(:nx_icmpv6_type), do: {:u8, :decimal} - def format_of(:nx_icmpv6_code), do: {:u8, :decimal} - def format_of(:nx_ipv6_nd_target), do: {:be128, :ipv6} - def format_of(:nx_ipv6_nd_sll), do: {:mac, :ethernet} - def format_of(:nx_ipv6_nd_tll), do: {:mac, :ethernet} - def format_of(:nx_ip_frag), do: {:u8, :decimal} - def format_of(:nx_ipv6_label), do: {:be32, :hexadecimal} - def format_of(:nx_ip_ecn), do: {:u8, :decimal} - def format_of(:nx_ip_ttl), do: {:u8, :decimal} - def format_of(:nx_mpls_ttl), do: {:u8, :decimal} - def format_of(:tun_src), do: {:be32, :ipv4} - def format_of(:tun_dst), do: {:be32, :ipv4} - def format_of(:pkt_mark), do: {:be32, :hexadecimal} - def format_of(:dp_hash), do: {:be32, :hexadecimal} - def format_of(:recirc_id), do: {:be32, :hexadecimal} - def format_of(:conj_id), do: {:be32, :hexadecimal} - def format_of(:nx_tun_gbp_id), do: {:be16, :decimal} - def format_of(:nx_tun_gbp_flags), do: {:u8, :decimal} - def format_of(:tun_metadata0), do: {:dynamic, :bytes} - def format_of(:tun_metadata1), do: {:dynamic, :bytes} - def format_of(:tun_metadata2), do: {:dynamic, :bytes} - def format_of(:tun_metadata3), do: {:dynamic, :bytes} - def format_of(:tun_metadata4), do: {:dynamic, :bytes} - def format_of(:tun_metadata5), do: {:dynamic, :bytes} - def format_of(:tun_metadata6), do: {:dynamic, :bytes} - def format_of(:tun_metadata7), do: {:dynamic, :bytes} - def format_of(:tun_metadata8), do: {:dynamic, :bytes} - def format_of(:tun_metadata9), do: {:dynamic, :bytes} - def format_of(:tun_metadata10), do: {:dynamic, :bytes} - def format_of(:tun_metadata11), do: {:dynamic, :bytes} - def format_of(:tun_metadata12), do: {:dynamic, :bytes} - def format_of(:tun_metadata13), do: {:dynamic, :bytes} - def format_of(:tun_metadata14), do: {:dynamic, :bytes} - def format_of(:tun_metadata15), do: {:dynamic, :bytes} - def format_of(:tun_metadata16), do: {:dynamic, :bytes} - def format_of(:tun_metadata17), do: {:dynamic, :bytes} - def format_of(:tun_metadata18), do: {:dynamic, :bytes} - def format_of(:tun_metadata19), do: {:dynamic, :bytes} - def format_of(:tun_metadata20), do: {:dynamic, :bytes} - def format_of(:tun_metadata21), do: {:dynamic, :bytes} - def format_of(:tun_metadata22), do: {:dynamic, :bytes} - def format_of(:tun_metadata23), do: {:dynamic, :bytes} - def format_of(:tun_metadata24), do: {:dynamic, :bytes} - def format_of(:tun_metadata25), do: {:dynamic, :bytes} - def format_of(:tun_metadata26), do: {:dynamic, :bytes} - def format_of(:tun_metadata27), do: {:dynamic, :bytes} - def format_of(:tun_metadata28), do: {:dynamic, :bytes} - def format_of(:tun_metadata29), do: {:dynamic, :bytes} - def format_of(:tun_metadata30), do: {:dynamic, :bytes} - def format_of(:tun_metadata31), do: {:dynamic, :bytes} - def format_of(:tun_metadata32), do: {:dynamic, :bytes} - def format_of(:tun_metadata33), do: {:dynamic, :bytes} - def format_of(:tun_metadata34), do: {:dynamic, :bytes} - def format_of(:tun_metadata35), do: {:dynamic, :bytes} - def format_of(:tun_metadata36), do: {:dynamic, :bytes} - def format_of(:tun_metadata37), do: {:dynamic, :bytes} - def format_of(:tun_metadata38), do: {:dynamic, :bytes} - def format_of(:tun_metadata39), do: {:dynamic, :bytes} - def format_of(:tun_metadata40), do: {:dynamic, :bytes} - def format_of(:tun_metadata41), do: {:dynamic, :bytes} - def format_of(:tun_metadata42), do: {:dynamic, :bytes} - def format_of(:tun_metadata43), do: {:dynamic, :bytes} - def format_of(:tun_metadata44), do: {:dynamic, :bytes} - def format_of(:tun_metadata45), do: {:dynamic, :bytes} - def format_of(:tun_metadata46), do: {:dynamic, :bytes} - def format_of(:tun_metadata47), do: {:dynamic, :bytes} - def format_of(:tun_metadata48), do: {:dynamic, :bytes} - def format_of(:tun_metadata49), do: {:dynamic, :bytes} - def format_of(:tun_metadata50), do: {:dynamic, :bytes} - def format_of(:tun_metadata51), do: {:dynamic, :bytes} - def format_of(:tun_metadata52), do: {:dynamic, :bytes} - def format_of(:tun_metadata53), do: {:dynamic, :bytes} - def format_of(:tun_metadata54), do: {:dynamic, :bytes} - def format_of(:tun_metadata55), do: {:dynamic, :bytes} - def format_of(:tun_metadata56), do: {:dynamic, :bytes} - def format_of(:tun_metadata57), do: {:dynamic, :bytes} - def format_of(:tun_metadata58), do: {:dynamic, :bytes} - def format_of(:tun_metadata59), do: {:dynamic, :bytes} - def format_of(:tun_metadata60), do: {:dynamic, :bytes} - def format_of(:tun_metadata61), do: {:dynamic, :bytes} - def format_of(:tun_metadata62), do: {:dynamic, :bytes} - def format_of(:tun_metadata63), do: {:dynamic, :bytes} - def format_of(:tun_flags), do: {:be16, :decimal} - def format_of(:ct_state), do: {:be32, :ct_state} - def format_of(:ct_zone), do: {:be16, :hexadecimal} - def format_of(:ct_mark), do: {:be32, :hexadecimal} - def format_of(:ct_label), do: {:be128, :hexadecimal} - def format_of(:tun_ipv6_src), do: {:be128, :ipv6} - def format_of(:tun_ipv6_dst), do: {:be128, :ipv6} - def format_of(:xxreg0), do: {:be128, :hexadecimal} - def format_of(:xxreg1), do: {:be128, :hexadecimal} - def format_of(:xxreg2), do: {:be128, :hexadecimal} - def format_of(:xxreg3), do: {:be128, :hexadecimal} - def format_of(:xxreg4), do: {:be128, :hexadecimal} - def format_of(:xxreg5), do: {:be128, :hexadecimal} - def format_of(:xxreg6), do: {:be128, :hexadecimal} - def format_of(:xxreg7), do: {:be128, :hexadecimal} - def format_of(:ct_ip_proto), do: {:u8, :decimal} - def format_of(:ct_ipv4_src), do: {:be32, :ipv4} - def format_of(:ct_ipv4_dst), do: {:be32, :ipv4} - def format_of(:ct_ipv6_src), do: {:be128, :ipv6} - def format_of(:ct_ipv6_dst), do: {:be128, :ipv6} - def format_of(:ct_tp_src), do: {:be16, :decimal} - def format_of(:ct_tp_dst), do: {:be16, :decimal} + def format_of(:reg0), do: {:be32, :hexadecimal} + def format_of(:reg1), do: {:be32, :hexadecimal} + def format_of(:reg2), do: {:be32, :hexadecimal} + def format_of(:reg3), do: {:be32, :hexadecimal} + def format_of(:reg4), do: {:be32, :hexadecimal} + def format_of(:reg5), do: {:be32, :hexadecimal} + def format_of(:reg6), do: {:be32, :hexadecimal} + def format_of(:reg7), do: {:be32, :hexadecimal} + def format_of(:reg8), do: {:be32, :hexadecimal} + def format_of(:reg9), do: {:be32, :hexadecimal} + def format_of(:reg10), do: {:be32, :hexadecimal} + def format_of(:reg11), do: {:be32, :hexadecimal} + def format_of(:reg12), do: {:be32, :hexadecimal} + def format_of(:reg13), do: {:be32, :hexadecimal} + def format_of(:reg14), do: {:be32, :hexadecimal} + def format_of(:reg15), do: {:be32, :hexadecimal} + def format_of(:tun_id), do: {:be64, :hexadecimal} + def format_of(:nx_arp_sha), do: {:mac, :ethernet} + def format_of(:nx_arp_tha), do: {:mac, :ethernet} + def format_of(:nx_ipv6_src), do: {:be128, :ipv6} + def format_of(:nx_ipv6_dst), do: {:be128, :ipv6} + def format_of(:nx_icmpv6_type), do: {:u8, :decimal} + def format_of(:nx_icmpv6_code), do: {:u8, :decimal} + def format_of(:nx_ipv6_nd_target), do: {:be128, :ipv6} + def format_of(:nx_ipv6_nd_sll), do: {:mac, :ethernet} + def format_of(:nx_ipv6_nd_tll), do: {:mac, :ethernet} + def format_of(:nx_ip_frag), do: {:u8, :decimal} + def format_of(:nx_ipv6_label), do: {:be32, :hexadecimal} + def format_of(:nx_ip_ecn), do: {:u8, :decimal} + def format_of(:nx_ip_ttl), do: {:u8, :decimal} + def format_of(:nx_mpls_ttl), do: {:u8, :decimal} + def format_of(:tun_src), do: {:be32, :ipv4} + def format_of(:tun_dst), do: {:be32, :ipv4} + def format_of(:pkt_mark), do: {:be32, :hexadecimal} + def format_of(:dp_hash), do: {:be32, :hexadecimal} + def format_of(:recirc_id), do: {:be32, :hexadecimal} + def format_of(:conj_id), do: {:be32, :hexadecimal} + def format_of(:nx_tun_gbp_id), do: {:be16, :decimal} + def format_of(:nx_tun_gbp_flags), do: {:u8, :decimal} + def format_of(:tun_metadata0), do: {:dynamic, :bytes} + def format_of(:tun_metadata1), do: {:dynamic, :bytes} + def format_of(:tun_metadata2), do: {:dynamic, :bytes} + def format_of(:tun_metadata3), do: {:dynamic, :bytes} + def format_of(:tun_metadata4), do: {:dynamic, :bytes} + def format_of(:tun_metadata5), do: {:dynamic, :bytes} + def format_of(:tun_metadata6), do: {:dynamic, :bytes} + def format_of(:tun_metadata7), do: {:dynamic, :bytes} + def format_of(:tun_metadata8), do: {:dynamic, :bytes} + def format_of(:tun_metadata9), do: {:dynamic, :bytes} + def format_of(:tun_metadata10), do: {:dynamic, :bytes} + def format_of(:tun_metadata11), do: {:dynamic, :bytes} + def format_of(:tun_metadata12), do: {:dynamic, :bytes} + def format_of(:tun_metadata13), do: {:dynamic, :bytes} + def format_of(:tun_metadata14), do: {:dynamic, :bytes} + def format_of(:tun_metadata15), do: {:dynamic, :bytes} + def format_of(:tun_metadata16), do: {:dynamic, :bytes} + def format_of(:tun_metadata17), do: {:dynamic, :bytes} + def format_of(:tun_metadata18), do: {:dynamic, :bytes} + def format_of(:tun_metadata19), do: {:dynamic, :bytes} + def format_of(:tun_metadata20), do: {:dynamic, :bytes} + def format_of(:tun_metadata21), do: {:dynamic, :bytes} + def format_of(:tun_metadata22), do: {:dynamic, :bytes} + def format_of(:tun_metadata23), do: {:dynamic, :bytes} + def format_of(:tun_metadata24), do: {:dynamic, :bytes} + def format_of(:tun_metadata25), do: {:dynamic, :bytes} + def format_of(:tun_metadata26), do: {:dynamic, :bytes} + def format_of(:tun_metadata27), do: {:dynamic, :bytes} + def format_of(:tun_metadata28), do: {:dynamic, :bytes} + def format_of(:tun_metadata29), do: {:dynamic, :bytes} + def format_of(:tun_metadata30), do: {:dynamic, :bytes} + def format_of(:tun_metadata31), do: {:dynamic, :bytes} + def format_of(:tun_metadata32), do: {:dynamic, :bytes} + def format_of(:tun_metadata33), do: {:dynamic, :bytes} + def format_of(:tun_metadata34), do: {:dynamic, :bytes} + def format_of(:tun_metadata35), do: {:dynamic, :bytes} + def format_of(:tun_metadata36), do: {:dynamic, :bytes} + def format_of(:tun_metadata37), do: {:dynamic, :bytes} + def format_of(:tun_metadata38), do: {:dynamic, :bytes} + def format_of(:tun_metadata39), do: {:dynamic, :bytes} + def format_of(:tun_metadata40), do: {:dynamic, :bytes} + def format_of(:tun_metadata41), do: {:dynamic, :bytes} + def format_of(:tun_metadata42), do: {:dynamic, :bytes} + def format_of(:tun_metadata43), do: {:dynamic, :bytes} + def format_of(:tun_metadata44), do: {:dynamic, :bytes} + def format_of(:tun_metadata45), do: {:dynamic, :bytes} + def format_of(:tun_metadata46), do: {:dynamic, :bytes} + def format_of(:tun_metadata47), do: {:dynamic, :bytes} + def format_of(:tun_metadata48), do: {:dynamic, :bytes} + def format_of(:tun_metadata49), do: {:dynamic, :bytes} + def format_of(:tun_metadata50), do: {:dynamic, :bytes} + def format_of(:tun_metadata51), do: {:dynamic, :bytes} + def format_of(:tun_metadata52), do: {:dynamic, :bytes} + def format_of(:tun_metadata53), do: {:dynamic, :bytes} + def format_of(:tun_metadata54), do: {:dynamic, :bytes} + def format_of(:tun_metadata55), do: {:dynamic, :bytes} + def format_of(:tun_metadata56), do: {:dynamic, :bytes} + def format_of(:tun_metadata57), do: {:dynamic, :bytes} + def format_of(:tun_metadata58), do: {:dynamic, :bytes} + def format_of(:tun_metadata59), do: {:dynamic, :bytes} + def format_of(:tun_metadata60), do: {:dynamic, :bytes} + def format_of(:tun_metadata61), do: {:dynamic, :bytes} + def format_of(:tun_metadata62), do: {:dynamic, :bytes} + def format_of(:tun_metadata63), do: {:dynamic, :bytes} + def format_of(:tun_flags), do: {:be16, :decimal} + def format_of(:ct_state), do: {:be32, :ct_state} + def format_of(:ct_zone), do: {:be16, :hexadecimal} + def format_of(:ct_mark), do: {:be32, :hexadecimal} + def format_of(:ct_label), do: {:be128, :hexadecimal} + def format_of(:tun_ipv6_src), do: {:be128, :ipv6} + def format_of(:tun_ipv6_dst), do: {:be128, :ipv6} + def format_of(:xxreg0), do: {:be128, :hexadecimal} + def format_of(:xxreg1), do: {:be128, :hexadecimal} + def format_of(:xxreg2), do: {:be128, :hexadecimal} + def format_of(:xxreg3), do: {:be128, :hexadecimal} + def format_of(:xxreg4), do: {:be128, :hexadecimal} + def format_of(:xxreg5), do: {:be128, :hexadecimal} + def format_of(:xxreg6), do: {:be128, :hexadecimal} + def format_of(:xxreg7), do: {:be128, :hexadecimal} + def format_of(:ct_ip_proto), do: {:u8, :decimal} + def format_of(:ct_ipv4_src), do: {:be32, :ipv4} + def format_of(:ct_ipv4_dst), do: {:be32, :ipv4} + def format_of(:ct_ipv6_src), do: {:be128, :ipv6} + def format_of(:ct_ipv6_dst), do: {:be128, :ipv6} + def format_of(:ct_tp_src), do: {:be16, :decimal} + def format_of(:ct_tp_dst), do: {:be16, :decimal} # OpenFlow Basic - def format_of(:in_port), do: {:be32, :openflow13_port} - def format_of(:in_phy_port), do: {:be32, :openflow13_port} - def format_of(:metadata), do: {:be64, :hexadecimal} - def format_of(:eth_dst), do: {:mac, :ethernet} - def format_of(:eth_src), do: {:mac, :ethernet} - def format_of(:eth_type), do: {:be16, :hexadecimal} - def format_of(:vlan_vid), do: {:be16, :hexadecimal} - def format_of(:vlan_pcp), do: {:u8, :decimal} - def format_of(:ip_dscp), do: {:u8, :decimal} - def format_of(:ip_ecn), do: {:u8, :decimal} - def format_of(:ip_proto), do: {:u8, :decimal} - def format_of(:ipv4_src), do: {:be32, :ipv4} - def format_of(:ipv4_dst), do: {:be32, :ipv4} - def format_of(:tcp_src), do: {:be16, :decimal} - def format_of(:tcp_dst), do: {:be16, :decimal} - def format_of(:udp_src), do: {:be16, :decimal} - def format_of(:udp_dst), do: {:be16, :decimal} - def format_of(:sctp_src), do: {:be16, :decimal} - def format_of(:sctp_dst), do: {:be16, :decimal} - def format_of(:icmpv4_type), do: {:u8, :decimal} - def format_of(:icmpv4_code), do: {:u8, :decimal} - def format_of(:arp_op), do: {:be16, :decimal} - def format_of(:arp_spa), do: {:be32, :ipv4} - def format_of(:arp_tpa), do: {:be32, :ipv4} - def format_of(:arp_sha), do: {:mac, :ethernet} - def format_of(:arp_tha), do: {:mac, :ethernet} - def format_of(:ipv6_src), do: {:be128, :ipv6} - def format_of(:ipv6_dst), do: {:be128, :ipv6} - def format_of(:ipv6_flabel), do: {:be32, :hexadecimal} - def format_of(:icmpv6_type), do: {:u8, :decimal} - def format_of(:icmpv6_code), do: {:u8, :decimal} - def format_of(:ipv6_nd_target), do: {:be128, :ipv6} - def format_of(:ipv6_nd_sll), do: {:mac, :ethernet} - def format_of(:ipv6_nd_tll), do: {:mac, :ethernet} - def format_of(:mpls_label), do: {:be32, :decimal} - def format_of(:mpls_tc), do: {:u8, :decimal} - def format_of(:mpls_bos), do: {:u8, :decimal} - def format_of(:pbb_isid), do: {:u24, :decimal} - def format_of(:tunnel_id), do: {:be64, :hexadecimal} - def format_of(:ipv6_exthdr), do: {:be16, :ipv6exthdr_flags} - def format_of(:pbb_uca), do: {:u8, :decimal} - def format_of(:packet_type), do: {:be32, :decimal} - def format_of(:gre_flags), do: {:be16, :decimal} - def format_of(:gre_ver), do: {:u8, :decimal} - def format_of(:gre_protocol), do: {:be16, :decimal} - def format_of(:gre_key), do: {:be32, :decimal} - def format_of(:gre_seqnum), do: {:be32, :decimal} - def format_of(:lisp_flags), do: {:u8, :decimal} - def format_of(:lisp_nonce), do: {:u24, :decimal} - def format_of(:lisp_id), do: {:be32, :decimal} - def format_of(:vxlan_flags), do: {:u8, :decimal} - def format_of(:vxlan_vni), do: {:u24, :decimal} - def format_of(:mpls_data_first_nibble), do: {:u8, :decimal} - def format_of(:mpls_ach_version), do: {:u8, :decimal} - def format_of(:mpls_ach_channel), do: {:be16, :decimal} - def format_of(:mpls_pw_metadata), do: {:u8, :decimal} - def format_of(:mpls_cw_flags), do: {:u8, :decimal} - def format_of(:mpls_cw_fragment), do: {:u8, :decimal} - def format_of(:mpls_cw_len), do: {:u8, :decimal} - def format_of(:mpls_cw_seq_num), do: {:be16, :decimal} - def format_of(:gtpu_flags), do: {:u8, :decimal} - def format_of(:gtpu_ver), do: {:u8, :decimal} - def format_of(:gtpu_msg_type), do: {:u8, :decimal} - def format_of(:gtpu_teid), do: {:be32, :decimal} - def format_of(:gtpu_extn_hdr), do: {:u8, :decimal} - def format_of(:gtpu_extn_udp_port), do: {:be16, :decimal} - def format_of(:gtpu_extn_sci), do: {:be16, :decimal} + def format_of(:in_port), do: {:be32, :openflow13_port} + def format_of(:in_phy_port), do: {:be32, :openflow13_port} + def format_of(:metadata), do: {:be64, :hexadecimal} + def format_of(:eth_dst), do: {:mac, :ethernet} + def format_of(:eth_src), do: {:mac, :ethernet} + def format_of(:eth_type), do: {:be16, :hexadecimal} + def format_of(:vlan_vid), do: {:be16, :hexadecimal} + def format_of(:vlan_pcp), do: {:u8, :decimal} + def format_of(:ip_dscp), do: {:u8, :decimal} + def format_of(:ip_ecn), do: {:u8, :decimal} + def format_of(:ip_proto), do: {:u8, :decimal} + def format_of(:ipv4_src), do: {:be32, :ipv4} + def format_of(:ipv4_dst), do: {:be32, :ipv4} + def format_of(:tcp_src), do: {:be16, :decimal} + def format_of(:tcp_dst), do: {:be16, :decimal} + def format_of(:udp_src), do: {:be16, :decimal} + def format_of(:udp_dst), do: {:be16, :decimal} + def format_of(:sctp_src), do: {:be16, :decimal} + def format_of(:sctp_dst), do: {:be16, :decimal} + def format_of(:icmpv4_type), do: {:u8, :decimal} + def format_of(:icmpv4_code), do: {:u8, :decimal} + def format_of(:arp_op), do: {:be16, :decimal} + def format_of(:arp_spa), do: {:be32, :ipv4} + def format_of(:arp_tpa), do: {:be32, :ipv4} + def format_of(:arp_sha), do: {:mac, :ethernet} + def format_of(:arp_tha), do: {:mac, :ethernet} + def format_of(:ipv6_src), do: {:be128, :ipv6} + def format_of(:ipv6_dst), do: {:be128, :ipv6} + def format_of(:ipv6_flabel), do: {:be32, :hexadecimal} + def format_of(:icmpv6_type), do: {:u8, :decimal} + def format_of(:icmpv6_code), do: {:u8, :decimal} + def format_of(:ipv6_nd_target), do: {:be128, :ipv6} + def format_of(:ipv6_nd_sll), do: {:mac, :ethernet} + def format_of(:ipv6_nd_tll), do: {:mac, :ethernet} + def format_of(:mpls_label), do: {:be32, :decimal} + def format_of(:mpls_tc), do: {:u8, :decimal} + def format_of(:mpls_bos), do: {:u8, :decimal} + def format_of(:pbb_isid), do: {:u24, :decimal} + def format_of(:tunnel_id), do: {:be64, :hexadecimal} + def format_of(:ipv6_exthdr), do: {:be16, :ipv6exthdr_flags} + def format_of(:pbb_uca), do: {:u8, :decimal} + def format_of(:packet_type), do: {:be32, :decimal} + def format_of(:gre_flags), do: {:be16, :decimal} + def format_of(:gre_ver), do: {:u8, :decimal} + def format_of(:gre_protocol), do: {:be16, :decimal} + def format_of(:gre_key), do: {:be32, :decimal} + def format_of(:gre_seqnum), do: {:be32, :decimal} + def format_of(:lisp_flags), do: {:u8, :decimal} + def format_of(:lisp_nonce), do: {:u24, :decimal} + def format_of(:lisp_id), do: {:be32, :decimal} + def format_of(:vxlan_flags), do: {:u8, :decimal} + def format_of(:vxlan_vni), do: {:u24, :decimal} + def format_of(:mpls_data_first_nibble), do: {:u8, :decimal} + def format_of(:mpls_ach_version), do: {:u8, :decimal} + def format_of(:mpls_ach_channel), do: {:be16, :decimal} + def format_of(:mpls_pw_metadata), do: {:u8, :decimal} + def format_of(:mpls_cw_flags), do: {:u8, :decimal} + def format_of(:mpls_cw_fragment), do: {:u8, :decimal} + def format_of(:mpls_cw_len), do: {:u8, :decimal} + def format_of(:mpls_cw_seq_num), do: {:be16, :decimal} + def format_of(:gtpu_flags), do: {:u8, :decimal} + def format_of(:gtpu_ver), do: {:u8, :decimal} + def format_of(:gtpu_msg_type), do: {:u8, :decimal} + def format_of(:gtpu_teid), do: {:be32, :decimal} + def format_of(:gtpu_extn_hdr), do: {:u8, :decimal} + def format_of(:gtpu_extn_udp_port), do: {:be16, :decimal} + def format_of(:gtpu_extn_sci), do: {:be16, :decimal} # Packet Register - def format_of(:xreg0), do: {:be64, :hexadecimal} - def format_of(:xreg1), do: {:be64, :hexadecimal} - def format_of(:xreg2), do: {:be64, :hexadecimal} - def format_of(:xreg3), do: {:be64, :hexadecimal} - def format_of(:xreg4), do: {:be64, :hexadecimal} - def format_of(:xreg5), do: {:be64, :hexadecimal} - def format_of(:xreg6), do: {:be64, :hexadecimal} - def format_of(:xreg7), do: {:be64, :hexadecimal} + def format_of(:xreg0), do: {:be64, :hexadecimal} + def format_of(:xreg1), do: {:be64, :hexadecimal} + def format_of(:xreg2), do: {:be64, :hexadecimal} + def format_of(:xreg3), do: {:be64, :hexadecimal} + def format_of(:xreg4), do: {:be64, :hexadecimal} + def format_of(:xreg5), do: {:be64, :hexadecimal} + def format_of(:xreg6), do: {:be64, :hexadecimal} + def format_of(:xreg7), do: {:be64, :hexadecimal} # Nicira Ext Match - def format_of(:nsh_flags), do: {:u8, :decimal} - def format_of(:nsh_mdtype), do: {:u8, :decimal} - def format_of(:nsh_np), do: {:u8, :decimal} - def format_of(:nsh_spi), do: {:be32, :decimal} - def format_of(:nsh_si), do: {:be32, :decimal} - def format_of(:nsh_c1), do: {:be32, :decimal} - def format_of(:nsh_c2), do: {:be32, :decimal} - def format_of(:nsh_c3), do: {:be32, :decimal} - def format_of(:nsh_c4), do: {:be32, :decimal} + def format_of(:nsh_flags), do: {:u8, :decimal} + def format_of(:nsh_mdtype), do: {:u8, :decimal} + def format_of(:nsh_np), do: {:u8, :decimal} + def format_of(:nsh_spi), do: {:be32, :decimal} + def format_of(:nsh_si), do: {:be32, :decimal} + def format_of(:nsh_c1), do: {:be32, :decimal} + def format_of(:nsh_c2), do: {:be32, :decimal} + def format_of(:nsh_c3), do: {:be32, :decimal} + def format_of(:nsh_c4), do: {:be32, :decimal} # HP Ext Match def format_of(:hp_udp_src_port_range), do: {:be32, :decimal} def format_of(:hp_udp_dst_port_range), do: {:be32, :decimal} def format_of(:hp_tcp_src_port_range), do: {:be32, :decimal} def format_of(:hp_tcp_dst_port_range), do: {:be32, :decimal} - def format_of(:hp_tcp_flags), do: {:be16, :tcp_flags} - def format_of(:hp_custom_1), do: {:dynamic, :bytes} - def format_of(:hp_custom_2), do: {:dynamic, :bytes} - def format_of(:hp_custom_3), do: {:dynamic, :bytes} - def format_of(:hp_custom_4), do: {:dynamic, :bytes} + def format_of(:hp_tcp_flags), do: {:be16, :tcp_flags} + def format_of(:hp_custom_1), do: {:dynamic, :bytes} + def format_of(:hp_custom_2), do: {:dynamic, :bytes} + def format_of(:hp_custom_3), do: {:dynamic, :bytes} + def format_of(:hp_custom_4), do: {:dynamic, :bytes} # ONF Ext Match - def format_of(:onf_tcp_flags), do: {:be16, :tcp_flags} + def format_of(:onf_tcp_flags), do: {:be16, :tcp_flags} def format_of(:onf_actset_output), do: {:be32, :openflow13_port} - def format_of(:onf_pbb_uca), do: {:u8, :decimal} + def format_of(:onf_pbb_uca), do: {:u8, :decimal} # Formatting = decimal def formatting(<>, :u8, :decimal), do: value @@ -577,17 +580,22 @@ defmodule Openflow.Match.Field do # Formatting = ethernet def formatting(<>, :mac, :ethernet), do: Openflow.Utils.to_hex_string(value) - def formatting(value, :mac, :ethernet), do: <<(String.to_integer(value, 16))::48>> + def formatting(value, :mac, :ethernet), do: <> # Formatting = IPv4 def formatting(<>, :be32, :ipv4), do: {a1, a2, a3, a4} def formatting({a1, a2, a3, a4}, :be32, :ipv4), do: <> # Formatting = IPv6 - def formatting(<>, :be128, :ipv6) do + def formatting( + <>, + :be128, + :ipv6 + ) do {a1, a2, a3, a4, a5, a6, a7, a8} end - def formatting({a1, a2, a3, a4, a5, a6, a7, a8},:be128, :ipv6) do + + def formatting({a1, a2, a3, a4, a5, a6, a7, a8}, :be128, :ipv6) do <> end @@ -599,13 +607,15 @@ defmodule Openflow.Match.Field do :bad_enum -> value end end + def formatting(value, :be16, :openflow10_port) do port_no = try do Openflow.Enums.to_int(value, :openflow10_port_no) catch - :bad_enum -> value + :bad_enum -> value end + <> end @@ -617,6 +627,7 @@ defmodule Openflow.Match.Field do :bad_enum -> value end end + def formatting(value, :be32, :openflow13_port) do port_no = try do @@ -624,6 +635,7 @@ defmodule Openflow.Match.Field do catch :bad_enum -> value end + <> end @@ -631,24 +643,27 @@ defmodule Openflow.Match.Field do def formatting(<>, :be16, :tcp_flags) do Openflow.Enums.int_to_flags(value, :tcp_flags) end + def formatting(value, :be16, :tcp_flags) do - <<(Openflow.Enums.flags_to_int(value, :tcp_flags))::16>> + <> end # CT State def formatting(<>, :be32, :ct_state) do Openflow.Enums.int_to_flags(value, :ct_state_flags) end + def formatting(value, :be32, :ct_state) do - <<(Openflow.Enums.flags_to_int(value, :ct_state_flags))::32>> + <> end # CT State def formatting(<>, :be16, :ipv6exthdr_flags) do Openflow.Enums.int_to_flags(value, :ipv6exthdr_flags) end + def formatting(value, :be16, :ipv6exthdr_flags) do - <<(Openflow.Enums.flags_to_int(value, :ipv6exthdr_flags))::16>> + <> end # Other diff --git a/lib/openflow/meter_band.ex b/lib/openflow/meter_band.ex index cbc4805..ab8a8b8 100644 --- a/lib/openflow/meter_band.ex +++ b/lib/openflow/meter_band.ex @@ -1,5 +1,4 @@ defmodule Openflow.MeterBand do - def read(meter_band_bin) do do_read([], meter_band_bin) end @@ -7,6 +6,7 @@ defmodule Openflow.MeterBand do def to_binary(meter_bands) when is_list(meter_bands) do to_binary(<<>>, meter_bands) end + def to_binary(meter_band) do to_binary([meter_band]) end @@ -14,15 +14,17 @@ defmodule Openflow.MeterBand do # private functions defp do_read(acc, <<>>), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary 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 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__ - to_binary(<>, rest) + to_binary(<>, rest) end end diff --git a/lib/openflow/meter_band/drop.ex b/lib/openflow/meter_band/drop.ex index 6336652..bacd01d 100644 --- a/lib/openflow/meter_band/drop.ex +++ b/lib/openflow/meter_band/drop.ex @@ -1,6 +1,6 @@ defmodule Openflow.MeterBand.Drop do defstruct( - rate: 0, + rate: 0, burst_size: 0 ) diff --git a/lib/openflow/meter_band/experimenter.ex b/lib/openflow/meter_band/experimenter.ex index 8a73171..1fab8e6 100644 --- a/lib/openflow/meter_band/experimenter.ex +++ b/lib/openflow/meter_band/experimenter.ex @@ -1,7 +1,7 @@ defmodule Openflow.MeterBand.Experimenter do defstruct( - rate: 0, - burst_size: 0, + rate: 0, + burst_size: 0, experimenter: 0 ) @@ -14,11 +14,11 @@ defmodule Openflow.MeterBand.Experimenter do %Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter} 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} end 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 diff --git a/lib/openflow/meter_band/remark.ex b/lib/openflow/meter_band/remark.ex index 6e0f4bf..1bb3f93 100644 --- a/lib/openflow/meter_band/remark.ex +++ b/lib/openflow/meter_band/remark.ex @@ -1,6 +1,6 @@ defmodule Openflow.MeterBand.Remark do defstruct( - rate: 0, + rate: 0, burst_size: 0, prec_level: 0 ) diff --git a/lib/openflow/meter_mod.ex b/lib/openflow/meter_mod.ex index 24aab63..05e47b3 100644 --- a/lib/openflow/meter_mod.ex +++ b/lib/openflow/meter_mod.ex @@ -3,7 +3,7 @@ defmodule Openflow.MeterMod do version: 4, xid: 0, datapath_id: "", - aux_id: 0, + aux_id: 0, command: :add, flags: [], meter_id: 0, diff --git a/lib/openflow/multipart/aggregate/reply.ex b/lib/openflow/multipart/aggregate/reply.ex index 7bb7beb..7b710c2 100644 --- a/lib/openflow/multipart/aggregate/reply.ex +++ b/lib/openflow/multipart/aggregate/reply.ex @@ -1,13 +1,14 @@ defmodule Openflow.Multipart.Aggregate.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], packet_count: 0, - byte_count: 0, - flow_count: 0 + byte_count: 0, + flow_count: 0 ) alias __MODULE__ diff --git a/lib/openflow/multipart/aggregate/request.ex b/lib/openflow/multipart/aggregate/request.ex index e7fa041..89f55e3 100644 --- a/lib/openflow/multipart/aggregate/request.ex +++ b/lib/openflow/multipart/aggregate/request.ex @@ -1,15 +1,16 @@ defmodule Openflow.Multipart.Aggregate.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - flags: [], - table_id: :all, - out_port: :any, - out_group: :any, - cookie: 0, - cookie_mask: 0, - match: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + table_id: :all, + out_port: :any, + out_group: :any, + cookie: 0, + cookie_mask: 0, + match: [] ) alias __MODULE__ @@ -23,44 +24,55 @@ defmodule Openflow.Multipart.Aggregate.Request do cookie = Keyword.get(options, :cookie, 0) cookie_mask = Keyword.get(options, :cookie, 0) match = Keyword.get(options, :match, []) - %Request{table_id: table_id, - out_port: out_port, - out_group: out_group, - cookie: cookie, - cookie_mask: cookie_mask, - match: match} + + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } end - def read(<>) do + def read( + <> + ) do table_id = Openflow.Utils.get_enum(table_id_int, :table_id) out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) out_group = Openflow.Utils.get_enum(out_group_int, :group_id) {match, _rest} = Openflow.Match.read(match_bin) - %Request{table_id: table_id, - out_port: out_port, - out_group: out_group, - cookie: cookie, - cookie_mask: cookie_mask, - match: match} + + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } end - def to_binary(%Request{table_id: table_id, - out_port: out_port, - out_group: out_group, - cookie: cookie, - cookie_mask: cookie_mask, - match: match} = msg) do + def to_binary( + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } = msg + ) do table_id_int = Openflow.Utils.get_enum(table_id, :table_id) out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) out_group_int = Openflow.Utils.get_enum(out_group, :group_id) match_bin = Openflow.Match.to_binary(match) - body_bin = <> + + body_bin = + <> + header_bin = Openflow.Multipart.Request.header(msg) <> end diff --git a/lib/openflow/multipart/desc/reply.ex b/lib/openflow/multipart/desc/reply.ex index 7794428..a995cf2 100644 --- a/lib/openflow/multipart/desc/reply.ex +++ b/lib/openflow/multipart/desc/reply.ex @@ -1,31 +1,36 @@ defmodule Openflow.Multipart.Desc.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - mfr_desc: "", - hw_desc: "", - sw_desc: "", - serial_num: "", - dp_desc: "" + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + mfr_desc: "", + hw_desc: "", + sw_desc: "", + serial_num: "", + dp_desc: "" ) alias __MODULE__ - @desc_str_len 256 + @desc_str_len 256 @serial_num_len 32 def ofp_type, do: 19 - def read(<>) do - %Reply{mfr_desc: Openflow.Utils.decode_string(mfr_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)} + def read( + <> + ) do + %Reply{ + mfr_desc: Openflow.Utils.decode_string(mfr_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 diff --git a/lib/openflow/multipart/desc/request.ex b/lib/openflow/multipart/desc/request.ex index ffd55e2..4d9bef7 100644 --- a/lib/openflow/multipart/desc/request.ex +++ b/lib/openflow/multipart/desc/request.ex @@ -1,8 +1,9 @@ defmodule Openflow.Multipart.Desc.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [] ) diff --git a/lib/openflow/multipart/flow/reply.ex b/lib/openflow/multipart/flow/reply.ex index 41941f0..135a222 100644 --- a/lib/openflow/multipart/flow/reply.ex +++ b/lib/openflow/multipart/flow/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.Flow.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - flows: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + flows: [] ) alias __MODULE__ @@ -22,29 +23,32 @@ defmodule Openflow.Multipart.Flow.Reply do end def append_body(%Reply{flows: flows} = message, %Reply{flags: [:more], flows: continue}) do - %{message|flows: [continue|flows]} + %{message | flows: [continue | flows]} end + def append_body(%Reply{flows: flows} = message, %Reply{flags: [], flows: continue}) do - new_flows = [continue|flows] - |> Enum.reverse - |> List.flatten - %{message|flows: new_flows} + new_flows = + [continue | flows] + |> Enum.reverse() + |> List.flatten() + + %{message | flows: new_flows} end end defmodule Openflow.Multipart.FlowStats do defstruct( - table_id: 0, - duration_sec: 0, + table_id: 0, + duration_sec: 0, duration_nsec: 0, - priority: 0, - idle_timeout: 0, - hard_timeout: 0, - flags: 0, - cookie: 0, - packet_count: 0, - byte_count: 0, - match: [], + priority: 0, + idle_timeout: 0, + hard_timeout: 0, + flags: 0, + cookie: 0, + packet_count: 0, + byte_count: 0, + match: [], instructions: [] ) @@ -57,30 +61,35 @@ defmodule Openflow.Multipart.FlowStats do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary - do_read([codec(flow_stats_bin)|acc], rest) + do_read([codec(flow_stats_bin) | acc], rest) end - defp codec(<<_length::16, table_id_int::8, 0::8, duration_sec::32, - duration_nsec::32, priority::16, idle::16, hard::16, - flags_int::16, _::size(4)-unit(8), cookie::64, - packet_count::64, byte_count::64, tail::bytes>>) do + defp codec( + <<_length::16, table_id_int::8, 0::8, duration_sec::32, duration_nsec::32, priority::16, + idle::16, hard::16, flags_int::16, _::size(4)-unit(8), cookie::64, packet_count::64, + byte_count::64, tail::bytes>> + ) do {match, instructions_bin} = Openflow.Match.read(tail) table_id = Openflow.Utils.get_enum(table_id_int, :table_id) flags = Openflow.Enums.int_to_flags(flags_int, :flow_mod_flags) instructions = Openflow.Instruction.read(instructions_bin) - %FlowStats{table_id: table_id, - duration_sec: duration_sec, - duration_nsec: duration_nsec, - priority: priority, - idle_timeout: idle, - hard_timeout: hard, - flags: flags, - cookie: cookie, - packet_count: packet_count, - byte_count: byte_count, - match: match, - instructions: instructions} + + %FlowStats{ + table_id: table_id, + duration_sec: duration_sec, + duration_nsec: duration_nsec, + priority: priority, + idle_timeout: idle, + hard_timeout: hard, + flags: flags, + cookie: cookie, + packet_count: packet_count, + byte_count: byte_count, + match: match, + instructions: instructions + } end end diff --git a/lib/openflow/multipart/flow/request.ex b/lib/openflow/multipart/flow/request.ex index 53e8146..dc14e43 100644 --- a/lib/openflow/multipart/flow/request.ex +++ b/lib/openflow/multipart/flow/request.ex @@ -1,15 +1,16 @@ defmodule Openflow.Multipart.Flow.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - flags: [], - table_id: :all, - out_port: :any, - out_group: :any, - cookie: 0, - cookie_mask: 0, - match: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + table_id: :all, + out_port: :any, + out_group: :any, + cookie: 0, + cookie_mask: 0, + match: [] ) alias __MODULE__ @@ -22,45 +23,56 @@ defmodule Openflow.Multipart.Flow.Request do out_group = Keyword.get(options, :out_group, :any) cookie = Keyword.get(options, :cookie, 0) cookie_mask = Keyword.get(options, :cookie, 0) - match = Keyword.get(options, :match, Openflow.Match.new) - %Request{table_id: table_id, - out_port: out_port, - out_group: out_group, - cookie: cookie, - cookie_mask: cookie_mask, - match: match} + match = Keyword.get(options, :match, Openflow.Match.new()) + + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } end - def read(<>) do + def read( + <> + ) do table_id = Openflow.Utils.get_enum(table_id_int, :table_id) out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) out_group = Openflow.Utils.get_enum(out_group_int, :group_id) {match, _rest} = Openflow.Match.read(match_bin) - %Request{table_id: table_id, - out_port: out_port, - out_group: out_group, - cookie: cookie, - cookie_mask: cookie_mask, - match: match} + + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } end - def to_binary(%Request{table_id: table_id, - out_port: out_port, - out_group: out_group, - cookie: cookie, - cookie_mask: cookie_mask, - match: match} = msg) do + def to_binary( + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } = msg + ) do table_id_int = Openflow.Utils.get_enum(table_id, :table_id) out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) out_group_int = Openflow.Utils.get_enum(out_group, :group_id) match_bin = Openflow.Match.to_binary(match) - body_bin = <> + + body_bin = + <> + header_bin = Openflow.Multipart.Request.header(msg) <> end diff --git a/lib/openflow/multipart/group/reply.ex b/lib/openflow/multipart/group/reply.ex index fc434a0..5e4b86f 100644 --- a/lib/openflow/multipart/group/reply.ex +++ b/lib/openflow/multipart/group/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.Group.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - groups: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + groups: [] ) alias __MODULE__ @@ -22,25 +23,28 @@ defmodule Openflow.Multipart.Group.Reply do end def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do - %{message|groups: [continue|groups]} + %{message | groups: [continue | groups]} end + def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do - new_groups = [continue|groups] - |> Enum.reverse - |> List.flatten - %{message|groups: new_groups} + new_groups = + [continue | groups] + |> Enum.reverse() + |> List.flatten() + + %{message | groups: new_groups} end end defmodule Openflow.Multipart.Group do defstruct( - group_id: 0, - ref_count: 0, - packet_count: 0, - byte_count: 0, - duration_sec: 0, + group_id: 0, + ref_count: 0, + packet_count: 0, + byte_count: 0, + duration_sec: 0, duration_nsec: 0, - bucket_stats: [] + bucket_stats: [] ) @ofp_group_stats_size 40 @@ -54,27 +58,32 @@ defmodule Openflow.Multipart.Group do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary - do_read([codec(group_bin)|acc], rest) + do_read([codec(group_bin) | acc], rest) end - defp codec(<>) do + defp codec( + <> + ) do bucket_stats_size = length - @ofp_group_stats_size <> = tail - bucket_stats = for <> do - %{packet_count: packet_count, byte_count: byte_count} - end - %Group{group_id: group_id, - ref_count: ref_count, - packet_count: packet_count, - byte_count: byte_count, - duration_sec: duration_sec, - duration_nsec: duration_nsec, - bucket_stats: bucket_stats} + + bucket_stats = + for <> do + %{packet_count: packet_count, byte_count: byte_count} + end + + %Group{ + group_id: group_id, + ref_count: ref_count, + packet_count: packet_count, + byte_count: byte_count, + duration_sec: duration_sec, + duration_nsec: duration_nsec, + bucket_stats: bucket_stats + } end end diff --git a/lib/openflow/multipart/group/request.ex b/lib/openflow/multipart/group/request.ex index 288123a..bc7130c 100644 --- a/lib/openflow/multipart/group/request.ex +++ b/lib/openflow/multipart/group/request.ex @@ -1,10 +1,11 @@ defmodule Openflow.Multipart.Group.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [], - group_id: :all + group_id: :all ) alias __MODULE__ diff --git a/lib/openflow/multipart/group_desc/reply.ex b/lib/openflow/multipart/group_desc/reply.ex index fea5684..8e8d424 100644 --- a/lib/openflow/multipart/group_desc/reply.ex +++ b/lib/openflow/multipart/group_desc/reply.ex @@ -1,10 +1,11 @@ defmodule Openflow.Multipart.GroupDesc.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - flags: [], - groups: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + groups: [] ) alias __MODULE__ @@ -21,21 +22,24 @@ defmodule Openflow.Multipart.GroupDesc.Reply do end def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do - %{message|groups: [continue|groups]} + %{message | groups: [continue | groups]} end + def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do - new_groups = [continue|groups] - |> Enum.reverse - |> List.flatten - %{message|groups: new_groups} + new_groups = + [continue | groups] + |> Enum.reverse() + |> List.flatten() + + %{message | groups: new_groups} end end defmodule Openflow.Multipart.GroupDescStats do defstruct( - type: :all, - group_id: 0, - buckets: [] + type: :all, + group_id: 0, + buckets: [] ) alias __MODULE__ @@ -49,9 +53,10 @@ defmodule Openflow.Multipart.GroupDescStats do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary - do_read([codec(group_stats_bin)|acc], rest) + do_read([codec(group_stats_bin) | acc], rest) end defp codec(<>) do diff --git a/lib/openflow/multipart/group_desc/request.ex b/lib/openflow/multipart/group_desc/request.ex index 6f7f390..7fda473 100644 --- a/lib/openflow/multipart/group_desc/request.ex +++ b/lib/openflow/multipart/group_desc/request.ex @@ -1,8 +1,9 @@ defmodule Openflow.Multipart.GroupDesc.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [] ) diff --git a/lib/openflow/multipart/group_features/reply.ex b/lib/openflow/multipart/group_features/reply.ex index 495ad83..a43667b 100644 --- a/lib/openflow/multipart/group_features/reply.ex +++ b/lib/openflow/multipart/group_features/reply.ex @@ -1,45 +1,47 @@ defmodule Openflow.Multipart.GroupFeatures.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - types: 0, + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + types: 0, capabilities: [], - max_groups_for_all: 0, - max_groups_for_select: 0, - max_groups_for_indirect: 0, + max_groups_for_all: 0, + max_groups_for_select: 0, + max_groups_for_indirect: 0, max_groups_for_fast_failover: 0, - actions_for_all: 0, - actions_for_select: 0, - actions_for_indirect: 0, - actions_for_fast_failover: 0 + actions_for_all: 0, + actions_for_select: 0, + actions_for_indirect: 0, + actions_for_fast_failover: 0 ) alias __MODULE__ def ofp_type, do: 18 - def read(<>) do + def read( + <> + ) do capabilities = Openflow.Enums.int_to_flags(capabilities_int, :group_capabilities) - %Reply{types: types_int, - capabilities: capabilities, - max_groups_for_all: max_groups_for_all_int, - max_groups_for_select: max_groups_for_select_int, - max_groups_for_indirect: max_groups_for_indirect_int, - max_groups_for_fast_failover: max_groups_for_fast_failover_int, - actions_for_all: actions_for_all_int, - actions_for_select: actions_for_select_int, - actions_for_indirect: actions_for_indirect_int, - actions_for_fast_failover: actions_for_fast_failover_int} + + %Reply{ + types: types_int, + capabilities: capabilities, + max_groups_for_all: max_groups_for_all_int, + max_groups_for_select: max_groups_for_select_int, + max_groups_for_indirect: max_groups_for_indirect_int, + max_groups_for_fast_failover: max_groups_for_fast_failover_int, + actions_for_all: actions_for_all_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 diff --git a/lib/openflow/multipart/group_features/request.ex b/lib/openflow/multipart/group_features/request.ex index c51278b..b44c0dd 100644 --- a/lib/openflow/multipart/group_features/request.ex +++ b/lib/openflow/multipart/group_features/request.ex @@ -1,8 +1,9 @@ defmodule Openflow.Multipart.GroupFeatures.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [] ) diff --git a/lib/openflow/multipart/meter/reply.ex b/lib/openflow/multipart/meter/reply.ex index 2aede6e..7fe9656 100644 --- a/lib/openflow/multipart/meter/reply.ex +++ b/lib/openflow/multipart/meter/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.Meter.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - meters: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + meters: [] ) alias __MODULE__ @@ -18,25 +19,28 @@ defmodule Openflow.Multipart.Meter.Reply do end def append_body(%Reply{meters: meters} = message, %Reply{flags: [:more], meters: continue}) do - %{message|meters: [continue|meters]} + %{message | meters: [continue | meters]} end + def append_body(%Reply{meters: meters} = message, %Reply{flags: [], meters: continue}) do - new_meters = [continue|meters] - |> Enum.reverse - |> List.flatten - %{message|meters: new_meters} + new_meters = + [continue | meters] + |> Enum.reverse() + |> List.flatten() + + %{message | meters: new_meters} end end defmodule Openflow.Multipart.Meter do defstruct( - meter_id: 0, - flow_count: 0, + meter_id: 0, + flow_count: 0, packet_in_count: 0, - byte_in_count: 0, - duration_sec: 0, - duration_nsec: 0, - band_stats: [] + byte_in_count: 0, + duration_sec: 0, + duration_nsec: 0, + band_stats: [] ) @ofp_meter_stats_size 40 @@ -50,25 +54,32 @@ defmodule Openflow.Multipart.Meter do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <<_::32, length::16, _binary::bytes>> = binary) do <> = binary - do_read([codec(meter_bin)|acc], rest) + do_read([codec(meter_bin) | acc], rest) end - defp codec(<>) do + defp codec( + <> + ) do band_stats_size = length - @ofp_meter_stats_size <> = tail - band_stats = for <> do - %{packet_band_count: packet_band_count,byte_band_count: byte_band_count} - end - %Meter{meter_id: meter_id, - flow_count: flow_count, - packet_in_count: packet_in_count, - byte_in_count: byte_in_count, - duration_sec: duration_sec, - duration_nsec: duration_nsec, - band_stats: band_stats} + + band_stats = + for <> do + %{packet_band_count: packet_band_count, byte_band_count: byte_band_count} + end + + %Meter{ + meter_id: meter_id, + flow_count: flow_count, + 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 diff --git a/lib/openflow/multipart/meter/request.ex b/lib/openflow/multipart/meter/request.ex index d9f1944..084b2fb 100644 --- a/lib/openflow/multipart/meter/request.ex +++ b/lib/openflow/multipart/meter/request.ex @@ -1,10 +1,11 @@ defmodule Openflow.Multipart.Meter.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [], - meter_id: :all + meter_id: :all ) alias __MODULE__ diff --git a/lib/openflow/multipart/meter_config/request.ex b/lib/openflow/multipart/meter_config/request.ex index ced8c02..afd7dd1 100644 --- a/lib/openflow/multipart/meter_config/request.ex +++ b/lib/openflow/multipart/meter_config/request.ex @@ -1,10 +1,11 @@ defmodule Openflow.Multipart.MeterConfig.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [], - meter_id: :all + meter_id: :all ) alias __MODULE__ diff --git a/lib/openflow/multipart/port_desc/reply.ex b/lib/openflow/multipart/port_desc/reply.ex index 73e0573..6025dab 100644 --- a/lib/openflow/multipart/port_desc/reply.ex +++ b/lib/openflow/multipart/port_desc/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.PortDesc.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - ports: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + ports: [] ) alias __MODULE__ @@ -17,17 +18,20 @@ defmodule Openflow.Multipart.PortDesc.Reply do end def read(<>) do - ports = for (<>), do: Openflow.Port.read(port_bin) + ports = for <>, do: Openflow.Port.read(port_bin) %Reply{ports: Enum.reverse(ports)} end def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do - %{message|ports: [continue|ports]} + %{message | ports: [continue | ports]} end + def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do - new_ports = [continue|ports] - |> Enum.reverse - |> List.flatten - %{message|ports: new_ports} + new_ports = + [continue | ports] + |> Enum.reverse() + |> List.flatten() + + %{message | ports: new_ports} end end diff --git a/lib/openflow/multipart/port_desc/request.ex b/lib/openflow/multipart/port_desc/request.ex index be0abde..e6bfe44 100644 --- a/lib/openflow/multipart/port_desc/request.ex +++ b/lib/openflow/multipart/port_desc/request.ex @@ -1,8 +1,9 @@ defmodule Openflow.Multipart.PortDesc.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [] ) diff --git a/lib/openflow/multipart/port_stats/reply.ex b/lib/openflow/multipart/port_stats/reply.ex index e57ed32..880c639 100644 --- a/lib/openflow/multipart/port_stats/reply.ex +++ b/lib/openflow/multipart/port_stats/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.PortStats.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - ports: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + ports: [] ) alias __MODULE__ @@ -22,32 +23,35 @@ defmodule Openflow.Multipart.PortStats.Reply do end def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do - %{message|ports: [continue|ports]} + %{message | ports: [continue | ports]} end + def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do - new_ports = [continue|ports] - |> Enum.reverse - |> List.flatten - %{message|ports: new_ports} + new_ports = + [continue | ports] + |> Enum.reverse() + |> List.flatten() + + %{message | ports: new_ports} end end defmodule Openflow.Multipart.PortStats do defstruct( - port_number: 0, - rx_packets: 0, - tx_packets: 0, - rx_bytes: 0, - tx_bytes: 0, - rx_dropped: 0, - tx_dropped: 0, - rx_errors: 0, - tx_errors: 0, - rx_frame_err: 0, - rx_over_err: 0, - rx_crc_err: 0, - collisions: 0, - duration_sec: 0, + port_number: 0, + rx_packets: 0, + tx_packets: 0, + rx_bytes: 0, + tx_bytes: 0, + rx_dropped: 0, + tx_dropped: 0, + rx_errors: 0, + tx_errors: 0, + rx_frame_err: 0, + rx_over_err: 0, + rx_crc_err: 0, + collisions: 0, + duration_sec: 0, duration_nsec: 0 ) @@ -60,30 +64,33 @@ defmodule Openflow.Multipart.PortStats do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <>) do - do_read([codec(port_stats_bin)|acc], rest) + do_read([codec(port_stats_bin) | acc], rest) end - defp codec(<>) do - %PortStats{port_number: port_no, - rx_packets: rx_packets, - tx_packets: tx_packets, - rx_bytes: rx_bytes, - tx_bytes: tx_bytes, - rx_dropped: rx_dropped, - tx_dropped: tx_dropped, - rx_errors: rx_errors, - tx_errors: tx_errors, - rx_frame_err: rx_frame_err, - rx_over_err: rx_over_err, - rx_crc_err: rx_crc_err, - collisions: collisions, - duration_sec: duration_sec, - duration_nsec: duration_nsec} + defp codec( + <> + ) do + %PortStats{ + port_number: port_no, + rx_packets: rx_packets, + tx_packets: tx_packets, + rx_bytes: rx_bytes, + tx_bytes: tx_bytes, + rx_dropped: rx_dropped, + tx_dropped: tx_dropped, + rx_errors: rx_errors, + tx_errors: tx_errors, + rx_frame_err: rx_frame_err, + rx_over_err: rx_over_err, + rx_crc_err: rx_crc_err, + collisions: collisions, + duration_sec: duration_sec, + duration_nsec: duration_nsec + } end end diff --git a/lib/openflow/multipart/port_stats/request.ex b/lib/openflow/multipart/port_stats/request.ex index e432be6..6b91648 100644 --- a/lib/openflow/multipart/port_stats/request.ex +++ b/lib/openflow/multipart/port_stats/request.ex @@ -1,8 +1,9 @@ defmodule Openflow.Multipart.PortStats.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [], port_number: :any ) diff --git a/lib/openflow/multipart/queue/reply.ex b/lib/openflow/multipart/queue/reply.ex index 38afbbc..a420ba1 100644 --- a/lib/openflow/multipart/queue/reply.ex +++ b/lib/openflow/multipart/queue/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.Queue.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - queues: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + queues: [] ) alias __MODULE__ @@ -22,24 +23,27 @@ defmodule Openflow.Multipart.Queue.Reply do end def append_body(%Reply{queues: queues} = message, %Reply{flags: [:more], queues: continue}) do - %{message|queues: [continue|queues]} + %{message | queues: [continue | queues]} end + def append_body(%Reply{queues: queues} = message, %Reply{flags: [], queues: continue}) do - new_queues = [continue|queues] - |> Enum.reverse - |> List.flatten - %{message|queues: new_queues} + new_queues = + [continue | queues] + |> Enum.reverse() + |> List.flatten() + + %{message | queues: new_queues} end end defmodule Openflow.Multipart.Queue do defstruct( - port_number: 0, - queue_id: 0, - tx_bytes: 0, - tx_packets: 0, - tx_errors: 0, - duration_sec: 0, + port_number: 0, + queue_id: 0, + tx_bytes: 0, + tx_packets: 0, + tx_errors: 0, + duration_sec: 0, duration_nsec: 0 ) @@ -52,19 +56,23 @@ defmodule Openflow.Multipart.Queue do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <>) do - do_read([codec(queue_bin)|acc], rest) + do_read([codec(queue_bin) | acc], rest) end - defp codec(<>) do - %Queue{port_number: port_no, - queue_id: queue_id, - tx_bytes: tx_bytes, - tx_packets: tx_packets, - tx_errors: tx_errors, - duration_sec: duration_sec, - duration_nsec: duration_nsec} + defp codec( + <> + ) do + %Queue{ + port_number: port_no, + queue_id: queue_id, + tx_bytes: tx_bytes, + tx_packets: tx_packets, + tx_errors: tx_errors, + duration_sec: duration_sec, + duration_nsec: duration_nsec + } end end diff --git a/lib/openflow/multipart/queue/request.ex b/lib/openflow/multipart/queue/request.ex index 654a407..7cab958 100644 --- a/lib/openflow/multipart/queue/request.ex +++ b/lib/openflow/multipart/queue/request.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.Queue.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [], port_number: :any, - queue_id: :all + queue_id: :all ) alias __MODULE__ diff --git a/lib/openflow/multipart/reply.ex b/lib/openflow/multipart/reply.ex index ad446cc..18893b0 100644 --- a/lib/openflow/multipart/reply.ex +++ b/lib/openflow/multipart/reply.ex @@ -5,15 +5,17 @@ defmodule Openflow.Multipart.Reply do codec = Openflow.Enums.to_atom(type_int, :multipart_reply_codec) flags = Openflow.Enums.int_to_flags(flags_int, :multipart_reply_flags) reply = codec.read(reply_bin) - %{reply|flags: flags} + %{reply | flags: flags} end def to_binary(%{__struct__: codec, flags: flags} = msg) do flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags) type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec) + case codec.to_binary(msg) do reply_bin when is_binary(reply_bin) -> <> + {:error, reason} -> {:error, reason} end diff --git a/lib/openflow/multipart/request.ex b/lib/openflow/multipart/request.ex index 4f6f454..43d6e78 100644 --- a/lib/openflow/multipart/request.ex +++ b/lib/openflow/multipart/request.ex @@ -5,15 +5,17 @@ defmodule Openflow.Multipart.Request do codec = Openflow.Enums.to_atom(type_int, :multipart_request_codec) flags = Openflow.Enums.int_to_flags(flags_int, :multipart_request_flags) request = codec.read(request_bin) - %{request|flags: flags} + %{request | flags: flags} end def to_binary(%{__struct__: codec, flags: flags} = msg) do flags_int = Openflow.Enums.flags_to_int(flags, :multipart_request_flags) type_int = Openflow.Enums.to_int(codec, :multipart_request_codec) + case codec.to_binary(msg) do request_bin when is_binary(request_bin) -> <> + {:error, reason} -> {:error, reason} end diff --git a/lib/openflow/multipart/table/reply.ex b/lib/openflow/multipart/table/reply.ex index 457de7c..f83406f 100644 --- a/lib/openflow/multipart/table/reply.ex +++ b/lib/openflow/multipart/table/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.Table.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - tables: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + tables: [] ) alias __MODULE__ @@ -18,21 +19,24 @@ defmodule Openflow.Multipart.Table.Reply do end def append_body(%Reply{tables: tables} = message, %Reply{flags: [:more], tables: continue}) do - %{message|tables: [continue|tables]} + %{message | tables: [continue | tables]} end + def append_body(%Reply{tables: tables} = message, %Reply{flags: [], tables: continue}) do - new_tables = [continue|tables] - |> Enum.reverse - |> List.flatten - %{message|tables: new_tables} + new_tables = + [continue | tables] + |> Enum.reverse() + |> List.flatten() + + %{message | tables: new_tables} end end defmodule Openflow.Multipart.TableStats do defstruct( - table_id: 0, - active_count: 0, - lookup_count: 0, + table_id: 0, + active_count: 0, + lookup_count: 0, matched_count: 0 ) @@ -45,12 +49,20 @@ defmodule Openflow.Multipart.TableStats do # private functions defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <>) do - do_read([codec(table_stats_bin)|acc], rest) + do_read([codec(table_stats_bin) | acc], rest) end - defp codec(<>) do - %TableStats{table_id: table_id, active_count: active_count, - lookup_count: lookup_count, matched_count: matched_count} + defp codec( + <> + ) do + %TableStats{ + table_id: table_id, + active_count: active_count, + lookup_count: lookup_count, + matched_count: matched_count + } end end diff --git a/lib/openflow/multipart/table/request.ex b/lib/openflow/multipart/table/request.ex index 8607068..39938c2 100644 --- a/lib/openflow/multipart/table/request.ex +++ b/lib/openflow/multipart/table/request.ex @@ -1,8 +1,9 @@ defmodule Openflow.Multipart.Table.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, flags: [] ) diff --git a/lib/openflow/multipart/table_features/body.ex b/lib/openflow/multipart/table_features/body.ex index c4903fc..3399a06 100644 --- a/lib/openflow/multipart/table_features/body.ex +++ b/lib/openflow/multipart/table_features/body.ex @@ -1,46 +1,44 @@ defmodule Openflow.Multipart.TableFeatures.Body do - defstruct [ - table_id: 0, - name: "", - metadata_match: 0, - metadata_write: 0, - config: [], - max_entries: 0, - instructions: nil, - instructions_miss: nil, - next_tables: nil, - next_tables_miss: nil, - write_actions: nil, - write_actions_miss: nil, - apply_actions: nil, - apply_actions_miss: nil, - match: nil, - wildcards: nil, - write_setfield: nil, - write_setfield_miss: nil, - apply_setfield: nil, - apply_setfield_miss: nil - ] + defstruct table_id: 0, + name: "", + metadata_match: 0, + metadata_write: 0, + config: [], + max_entries: 0, + instructions: nil, + instructions_miss: nil, + next_tables: nil, + next_tables_miss: nil, + write_actions: nil, + write_actions_miss: nil, + apply_actions: nil, + apply_actions_miss: nil, + match: nil, + wildcards: nil, + write_setfield: nil, + write_setfield_miss: nil, + apply_setfield: nil, + apply_setfield_miss: nil alias __MODULE__ - @max_table_name_len 32 - @prop_header_length 4 + @max_table_name_len 32 + @prop_header_length 4 @table_features_length 64 - @instructions 0 - @instructions_miss 1 - @next_tables 2 - @next_tables_miss 3 - @write_actions 4 - @write_actions_miss 5 - @apply_actions 6 - @apply_actions_miss 7 - @match 8 - @wildcards 10 - @write_setfield 12 + @instructions 0 + @instructions_miss 1 + @next_tables 2 + @next_tables_miss 3 + @write_actions 4 + @write_actions_miss 5 + @apply_actions 6 + @apply_actions_miss 7 + @match 8 + @wildcards 10 + @write_setfield 12 @write_setfield_miss 13 - @apply_setfield 14 + @apply_setfield 14 @apply_setfield_miss 15 @prop_keys [ @@ -62,25 +60,25 @@ defmodule Openflow.Multipart.TableFeatures.Body do def new(options) do %Body{ - table_id: options[:table_id] || 0, - name: options[:name] || "", - metadata_match: options[:metadata_match] || 0, - metadata_write: options[:metadata_write] || 0, - config: options[:config] || [], - max_entries: options[:max_entries] || 0, - instructions: options[:instructions], - instructions_miss: options[:instructions_miss], - next_tables: options[:next_tables], - next_tables_miss: options[:next_tables_miss], - write_actions: options[:write_actions], - write_actions_miss: options[:write_actions_miss], - apply_actions: options[:apply_actions], - apply_actions_miss: options[:apply_actions_miss], - match: options[:match], - wildcards: options[:wildcards], - write_setfield: options[:write_setfield], + table_id: options[:table_id] || 0, + name: options[:name] || "", + metadata_match: options[:metadata_match] || 0, + metadata_write: options[:metadata_write] || 0, + config: options[:config] || [], + max_entries: options[:max_entries] || 0, + instructions: options[:instructions], + instructions_miss: options[:instructions_miss], + next_tables: options[:next_tables], + next_tables_miss: options[:next_tables_miss], + write_actions: options[:write_actions], + write_actions_miss: options[:write_actions_miss], + apply_actions: options[:apply_actions], + apply_actions_miss: options[:apply_actions_miss], + match: options[:match], + wildcards: options[:wildcards], + write_setfield: options[:write_setfield], write_setfield_miss: options[:write_setfield_miss], - apply_setfield: options[:apply_setfield], + apply_setfield: options[:apply_setfield], apply_setfield_miss: options[:apply_setfield_miss] } end @@ -96,102 +94,120 @@ defmodule Openflow.Multipart.TableFeatures.Body do # private functions defp do_to_binary(acc, []), do: acc - defp do_to_binary(acc, [table|rest]) do - do_to_binary(<>, rest) + + defp do_to_binary(acc, [table | rest]) do + do_to_binary(<>, rest) end defp do_read(acc, ""), do: Enum.reverse(acc) + defp do_read(acc, <> = binary) do <> = binary - do_read([decode(features_bin)|acc], rest) + do_read([decode(features_bin) | acc], rest) end - defp decode(<<_length::16, table_id::8, _::size(5)-unit(8), - name_bin::size(@max_table_name_len)-bytes, - metadata_match::64, metadata_write::64, - config_int::32, max_entries::32, props_bin::bytes>>) do + defp decode( + <<_length::16, table_id::8, _::size(5)-unit(8), + name_bin::size(@max_table_name_len)-bytes, metadata_match::64, metadata_write::64, + config_int::32, max_entries::32, props_bin::bytes>> + ) do name = Openflow.Utils.decode_string(name_bin) config = Openflow.Enums.int_to_flags(config_int, :table_config) - body = %Body{table_id: table_id, - name: name, - metadata_match: metadata_match, - metadata_write: metadata_write, - config: config, - max_entries: max_entries} + + body = %Body{ + table_id: table_id, + name: name, + metadata_match: metadata_match, + metadata_write: metadata_write, + config: config, + max_entries: max_entries + } + decode_props(body, props_bin) end defp encode(table) do - filter_fn = fn(key) -> not is_nil(Map.get(table, key)) end + filter_fn = fn key -> not is_nil(Map.get(table, key)) end keys = Enum.filter(@prop_keys, filter_fn) props_bin = encode_props("", table, keys) length = @table_features_length + byte_size(props_bin) - %Body{table_id: table_id, - name: name, - metadata_match: metadata_match, - metadata_write: metadata_write, - config: config, - max_entries: max_entries} = table + + %Body{ + table_id: table_id, + name: name, + metadata_match: metadata_match, + metadata_write: metadata_write, + config: config, + max_entries: max_entries + } = table + config_int = Openflow.Enums.flags_to_int(config, :table_config) name_bin = Openflow.Utils.encode_string(name, @max_table_name_len) - <> + + <> end defp decode_props(body, ""), do: body + defp decode_props(body, <>) - when type_int == @instructions or type_int == @instructions_miss do + when type_int == @instructions or type_int == @instructions_miss do pad_length = Openflow.Utils.pad_length(length, 8) value_length = length - @prop_header_length - <> = tail + + <> = + tail + instructions = decode_instructions([], instructions_bin) type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + body |> struct(%{type => instructions}) |> decode_props(rest) end + defp decode_props(body, <>) - when type_int == @next_tables or type_int == @next_tables_miss do + when type_int == @next_tables or type_int == @next_tables_miss do pad_length = Openflow.Utils.pad_length(length, 8) value_length = length - @prop_header_length <> = tail next_tables = for <>, do: table_id type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + body |> struct(%{type => next_tables}) |> decode_props(rest) end + defp decode_props(body, <>) - when type_int == @write_actions or - type_int == @write_actions_miss or - type_int == @apply_actions or - type_int == @apply_actions_miss do + when type_int == @write_actions or type_int == @write_actions_miss or + type_int == @apply_actions or type_int == @apply_actions_miss do pad_length = Openflow.Utils.pad_length(length, 8) value_length = length - @prop_header_length <> = tail actions = decode_actions([], actions_bin) type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + body |> struct(%{type => actions}) |> decode_props(rest) end + defp decode_props(body, <>) - when type_int == @match or - type_int == @wildcards or - type_int == @write_setfield or - type_int == @write_setfield_miss or - type_int == @apply_setfield or - type_int == @apply_setfield_miss do + when type_int == @match or type_int == @wildcards or type_int == @write_setfield or + type_int == @write_setfield_miss or type_int == @apply_setfield or + type_int == @apply_setfield_miss do pad_length = Openflow.Utils.pad_length(length, 8) value_length = length - @prop_header_length <> = tail matches = decode_matches([], matches_bin) type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + body |> struct(%{type => matches}) |> decode_props(rest) end + defp decode_props(body, <<_type_int::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) value_length = length - @prop_header_length @@ -200,8 +216,9 @@ defmodule Openflow.Multipart.TableFeatures.Body do end defp encode_props(acc, _table, []), do: acc - defp encode_props(acc, table, [type|rest]) - when type == :instructions or type == :instructions_miss do + + defp encode_props(acc, table, [type | rest]) + when type == :instructions or type == :instructions_miss do type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) instructions_bin = encode_instructions("", Map.get(table, type)) length = @prop_header_length + byte_size(instructions_bin) @@ -209,8 +226,9 @@ defmodule Openflow.Multipart.TableFeatures.Body do body = <> encode_props(<>, table, rest) end - defp encode_props(acc, table, [type|rest]) - when type == :next_tables or type == :next_tables_miss do + + defp encode_props(acc, table, [type | rest]) + when type == :next_tables or type == :next_tables_miss do type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) next_tables_bin = to_string(Map.get(table, type)) length = @prop_header_length + byte_size(next_tables_bin) @@ -218,11 +236,10 @@ defmodule Openflow.Multipart.TableFeatures.Body do body = <> encode_props(<>, table, rest) end - defp encode_props(acc, table, [type|rest]) - when (type == :write_actions or - type == :write_actions_miss or - type == :apply_actions or - type == :apply_actions_miss) do + + defp encode_props(acc, table, [type | rest]) + when type == :write_actions or type == :write_actions_miss or type == :apply_actions or + type == :apply_actions_miss do type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) actions_bin = encode_actions("", Map.get(table, type)) length = @prop_header_length + byte_size(actions_bin) @@ -230,13 +247,11 @@ defmodule Openflow.Multipart.TableFeatures.Body do body = <> encode_props(<>, table, rest) end - defp encode_props(acc, table, [type|rest]) - when (type == :match or - type == :wildcards or - type == :write_setfield or - type == :write_setfield_miss or - type == :apply_setfield or - type == :apply_setfield_miss) do + + defp encode_props(acc, table, [type | rest]) + when type == :match or type == :wildcards or type == :write_setfield or + type == :write_setfield_miss or type == :apply_setfield or + type == :apply_setfield_miss do type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) matches_bin = encode_matches("", Map.get(table, type)) length = @prop_header_length + byte_size(matches_bin) @@ -246,51 +261,61 @@ defmodule Openflow.Multipart.TableFeatures.Body do end defp decode_instructions(acc, ""), do: Enum.reverse(acc) - defp decode_instructions(acc, <<0xffff::16, _::16, exp_id::32, rest::bytes>>) do - decode_instructions([Openflow.Instruction.Experimenter.new(exp_id)|acc], rest) + + defp decode_instructions(acc, <<0xFFFF::16, _::16, exp_id::32, rest::bytes>>) do + decode_instructions([Openflow.Instruction.Experimenter.new(exp_id) | acc], rest) end + defp decode_instructions(acc, <>) do instruction = Openflow.Enums.to_atom(type_int, :instruction_type) - decode_instructions([instruction|acc], rest) + decode_instructions([instruction | acc], rest) end defp encode_instructions(acc, []), do: acc - defp encode_instructions(acc, [%Openflow.Instruction.Experimenter{exp_id: exp_id}|rest]) do - encode_instructions(<>, rest) + + defp encode_instructions(acc, [%Openflow.Instruction.Experimenter{exp_id: exp_id} | rest]) do + encode_instructions(<>, rest) end - defp encode_instructions(acc, [type|rest]) do + + defp encode_instructions(acc, [type | rest]) do type_int = Openflow.Enums.to_int(type, :instruction_type) encode_instructions(<>, rest) end defp decode_actions(acc, ""), do: Enum.reverse(acc) - defp decode_actions(acc, <<0xffff::16, _::16, exp_id::32, rest::bytes>>) do - decode_actions([Openflow.Action.Experimenter.new(exp_id)|acc], rest) + + defp decode_actions(acc, <<0xFFFF::16, _::16, exp_id::32, rest::bytes>>) do + decode_actions([Openflow.Action.Experimenter.new(exp_id) | acc], rest) end + defp decode_actions(acc, <>) do action = Openflow.Enums.to_atom(type_int, :action_type) - decode_actions([action|acc], rest) + decode_actions([action | acc], rest) end defp encode_actions(acc, []), do: acc - defp encode_actions(acc, [%Openflow.Action.Experimenter{exp_id: exp_id}|rest]) do - encode_actions(<>, rest) + + defp encode_actions(acc, [%Openflow.Action.Experimenter{exp_id: exp_id} | rest]) do + encode_actions(<>, rest) end - defp encode_actions(acc, [type|rest]) do + + defp encode_actions(acc, [type | rest]) do type_int = Openflow.Enums.to_int(type, :action_type) encode_actions(<>, rest) end defp decode_matches(acc, ""), do: Enum.reverse(acc) + defp decode_matches(acc, binary) do length = Openflow.Match.header_size(binary) <> = binary field = Openflow.Match.codec_header(header_bin) - decode_matches([field|acc], rest) + decode_matches([field | acc], rest) end defp encode_matches(acc, []), do: acc - defp encode_matches(acc, [field|rest]) do + + defp encode_matches(acc, [field | rest]) do header_bin = Openflow.Match.codec_header(field) encode_matches(<>, rest) end diff --git a/lib/openflow/multipart/table_features/reply.ex b/lib/openflow/multipart/table_features/reply.ex index 0d3c834..f44f4fa 100644 --- a/lib/openflow/multipart/table_features/reply.ex +++ b/lib/openflow/multipart/table_features/reply.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.TableFeatures.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - tables: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + tables: [] ) alias __MODULE__ @@ -30,12 +31,15 @@ defmodule Openflow.Multipart.TableFeatures.Reply do end def append_body(%Reply{tables: tables} = message, %Reply{flags: [:more], tables: continue}) do - %{message|tables: [continue|tables]} + %{message | tables: [continue | tables]} end + def append_body(%Reply{tables: tables} = message, %Reply{flags: [], tables: continue}) do - new_tables = [continue|tables] - |> Enum.reverse - |> List.flatten - %{message|tables: new_tables} + new_tables = + [continue | tables] + |> Enum.reverse() + |> List.flatten() + + %{message | tables: new_tables} end end diff --git a/lib/openflow/multipart/table_features/request.ex b/lib/openflow/multipart/table_features/request.ex index 3259c5d..b4b9fad 100644 --- a/lib/openflow/multipart/table_features/request.ex +++ b/lib/openflow/multipart/table_features/request.ex @@ -1,11 +1,12 @@ defmodule Openflow.Multipart.TableFeatures.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: nil, - flags: [], - tables: [] + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + tables: [] ) alias __MODULE__ @@ -30,12 +31,15 @@ defmodule Openflow.Multipart.TableFeatures.Request do end def append_body(%Request{tables: tables} = message, %Request{flags: [:more], tables: continue}) do - %{message|tables: [continue|tables]} + %{message | tables: [continue | tables]} end + def append_body(%Request{tables: tables} = message, %Request{flags: [], tables: continue}) do - new_tables = [continue|tables] - |> Enum.reverse - |> List.flatten - %{message|tables: new_tables} + new_tables = + [continue | tables] + |> Enum.reverse() + |> List.flatten() + + %{message | tables: new_tables} end end diff --git a/lib/openflow/nx_packet_in2.ex b/lib/openflow/nx_packet_in2.ex index dfa8b34..77955be 100644 --- a/lib/openflow/nx_packet_in2.ex +++ b/lib/openflow/nx_packet_in2.ex @@ -1,26 +1,26 @@ defmodule Openflow.NxPacketIn2 do defstruct( - version: 4, - xid: 0, - datapath_id: "", - aux_id: 0, + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, # packet_in properties: - packet: nil, - full_len: nil, - buffer_id: nil, - table_id: nil, - cookie: nil, - reason: nil, - metadata: nil, - userdata: nil, + packet: nil, + full_len: nil, + buffer_id: nil, + table_id: nil, + cookie: nil, + reason: nil, + metadata: nil, + userdata: nil, # continuation properties: - continuation_bridge: "", - continuation_stack: [], + continuation_bridge: "", + continuation_stack: [], continuation_conntracked: false, - continuation_table_id: nil, - continuation_cookie: nil, - continuation_actions: [], - continuation_action_set: nil + continuation_table_id: nil, + continuation_cookie: nil, + continuation_actions: [], + continuation_action_set: nil ) alias __MODULE__ @@ -28,24 +28,24 @@ defmodule Openflow.NxPacketIn2 do @experimenter 0x00002320 @nx_type 30 - @packet 0 - @full_len 1 - @buffer_id 2 - @table_id 3 - @cookie 4 - @reason 5 - @metadata 6 - @userdata 7 + @packet 0 + @full_len 1 + @buffer_id 2 + @table_id 3 + @cookie 4 + @reason 5 + @metadata 6 + @userdata 7 @continuation 8 - @nxcpt_bridge 0x8000 - @nxcpt_stack 0x8001 - @nxcpt_mirrors 0x8002 + @nxcpt_bridge 0x8000 + @nxcpt_stack 0x8001 + @nxcpt_mirrors 0x8002 @nxcpt_conntracked 0x8003 - @nxcpt_table_id 0x8004 - @nxcpt_cookie 0x8005 - @nxcpt_actions 0x8006 - @nxcpt_action_set 0x8007 + @nxcpt_table_id 0x8004 + @nxcpt_cookie 0x8005 + @nxcpt_actions 0x8006 + @nxcpt_action_set 0x8007 @prop_header_length 4 @@ -59,52 +59,66 @@ defmodule Openflow.NxPacketIn2 do ## private functions defp decode_props(pktin, ""), do: pktin + defp decode_props(pktin, <<@packet::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) packet_length = length - @prop_header_length <> = tail - decode_props(%{pktin|packet: packet}, rest) + decode_props(%{pktin | packet: packet}, rest) end + defp decode_props(pktin, <<@full_len::16, _length::16, full_len::32, rest::bytes>>) do - decode_props(%{pktin|full_len: full_len}, rest) + decode_props(%{pktin | full_len: full_len}, rest) end + defp decode_props(pktin, <<@buffer_id::16, _length::16, buffer_id::32, rest::bytes>>) do - decode_props(%{pktin|buffer_id: buffer_id}, rest) + decode_props(%{pktin | buffer_id: buffer_id}, rest) end + defp decode_props(pktin, <<@table_id::16, _length::16, table_id::8, _::24, rest::bytes>>) do - decode_props(%{pktin|table_id: table_id}, rest) + decode_props(%{pktin | table_id: table_id}, rest) end + defp decode_props(pktin, <<@cookie::16, _length::16, _::32, cookie::64, rest::bytes>>) do - decode_props(%{pktin|cookie: cookie}, rest) + decode_props(%{pktin | cookie: cookie}, rest) end + defp decode_props(pktin, <<@reason::16, _length::16, reason_int::8, _::24, rest::bytes>>) do reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason) - decode_props(%{pktin|reason: reason}, rest) + decode_props(%{pktin | reason: reason}, rest) end + defp decode_props(pktin, <<@metadata::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) match_field_length = length - @prop_header_length - <> = tail + + <> = + tail + match_len = 4 + byte_size(match_fields_bin) padding = Openflow.Utils.pad_length(match_len, 8) - match_bin = (<<1::16, match_len::16, match_fields_bin::bytes, 0::size(padding)-unit(8)>>) + match_bin = <<1::16, match_len::16, match_fields_bin::bytes, 0::size(padding)-unit(8)>> {fields, _rest} = Openflow.Match.read(match_bin) - decode_props(%{pktin|metadata: fields}, rest) + decode_props(%{pktin | metadata: fields}, rest) end + defp decode_props(pktin, <<@userdata::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) userdata_length = length - @prop_header_length <> = tail - decode_props(%{pktin|userdata: userdata}, rest) + decode_props(%{pktin | userdata: userdata}, rest) end + defp decode_props(pktin, <<@continuation::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length - 4 <<_pad::32, data::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail + pktin |> decode_continuations(data) |> decode_props(rest) end + defp decode_props(pktin, <<_::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length @@ -113,52 +127,64 @@ defmodule Openflow.NxPacketIn2 do end defp decode_continuations(pktin, ""), do: pktin + defp decode_continuations(pktin, <<@nxcpt_bridge::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length <> = tail - decode_continuations(%{pktin|continuation_bridge: bridge}, rest) + decode_continuations(%{pktin | continuation_bridge: bridge}, rest) end + defp decode_continuations(pktin, <<@nxcpt_stack::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = (length - @prop_header_length) * 8 <> = tail - decode_continuations(%{pktin|continuation_stack: pktin.continuation_stack ++ [stack]}, rest) + decode_continuations(%{pktin | continuation_stack: pktin.continuation_stack ++ [stack]}, rest) end + defp decode_continuations(pktin, <<@nxcpt_mirrors::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length <> = tail - decode_continuations(%{pktin|continuation_mirrors: mirrors}, rest) + decode_continuations(%{pktin | continuation_mirrors: mirrors}, rest) end + defp decode_continuations(pktin, <<@nxcpt_conntracked::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length <<_::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail - decode_continuations(%{pktin|continuation_conntracked: true}, rest) + decode_continuations(%{pktin | continuation_conntracked: true}, rest) end + defp decode_continuations(pktin, <<@nxcpt_table_id::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) <> = tail - decode_continuations(%{pktin|continuation_table_id: table_id}, rest) + decode_continuations(%{pktin | continuation_table_id: table_id}, rest) end + defp decode_continuations(pktin, <<@nxcpt_cookie::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) <> = tail - decode_continuations(%{pktin|continuation_cookie: cookie}, rest) + decode_continuations(%{pktin | continuation_cookie: cookie}, rest) end + defp decode_continuations(pktin, <<@nxcpt_actions::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length - 4 - <<_pad::32, actions::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail - decode_continuations(%{pktin|continuation_actions: Openflow.Action.read(actions)}, rest) + + <<_pad::32, actions::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = + tail + + decode_continuations(%{pktin | continuation_actions: Openflow.Action.read(actions)}, rest) end + defp decode_continuations(pktin, <<@nxcpt_action_set::16, length::16, tail::bytes>>) do pad_length = Openflow.Utils.pad_length(length, 8) data_length = length - @prop_header_length <> = tail - decode_continuations(%{pktin|continuation_action_set: action_set}, rest) + decode_continuations(%{pktin | continuation_action_set: action_set}, rest) end + defp decode_continuations(pktin, _) do decode_continuations(pktin, "") end diff --git a/lib/openflow/nx_packet_in_format.ex b/lib/openflow/nx_packet_in_format.ex index c5f2dd5..e42b570 100644 --- a/lib/openflow/nx_packet_in_format.ex +++ b/lib/openflow/nx_packet_in_format.ex @@ -1,9 +1,9 @@ defmodule Openflow.NxSetPacketInFormat do defstruct( - version: 4, - xid: 0, + version: 4, + xid: 0, datapath_id: "", - aux_id: 0, + aux_id: 0, format: :standard ) diff --git a/lib/openflow/nx_set_controller_id.ex b/lib/openflow/nx_set_controller_id.ex index de9c95e..f249960 100644 --- a/lib/openflow/nx_set_controller_id.ex +++ b/lib/openflow/nx_set_controller_id.ex @@ -1,8 +1,8 @@ defmodule Openflow.NxSetControllerId do defstruct( version: 4, - xid: 0, - id: 0 + xid: 0, + id: 0 ) @experimenter 0x00002320 diff --git a/lib/openflow/packet_in.ex b/lib/openflow/packet_in.ex index 415aa92..2d436e8 100644 --- a/lib/openflow/packet_in.ex +++ b/lib/openflow/packet_in.ex @@ -3,23 +3,25 @@ defmodule Openflow.PacketIn do version: 4, xid: 0, datapath_id: "", - aux_id: 0, - buffer_id: :no_buffer, - total_len: 0, - reason: :no_match, - table_id: 0, - cookie: 0, - in_port: :controller, - match: [], - data: "" + aux_id: 0, + buffer_id: :no_buffer, + total_len: 0, + reason: :no_match, + table_id: 0, + cookie: 0, + in_port: :controller, + match: [], + data: "" ) alias __MODULE__ def ofp_type, do: 10 - def read(<>) do + def read( + <> + ) do buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id) reason = Openflow.Utils.get_enum(reason_int, :packet_in_reason) table_id = Openflow.Utils.get_enum(table_id_int, :table_id) @@ -27,34 +29,41 @@ defmodule Openflow.PacketIn do <<_pad::size(2)-unit(8), data::bytes>> = rest1 in_port = Keyword.get(match_fields0, :in_port, :any) match_fields = Keyword.delete(match_fields0, :in_port) - %PacketIn{buffer_id: buffer_id, - total_len: total_len, - reason: reason, - table_id: table_id, - cookie: cookie, - in_port: in_port, - match: match_fields, - data: data} + + %PacketIn{ + buffer_id: buffer_id, + total_len: total_len, + reason: reason, + table_id: table_id, + cookie: cookie, + in_port: in_port, + match: match_fields, + data: data + } end def to_binary(%PacketIn{} = packet_in) do - %PacketIn{buffer_id: buffer_id, - total_len: total_len, - reason: reason, - table_id: table_id, - cookie: cookie, - in_port: in_port, - match: match_fields, - data: data} = packet_in + %PacketIn{ + buffer_id: buffer_id, + total_len: total_len, + reason: reason, + table_id: table_id, + cookie: cookie, + in_port: in_port, + match: match_fields, + data: data + } = packet_in + buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id) reason_int = Openflow.Utils.get_enum(reason, :packet_in_reason) table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + match_fields_bin = - [{:in_port, in_port}|match_fields] - |> Openflow.Match.new - |> Openflow.Match.to_binary - <> + [{:in_port, in_port} | match_fields] + |> Openflow.Match.new() + |> Openflow.Match.to_binary() + + <> end end diff --git a/lib/openflow/packet_out.ex b/lib/openflow/packet_out.ex index dcadd43..42ca76b 100644 --- a/lib/openflow/packet_out.ex +++ b/lib/openflow/packet_out.ex @@ -3,11 +3,11 @@ defmodule Openflow.PacketOut do version: 4, xid: 0, datapath_id: "", - aux_id: 0, - buffer_id: :no_buffer, - in_port: :controller, - actions: [], - data: "" + aux_id: 0, + buffer_id: :no_buffer, + in_port: :controller, + actions: [], + data: "" ) alias __MODULE__ @@ -19,32 +19,26 @@ defmodule Openflow.PacketOut do in_port = Keyword.get(options, :in_port, :controller) actions = Keyword.get(options, :actions, []) data = Keyword.get(options, :data, "") - %PacketOut{buffer_id: buffer_id, - in_port: in_port, - actions: actions, - data: data} + %PacketOut{buffer_id: buffer_id, in_port: in_port, actions: actions, data: data} end - def read(<>) do + def read( + <> + ) do buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id) in_port = Openflow.Utils.get_enum(in_port_int, :openflow13_port_no) actions = Openflow.Action.read(actions_bin) - %PacketOut{buffer_id: buffer_id, - in_port: in_port, - actions: actions, - data: data} + %PacketOut{buffer_id: buffer_id, in_port: in_port, actions: actions, data: data} end def to_binary(%PacketOut{} = packet_out) do - %PacketOut{buffer_id: buffer_id, - in_port: in_port, - actions: actions, - data: data} = packet_out + %PacketOut{buffer_id: buffer_id, in_port: in_port, actions: actions, data: data} = packet_out buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id) in_port_int = Openflow.Utils.get_enum(in_port, :openflow13_port_no) actions_bin = Openflow.Action.to_binary(actions) actions_len = byte_size(actions_bin) + <> end diff --git a/lib/openflow/port.ex b/lib/openflow/port.ex index 1f71180..099b0bc 100644 --- a/lib/openflow/port.ex +++ b/lib/openflow/port.ex @@ -2,27 +2,27 @@ defmodule Openflow.Port do defstruct( number: 0, hw_addr: "000000000000", - name: "", + name: "", config: [], - state: [], - current_features: [], + state: [], + current_features: [], advertised_features: [], - supported_features: [], - peer_features: [], + supported_features: [], + peer_features: [], current_speed: :"10mb_hd", - max_speed: :"10mb_hd" + max_speed: :"10mb_hd" ) @ofp_max_port_name_len 16 alias __MODULE__ - def read(<>) do + def read( + <> + ) do port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) hw_addr = Openflow.Utils.to_hex_string(hw_addr_bin) name = Openflow.Utils.decode_string(name_bin) @@ -32,16 +32,19 @@ defmodule Openflow.Port do adv = Openflow.Enums.int_to_flags(advertised_int, :port_features) supp = Openflow.Enums.int_to_flags(supp_int, :port_features) peer = Openflow.Enums.int_to_flags(peer_int, :port_features) - %Port{number: port_no, - hw_addr: hw_addr, - name: name, - config: config, - state: state, - current_features: curr, - advertised_features: adv, - supported_features: supp, - peer_features: peer, - current_speed: curr_speed, - max_speed: max_speed} + + %Port{ + number: port_no, + hw_addr: hw_addr, + name: name, + config: config, + state: state, + current_features: curr, + advertised_features: adv, + supported_features: supp, + peer_features: peer, + current_speed: curr_speed, + max_speed: max_speed + } end end diff --git a/lib/openflow/port_mod.ex b/lib/openflow/port_mod.ex index 01506f5..2a8ff57 100644 --- a/lib/openflow/port_mod.ex +++ b/lib/openflow/port_mod.ex @@ -1,14 +1,14 @@ defmodule Openflow.PortMod do defstruct( - version: 4, - xid: 0, + version: 4, + xid: 0, datapath_id: "", - aux_id: 0, - number: 0, - hw_addr: "000000000000", - config: [], - mask: [], - advertise: [] + aux_id: 0, + number: 0, + hw_addr: "000000000000", + config: [], + mask: [], + advertise: [] ) alias __MODULE__ @@ -24,9 +24,10 @@ defmodule Openflow.PortMod do %PortMod{number: port_no, hw_addr: hw_addr, config: config, mask: mask, advertise: advertise} end - def read(<>) do + def read( + <> + ) do port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) hw_addr = Openflow.Utils.to_hex_string(hw_addr_bin) config = Openflow.Enums.int_to_flags(config_int, :port_config) @@ -35,14 +36,20 @@ defmodule Openflow.PortMod do %PortMod{number: port_no, hw_addr: hw_addr, config: config, mask: mask, advertise: adv} end - def to_binary(%PortMod{number: port_no, hw_addr: hw_addr, config: config, mask: mask, advertise: adv}) do + def to_binary(%PortMod{ + number: port_no, + hw_addr: hw_addr, + config: config, + mask: mask, + advertise: adv + }) do port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no) - hw_addr_bin = <<(String.to_integer(hw_addr, 16))::48>> + hw_addr_bin = <> config_int = Openflow.Enums.flags_to_int(config, :port_config) mask_int = Openflow.Enums.flags_to_int(mask, :port_config) advertised_int = Openflow.Enums.flags_to_int(adv, :port_features) - <> + + <> end end diff --git a/lib/openflow/port_status.ex b/lib/openflow/port_status.ex index 83ea182..9b92554 100644 --- a/lib/openflow/port_status.ex +++ b/lib/openflow/port_status.ex @@ -1,11 +1,11 @@ defmodule Openflow.PortStatus do defstruct( - version: 4, - xid: 0, + version: 4, + xid: 0, datapath_id: "", - aux_id: 0, - reason: :add, - port: nil + aux_id: 0, + reason: :add, + port: nil ) alias __MODULE__ diff --git a/lib/openflow/role/reply.ex b/lib/openflow/role/reply.ex index 9e81329..0480a0f 100644 --- a/lib/openflow/role/reply.ex +++ b/lib/openflow/role/reply.ex @@ -1,9 +1,11 @@ defmodule Openflow.Role.Reply do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, role: :nochange, generation_id: 0 ) diff --git a/lib/openflow/role/request.ex b/lib/openflow/role/request.ex index e2ed43e..fcb66f1 100644 --- a/lib/openflow/role/request.ex +++ b/lib/openflow/role/request.ex @@ -1,9 +1,11 @@ defmodule Openflow.Role.Request do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0, # virtual field + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, role: :nochange, generation_id: 0 ) diff --git a/lib/openflow/set_async.ex b/lib/openflow/set_async.ex index fb245d8..717d644 100644 --- a/lib/openflow/set_async.ex +++ b/lib/openflow/set_async.ex @@ -1,40 +1,46 @@ defmodule Openflow.SetAsync do defstruct( - version: 4, - xid: 0, - datapath_id: nil, # virtual field - aux_id: 0, # virtual field - packet_in_mask_master: 0, - packet_in_mask_slave: 0, - port_status_mask_master: 0, - port_status_mask_slave: 0, + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, + packet_in_mask_master: 0, + packet_in_mask_slave: 0, + port_status_mask_master: 0, + port_status_mask_slave: 0, flow_removed_mask_master: 0, - flow_removed_mask_slave: 0 + flow_removed_mask_slave: 0 ) alias __MODULE__ def ofp_type, do: 28 - def read(<>) do - %SetAsync{packet_in_mask_master: packet_in_mask_master, - packet_in_mask_slave: packet_in_mask_slave, - port_status_mask_master: port_status_mask_master, - port_status_mask_slave: port_status_mask_slave, - flow_removed_mask_master: flow_removed_mask_master, - flow_removed_mask_slave: flow_removed_mask_slave} + def read( + <> + ) do + %SetAsync{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + 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 - def to_binary(%SetAsync{packet_in_mask_master: packet_in_mask_master, - packet_in_mask_slave: packet_in_mask_slave, - port_status_mask_master: port_status_mask_master, - port_status_mask_slave: port_status_mask_slave, - flow_removed_mask_master: flow_removed_mask_master, - flow_removed_mask_slave: flow_removed_mask_slave}) do - <> + def to_binary(%SetAsync{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + port_status_mask_slave: port_status_mask_slave, + flow_removed_mask_master: flow_removed_mask_master, + flow_removed_mask_slave: flow_removed_mask_slave + }) do + <> end end diff --git a/lib/openflow/set_config.ex b/lib/openflow/set_config.ex index 0a08ff5..18f3a8c 100644 --- a/lib/openflow/set_config.ex +++ b/lib/openflow/set_config.ex @@ -1,10 +1,11 @@ defmodule Openflow.SetConfig do defstruct( - version: 4, - xid: 0, - datapath_id: "", - aux_id: 0, - flags: [], # default = "normal" is no special handling + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # default = "normal" is no special handling + flags: [], miss_send_len: 128 ) diff --git a/lib/openflow/table_mod.ex b/lib/openflow/table_mod.ex index d06f45b..2ea364a 100644 --- a/lib/openflow/table_mod.ex +++ b/lib/openflow/table_mod.ex @@ -1,11 +1,11 @@ defmodule Openflow.TableMod do defstruct( - version: 4, - xid: 0, + version: 4, + xid: 0, datapath_id: "", - aux_id: 0, - table_id: 0, - config: 0 + aux_id: 0, + table_id: 0, + config: 0 ) alias __MODULE__ diff --git a/lib/openflow/utils.ex b/lib/openflow/utils.ex index afe8cf8..79456f0 100644 --- a/lib/openflow/utils.ex +++ b/lib/openflow/utils.ex @@ -1,16 +1,19 @@ defmodule Openflow.Utils do import Bitwise - def int_to_flags(acc, int, [{type, flagint}|rest]) when (int &&& flagint) == flagint do - int_to_flags([type|acc], int, rest) + def int_to_flags(acc, int, [{type, flagint} | rest]) when (int &&& flagint) == flagint do + int_to_flags([type | acc], int, rest) end - def int_to_flags(acc, int, [_h|rest]) do + + def int_to_flags(acc, int, [_h | rest]) do int_to_flags(acc, int, rest) end + def int_to_flags(acc, _int, []), do: Enum.reverse(acc) def flags_to_int(acc, [], _enum), do: acc - def flags_to_int(acc0, [flag|rest], enum) do + + def flags_to_int(acc0, [flag | rest], enum) do acc = acc0 ||| Keyword.get(enum, flag, 0) flags_to_int(acc, rest, enum) end @@ -18,14 +21,14 @@ defmodule Openflow.Utils do def to_hex_string(binary), do: datapath_id(binary) def padding(length, padding) do - case (padding - rem(length, padding)) do + case padding - rem(length, padding) do ^padding -> 0 - pad_len -> pad_len + pad_len -> pad_len end end def pad_length(length, width) do - rem((width - rem(length, width)), width) + rem(width - rem(length, width), width) end def decode_string(binary) do @@ -43,6 +46,7 @@ defmodule Openflow.Utils do :bad_enum -> int end end + def get_enum(int, type) do try do Openflow.Enums.to_int(int, type) @@ -57,7 +61,7 @@ defmodule Openflow.Utils do binary |> split_to_hex_string |> Enum.join("") - |> String.downcase + |> String.downcase() end defp split_to_hex_string(binary) do @@ -67,7 +71,7 @@ defmodule Openflow.Utils do defp integer_to_hex(int) do case Integer.to_string(int, 16) do <> -> <<48, d>> - dd -> dd + dd -> dd end end end diff --git a/lib/ovsdb/open_vswitch.ex b/lib/ovsdb/open_vswitch.ex index 67baaa9..43b15ca 100644 --- a/lib/ovsdb/open_vswitch.ex +++ b/lib/ovsdb/open_vswitch.ex @@ -2,21 +2,19 @@ defmodule OVSDB.OpenvSwitch do use GenServer defmodule State do - defstruct [ - server: nil, - client_pid: nil, - monitor_pid: nil, - ovs_uuid: nil - ] + defstruct server: nil, + client_pid: nil, + monitor_pid: nil, + ovs_uuid: nil end @database "Open_vSwitch" @open_vswitch "Open_vSwitch" - @interface "Interface" - @port "Port" - @controller "Controller" - @bridge "Bridge" + @interface "Interface" + @port "Port" + @controller "Controller" + @bridge "Bridge" def start_link(server) do GenServer.start_link(__MODULE__, [server]) @@ -28,13 +26,15 @@ defmodule OVSDB.OpenvSwitch do def add_br(pid, bridge, options \\ []) do br_uuids = GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"}) + add_br_options = [ - bridge: bridge, + bridge: bridge, controller: options[:controller] || "tcp:127.0.0.1:6653", - protocol: options[:protocol] || "OpenFlow13", - fail_mode: options[:fail_mode] || "standalone", - br_uuids: br_uuids + protocol: options[:protocol] || "OpenFlow13", + fail_mode: options[:fail_mode] || "standalone", + br_uuids: br_uuids ] + GenServer.call(pid, {:add_br, add_br_options}) end @@ -44,92 +44,120 @@ defmodule OVSDB.OpenvSwitch do new_bridges = case GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"}) do ["set", bridges] -> %{"bridges" => ["set", bridges -- [uuid]]} - ^uuid -> %{"bridges" => ["set", []]} - curr_bridges -> %{"bridges" => curr_bridges} + ^uuid -> %{"bridges" => ["set", []]} + curr_bridges -> %{"bridges" => curr_bridges} end + GenServer.call(pid, {:del_br, new_bridges}) + :not_found -> {:error, :not_found} end end def init([server]) do - state = server - |> String.to_charlist - |> init_client + state = + server + |> String.to_charlist() + |> init_client + {:ok, state} end def handle_call({:sync_get, table, col_name}, _from, state) do - [%{"rows" => [%{^col_name => values}|_]}] = + [%{"rows" => [%{^col_name => values} | _]}] = [col_name] |> :eovsdb_op.select(table, []) |> xact(state.client_pid) + {:reply, values, state} end + def handle_call({:add_br, options}, _from, state) do %State{client_pid: pid, ovs_uuid: ovs} = state br_iface = %{name: options[:bridge], type: :internal} br_port = %{name: options[:bridge], interfaces: ["named-uuid", "brinterface"]} controller = %{target: options[:controller]} + new_bridge = %{ - name: options[:bridge], - ports: ["named-uuid", "brport"], + name: options[:bridge], + ports: ["named-uuid", "brport"], controller: ["named-uuid", "brcontroller"], - fail_mode: options[:fail_mode], - protocols: options[:protocol] + fail_mode: options[:fail_mode], + protocols: options[:protocol] } + named_uuid = ["named-uuid", "bridge"] + new_bridges = case options[:br_uuids] do - ["set", []] -> %{bridges: named_uuid} - ["set", bridges] -> %{bridges: ["set", bridges ++ [named_uuid]]} + ["set", []] -> %{bridges: named_uuid} + ["set", bridges] -> %{bridges: ["set", bridges ++ [named_uuid]]} ["uuid", _] = bridge -> %{bridges: ["set", [bridge] ++ [named_uuid]]} end + next_config = [{"next_cfg", "+=", 1}] eq_ovs_uuid = [{"_uuid", "==", ovs}] - replies = xact([ - :eovsdb_op.insert(@interface, br_iface, "brinterface"), - :eovsdb_op.insert(@port, br_port, "brport"), - :eovsdb_op.insert(@controller, controller, "brcontroller"), - :eovsdb_op.insert(@bridge, new_bridge, "bridge"), - :eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges), - :eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config) - ], pid) + + replies = + xact( + [ + :eovsdb_op.insert(@interface, br_iface, "brinterface"), + :eovsdb_op.insert(@port, br_port, "brport"), + :eovsdb_op.insert(@controller, controller, "brcontroller"), + :eovsdb_op.insert(@bridge, new_bridge, "bridge"), + :eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges), + :eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config) + ], + pid + ) + {:reply, replies, state} end + def handle_call({:del_br, new_bridges}, _from, state) do %State{client_pid: pid, ovs_uuid: ovs} = state eq_ovs_uuid = [{"_uuid", "==", ovs}] next_config = [{"next_cfg", "+=", 1}] - replies = xact([ - :eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges), - :eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config) - ], pid) + + replies = + xact( + [ + :eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges), + :eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config) + ], + pid + ) + {:reply, replies, state} end + def handle_call({:find_by_name, table, name}, _from, state) do %State{client_pid: pid} = state query = :eovsdb_op.select('*', table, [{"name", "==", name}]) - reply = case xact(query, pid) do - [%{"rows" => []}] -> :not_found - [%{"rows" => [row]}] -> row - end + + reply = + case xact(query, pid) do + [%{"rows" => []}] -> :not_found + [%{"rows" => [row]}] -> row + end + {:reply, reply, state} end def handle_cast({:async_get, "_uuid"}, state) do - [%{"rows" => [%{"_uuid" => values}|_]}] = + [%{"rows" => [%{"_uuid" => values} | _]}] = ["_uuid"] |> :eovsdb_op.select(@open_vswitch, []) |> xact(state.client_pid) - {:noreply, %{state|ovs_uuid: values}} + + {:noreply, %{state | ovs_uuid: values}} end # private functions defp init_client(server) do - {:ok, pid} = :eovsdb_client.connect(server, [database: @database]) + {:ok, pid} = :eovsdb_client.connect(server, database: @database) :eovsdb_client.regist_schema(pid) :ok = GenServer.cast(self(), {:async_get, "_uuid"}) %State{server: server, client_pid: pid} @@ -139,6 +167,7 @@ defmodule OVSDB.OpenvSwitch do {:ok, res} = :eovsdb_client.transaction(pid, query) res end + defp xact(query, pid) when is_map(query) do xact([query], pid) end diff --git a/lib/tres/application.ex b/lib/tres/application.ex index 5af2b67..f5ecd20 100644 --- a/lib/tres/application.ex +++ b/lib/tres/application.ex @@ -8,12 +8,16 @@ defmodule Tres.Application do def start(_type, _args) do import Supervisor.Spec - {cb_mod, _cb_args} = Tres.Utils.get_callback_module - children = [worker(Registry, [[keys: :unique, name: SwitchRegistry]], id: SwitchRegistry), - supervisor(Tres.MessageHandlerSup, [cb_mod], id: MessageHandlerSup), - supervisor(OVSDB, [], id: OVSDB)] + {cb_mod, _cb_args} = Tres.Utils.get_callback_module() + + children = [ + worker(Registry, [[keys: :unique, name: SwitchRegistry]], id: SwitchRegistry), + supervisor(Tres.MessageHandlerSup, [cb_mod], id: MessageHandlerSup), + supervisor(OVSDB, [], id: OVSDB) + ] + opts = [strategy: :one_for_one, name: Tres.Supervisor] - {:ok, _connection_pid} = Tres.Utils.start_openflow_listener + {:ok, _connection_pid} = Tres.Utils.start_openflow_listener() Supervisor.start_link(children, opts) end end diff --git a/lib/tres/example_handler.ex b/lib/tres/example_handler.ex index ded3129..5e9a7b7 100644 --- a/lib/tres/example_handler.ex +++ b/lib/tres/example_handler.ex @@ -5,11 +5,9 @@ defmodule Tres.ExampleHandler do import Logger defmodule State do - defstruct [ - datapath_id: nil, - aux_id: nil, - conn_ref: nil - ] + defstruct datapath_id: nil, + aux_id: nil, + conn_ref: nil end def start_link(datapath, args) do @@ -17,10 +15,11 @@ defmodule Tres.ExampleHandler do end def init([{datapath_id, aux_id}, _args]) do - info("[#{__MODULE__}] Switch Ready: " - <> "datapath_id: #{datapath_id} " - <> "aux_id: #{aux_id} " - <> "on #{inspect(self())}") + info( + "[#{__MODULE__}] Switch Ready: " <> + "datapath_id: #{datapath_id} " <> "aux_id: #{aux_id} " <> "on #{inspect(self())}" + ) + _ = send_desc_stats_request(datapath_id) _ = send_port_desc_stats_request(datapath_id) state = %State{datapath_id: datapath_id, aux_id: aux_id} @@ -31,18 +30,24 @@ defmodule Tres.ExampleHandler do handle_port_desc_stats_reply(desc, datapath_id) {:noreply, state} end + def handle_info(%Desc.Reply{datapath_id: datapath_id} = desc, state) do handle_desc_stats_reply(desc, datapath_id) {:noreply, state} end + def handle_info({:switch_disconnected, reason}, state) do - :ok = warn("[#{__MODULE__}] Switch Disconnected: datapath_id: #{state.datapath_id} by #{reason}") + :ok = + warn("[#{__MODULE__}] Switch Disconnected: datapath_id: #{state.datapath_id} by #{reason}") + {:stop, :normal, state} end + def handle_info({:switch_hang, _datapath_id}, state) do :ok = warn("[#{__MODULE__}] Switch possible hang: datapath_id: #{state.datapath_id}") {:noreply, state} end + # `Catch all` function is required. def handle_info(info, state) do :ok = warn("[#{__MODULE__}] unhandled message #{inspect(info)}: #{state.datapath_id}") @@ -52,35 +57,32 @@ defmodule Tres.ExampleHandler do # private functions defp send_desc_stats_request(datapath_id) do - Desc.Request.new + Desc.Request.new() |> send_message(datapath_id) end defp send_port_desc_stats_request(datapath_id) do - PortDesc.Request.new + PortDesc.Request.new() |> send_message(datapath_id) end defp handle_desc_stats_reply(desc, datapath_id) do info( - "[#{__MODULE__}] Switch Desc: " - <> "mfr = #{desc.mfr_desc} " - <> "hw = #{desc.hw_desc} " - <> "sw = #{desc.sw_desc} " - <> "for #{datapath_id}" + "[#{__MODULE__}] Switch Desc: " <> + "mfr = #{desc.mfr_desc} " <> + "hw = #{desc.hw_desc} " <> "sw = #{desc.sw_desc} " <> "for #{datapath_id}" ) end defp handle_port_desc_stats_reply(port_desc, datapath_id) do for port <- port_desc.ports do info( - "[#{__MODULE__}] Switch has port: " - <> "number = #{port.number} " - <> "hw_addr = #{port.hw_addr} " - <> "name = #{port.name} " - <> "config = #{inspect(port.config)} " - <> "current_speed = #{port.current_speed} " - <> "on #{datapath_id}" + "[#{__MODULE__}] Switch has port: " <> + "number = #{port.number} " <> + "hw_addr = #{port.hw_addr} " <> + "name = #{port.name} " <> + "config = #{inspect(port.config)} " <> + "current_speed = #{port.current_speed} " <> "on #{datapath_id}" ) end end diff --git a/lib/tres/message_handler_sup.ex b/lib/tres/message_handler_sup.ex index 9c250f6..b847bff 100644 --- a/lib/tres/message_handler_sup.ex +++ b/lib/tres/message_handler_sup.ex @@ -11,7 +11,7 @@ defmodule Tres.MessageHandlerSup do end def start_child({dpid, aux_id}) do - {_cb_mod, cb_args} = Tres.Utils.get_callback_module + {_cb_mod, cb_args} = Tres.Utils.get_callback_module() Supervisor.start_child(__MODULE__, [{dpid, aux_id}, cb_args]) end end diff --git a/lib/tres/message_helper.ex b/lib/tres/message_helper.ex index 1445288..87d6a00 100644 --- a/lib/tres/message_helper.ex +++ b/lib/tres/message_helper.ex @@ -3,7 +3,7 @@ defmodule Tres.MessageHelper do quote location: :keep do defp send_flow_mod_add(datapath_id, options \\ []) do flow_mod = %Openflow.FlowMod{ - cookie: options[:cookie] || 0, + cookie: options[:cookie] || 0, priority: options[:priority] || 0, table_id: options[:table_id] || 0, command: :add, @@ -11,41 +11,46 @@ defmodule Tres.MessageHelper do hard_timeout: options[:hard_timeout] || 0, buffer_id: :no_buffer, out_port: :any, - out_group: :any, + out_group: :any, flags: options[:flags] || [], - match: options[:match] || Openflow.Match.new, - instructions: options[:instructions] || [], + match: options[:match] || Openflow.Match.new(), + instructions: options[:instructions] || [] } + send_message(flow_mod, datapath_id) end defp send_flow_mod_modify(datapath_id, options \\ []) do command = Tres.Utils.flow_command(:modify, options) + flow_mod = %Openflow.FlowMod{ - cookie: options[:cookie] || 0, + cookie: options[:cookie] || 0, table_id: options[:table_id] || 0, command: command, idle_timeout: options[:idle_timeout] || 0, hard_timeout: options[:hard_timeout] || 0, out_port: :any, out_group: :any, - match: options[:match] || Openflow.Match.new, - instructions: options[:instructions] || [], + match: options[:match] || Openflow.Match.new(), + instructions: options[:instructions] || [] } + send_message(flow_mod, datapath_id) end defp send_flow_mod_delete(datapath_id, options \\ []) do command = Tres.Utils.flow_command(:delete, options) + flow_mod = %Openflow.FlowMod{ - cookie: options[:cookie] || 0, + cookie: options[:cookie] || 0, cookie_mask: options[:cookie_mask] || 0, table_id: options[:table_id] || :all, command: command, out_port: options[:out_port] || :any, out_group: options[:out_group] || :any, - match: options[:match] || Openflow.Match.new + match: options[:match] || Openflow.Match.new() } + send_message(flow_mod, datapath_id) end @@ -56,16 +61,19 @@ defmodule Tres.MessageHelper do actions: options[:actions] || [], data: options[:data] || "" } + send_message(packet_out, datapath_id) end defp send_group_mod_add(datapath_id, options \\ []) do - group_mod = Openflow.GroupMod.new( - command: :add, - type: options[:type] || :all, - group_id: options[:group_id] || 0, - buckets: options[:buckets] || [] - ) + group_mod = + Openflow.GroupMod.new( + command: :add, + type: options[:type] || :all, + group_id: options[:group_id] || 0, + buckets: options[:buckets] || [] + ) + send_message(group_mod, datapath_id) end @@ -75,12 +83,14 @@ defmodule Tres.MessageHelper do end defp send_group_mod_modify(datapath_id, options) do - group_mod = Openflow.GroupMod.new( - command: :modify, - type: options[:type] || :all, - group_id: options[:group_id] || 0, - buckets: options[:buckets] || [] - ) + group_mod = + Openflow.GroupMod.new( + command: :modify, + type: options[:type] || :all, + group_id: options[:group_id] || 0, + buckets: options[:buckets] || [] + ) + send_message(group_mod, datapath_id) end end diff --git a/lib/tres/secure_channel.ex b/lib/tres/secure_channel.ex index 78c3350..b486182 100644 --- a/lib/tres/secure_channel.ex +++ b/lib/tres/secure_channel.ex @@ -4,21 +4,21 @@ defmodule Tres.SecureChannel do import Logger alias :tres_xact_kv, as: XACT_KV - alias :queue, as: Queue + alias :queue, as: Queue alias Tres.SecureChannelState, as: State alias Tres.SwitchRegistry alias Tres.MessageHandlerSup @process_flags [ - trap_exit: true, + trap_exit: true, message_queue_data: :on_heap ] @supported_version 4 - @hello_handshake_timeout 1000 + @hello_handshake_timeout 1000 @features_handshake_timeout 1000 - @ping_timeout 5000 + @ping_timeout 5000 # @transaction_timeout 5000 @ping_interval 5000 @@ -35,47 +35,73 @@ defmodule Tres.SecureChannel do def init([ref, socket, transport, _opts]) do state_data = init_secure_channel(ref, socket, transport) - debug("[#{__MODULE__}] TCP connected to Switch on" - <> " #{state_data.ip_addr}:#{state_data.port}" - <> " on #{inspect(self())}") + + debug( + "[#{__MODULE__}] TCP connected to Switch on" <> + " #{state_data.ip_addr}:#{state_data.port}" <> " on #{inspect(self())}" + ) + :gen_statem.enter_loop(__MODULE__, [debug: [:debug]], :INIT, state_data, []) end # TCP handler - def handle_event(:info, {:tcp, socket, packet}, state, - %State{socket: socket, transport: transport} = state_data) do - transport.setopts(socket, [active: :once]) + def handle_event( + :info, + {:tcp, socket, packet}, + state, + %State{socket: socket, transport: transport} = state_data + ) do + transport.setopts(socket, active: :once) handle_packet(packet, state_data, state, []) end - def handle_event(:info, {:tcp_closed, socket}, _state, - %State{socket: socket} = state_data) do + + def handle_event(:info, {:tcp_closed, socket}, _state, %State{socket: socket} = state_data) do close_connection(:tcp_closed, state_data) end - def handle_event(:info, {:tcp_error, socket, reason}, _state, - %State{socket: socket} = state_data) do + + def handle_event( + :info, + {:tcp_error, socket, reason}, + _state, + %State{socket: socket} = state_data + ) do close_connection({:tcp_error, reason}, state_data) end - def handle_event(:info, {:'DOWN', _ref, :process, _main_pid, _reason} = signal, _state, state_data) do + + def handle_event( + :info, + {:DOWN, _ref, :process, _main_pid, _reason} = signal, + _state, + state_data + ) do handle_signal(signal, state_data) end - def handle_event(:info, {:'EXIT', _pid, _reason} = signal, _state, state_data) do + + def handle_event(:info, {:EXIT, _pid, _reason} = signal, _state, state_data) do handle_signal(signal, state_data) end + def handle_event(type, message, :INIT, state_data) do handle_INIT(type, message, state_data) end + def handle_event(type, message, :CONNECTING, state_data) do handle_CONNECTING(type, message, state_data) end + def handle_event(type, message, :CONNECTED, state_data) do handle_CONNECTED(type, message, state_data) end + def handle_event(type, message, :WAITING, state_data) do handle_WATING(type, message, state_data) end - def terminate(reason, state, - %State{datapath_id: datapath_id, aux_id: aux_id, xact_kv_ref: kv_ref}) do + def terminate(reason, state, %State{ + datapath_id: datapath_id, + aux_id: aux_id, + xact_kv_ref: kv_ref + }) do warn("[#{__MODULE__}] termiate: #{inspect(reason)} state = #{inspect(state)}") true = XACT_KV.drop(kv_ref) :ok = SwitchRegistry.unregister({datapath_id, aux_id}) @@ -85,8 +111,8 @@ defmodule Tres.SecureChannel do defp init_secure_channel(ref, socket, transport) do init_process(ref) - :ok = transport.setopts(socket, [active: :once]) - kv_ref = XACT_KV.create + :ok = transport.setopts(socket, active: :once) + kv_ref = XACT_KV.create() State.new(ref: ref, socket: socket, transport: transport, xact_kv_ref: kv_ref) end @@ -100,52 +126,76 @@ defmodule Tres.SecureChannel do %State{datapath_id: dpid, aux_id: aux_id} = state_data {:ok, pid} = MessageHandlerSup.start_child({dpid, aux_id}) ref = Process.monitor(pid) - %{state_data|handler_pid: pid, handler_ref: ref} + %{state_data | handler_pid: pid, handler_ref: ref} end # INIT state defp handle_INIT(:enter, _old_state, state_data) do - debug("[#{__MODULE__}] Initiate HELLO handshake: "<> - ">#{state_data.ip_addr}:#{state_data.port}") + debug( + "[#{__MODULE__}] Initiate HELLO handshake: " <> ">#{state_data.ip_addr}:#{state_data.port}" + ) + initiate_hello_handshake(state_data) end + defp handle_INIT(:info, :hello_timeout, state_data) do close_connection(:hello_handshake_timeout, state_data) end + defp handle_INIT(:internal, {:openflow, %Openflow.Hello{} = hello}, state_data) do handle_hello_handshake_1(hello, state_data) end + defp handle_INIT(:internal, message, _state_data) do - debug("[#{__MODULE__}] Hello handshake in progress, " - <>"dropping message: #{inspect(message)}") + debug( + "[#{__MODULE__}] Hello handshake in progress, " <> "dropping message: #{inspect(message)}" + ) + :keep_state_and_data end # CONNECTING state defp handle_CONNECTING(:enter, :INIT, state_data) do - debug("[#{__MODULE__}] Initiate FEATURES handshake:" - <>" #{state_data.ip_addr}:#{state_data.port}") + debug( + "[#{__MODULE__}] Initiate FEATURES handshake:" <> + " #{state_data.ip_addr}:#{state_data.port}" + ) + initiate_features_handshake(state_data) end + defp handle_CONNECTING(:enter, :WAITING, state_data) do debug("[#{__MODULE__}] Re-entered features handshake") initiate_features_handshake(state_data) end + defp handle_CONNECTING(:info, :features_timeout, state_data) do close_connection(:features_handshake_timeout, state_data) end - defp handle_CONNECTING(:internal, {:openflow, %Openflow.Features.Reply{} = features}, state_data) do - debug("[#{__MODULE__}] Switch connected "<> - "datapath_id: #{features.datapath_id}"<> - " auxiliary_id: #{features.aux_id}") + + defp handle_CONNECTING( + :internal, + {:openflow, %Openflow.Features.Reply{} = features}, + state_data + ) do + debug( + "[#{__MODULE__}] Switch connected " <> + "datapath_id: #{features.datapath_id}" <> " auxiliary_id: #{features.aux_id}" + ) + _ = maybe_cancel_timer(state_data.timer_ref) handle_features_handshake(features, state_data) end + defp handle_CONNECTING(:internal, {:openflow, message}, _state_data) do - debug("[#{__MODULE__}] Features handshake in progress,"<> - " dropping message: #{inspect(message.__struct__)}") + debug( + "[#{__MODULE__}] Features handshake in progress," <> + " dropping message: #{inspect(message.__struct__)}" + ) + :keep_state_and_data end + defp handle_CONNECTING(type, _message, state_data) when type == :cast or type == :call do {:keep_state, state_data, [{:postpone, true}]} end @@ -156,46 +206,61 @@ defmodule Tres.SecureChannel do start_periodic_idle_check() {:keep_state, new_state_data} end + defp handle_CONNECTED(:info, :idle_check, state_data) do start_periodic_idle_check() new_state_data = maybe_ping(state_data) {:keep_state, new_state_data} end + defp handle_CONNECTED(:info, :ping_timeout, state_data) do handle_ping_timeout(state_data, :CONNECTED) end - defp handle_CONNECTED(:internal, {:openflow, %Openflow.Echo.Reply{xid: xid}}, - %State{ping_xid: xid} = state_data) do + + defp handle_CONNECTED( + :internal, + {:openflow, %Openflow.Echo.Reply{xid: xid}}, + %State{ping_xid: xid} = state_data + ) do handle_ping_reply(state_data) end + defp handle_CONNECTED(:internal, {:openflow, %Openflow.Echo.Request{} = echo}, state_data) do send_echo_reply(echo.xid, echo.data, state_data) :keep_state_and_data end + defp handle_CONNECTED(:internal, {:openflow, %Openflow.Barrier.Reply{} = barrier}, state_data) do {new_state_data, next_actions} = process_xact(barrier, state_data) {:keep_state, new_state_data, next_actions} end + defp handle_CONNECTED(:internal, {:openflow, message}, state_data) do %State{datapath_id: dpid, aux_id: aux_id} = state_data - new_message = %{message|datapath_id: dpid, aux_id: aux_id} + new_message = %{message | datapath_id: dpid, aux_id: aux_id} + state_data.xact_kv_ref |> XACT_KV.is_exists(message.xid) |> handle_message(new_message, state_data) + :keep_state_and_data end + defp handle_CONNECTED(:internal, {:send_message, message}, state_data) do xactional_send_message(message, state_data) :keep_state_and_data end + defp handle_CONNECTED(:cast, {:send_message, message} = action, state_data) do - new_action_queue = if XACT_KV.is_empty(state_data.xact_kv_ref) do - xactional_send_message(message, state_data) - state_data.action_queue - else - Queue.in(action, state_data.action_queue) - end - {:keep_state, %{state_data|action_queue: new_action_queue}} + new_action_queue = + if XACT_KV.is_empty(state_data.xact_kv_ref) do + xactional_send_message(message, state_data) + state_data.action_queue + else + Queue.in(action, state_data.action_queue) + end + + {:keep_state, %{state_data | action_queue: new_action_queue}} end # WATING state @@ -206,21 +271,25 @@ defmodule Tres.SecureChannel do start_periodic_idle_check() :keep_state_and_data end + defp handle_WATING(:info, :idle_check, state_data) do start_periodic_idle_check() new_state_data = maybe_ping(state_data) {:keep_state, new_state_data} end + defp handle_WATING(:info, :ping_timeout, state_data) do handle_ping_timeout(state_data, :WAITING) end + defp handle_WATING(:internal, {:openflow, message}, state_data) do %State{handler_pid: handler_pid, datapath_id: dpid, aux_id: aux_id} = state_data - send(handler_pid, %{message|datapath_id: dpid, aux_id: aux_id}) + send(handler_pid, %{message | datapath_id: dpid, aux_id: aux_id}) {:next_state, :CONNECTING, state_data} end + defp handle_WATING(type, message, state_data) - when type == :cast or type == :call do + when type == :cast or type == :call do debug("[#{__MODULE__}] Postponed: #{inspect(message)}, now WATING") {:keep_state, state_data, [{:postpone, true}]} end @@ -228,17 +297,24 @@ defmodule Tres.SecureChannel do defp handle_packet("", state_data, _state, actions) do {:keep_state, state_data, Enum.reverse(actions)} end + defp handle_packet(packet, %State{buffer: buffer} = state_data, state, actions) do binary = <> + case Openflow.read(binary) do {:ok, message, leftovers} -> - debug("[#{__MODULE__}] Received: #{inspect(message.__struct__)}"<> - "(xid: #{message.xid}) in #{state}") + debug( + "[#{__MODULE__}] Received: #{inspect(message.__struct__)}" <> + "(xid: #{message.xid}) in #{state}" + ) + action = {:next_event, :internal, {:openflow, message}} - new_state_data = %{state_data|buffer: "", last_received: :os.timestamp} - handle_packet(leftovers, new_state_data, state, [action|actions]) + new_state_data = %{state_data | buffer: "", last_received: :os.timestamp()} + handle_packet(leftovers, new_state_data, state, [action | actions]) + {:error, :binary_too_small} -> - handle_packet("", %{state_data|buffer: binary}, state, actions) + handle_packet("", %{state_data | buffer: binary}, state, actions) + {:error, _reason} -> handle_packet("", state_data, state, actions) end @@ -246,20 +322,24 @@ defmodule Tres.SecureChannel do defp handle_message(_in_xact = true, message, state_data) do case XACT_KV.get(state_data.xact_kv_ref, message.xid) do - [{:xact_entry, _xid, prev_message, _orig}|_] -> + [{:xact_entry, _xid, prev_message, _orig} | _] -> new_message = Openflow.append_body(prev_message, message) XACT_KV.update(state_data.xact_kv_ref, message.xid, new_message) + _ -> XACT_KV.delete(state_data.xact_kv_ref, message.xid) end end + defp handle_message(_in_xact = false, message, state_data), do: send(state_data.handler_pid, message) defp process_xact(%Openflow.Barrier.Reply{xid: xid}, state_data) do - :ok = state_data.xact_kv_ref - |> XACT_KV.get(xid) - |> Enum.each(&process_xact_entry(&1, state_data)) + :ok = + state_data.xact_kv_ref + |> XACT_KV.get(xid) + |> Enum.each(&process_xact_entry(&1, state_data)) + pop_action_queue(state_data) end @@ -273,23 +353,26 @@ defmodule Tres.SecureChannel do case Queue.out(queue) do {:empty, action_queue} -> {[], action_queue} + {{:value, next_action}, action_queue} -> {[{:next_event, :internal, next_action}], action_queue} end - {%{state_data|action_queue: new_queue}, next_actions} + + {%{state_data | action_queue: new_queue}, next_actions} end defp initiate_hello_handshake(state_data) do send_hello(state_data) ref = :erlang.send_after(@hello_handshake_timeout, self(), :hello_timeout) - {:keep_state, %{state_data|timer_ref: ref}} + {:keep_state, %{state_data | timer_ref: ref}} end defp handle_hello_handshake_1(hello, state_data) do maybe_cancel_timer(state_data.timer_ref) State.set_transaction_id(state_data.xid, hello.xid) + if Openflow.Hello.supported_version?(hello) do - {:next_state, :CONNECTING, %{state_data|timer_ref: nil}} + {:next_state, :CONNECTING, %{state_data | timer_ref: nil}} else close_connection(:failed_version_negotiation, state_data) end @@ -299,45 +382,49 @@ defmodule Tres.SecureChannel do new_xid = State.increment_transaction_id(state_data.xid) send_features(new_xid, state_data) ref = :erlang.send_after(@features_handshake_timeout, self(), :features_timeout) - {:keep_state, %{state_data|timer_ref: ref}} + {:keep_state, %{state_data | timer_ref: ref}} end - defp handle_features_handshake(%Openflow.Features.Reply{datapath_id: datapath_id, - aux_id: aux_id}, state_data) do + defp handle_features_handshake( + %Openflow.Features.Reply{datapath_id: datapath_id, aux_id: aux_id}, + state_data + ) do {:ok, _} = SwitchRegistry.register({datapath_id, aux_id}) + new_state_data = %{ - state_data| - datapath_id: datapath_id, - aux_id: aux_id, - timer_ref: nil, - main_monitor_ref: monitor_connection(datapath_id, aux_id) + state_data + | datapath_id: datapath_id, + aux_id: aux_id, + timer_ref: nil, + main_monitor_ref: monitor_connection(datapath_id, aux_id) } + {:next_state, :CONNECTED, new_state_data} end defp monitor_connection(datapath_id, aux_id) when aux_id > 0, do: SwitchRegistry.monitor(datapath_id) - defp monitor_connection(_datapath_id, _aux_id), - do: nil + + defp monitor_connection(_datapath_id, _aux_id), do: nil defp send_hello(state_data) do @supported_version - |> Openflow.Hello.new + |> Openflow.Hello.new() |> send_message(state_data) end defp send_features(xid, state_data) do - %{Openflow.Features.Request.new|xid: xid} + %{Openflow.Features.Request.new() | xid: xid} |> send_message(state_data) end defp send_echo_reply(xid, data, state_data) do - %{Openflow.Echo.Reply.new(data)|xid: xid} + %{Openflow.Echo.Reply.new(data) | xid: xid} |> send_message(state_data) end defp send_echo_request(xid, data, state_data) do - %{Openflow.Echo.Request.new(data)|xid: xid} + %{Openflow.Echo.Request.new(data) | xid: xid} |> send_message(state_data) end @@ -347,14 +434,15 @@ defmodule Tres.SecureChannel do defp maybe_ping(state_data) do case should_be_ping?(state_data) do - true -> send_ping(state_data) + true -> send_ping(state_data) false -> state_data end end defp should_be_ping?(%State{last_received: last_received, aux_id: 0}) do - :timer.now_diff(:os.timestamp(), last_received) > (1000 * @ping_interval) + :timer.now_diff(:os.timestamp(), last_received) > 1000 * @ping_interval end + defp should_be_ping?(_) do false end @@ -363,32 +451,36 @@ defmodule Tres.SecureChannel do xid = State.increment_transaction_id(x_agent) send_echo_request(xid, "", state_data) ping_ref = :erlang.send_after(@ping_timeout, self(), :ping_timeout) - %{state_data|ping_timer_ref: ping_ref, ping_xid: xid} + %{state_data | ping_timer_ref: ping_ref, ping_xid: xid} end defp handle_ping_timeout(%State{ping_fail_count: fail_count} = state_data, :CONNECTING) - when fail_count > @ping_fail_max_count do + when fail_count > @ping_fail_max_count do {:next_state, :WAITING, state_data} end + defp handle_ping_timeout(%State{ping_fail_count: fail_count} = state_data, :WAITING) - when fail_count > @ping_fail_max_count do + when fail_count > @ping_fail_max_count do close_connection(:ping_failed, state_data) end + defp handle_ping_timeout(state_data, _) do new_state_data = maybe_ping(state_data) {:keep_state, new_state_data} end defp handle_ping_reply(state_data) do - {:keep_state, %{state_data|ping_timer_ref: nil, ping_xid: nil}} + {:keep_state, %{state_data | ping_timer_ref: nil, ping_xid: nil}} end defp xactional_send_message(message, state_data) do xid = State.increment_transaction_id(state_data.xid) + messages = [ - %{message|xid: xid}, - %{Openflow.Barrier.Request.new|xid: xid} + %{message | xid: xid}, + %{Openflow.Barrier.Request.new() | xid: xid} ] + XACT_KV.insert(state_data.xact_kv_ref, xid, message) send_message(messages, state_data) end @@ -396,83 +488,101 @@ defmodule Tres.SecureChannel do defp send_message(message, %State{socket: socket, transport: transport}) do if is_list(message) do for message <- message, - do: debug("[#{__MODULE__}] Sending: #{inspect(message.__struct__)}(xid: #{message.xid})") + do: + debug("[#{__MODULE__}] Sending: #{inspect(message.__struct__)}(xid: #{message.xid})") else debug("[#{__MODULE__}] Sending: #{inspect(message.__struct__)}(xid: #{message.xid})") end + Tres.Utils.send_message(message, socket, transport) end defp maybe_cancel_timer(ref) when not is_reference(ref), do: :ok + defp maybe_cancel_timer(ref) do :erlang.cancel_timer(ref) :ok end - defp handle_signal({:'DOWN', mon_ref, :process, _main_pid, reason}, - %State{main_monitor_ref: mon_ref} = state_data) do + defp handle_signal( + {:DOWN, mon_ref, :process, _main_pid, reason}, + %State{main_monitor_ref: mon_ref} = state_data + ) do close_connection({:main_closed, reason}, state_data) end - defp handle_signal({:'DOWN', handler_ref, :process, _main_pid, reason}, - %State{handler_ref: handler_ref} = state_data) do + + defp handle_signal( + {:DOWN, handler_ref, :process, _main_pid, reason}, + %State{handler_ref: handler_ref} = state_data + ) do close_connection({:handler_down, reason}, state_data) end - defp handle_signal({:'EXIT', _pid, reason}, state_data) do + + defp handle_signal({:EXIT, _pid, reason}, state_data) do close_connection({:trap_detected, reason}, state_data) end defp close_connection(:failed_version_negotiation, state_data) do warn("[#{__MODULE__}] connection terminated: Version negotiation failed") - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection(:hello_handshake_timeout, state_data) do warn("[#{__MODULE__}] connection terminated: Hello handshake timed out") - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection(:features_timeout, state_data) do warn("[#{__MODULE__}] connection terminated: Features handshake timed out") - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection(:handler_error = disconnected_reason, state_data) do warn("[#{__MODULE__}] connection terminated: Got handler error") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection(:ping_failed = disconnected_reason, state_data) do warn("[#{__MODULE__}] connection terminated: Exceeded to max_ping_fail_count") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection({:main_closed = disconnected_reason, reason}, state_data) do warn("[#{__MODULE__}] connection terminated: Main connection down by #{reason}") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection({:handler_down = disconnected_reason, reason}, state_data) do warn("[#{__MODULE__}] connection terminated: Handler process down by #{reason}") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection({:trap_detected = disconnected_reason, reason}, state_data) do warn("[#{__MODULE__}] connection terminated: Trapped by #{reason}") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection(:tcp_closed = disconnected_reason, state_data) do warn("[#{__MODULE__}] connection terminated: TCP Closed by peer") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end + defp close_connection({:tcp_error, reason} = disconnected_reason, state_data) do warn("[#{__MODULE__}] connection terminated: TCP Error occured: #{reason}") %State{handler_pid: handler_pid} = state_data send(handler_pid, {:switch_disconnected, disconnected_reason}) - {:stop, :normal, %{state_data|socket: nil}} + {:stop, :normal, %{state_data | socket: nil}} end end diff --git a/lib/tres/secure_channel_state.ex b/lib/tres/secure_channel_state.ex index 71f04ff..4d1c29b 100644 --- a/lib/tres/secure_channel_state.ex +++ b/lib/tres/secure_channel_state.ex @@ -1,24 +1,24 @@ defmodule Tres.SecureChannelState do defstruct( - handler_pid: nil, - handler_ref: nil, - ref: nil, - socket: nil, - transport: nil, - buffer: "", - ip_addr: nil, - port: "", - datapath_id: "", - aux_id: "", - timer_ref: nil, - xid: nil, - main_monitor_ref: nil, - ping_xid: 0, - ping_timer_ref: nil, - ping_fail_count: 0, - last_received: 0, - xact_kv_ref: nil, - action_queue: :queue.new + handler_pid: nil, + handler_ref: nil, + ref: nil, + socket: nil, + transport: nil, + buffer: "", + ip_addr: nil, + port: "", + datapath_id: "", + aux_id: "", + timer_ref: nil, + xid: nil, + main_monitor_ref: nil, + ping_xid: 0, + ping_timer_ref: nil, + ping_fail_count: 0, + last_received: 0, + xact_kv_ref: nil, + action_queue: :queue.new() ) alias __MODULE__ @@ -30,27 +30,28 @@ defmodule Tres.SecureChannelState do transport = Keyword.get(options, :transport) {:ok, {ip_addr, port}} = :inet.peername(socket) {:ok, xid_agent} = Agent.start_link(fn -> 0 end) - kv_ref = XACT_KV.create + kv_ref = XACT_KV.create() + %SecureChannelState{ - ref: ref, - socket: socket, + ref: ref, + socket: socket, transport: transport, - ip_addr: :inet.ntoa(ip_addr), - port: port, - xid: xid_agent, + ip_addr: :inet.ntoa(ip_addr), + port: port, + xid: xid_agent, xact_kv_ref: kv_ref } end def increment_transaction_id(xid_agent) do - Agent.get_and_update(xid_agent, &({&1 + 1, &1 + 1})) + Agent.get_and_update(xid_agent, &{&1 + 1, &1 + 1}) end def set_transaction_id(xid_agent, xid) do - Agent.update(xid_agent, fn(_) -> xid end) + Agent.update(xid_agent, fn _ -> xid end) end def get_transaction_id(xid_agent) do - Agent.get(xid_agent, &(&1)) + Agent.get(xid_agent, & &1) end end diff --git a/lib/tres/switch_registry.ex b/lib/tres/switch_registry.ex index 1145ee3..40653b6 100644 --- a/lib/tres/switch_registry.ex +++ b/lib/tres/switch_registry.ex @@ -13,6 +13,7 @@ defmodule Tres.SwitchRegistry do [] -> nil end end + def lookup_pid(datapath_id) do lookup_pid({datapath_id, 0}) end @@ -20,6 +21,7 @@ defmodule Tres.SwitchRegistry do def send_message(message, {_dpid, _aux_id} = datapath_id) do Registry.dispatch(__MODULE__, datapath_id, &dispatch(&1, message)) end + def send_message(message, dpid) when is_binary(dpid) do send_message(message, {dpid, 0}) end @@ -27,7 +29,7 @@ defmodule Tres.SwitchRegistry do def monitor(datapath_id) do datapath_id |> lookup_pid - |> Process.monitor + |> Process.monitor() end # private function diff --git a/lib/tres/utils.ex b/lib/tres/utils.ex index b99f3a1..e215ff0 100644 --- a/lib/tres/utils.ex +++ b/lib/tres/utils.ex @@ -3,8 +3,8 @@ defmodule Tres.Utils do @connection_manager Tres.SecureChannel @default_max_connections 10 - @default_num_acceptors 10 - @default_openflow_port 6633 + @default_num_acceptors 10 + @default_openflow_port 6633 def get_callback_module do cb_mod = get_config(:callback_module, Tres.ExampleHandler) @@ -32,7 +32,7 @@ defmodule Tres.Utils do def is_multipart?(message) do message.__struct__ - |> Module.split + |> Module.split() |> Enum.at(1) |> String.match?(~r/Multipart/) end @@ -44,6 +44,7 @@ defmodule Tres.Utils do :delete end end + def flow_command(:modify, options) do if Keyword.get(options, :strict, false) do :modify_strict diff --git a/mix.exs b/mix.exs index ffbf3d9..3f60fca 100644 --- a/mix.exs +++ b/mix.exs @@ -2,25 +2,28 @@ defmodule Tres.Mixfile do use Mix.Project def project do - [app: :tres, - version: "0.1.0", - elixir: "~> 1.5", - start_permanent: Mix.env == :prod, - compilers: [:erlang] ++ Mix.compilers, - deps: deps(), - aliases: [test: "test --no-start"]] + [ + app: :tres, + version: "0.1.0", + elixir: "~> 1.5", + start_permanent: Mix.env() == :prod, + compilers: [:erlang] ++ Mix.compilers(), + deps: deps(), + aliases: [test: "test --no-start"] + ] end # Run "mix help compile.app" to learn about applications. def application do - [extra_applications: [:logger, :ranch, :eovsdb], - mod: {Tres.Application, []}] + [extra_applications: [:logger, :ranch, :eovsdb], mod: {Tres.Application, []}] end # Run "mix help deps" to learn about dependencies. defp deps do - [{:ranch, "~> 1.4.0"}, - {:eovsdb, github: "shun159/eovsdb", branch: "master"}, - {:epcap, github: "msantos/epcap", branch: "master", only: :test}] + [ + {:ranch, "~> 1.4.0"}, + {:eovsdb, github: "shun159/eovsdb", branch: "master"}, + {:epcap, github: "msantos/epcap", branch: "master", only: :test} + ] end end diff --git a/test/flay.ex b/test/flay.ex index a6fbccf..2c26cf5 100644 --- a/test/flay.ex +++ b/test/flay.ex @@ -5,13 +5,11 @@ defmodule Flay do import Logger defmodule State do - defstruct [ - datapath_id: nil, - tester_pid: nil, - conn_ref: nil, - reply_to: nil, - default_profile: nil, - ] + defstruct datapath_id: nil, + tester_pid: nil, + conn_ref: nil, + reply_to: nil, + default_profile: nil end def start_link(datapath, args) do @@ -26,32 +24,37 @@ defmodule Flay do end def handle_call(:port_desc_stats, from, state) do - send_message(PortDesc.Request.new, state.datapath_id) - {:noreply, %{state|reply_to: from}} + send_message(PortDesc.Request.new(), state.datapath_id) + {:noreply, %{state | reply_to: from}} end + def handle_call(:flow_stats, from, state) do - send_message(Flow.Request.new, state.datapath_id) - {:noreply, %{state|reply_to: from}} + send_message(Flow.Request.new(), state.datapath_id) + {:noreply, %{state | reply_to: from}} end def handle_cast(:desc_stats, state) do - send_message(Desc.Request.new, state.datapath_id) + send_message(Desc.Request.new(), state.datapath_id) {:noreply, state} end + def handle_cast({:register_pid, tester_pid}, state) do - {:noreply, %{state|tester_pid: tester_pid}} + {:noreply, %{state | tester_pid: tester_pid}} end + def handle_cast({:flow_install, flow_opts, tester_pid}, state) do send_flow_mod_add(state.datapath_id, flow_opts) flow_opts_to_ofp_print(flow_opts) - {:noreply, %{state|tester_pid: tester_pid}} + {:noreply, %{state | tester_pid: tester_pid}} end + def handle_cast(:flow_del, state) do send_flow_mod_delete(state.datapath_id) {:noreply, state} end + def handle_cast({:flow_del, cookie}, state) do - send_flow_mod_delete(state.datapath_id, cookie: cookie, cookie_mask: 0xffffffffffffffff) + send_flow_mod_delete(state.datapath_id, cookie: cookie, cookie_mask: 0xFFFFFFFFFFFFFFFF) {:noreply, state} end @@ -59,31 +62,36 @@ defmodule Flay do send(state.tester_pid, error) {:noreply, state} end + def handle_info(%PacketIn{} = pktin, state) do send(state.tester_pid, pktin) {:noreply, state} end + def handle_info(%TableFeatures.Reply{} = table, state) do - {:noreply, %{state|default_profile: table}} + {:noreply, %{state | default_profile: table}} end + def handle_info(%PortDesc.Reply{} = desc, state) do GenServer.reply(state.reply_to, desc) {:noreply, state} end + def handle_info(%Desc.Reply{} = desc, state) do info( - "[#{__MODULE__}] Switch Desc: " - <> "mfr = #{desc.mfr_desc} " - <> "hw = #{desc.hw_desc} " - <> "sw = #{desc.sw_desc} " + "[#{__MODULE__}] Switch Desc: " <> + "mfr = #{desc.mfr_desc} " <> "hw = #{desc.hw_desc} " <> "sw = #{desc.sw_desc} " ) + init_bridge(state.datapath_id, desc) {:noreply, state} end + def handle_info(%Flow.Reply{} = desc, state) do GenServer.reply(state.reply_to, desc) - {:noreply, %{state|reply_to: nil}} + {:noreply, %{state | reply_to: nil}} end + # `Catch all` function is required. def handle_info(info, state) do :ok = warn("[#{__MODULE__}] unhandled message #{inspect(info)}") @@ -94,11 +102,11 @@ defmodule Flay do defp flow_opts_to_ofp_print(flow_opts) do flow_opts - |> FlowMod.new - |> Openflow.to_binary + |> FlowMod.new() + |> Openflow.to_binary() |> binary_to_space_delimited_hex |> ofp_print_cmd - |> Logger.info + |> Logger.info() end defp ofp_print_cmd(print_args) do @@ -110,7 +118,7 @@ defmodule Flay do binary |> split_to_hex_string |> Enum.join(" ") - |> String.downcase + |> String.downcase() end defp split_to_hex_string(binary) do @@ -120,24 +128,26 @@ defmodule Flay do defp integer_to_hex(int) do case Integer.to_string(int, 16) do <> -> <<48, d>> - dd -> dd + dd -> dd end end defp init_controller([datapath_id, tester_pid]) do conn_ref = SwitchRegistry.monitor(datapath_id) + %State{ datapath_id: datapath_id, - tester_pid: tester_pid, - conn_ref: conn_ref + tester_pid: tester_pid, + conn_ref: conn_ref } end defp init_bridge(datapath_id, %Desc.Reply{mfr_desc: "Aruba"}) do :ok = info("Transform flow table pipeline") + tables = [ TableFeatures.Body.new( - table_id: 0, + table_id: 0, name: "classifier", max_entries: 50, config: [:table_miss_mask], @@ -161,7 +171,7 @@ defmodule Flay do :ip_proto, :ipv4_src, :udp_dst, - :tcp_dst, + :tcp_dst ], instructions: [ Openflow.Instruction.GotoTable, @@ -178,11 +188,11 @@ defmodule Flay do :vlan_vid ], next_tables: [ - 1, - ], + 1 + ] ), TableFeatures.Body.new( - table_id: 1, + table_id: 1, name: "admission_control", max_entries: 50, config: [:table_miss_mask], @@ -223,13 +233,16 @@ defmodule Flay do :vlan_vid, :ipv4_src, :ipv4_dst - ], + ] ) ] + TableFeatures.Request.new(tables) |> send_message(datapath_id) + send_flow_mod_delete(datapath_id, table_id: :all) end + defp init_bridge(_datapath_id, _mfr) do :ok = info("Flow pipeline profile is not defined") :ok diff --git a/test/flog_test.exs b/test/flog_test.exs index 3037cc7..dc31453 100644 --- a/test/flog_test.exs +++ b/test/flog_test.exs @@ -4,32 +4,38 @@ defmodule FlogTest do @listen_port 6653 - @vlan_trunk_port "veth0" # FIXME: - @access_port1 "veth3" # FIXME: - @access_port2 "veth4" # FIXME: + # FIXME: + @vlan_trunk_port "veth0" + # FIXME: + @access_port1 "veth3" + # FIXME: + @access_port2 "veth4" - @vlan_trunk_port_sniffer "veth1" # FIXME: - @access_port1_sniffer "veth2" # FIXME: - @access_port2_sniffer "veth5" # FIXME: + # FIXME: + @vlan_trunk_port_sniffer "veth1" + # FIXME: + @access_port1_sniffer "veth2" + # FIXME: + @access_port2_sniffer "veth5" - @bootnet_vid 0x1000 ||| 5 - @user_vid 0x1000 ||| 123 - @vlan_present {0x1000, 0x1000} - @mcast {"010000000000", "010000000000"} - @sdl_vmac "000000000001" - @bcast "ffffffffffff" - @mac "000102030405" - @auth_ipv4_address {192,168,5,4} - @captive_ipv4_address {192,168,5,5} - @quad_0_ip {0,0,0,0} - @bcast_ip {255,255,255,255} - @client_ip {192,168,5,10} - @client_farm_ip {192,168,255,1} - @gateway_ip {192,168,5,4} - @farm_gw_ip {192,168,255,254} + @bootnet_vid 0x1000 ||| 5 + @user_vid 0x1000 ||| 123 + @vlan_present {0x1000, 0x1000} + @mcast {"010000000000", "010000000000"} + @sdl_vmac "000000000001" + @bcast "ffffffffffff" + @mac "000102030405" + @auth_ipv4_address {192, 168, 5, 4} + @captive_ipv4_address {192, 168, 5, 5} + @quad_0_ip {0, 0, 0, 0} + @bcast_ip {255, 255, 255, 255} + @client_ip {192, 168, 5, 10} + @client_farm_ip {192, 168, 255, 1} + @gateway_ip {192, 168, 5, 4} + @farm_gw_ip {192, 168, 255, 254} @farm_gw_mac "00000000000f" - @internet {8,8,8,8} - @trusted_macs [ + @internet {8, 8, 8, 8} + @trusted_macs [ "0800274d3297", "0800274d3298", "0800274d3299" @@ -49,12 +55,13 @@ defmodule FlogTest do setup_applications() wait_for_connected() ports = get_ports_desc() - vlan_trunk = Enum.find(ports, fn(port) -> port.name == @vlan_trunk_port end) - port = Enum.find(ports, fn(port) -> port.name == @access_port1 end) - port2 = Enum.find(ports, fn(port) -> port.name == @access_port2 end) - cookie = 0x1000000000000001 + vlan_trunk = Enum.find(ports, fn port -> port.name == @vlan_trunk_port end) + port = Enum.find(ports, fn port -> port.name == @access_port1 end) + port2 = Enum.find(ports, fn port -> port.name == @access_port2 end) + cookie = 0x1000000000000001 cookie2 = 0x2000000000000001 timeout = 32_678 + options = [ vlan_trunk: vlan_trunk, port: port, @@ -63,18 +70,20 @@ defmodule FlogTest do cookie2: cookie2, timeout: timeout ] + {:ok, options} end - describe("switch:merged_handler:table=0,priority=0,cookie=0x8000000000000000,actions=drop") do + describe "switch:merged_handler:table=0,priority=0,cookie=0x8000000000000000,actions=drop" do test "Install Flow" do options = [ cookie: 0x8000000000000000, table_id: 0, priority: 0 ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -85,10 +94,12 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@mac, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) payload = <<0::size(16)-unit(8)>> + packet = [ ether(dhost: dhost, shost: shost, type: 0x0806), arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + Pf.inject!(pid1, packet, payload) refute_receive {@vlan_trunk_port_sniffer, ^packet}, 1000 Pf.stop(pid1) @@ -96,26 +107,31 @@ defmodule FlogTest do end end - describe("switch:merged_handler:" <> - "table=0,priority=200,cookie=0x4000000000000000,in_port=%d,dl_dst=%s,dl_vlan=0x0000/0x1fff,dl_type=%s," <> - "actions=controller") do + describe "switch:merged_handler:" <> + "table=0,priority=200,cookie=0x4000000000000000,in_port=%d,dl_dst=%s,dl_vlan=0x0000/0x1fff,dl_type=%s," <> + "actions=controller" do test "Install Flow", state do - match = Openflow.Match.new( - in_port: state.vlan_trunk.number, - eth_dst: @bcast, - vlan_vid: 0x0000, - eth_type: 0x88cc - ) + match = + Openflow.Match.new( + in_port: state.vlan_trunk.number, + eth_dst: @bcast, + vlan_vid: 0x0000, + eth_type: 0x88CC + ) + action = Openflow.Action.Output.new(:controller) ins = Openflow.Instruction.ApplyActions.new(action) - options = - [cookie: 0x4000000000000000, - table_id: 0, - priority: 200, - match: match, - instructions: [ins]] + + options = [ + cookie: 0x4000000000000000, + table_id: 0, + priority: 200, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 {:ok, pid1} = Pf.start_link(@access_port1_sniffer) @@ -123,12 +139,18 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(state.vlan_trunk.hw_addr, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) + packet = [ - ether(dhost: dhost, shost: shost, type: 0x88cc), - lldp(pdus: [chassis_id(value: "hogehoge"), - port_id(subtype: :mac_address, value: shost), - ttl(value: 128)]) + ether(dhost: dhost, shost: shost, type: 0x88CC), + lldp( + pdus: [ + chassis_id(value: "hogehoge"), + port_id(subtype: :mac_address, value: shost), + ttl(value: 128) + ] + ) ] + Pf.inject!(pid2, packet) in_port = state.vlan_trunk.number assert_receive %Openflow.PacketIn{in_port: ^in_port}, 1000 @@ -139,37 +161,36 @@ defmodule FlogTest do end end - describe("switch:merged_handler:" <> - "table=0,priority=201,cookie=0x4000000000000000,in_port=%d,dl_src=%s,actions=drop") do + describe "switch:merged_handler:" <> + "table=0,priority=201,cookie=0x4000000000000000,in_port=%d,dl_src=%s,actions=drop" do test "Install Flow", state do for port <- [state.vlan_trunk, state.port] do match = Openflow.Match.new(in_port: port.number, eth_src: port.hw_addr) - options = - [cookie: 0x4000000000000000, - table_id: 0, - priority: 201, - match: match] + options = [cookie: 0x4000000000000000, table_id: 0, priority: 201, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end end - describe("switch:uplink_escalation_flow:" <> - "table=0,priority=10,cookie=0x1000000000000000,arp,actions=controller") do + describe "switch:uplink_escalation_flow:" <> + "table=0,priority=10,cookie=0x1000000000000000,arp,actions=controller" do test "Install Flow", state do match = Openflow.Match.new(eth_type: 0x0806) action = Openflow.Action.Output.new(:controller) ins = Openflow.Instruction.ApplyActions.new(action) - options = - [cookie: 0x1000000000000000, - table_id: 0, - priority: 10, - match: match, - instructions: [ins]] + + options = [ + cookie: 0x1000000000000000, + table_id: 0, + priority: 10, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 {:ok, pid1} = Pf.start_link(@access_port1_sniffer) @@ -178,10 +199,12 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@mac, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) payload = <<0::size(16)-unit(8)>> + packet = [ ether(dhost: dhost, shost: shost, type: 0x0806), arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + Pf.inject!(pid1, packet, payload) in_port = state.port.number assert_receive %Openflow.PacketIn{in_port: ^in_port}, 1000 @@ -191,20 +214,23 @@ defmodule FlogTest do end end - describe("switch:uplink_escalation_flow:" <> - "table=0,priority=10,cookie=0x1000000000000000,udp,udp_dst=67,actions=controller") do + describe "switch:uplink_escalation_flow:" <> + "table=0,priority=10,cookie=0x1000000000000000,udp,udp_dst=67,actions=controller" do test "Install Flow", state do match = Openflow.Match.new(eth_type: 0x0800, ip_proto: 17, udp_dst: 67) - action = Openflow.Action.Output.new(:controller) + action = Openflow.Action.Output.new(:controller) ins = Openflow.Instruction.ApplyActions.new(action) - options = - [cookie: 0x1000000000000000, - table_id: 0, - priority: 10, - match: match, - instructions: [ins]] + + options = [ + cookie: 0x1000000000000000, + table_id: 0, + priority: 10, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 {:ok, pid1} = Pf.start_link(@access_port1_sniffer) @@ -218,11 +244,13 @@ defmodule FlogTest do udp_header = udp(sport: 68, dport: 67, ulen: length) ipv4_header = ipv4(saddr: @quad_0_ip, daddr: @bcast_ip, p: 17, len: 20 + length) udp_sum = :pkt.makesum([ipv4_header, udp_header, payload]) + packet = [ ether(dhost: dhost, shost: shost, type: 0x0800), ipv4_header, udp(udp_header, sum: udp_sum) ] + Pf.inject!(pid1, packet, <>) in_port = state.port.number assert_receive %Openflow.PacketIn{in_port: ^in_port}, 1000 @@ -232,17 +260,13 @@ defmodule FlogTest do end end - describe("switch:uplink_escalation_flow:" <> - "table=0,priority=11,cookie=0x1000000000000000,in_port={trunk_port},actions=drop") do + describe "switch:uplink_escalation_flow:" <> + "table=0,priority=11,cookie=0x1000000000000000,in_port={trunk_port},actions=drop" do test "Install Flow", state do match = Openflow.Match.new(in_port: state.vlan_trunk.number) - options = - [cookie: 0x1000000000000000, - table_id: 0, - priority: 11, - match: match] + options = [cookie: 0x1000000000000000, table_id: 0, priority: 11, match: match] :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -253,10 +277,12 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@mac, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) payload = <<0::size(16)-unit(8)>> + packet = [ ether(dhost: dhost, shost: shost, type: 0x0806), arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + Pf.inject!(pid2, packet, payload) refute_receive {@access_port1_sniffer, ^packet}, 1000 Pf.stop(pid1) @@ -264,32 +290,38 @@ defmodule FlogTest do end end - describe("associate:register_bootstrap_rule:" <> - "send_flow_rem," <> - "dl_src={mac},in_port={port_no}," <> - "actions=push_vlan:0x8100,set_field:{vlan}->vlan_vid,output:{vlan_trunk_port}") do + describe "associate:register_bootstrap_rule:" <> + "send_flow_rem," <> + "dl_src={mac},in_port={port_no}," <> + "actions=push_vlan:0x8100,set_field:{vlan}->vlan_vid,output:{vlan_trunk_port}" do test "Install Flow", state do - match = Openflow.Match.new( - in_port: state.port.number, - eth_src: @mac - ) + match = + Openflow.Match.new( + in_port: state.port.number, + eth_src: @mac + ) + actions = [ - Openflow.Action.PushVlan.new, + Openflow.Action.PushVlan.new(), Openflow.Action.SetField.new({:vlan_vid, @bootnet_vid}), - Openflow.Action.Output.new(state.vlan_trunk.number), + Openflow.Action.Output.new(state.vlan_trunk.number) ] + ins = Openflow.Instruction.ApplyActions.new(actions) - options = - [cookie: state.cookie, - table_id: 0, - priority: 20, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: [ins]] + + options = [ + cookie: state.cookie, + table_id: 0, + priority: 20, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -299,13 +331,18 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@mac, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) - packet = [ether(dhost: dhost, shost: shost, type: 0x0806), - arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip)] + + packet = [ + ether(dhost: dhost, shost: shost, type: 0x0806), + arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) + ] + expect = [ ether(dhost: dhost, shost: shost, type: 0x8100), {:"802.1q", 0, 0, 5, 0x0806}, - arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip), + arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + Pf.inject!(pid1, packet) assert_receive {@vlan_trunk_port_sniffer, ^expect}, 3000 Pf.stop(pid1) @@ -313,33 +350,39 @@ defmodule FlogTest do end end - describe("associate:register_bootstrap_rule:" <> - "send_flow_rem," <> - "in_port={vlan_trunk_port},dl_vlan={vlan},dl_dst={mcast}," <> - "actions=strip_vlan,{outputs}") do + describe "associate:register_bootstrap_rule:" <> + "send_flow_rem," <> + "in_port={vlan_trunk_port},dl_vlan={vlan},dl_dst={mcast}," <> + "actions=strip_vlan,{outputs}" do test "Install Flow", state do - match = Openflow.Match.new( - in_port: state.vlan_trunk.number, - vlan_vid: @bootnet_vid, - eth_dst: @mcast - ) + match = + Openflow.Match.new( + in_port: state.vlan_trunk.number, + vlan_vid: @bootnet_vid, + eth_dst: @mcast + ) + actions = [ - Openflow.Action.PopVlan.new, + Openflow.Action.PopVlan.new(), Openflow.Action.Output.new(state.port.number), - Openflow.Action.Output.new(state.port2.number), + Openflow.Action.Output.new(state.port2.number) ] + ins = Openflow.Instruction.ApplyActions.new(actions) - options = - [cookie: state.cookie, - table_id: 0, - priority: 50, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: [ins]] + + options = [ + cookie: state.cookie, + table_id: 0, + priority: 50, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -350,15 +393,18 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@mac, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) + packet = [ ether(dhost: dhost, shost: shost, type: 0x8100), {:"802.1q", 0, 0, 5, 0x0806}, - arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip), + arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + expect = [ ether(dhost: dhost, shost: shost, type: 0x0806), - arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip), + arp(op: 1, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + Pf.inject!(pid2, packet) assert_receive {@access_port1_sniffer, ^expect}, 3000 assert_receive {@access_port2_sniffer, ^expect}, 3000 @@ -368,32 +414,38 @@ defmodule FlogTest do end end - describe("associate:register_bootstrap_rule:" <> - "send_flow_rem," <> - "in_port={vlan_trunk_port},dl_vlan={vlan},dl_dst={mac}," <> - "actions=strip_vlan,output:{port_no}") do + describe "associate:register_bootstrap_rule:" <> + "send_flow_rem," <> + "in_port={vlan_trunk_port},dl_vlan={vlan},dl_dst={mac}," <> + "actions=strip_vlan,output:{port_no}" do test "Install Flow", state do - match = Openflow.Match.new( - in_port: state.vlan_trunk.number, - vlan_vid: @bootnet_vid, - eth_dst: @mac - ) + match = + Openflow.Match.new( + in_port: state.vlan_trunk.number, + vlan_vid: @bootnet_vid, + eth_dst: @mac + ) + actions = [ - Openflow.Action.PopVlan.new, - Openflow.Action.Output.new(state.port.number), + Openflow.Action.PopVlan.new(), + Openflow.Action.Output.new(state.port.number) ] + ins = Openflow.Instruction.ApplyActions.new(actions) - options = - [cookie: state.cookie, - table_id: 0, - priority: 50, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: [ins]] + + options = [ + cookie: state.cookie, + table_id: 0, + priority: 50, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -403,15 +455,18 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@sdl_vmac, :eth_src) dhost = Openflow.Match.Field.codec(@mac, :eth_dst) + packet = [ ether(dhost: dhost, shost: shost, type: 0x8100), {:"802.1q", 0, 0, 5, 0x0806}, - arp(op: 2, sha: shost, tip: @client_ip, sip: @gateway_ip), + arp(op: 2, sha: shost, tip: @client_ip, sip: @gateway_ip) ] + expect = [ ether(dhost: dhost, shost: shost, type: 0x0806), - arp(op: 2, sha: shost, tip: @client_ip, sip: @gateway_ip), + arp(op: 2, sha: shost, tip: @client_ip, sip: @gateway_ip) ] + Pf.inject!(pid2, packet) assert_receive {@access_port1_sniffer, ^expect}, 3000 Pf.stop(pid1) @@ -419,25 +474,27 @@ defmodule FlogTest do end end - describe("associate:register_bootstrap_rule:" <> - "send_flow_rem," <> - "dl_src={mac},in_port={vlan_trunk_port}," <> - "actions=drop") do + describe "associate:register_bootstrap_rule:" <> + "send_flow_rem," <> "dl_src={mac},in_port={vlan_trunk_port}," <> "actions=drop" do test "Install Flow", state do - match = Openflow.Match.new( - in_port: state.vlan_trunk.number, - eth_src: @mac - ) - options = - [cookie: state.cookie, - table_id: 0, - priority: 19, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match] + match = + Openflow.Match.new( + in_port: state.vlan_trunk.number, + eth_src: @mac + ) + + options = [ + cookie: state.cookie, + table_id: 0, + priority: 19, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -448,10 +505,12 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(@mac, :eth_src) dhost = Openflow.Match.Field.codec(@bcast, :eth_dst) payload = <<0::size(16)-unit(8)>> + packet = [ ether(dhost: dhost, shost: shost, type: 0x0806), arp(op: 2, sha: shost, sip: @client_ip, tip: @gateway_ip) ] + Pf.inject!(pid2, packet, payload) refute_receive {@access_port1_sniffer, ^packet}, 3000 Pf.stop(pid1) @@ -459,34 +518,40 @@ defmodule FlogTest do end end - describe("associate:register_bootstrap_rule:" <> - "send_flow_rem," <> - "in_port={vlan_trunk_port},dl_vlan={vlan},dl_src={trusted},dl_dst={mac}," <> - "actions=strip_vlan,output:{port_no}") do + describe "associate:register_bootstrap_rule:" <> + "send_flow_rem," <> + "in_port={vlan_trunk_port},dl_vlan={vlan},dl_src={trusted},dl_dst={mac}," <> + "actions=strip_vlan,output:{port_no}" do test "Install Flow", state do for trusted <- @trusted_macs do - match = Openflow.Match.new( - in_port: state.vlan_trunk.number, - vlan_vid: @bootnet_vid, - eth_src: trusted, - eth_dst: @mac - ) + match = + Openflow.Match.new( + in_port: state.vlan_trunk.number, + vlan_vid: @bootnet_vid, + eth_src: trusted, + eth_dst: @mac + ) + actions = [ - Openflow.Action.PopVlan.new, - Openflow.Action.Output.new(state.port.number), + Openflow.Action.PopVlan.new(), + Openflow.Action.Output.new(state.port.number) ] + ins = Openflow.Instruction.ApplyActions.new(actions) - options = - [cookie: state.cookie, - table_id: 0, - priority: 50, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: [ins]] + + options = [ + cookie: state.cookie, + table_id: 0, + priority: 50, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end @@ -499,15 +564,18 @@ defmodule FlogTest do shost = Openflow.Match.Field.codec(trusted, :eth_src) dhost = Openflow.Match.Field.codec(@mac, :eth_dst) payload = <<0::size(16)-unit(8)>> + packet = [ ether(dhost: dhost, shost: shost, type: 0x8100), {:"802.1q", 0, 0, 5, 0x0806}, arp(op: 2, sha: shost, tha: dhost, tip: @client_ip, sip: @gateway_ip) ] + expect = [ ether(dhost: dhost, shost: shost, type: 0x0806), - arp(op: 2, sha: shost, tha: dhost, tip: @client_ip, sip: @gateway_ip), + arp(op: 2, sha: shost, tha: dhost, tip: @client_ip, sip: @gateway_ip) ] + Pf.inject!(pid2, packet, payload) assert_receive {@access_port1_sniffer, ^expect}, 3000 Pf.stop(pid1) @@ -516,101 +584,115 @@ defmodule FlogTest do end end - describe("associate:register_bootstrap_rule:" <> - "send_flow_rem," <> - "dl_src={trusted}," <> - "actions=drop") do + describe "associate:register_bootstrap_rule:" <> + "send_flow_rem," <> "dl_src={trusted}," <> "actions=drop" do test "Install Flow", state do for trusted <- @trusted_macs do match = Openflow.Match.new(eth_src: trusted) - options = - [cookie: state.cookie, - table_id: 0, - priority: 29, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match] + + options = [ + cookie: state.cookie, + table_id: 0, + priority: 29, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end end - describe("associate:register_usernet_rule:" <> - "in_port={vlan_trunk_port},dl_vlan={vlan}," <> - "actions=goto_table:1") do + describe "associate:register_usernet_rule:" <> + "in_port={vlan_trunk_port},dl_vlan={vlan}," <> "actions=goto_table:1" do setup [:flow_del_by_cookie] test "Install Flow", state do match = Openflow.Match.new(in_port: state.vlan_trunk.number, vlan_vid: @user_vid) ins = [Openflow.Instruction.GotoTable.new(1)] - options = - [cookie: state.cookie2, - table_id: 0, - priority: 50, - match: match, - instructions: ins] + + options = [ + cookie: state.cookie2, + table_id: 0, + priority: 50, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end - describe("associate:register_usernet_rule:" <> - "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem, dl_src={mac},in_port={port_no}," <> - "actions=push_vlan:0x8100,set_field:{vlan}->vlan_vid,goto_table:1") do + describe "associate:register_usernet_rule:" <> + "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem, dl_src={mac},in_port={port_no}," <> + "actions=push_vlan:0x8100,set_field:{vlan}->vlan_vid,goto_table:1" do test "Install Flow", state do match = Openflow.Match.new(in_port: state.port.number, eth_src: @mac) + actions = [ - Openflow.Action.PushVlan.new, + Openflow.Action.PushVlan.new(), Openflow.Action.SetField.new({:vlan_vid, @user_vid}) ] + ins = [ Openflow.Instruction.ApplyActions.new(actions), Openflow.Instruction.GotoTable.new(1) ] - options = - [cookie: state.cookie2, - table_id: 0, - priority: 20, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: ins] + + options = [ + cookie: state.cookie2, + table_id: 0, + priority: 20, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end - describe("associate:register_usernet_rule:" <> - "vlan_vid=0x1000/0x1000,tcp,tcp_dst=443,nw_dst={auth_ipv4_address}," <> - "strip_vlan,set_field:{sdl_vmac}->eth_dst,output:{vlan_trunk_port}") do + describe "associate:register_usernet_rule:" <> + "vlan_vid=0x1000/0x1000,tcp,tcp_dst=443,nw_dst={auth_ipv4_address}," <> + "strip_vlan,set_field:{sdl_vmac}->eth_dst,output:{vlan_trunk_port}" do test "Install Flow", state do - match = Openflow.Match.new( - vlan_vid: @vlan_present, - eth_type: 0x0800, - ip_proto: 6, - ipv4_dst: @auth_ipv4_address, - tcp_dst: 443 - ) + match = + Openflow.Match.new( + vlan_vid: @vlan_present, + eth_type: 0x0800, + ip_proto: 6, + ipv4_dst: @auth_ipv4_address, + tcp_dst: 443 + ) + actions = [ - Openflow.Action.PopVlan.new, + Openflow.Action.PopVlan.new(), Openflow.Action.SetField.new({:eth_dst, @sdl_vmac}), - Openflow.Action.Output.new(state.vlan_trunk.number), + Openflow.Action.Output.new(state.vlan_trunk.number) ] + ins = Openflow.Instruction.ApplyActions.new(actions) - options = - [cookie: state.cookie2, - table_id: 1, - priority: 30, - match: match, - instructions: [ins]] + + options = [ + cookie: state.cookie2, + table_id: 1, + priority: 30, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -622,15 +704,18 @@ defmodule FlogTest do dhost = Openflow.Match.Field.codec(@sdl_vmac, :eth_dst) payload = "" - tcp_header = tcp( - sport: 53_688, - dport: 443, - seqno: 1_488_352_223, - off: 10, - syn: 1, - win: 29_200, - opt: <<2, 4, 5, 180, 4, 2, 8, 10, 156, 30, 232, 154, 0, 0, 0, 0, 1, 3, 3, 7>> - ) + + tcp_header = + tcp( + sport: 53_688, + dport: 443, + seqno: 1_488_352_223, + off: 10, + syn: 1, + win: 29_200, + opt: <<2, 4, 5, 180, 4, 2, 8, 10, 156, 30, 232, 154, 0, 0, 0, 0, 1, 3, 3, 7>> + ) + ipv4_header = ipv4(saddr: @client_ip, daddr: @auth_ipv4_address, p: 6, len: 60) tcp_sum = :pkt.makesum([ipv4_header, tcp_header, payload]) ether_header = ether(dhost: dhost, shost: shost, type: 0x0800) @@ -643,31 +728,37 @@ defmodule FlogTest do end end - describe("associate:register_usernet_rule:" <> - "vlan_vid=0x1000/0x1000,tcp,tcp_dst=80,nw_dst={captive_ipv4_address}," <> - "strip_vlan,set_field:{sdl_vmac}->eth_dst,output:{vlan_trunk_port}") do + describe "associate:register_usernet_rule:" <> + "vlan_vid=0x1000/0x1000,tcp,tcp_dst=80,nw_dst={captive_ipv4_address}," <> + "strip_vlan,set_field:{sdl_vmac}->eth_dst,output:{vlan_trunk_port}" do test "Install Flow", state do - match = Openflow.Match.new( - vlan_vid: @vlan_present, - eth_type: 0x0800, - ip_proto: 6, - ipv4_dst: @captive_ipv4_address, - tcp_dst: 80 - ) + match = + Openflow.Match.new( + vlan_vid: @vlan_present, + eth_type: 0x0800, + ip_proto: 6, + ipv4_dst: @captive_ipv4_address, + tcp_dst: 80 + ) + actions = [ - Openflow.Action.PopVlan.new, + Openflow.Action.PopVlan.new(), Openflow.Action.SetField.new({:eth_dst, @sdl_vmac}), - Openflow.Action.Output.new(state.vlan_trunk.number), + Openflow.Action.Output.new(state.vlan_trunk.number) ] + ins = Openflow.Instruction.ApplyActions.new(actions) - options = - [cookie: state.cookie2, - table_id: 1, - priority: 30, - match: match, - instructions: [ins]] + + options = [ + cookie: state.cookie2, + table_id: 1, + priority: 30, + match: match, + instructions: [ins] + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -679,15 +770,18 @@ defmodule FlogTest do dhost = Openflow.Match.Field.codec(@sdl_vmac, :eth_dst) payload = "" - tcp_header = tcp( - sport: 53_688, - dport: 80, - seqno: 1_488_352_223, - off: 10, - syn: 1, - win: 29_200, - opt: <<2, 4, 5, 180, 4, 2, 8, 10, 156, 30, 232, 154, 0, 0, 0, 0, 1, 3, 3, 7>> - ) + + tcp_header = + tcp( + sport: 53_688, + dport: 80, + seqno: 1_488_352_223, + off: 10, + syn: 1, + win: 29_200, + opt: <<2, 4, 5, 180, 4, 2, 8, 10, 156, 30, 232, 154, 0, 0, 0, 0, 1, 3, 3, 7>> + ) + ipv4_header = ipv4(saddr: @client_ip, daddr: @captive_ipv4_address, p: 6, len: 60) tcp_sum = :pkt.makesum([ipv4_header, tcp_header, payload]) ether_header = ether(dhost: dhost, shost: shost, type: 0x0800) @@ -700,67 +794,74 @@ defmodule FlogTest do end end - describe("associate:register_usernet_rule:" <> - "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem,dl_src={mac},in_port={vlan_trunk_port}," <> - "actions=drop") do + describe "associate:register_usernet_rule:" <> + "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem,dl_src={mac},in_port={vlan_trunk_port}," <> + "actions=drop" do test "Install Flow", state do match = Openflow.Match.new(in_port: state.vlan_trunk.number, eth_src: @mac) - options = - [cookie: state.cookie2, - table_id: 0, - priority: 19, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match] + + options = [ + cookie: state.cookie2, + table_id: 0, + priority: 19, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end - describe("associate:register_usernet_rule:" <> - "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem,dl_src={mac}," <> - "actions=controller") do + describe "associate:register_usernet_rule:" <> + "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem,dl_src={mac}," <> + "actions=controller" do test "Install Flow", state do match = Openflow.Match.new(eth_src: @mac) actions = [Openflow.Action.Output.new(:controller)] ins = [Openflow.Instruction.ApplyActions.new(actions)] - options = - [cookie: state.cookie2, - table_id: 0, - priority: 18, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: ins] + + options = [ + cookie: state.cookie2, + table_id: 0, + priority: 18, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end - describe("associate:register_usernet_rule:" <> - "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem,vlan_vid=0x1000/0x1000,dl_dst={mac}," <> - "actions=strip_vlan,output:{port_no}") do + describe "associate:register_usernet_rule:" <> + "idle_timeout={itimeout},hard_timeout={htimeout},send_flow_rem,vlan_vid=0x1000/0x1000,dl_dst={mac}," <> + "actions=strip_vlan,output:{port_no}" do test "Install Flow", state do match = Openflow.Match.new(vlan_vid: @vlan_present, eth_dst: @mac) - actions = [ - Openflow.Action.PopVlan.new, - Openflow.Action.Output.new(state.port.number)] + actions = [Openflow.Action.PopVlan.new(), Openflow.Action.Output.new(state.port.number)] ins = [Openflow.Instruction.ApplyActions.new(actions)] - options = - [cookie: state.cookie2, - table_id: 1, - priority: 50, - flags: [:send_flow_rem], - idle_timeout: state.timeout, - hard_timeout: state.timeout, - match: match, - instructions: ins] + + options = [ + cookie: state.cookie2, + table_id: 1, + priority: 50, + flags: [:send_flow_rem], + idle_timeout: state.timeout, + hard_timeout: state.timeout, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -783,26 +884,31 @@ defmodule FlogTest do end end - describe("associate:register_usernet_rule:" <> - "dl_vlan={vlan},dl_dst={mcast}," <> - "actions=output:{vlan_trunk_port},strip_vlan,{outputs}") do + describe "associate:register_usernet_rule:" <> + "dl_vlan={vlan},dl_dst={mcast}," <> + "actions=output:{vlan_trunk_port},strip_vlan,{outputs}" do test "Install Flow", state do match = Openflow.Match.new(vlan_vid: @user_vid, eth_dst: @mcast) + actions = [ Openflow.Action.Output.new(state.vlan_trunk.number), - Openflow.Action.PopVlan.new, + Openflow.Action.PopVlan.new(), Openflow.Action.Output.new(state.port.number), Openflow.Action.Output.new(state.port2.number) ] + ins = [Openflow.Instruction.ApplyActions.new(actions)] - options = - [cookie: state.cookie2, - table_id: 1, - priority: 60, - match: match, - instructions: ins] + + options = [ + cookie: state.cookie2, + table_id: 1, + priority: 60, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -840,10 +946,12 @@ defmodule FlogTest do arp_header = arp(op: 1, sha: shost, tip: @client_ip, sip: @gateway_ip) packet = [ether_header, arp_header] Pf.inject!(pid1, packet) + expects = [ {@vlan_trunk_port_sniffer, [vlan_ether_header, vlan_header, arp_header]}, {@access_port2_sniffer, [ether_header, arp_header]} ] + :ok = assert_receives(expects) Pf.stop(pid1) Pf.stop(pid2) @@ -851,39 +959,46 @@ defmodule FlogTest do end end - describe("associate:register_usernet_rule:" <> - "dl_vlan={vlan}," <> - "actions=output:{vlan_trunk_port},strip_vlan,{outputs}") do + describe "associate:register_usernet_rule:" <> + "dl_vlan={vlan}," <> "actions=output:{vlan_trunk_port},strip_vlan,{outputs}" do test "Install Flow", state do match = Openflow.Match.new(vlan_vid: @user_vid) + actions = [ Openflow.Action.Output.new(state.vlan_trunk.number), - Openflow.Action.PopVlan.new, - Openflow.Action.Output.new(state.port.number)] + Openflow.Action.PopVlan.new(), + Openflow.Action.Output.new(state.port.number) + ] + ins = [Openflow.Instruction.ApplyActions.new(actions)] - options = - [cookie: state.cookie2, - table_id: 1, - priority: 20, - match: match, - instructions: ins] + + options = [ + cookie: state.cookie2, + table_id: 1, + priority: 20, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end - describe("switch:register_farm_nat_rule:" <> - "dl_src={src_mac},arp,arp_spa={src_ip},arp_tpa={dst_ip}," <> - "actions=set_field:{farm_vmac}->eth_dst,set_field:{src_fip}->arp_spa," <> - "set_field:{dst_fip}->arp_tpa,output:{vlan_trunk_port}") do + describe "switch:register_farm_nat_rule:" <> + "dl_src={src_mac},arp,arp_spa={src_ip},arp_tpa={dst_ip}," <> + "actions=set_field:{farm_vmac}->eth_dst,set_field:{src_fip}->arp_spa," <> + "set_field:{dst_fip}->arp_tpa,output:{vlan_trunk_port}" do test "Install Flow", state do - match = Openflow.Match.new( - eth_src: @mac, - eth_type: 0x0806, - arp_spa: @client_ip, - arp_tpa: @gateway_ip - ) + match = + Openflow.Match.new( + eth_src: @mac, + eth_type: 0x0806, + arp_spa: @client_ip, + arp_tpa: @gateway_ip + ) + actions = [ Openflow.Action.SetField.new({:eth_dst, @farm_gw_mac}), Openflow.Action.SetField.new({:arp_spa, @client_farm_ip}), @@ -891,51 +1006,61 @@ defmodule FlogTest do # Following is not work properly in "SwitchNode" configuration. # Openflow.Action.PushVlan.new, # Openflow.Action.SetField.new({:vlan_vid, @user_vid}), - Openflow.Action.Output.new(state.vlan_trunk.number), + Openflow.Action.Output.new(state.vlan_trunk.number) ] + ins = [Openflow.Instruction.ApplyActions.new(actions)] - options = - [cookie: 0x3000000000000001, - table_id: 1, - priority: 30, - idle_timeout: 60, - match: match, - instructions: ins] + + options = [ + cookie: 0x3000000000000001, + table_id: 1, + priority: 30, + idle_timeout: 60, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end end - describe("switch:register_farm_nat_rule:" <> - "dl_src={src_mac},ip,nw_src={src_ip},nw_dst={dst_ip}," <> - "actions=push_vlan:0x8100,set_field:{vlan}->vlan_vid,set_field:{farm_vmac}->eth_dst," <> - "set_field:{src_fip}->nw_src,output:{vlan_trunk_port}") do + describe "switch:register_farm_nat_rule:" <> + "dl_src={src_mac},ip,nw_src={src_ip},nw_dst={dst_ip}," <> + "actions=push_vlan:0x8100,set_field:{vlan}->vlan_vid,set_field:{farm_vmac}->eth_dst," <> + "set_field:{src_fip}->nw_src,output:{vlan_trunk_port}" do test "Install Flow", state do - match = Openflow.Match.new( - eth_src: @mac, - eth_type: 0x0800, - ipv4_src: @client_ip, - ipv4_dst: @internet - ) + match = + Openflow.Match.new( + eth_src: @mac, + eth_type: 0x0800, + ipv4_src: @client_ip, + ipv4_dst: @internet + ) + actions = [ Openflow.Action.SetField.new({:eth_dst, @farm_gw_mac}), # Following is not work properly in "SwitchNode" configuration. # Openflow.Action.PushVlan.new, # Openflow.Action.SetField.new({:vlan_vid, @user_vid}), Openflow.Action.SetField.new({:ipv4_src, @client_farm_ip}), - Openflow.Action.Output.new(state.vlan_trunk.number), + Openflow.Action.Output.new(state.vlan_trunk.number) ] + ins = [Openflow.Instruction.ApplyActions.new(actions)] - options = - [cookie: 0x3000000000000001, - table_id: 1, - priority: 30, - idle_timeout: 60, - match: match, - instructions: ins] + + options = [ + cookie: 0x3000000000000001, + table_id: 1, + priority: 30, + idle_timeout: 60, + match: match, + instructions: ins + ] + :ok = GenServer.cast(Flay, {:flow_install, options, self()}) - :timer.sleep 1000 + :timer.sleep(1000) refute_receive %Openflow.ErrorMsg{}, 1000 end @@ -947,15 +1072,18 @@ defmodule FlogTest do dhost = Openflow.Match.Field.codec(@sdl_vmac, :eth_dst) payload = "" - tcp_header = tcp( - sport: 53_688, - dport: 80, - seqno: 1_488_352_223, - off: 10, - syn: 1, - win: 29_200, - opt: <<2, 4, 5, 180, 4, 2, 8, 10, 156, 30, 232, 154, 0, 0, 0, 0, 1, 3, 3, 7>> - ) + + tcp_header = + tcp( + sport: 53_688, + dport: 80, + seqno: 1_488_352_223, + off: 10, + syn: 1, + win: 29_200, + opt: <<2, 4, 5, 180, 4, 2, 8, 10, 156, 30, 232, 154, 0, 0, 0, 0, 1, 3, 3, 7>> + ) + ipv4_header = ipv4(saddr: @client_ip, daddr: @internet, p: 6, len: 60) tcp_sum = :pkt.makesum([ipv4_header, tcp_header, payload]) ether_header = ether(dhost: dhost, shost: shost, type: 0x0800) @@ -968,7 +1096,14 @@ defmodule FlogTest do vlan_header = {:"802.1q", 0, 0, 123, 0x0800} ipv4_header = ipv4(saddr: @client_farm_ip, daddr: @internet, p: 6, len: 60) tcp_sum = :pkt.makesum([ipv4_header, tcp_header, payload]) - expect = [ether_header, vlan_header, ipv4(ipv4_header, sum: 1544), tcp(tcp_header, sum: tcp_sum)] + + expect = [ + ether_header, + vlan_header, + ipv4(ipv4_header, sum: 1544), + tcp(tcp_header, sum: tcp_sum) + ] + assert_receives([{@vlan_trunk_port_sniffer, expect}], 5000) Pf.stop(pid1) Pf.stop(pid2) @@ -982,12 +1117,14 @@ defmodule FlogTest do end defp assert_receives(_expects, 0, _timeout), do: :ok + defp assert_receives(expects, count, timeout) do receive do message -> assert(message in expects) assert_receives(expects, count - 1, timeout) - after timeout -> + after + timeout -> flunk("Timeout") end end @@ -1011,6 +1148,7 @@ defmodule FlogTest do case Process.whereis(Flay) do nil -> wait_for_connected() + pid when is_pid(pid) -> :ok end @@ -1018,7 +1156,7 @@ defmodule FlogTest do defp flow_del_by_cookie(context) do :ok = GenServer.cast(Flay, {:flow_del, context.cookie}) - :timer.sleep 3000 + :timer.sleep(3000) end defp get_ports_desc do diff --git a/test/ofp_action_test.exs b/test/ofp_action_test.exs index 061d036..146b27d 100644 --- a/test/ofp_action_test.exs +++ b/test/ofp_action_test.exs @@ -6,11 +6,13 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_bundle.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) + bundle = Openflow.Action.NxBundle.new( algorithm: :highest_random_weight, - slaves: [4, 8] + slaves: [4, 8] ) + actions_bin = Openflow.Action.to_binary(bundle) assert actions_bin == packet assert actions == [bundle] @@ -20,12 +22,14 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_bundle_load.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) + bundle_load = Openflow.Action.NxBundleLoad.new( algorithm: :highest_random_weight, slaves: [4, 8], dst_field: :reg0 ) + actions_bin = Openflow.Action.to_binary(bundle_load) assert actions_bin == packet assert actions == [bundle_load] @@ -35,11 +39,14 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_controller.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - controller = Openflow.Action.NxController.new( - max_len: 1234, - reason: :invalid_ttl, - id: 5678 - ) + + controller = + Openflow.Action.NxController.new( + max_len: 1234, + reason: :invalid_ttl, + id: 5678 + ) + actions_bin = Openflow.Action.to_binary(controller) assert actions_bin == packet assert actions == [controller] @@ -49,12 +56,15 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_controller2.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - controller2 = Openflow.Action.NxController2.new( - max_len: 1234, - reason: :invalid_ttl, - userdata: <<1,2,3,4,5>>, - pause: true - ) + + controller2 = + Openflow.Action.NxController2.new( + max_len: 1234, + reason: :invalid_ttl, + userdata: <<1, 2, 3, 4, 5>>, + pause: true + ) + assert actions == [controller2] end @@ -102,13 +112,19 @@ defmodule OfpActionTest do test "with ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63]))" do test_file = "test/packet_data/nx_ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63])).raw" + packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_label, value: 0, offset: 64, n_bits: 64), - Openflow.Action.NxRegLoad.new(dst_field: :ct_label, value: 0x1d, n_bits: 64)] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxRegLoad.new(dst_field: :ct_label, value: 0, offset: 64, n_bits: 64), + Openflow.Action.NxRegLoad.new(dst_field: :ct_label, value: 0x1D, n_bits: 64) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -118,10 +134,13 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_mark, value: 0xf009)] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_mark, value: 0xF009)] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -131,10 +150,13 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[])).raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new( - flags: [:commit, :force], - exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_mark, value: 0xf009)] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit, :force], + exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_mark, value: 0xF009)] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -144,10 +166,13 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct(commit,nat(dst)).raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [Openflow.Action.NxNat.new(flags: [:dst])] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxNat.new(flags: [:dst])] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -159,16 +184,19 @@ defmodule OfpActionTest do actions = Openflow.Action.read(packet) {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.128') {:ok, ipv4_max} = :inet.parse_ipv4_address('10.0.0.254') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [ - Openflow.Action.NxNat.new( - flags: [:dst, :protocol_hash], - ipv4_min: ipv4_min, - ipv4_max: ipv4_max - ) - ] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:dst, :protocol_hash], + ipv4_min: ipv4_min, + ipv4_max: ipv4_max + ) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -178,10 +206,13 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct(commit,nat(src)).raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [Openflow.Action.NxNat.new(flags: [:src])] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxNat.new(flags: [:src])] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -192,38 +223,46 @@ defmodule OfpActionTest do packet = File.read!(test_file) actions = Openflow.Action.read(packet) {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.240') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [ - Openflow.Action.NxNat.new( - flags: [:src, :protocol_random], - ipv4_min: ipv4_min - ) - ] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv4_min: ipv4_min + ) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] end test "with ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent))" do - test_file = "test/packet_data/nx_ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent)).raw" + test_file = + "test/packet_data/nx_ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent)).raw" + packet = File.read!(test_file) actions = Openflow.Action.read(packet) {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.240') {:ok, ipv4_max} = :inet.parse_ipv4_address('10.0.0.254') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [ - Openflow.Action.NxNat.new( - flags: [:src, :persistent], - ipv4_min: ipv4_min, - ipv4_max: ipv4_max, - proto_min: 32_768, - proto_max: 65_535 - ) - ] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :persistent], + ipv4_min: ipv4_min, + ipv4_max: ipv4_max, + proto_min: 32_768, + proto_max: 65_535 + ) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -234,61 +273,74 @@ defmodule OfpActionTest do packet = File.read!(test_file) actions = Openflow.Action.read(packet) {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.240') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [ - Openflow.Action.NxNat.new( - flags: [:src, :protocol_random], - ipv4_min: ipv4_min, - proto_min: 32_768, - proto_max: 65_535 - ) - ] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv4_min: ipv4_min, + proto_min: 32_768, + proto_max: 65_535 + ) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] end test "with ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random))" do - test_file = "test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random)).raw" + test_file = + "test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random)).raw" + packet = File.read!(test_file) actions = Openflow.Action.read(packet) {:ok, ipv6_min} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:1') {:ok, ipv6_max} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:a18b') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [ - Openflow.Action.NxNat.new( - flags: [:src, :protocol_random], - ipv6_min: ipv6_min, - ipv6_max: ipv6_max, - proto_min: 255, - proto_max: 4096 - ) - ] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv6_min: ipv6_min, + ipv6_max: ipv6_max, + proto_min: 255, + proto_max: 4096 + ) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] end test "with ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random))" do - test_file = "test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random)).raw" + test_file = + "test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random)).raw" + packet = File.read!(test_file) actions = Openflow.Action.read(packet) {:ok, ipv6_min} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:1') {:ok, ipv6_max} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:a18b') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [ - Openflow.Action.NxNat.new( - flags: [:src, :protocol_random], - ipv6_min: ipv6_min, - ipv6_max: ipv6_max - ) - ] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv6_min: ipv6_min, + ipv6_max: ipv6_max + ) + ] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -299,10 +351,13 @@ defmodule OfpActionTest do packet = File.read!(test_file) actions = Openflow.Action.read(packet) {:ok, ipv6_min} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:a18b') - ct = Openflow.Action.NxConntrack.new( - flags: [:commit], - exec: [Openflow.Action.NxNat.new(flags: [:src, :protocol_random], ipv6_min: ipv6_min)] - ) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxNat.new(flags: [:src, :protocol_random], ipv6_min: ipv6_min)] + ) + actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -312,7 +367,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct(nat).raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new(exec: [Openflow.Action.NxNat.new]) + ct = Openflow.Action.NxConntrack.new(exec: [Openflow.Action.NxNat.new()]) actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -352,7 +407,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxConntrack.new + ct = Openflow.Action.NxConntrack.new() actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -362,7 +417,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_ct_clear.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - ct = Openflow.Action.NxCtClear.new + ct = Openflow.Action.NxCtClear.new() actions_bin = Openflow.Action.to_binary(ct) assert actions_bin == packet assert actions == [ct] @@ -372,7 +427,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_dec_ttl.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - dec_ttl = Openflow.Action.NxDecTtl.new + dec_ttl = Openflow.Action.NxDecTtl.new() actions_bin = Openflow.Action.to_binary(dec_ttl) assert actions_bin == packet assert actions == [dec_ttl] @@ -392,7 +447,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_exit.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - exit = Openflow.Action.NxExit.new + exit = Openflow.Action.NxExit.new() actions_bin = Openflow.Action.to_binary(exit) assert actions_bin == packet assert actions == [exit] @@ -412,21 +467,24 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_learn.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - learn = Openflow.Action.NxLearn.new( - idle_timeout: 10, - hard_timeout: 20, - priority: 80, - cookie: 0x123456789abcdef0, - flags: [], - table_id: 2, - fin_idle_timeout: 2, - fin_hard_timeout: 4, - flow_specs: [ - Openflow.Action.NxFlowSpecMatch.new(src: :nx_vlan_tci, dst: :nx_vlan_tci, n_bits: 12), - Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), - Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port) - ] - ) + + learn = + Openflow.Action.NxLearn.new( + idle_timeout: 10, + hard_timeout: 20, + priority: 80, + cookie: 0x123456789ABCDEF0, + flags: [], + table_id: 2, + fin_idle_timeout: 2, + fin_hard_timeout: 4, + flow_specs: [ + Openflow.Action.NxFlowSpecMatch.new(src: :nx_vlan_tci, dst: :nx_vlan_tci, n_bits: 12), + Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), + Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port) + ] + ) + actions_bin = Openflow.Action.to_binary(learn) assert actions_bin == packet assert actions == [learn] @@ -436,24 +494,27 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_learn2.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - learn2 = Openflow.Action.NxLearn2.new( - idle_timeout: 10, - hard_timeout: 20, - priority: 80, - cookie: 0x123456789abcdef0, - flags: [:write_result], - table_id: 2, - fin_idle_timeout: 2, - fin_hard_timeout: 4, - limit: 1, - result_dst: :reg0, - result_dst_offset: 8, - flow_specs: [ - Openflow.Action.NxFlowSpecMatch.new(src: :nx_vlan_tci, dst: :nx_vlan_tci, n_bits: 12), - Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), - Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port) - ] - ) + + learn2 = + Openflow.Action.NxLearn2.new( + idle_timeout: 10, + hard_timeout: 20, + priority: 80, + cookie: 0x123456789ABCDEF0, + flags: [:write_result], + table_id: 2, + fin_idle_timeout: 2, + fin_hard_timeout: 4, + limit: 1, + result_dst: :reg0, + result_dst_offset: 8, + flow_specs: [ + Openflow.Action.NxFlowSpecMatch.new(src: :nx_vlan_tci, dst: :nx_vlan_tci, n_bits: 12), + Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), + Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port) + ] + ) + actions_bin = Openflow.Action.to_binary(learn2) assert actions_bin == packet assert actions == [learn2] @@ -463,11 +524,14 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_multipath.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - multipath = Openflow.Action.NxMultipath.new( - algorithm: :modulo_n, - basis: 50, - dst_field: :reg0 - ) + + multipath = + Openflow.Action.NxMultipath.new( + algorithm: :modulo_n, + basis: 50, + dst_field: :reg0 + ) + actions_bin = Openflow.Action.to_binary(multipath) assert actions_bin == packet assert actions == [multipath] @@ -477,7 +541,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_note.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - note = Openflow.Action.NxNote.new(<<0x11, 0xe9, 0x9a, 0xad, 0x67, 0xf3>>) + note = Openflow.Action.NxNote.new(<<0x11, 0xE9, 0x9A, 0xAD, 0x67, 0xF3>>) actions_bin = Openflow.Action.to_binary(note) assert actions_bin == packet assert actions == [note] @@ -507,7 +571,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_pop_queue.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - pop_queue = Openflow.Action.NxPopQueue.new + pop_queue = Openflow.Action.NxPopQueue.new() actions_bin = Openflow.Action.to_binary(pop_queue) assert actions_bin == packet assert actions == [pop_queue] @@ -517,7 +581,7 @@ defmodule OfpActionTest do test_file = "test/packet_data/nx_reg_load.raw" packet = File.read!(test_file) actions = Openflow.Action.read(packet) - reg_load = Openflow.Action.NxRegLoad.new(dst_field: :nx_vlan_tci, value: 0xf009) + reg_load = Openflow.Action.NxRegLoad.new(dst_field: :nx_vlan_tci, value: 0xF009) actions_bin = Openflow.Action.to_binary(reg_load) assert actions_bin == packet assert actions == [reg_load] diff --git a/test/ofp_echo_test.exs b/test/ofp_echo_test.exs index 13aa181..5e21fed 100644 --- a/test/ofp_echo_test.exs +++ b/test/ofp_echo_test.exs @@ -6,8 +6,9 @@ defmodule OfpEchoTest do test "with OFP_ECHO_REQUEST packet" do {:ok, %Openflow.Echo.Request{} = echo, ""} = "test/packet_data/ofp_echo_request.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert echo.version == 4 assert echo.xid == 0 assert echo.data == "" @@ -16,8 +17,9 @@ defmodule OfpEchoTest do test "with OFP_ECHO_REPLY packet" do {:ok, %Openflow.Echo.Reply{} = echo, ""} = "test/packet_data/ofp_echo_reply.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert echo.version == 4 assert echo.xid == 0 assert echo.data == "" @@ -31,9 +33,11 @@ defmodule OfpEchoTest do xid: 0, data: "" } + expect = "test/packet_data/ofp_echo_request.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(echo) == expect end @@ -43,9 +47,11 @@ defmodule OfpEchoTest do xid: 0, data: "" } + expect = "test/packet_data/ofp_echo_reply.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(echo) == expect end end diff --git a/test/ofp_error_test.exs b/test/ofp_error_test.exs index a7c9de1..b49f6bf 100644 --- a/test/ofp_error_test.exs +++ b/test/ofp_error_test.exs @@ -6,8 +6,9 @@ defmodule OfpErrorTest do test "with OFP_ERROR packet" do {:ok, error, ""} = "test/packet_data/ofp_error.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert error.version == 4 assert error.xid == 0 assert error.type == :bad_action @@ -19,35 +20,55 @@ defmodule OfpErrorTest do describe "Openflow.to_binary/1" do test "with %Openflow.Error{}" do error = %Openflow.ErrorMsg{ - version: 4, + version: 4, xid: 0, type: :bad_action, code: :unsupported_order, - data: "fugafuga", + data: "fugafuga" } expect = "test/packet_data/ofp_error.raw" - |> File.read! + |> File.read!() assert Openflow.to_binary(error) == expect end test "with experimenter %Openflow.Error{}" do error = %Openflow.ErrorMsg{ - version: 4, + version: 4, xid: 0, type: :experimenter, exp_type: 1, - experimenter: 0xdeadbeef, - data: "hogehoge", + experimenter: 0xDEADBEEF, + data: "hogehoge" } expect = << - 4, 1, 0, 24, 0, 0, 0, - 0, 255, 255, 0, 1, 222, - 173, 190, 239, 104, 111, 103, - 101, 104, 111, 103, 101 + 4, + 1, + 0, + 24, + 0, + 0, + 0, + 0, + 255, + 255, + 0, + 1, + 222, + 173, + 190, + 239, + 104, + 111, + 103, + 101, + 104, + 111, + 103, + 101 >> assert Openflow.to_binary(error) == expect diff --git a/test/ofp_features_test.exs b/test/ofp_features_test.exs index b03960c..5d38572 100644 --- a/test/ofp_features_test.exs +++ b/test/ofp_features_test.exs @@ -6,8 +6,9 @@ defmodule OfpFeaturesTest do test "with OFP_FEATURES_REQUEST packet" do {:ok, %Openflow.Features.Request{} = features, ""} = "test/packet_data/ofp_features_request.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert features.version == 4 assert features.xid == 0 end @@ -15,15 +16,23 @@ defmodule OfpFeaturesTest do test "with OFP_FEATURES_REPLY packet" do {:ok, %Openflow.Features.Reply{} = features, ""} = "test/packet_data/ofp_features_reply.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert features.version == 4 assert features.xid == 0 assert features.datapath_id == "0000000000000001" assert features.n_buffers == 255 assert features.n_tables == 255 assert features.aux_id == 0 - assert features.capabilities == [:flow_stats, :table_stats, :port_stats, :group_stats, :queue_stats] + + assert features.capabilities == [ + :flow_stats, + :table_stats, + :port_stats, + :group_stats, + :queue_stats + ] end end @@ -33,9 +42,11 @@ defmodule OfpFeaturesTest do version: 4, xid: 0 } + expect = "test/packet_data/ofp_features_request.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(features) == expect end end @@ -48,11 +59,13 @@ defmodule OfpFeaturesTest do n_buffers: 255, n_tables: 255, aux_id: 0, - capabilities: [:flow_stats, :table_stats, :port_stats, :group_stats, :queue_stats], + capabilities: [:flow_stats, :table_stats, :port_stats, :group_stats, :queue_stats] } + expect = "test/packet_data/ofp_features_reply.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(features) == expect end end diff --git a/test/ofp_flow_mod_test.exs b/test/ofp_flow_mod_test.exs index 81661a2..9671698 100644 --- a/test/ofp_flow_mod_test.exs +++ b/test/ofp_flow_mod_test.exs @@ -23,37 +23,39 @@ defmodule OfpFlowModTest do assert fm.idle_timeout == 0 assert fm.hard_timeout == 0 assert fm.priority == 123 - assert fm.buffer_id == 0xffff + assert fm.buffer_id == 0xFFFF assert fm.out_port == :any assert fm.out_group == :any assert fm.flags == [] assert fm.match == Openflow.Match.new(eth_dst: "f20ba47df8ea") + assert fm.instructions == [ - Openflow.Instruction.WriteActions.new([ - Openflow.Action.SetField.new({:vlan_vid, 258}), - Openflow.Action.CopyTtlOut.new, - Openflow.Action.CopyTtlIn.new, - Openflow.Action.CopyTtlIn.new, - Openflow.Action.PopPbb.new, - Openflow.Action.PushPbb.new(4660), - Openflow.Action.PopMpls.new(39030), - Openflow.Action.PushMpls.new(34887), - Openflow.Action.PopVlan.new, - Openflow.Action.PushVlan.new(33024), - Openflow.Action.DecMplsTtl.new, - Openflow.Action.SetMplsTtl.new(10), - Openflow.Action.DecNwTtl.new, - Openflow.Action.SetNwTtl.new(10), - Openflow.Action.Experimenter.new(101, <<0, 1, 2, 3, 4, 5, 6, 7>>), - Openflow.Action.SetQueue.new(3), - Openflow.Action.Group.new(99), - Openflow.Action.Output.new(6) - ]), - Openflow.Instruction.ApplyActions.new([ - Openflow.Action.SetField.new({:eth_src, "010203040506"}), - Openflow.Action.SetField.new({:onf_pbb_uca, 1}) - ]) - ] + Openflow.Instruction.WriteActions.new([ + Openflow.Action.SetField.new({:vlan_vid, 258}), + Openflow.Action.CopyTtlOut.new(), + Openflow.Action.CopyTtlIn.new(), + Openflow.Action.CopyTtlIn.new(), + Openflow.Action.PopPbb.new(), + Openflow.Action.PushPbb.new(4660), + Openflow.Action.PopMpls.new(39030), + Openflow.Action.PushMpls.new(34887), + Openflow.Action.PopVlan.new(), + Openflow.Action.PushVlan.new(33024), + Openflow.Action.DecMplsTtl.new(), + Openflow.Action.SetMplsTtl.new(10), + Openflow.Action.DecNwTtl.new(), + Openflow.Action.SetNwTtl.new(10), + Openflow.Action.Experimenter.new(101, <<0, 1, 2, 3, 4, 5, 6, 7>>), + Openflow.Action.SetQueue.new(3), + Openflow.Action.Group.new(99), + Openflow.Action.Output.new(6) + ]), + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.SetField.new({:eth_src, "010203040506"}), + Openflow.Action.SetField.new({:onf_pbb_uca, 1}) + ]) + ] + assert Openflow.to_binary(fm) == binary end @@ -69,7 +71,7 @@ defmodule OfpFlowModTest do assert fm.idle_timeout == 0 assert fm.hard_timeout == 0 assert fm.priority == 123 - assert fm.buffer_id == 0xffff + assert fm.buffer_id == 0xFFFF assert fm.out_port == :any assert fm.out_group == :any assert fm.flags == [] @@ -89,15 +91,17 @@ defmodule OfpFlowModTest do assert fm.idle_timeout == 0 assert fm.hard_timeout == 0 assert fm.priority == 123 - assert fm.buffer_id == 0xffff + assert fm.buffer_id == 0xFFFF assert fm.out_port == :any assert fm.out_group == :any assert fm.flags == [] assert fm.match == Openflow.Match.new(eth_dst: "f20ba47df8ea") + assert fm.instructions == [ - Openflow.Instruction.Meter.new(1), - Openflow.Instruction.WriteActions.new([Openflow.Action.Output.new(6)]) - ] + Openflow.Instruction.Meter.new(1), + Openflow.Instruction.WriteActions.new([Openflow.Action.Output.new(6)]) + ] + assert Openflow.to_binary(fm) == binary end @@ -112,54 +116,57 @@ defmodule OfpFlowModTest do assert fm.idle_timeout == 0 assert fm.hard_timeout == 0 assert fm.priority == 123 - assert fm.buffer_id == 0xffff + assert fm.buffer_id == 0xFFFF assert fm.out_port == :any assert fm.out_group == :any assert fm.flags == [] - assert fm.match == Openflow.Match.new( - in_port: 84_281_096, - in_phy_port: 16_909_060, - metadata: 283_686_952_306_183, - eth_type: 2054, - eth_dst: "ffffffffffff", - eth_src: "f20ba47df8ea", - vlan_vid: 999, - ip_dscp: 9, - ip_ecn: 3, - ip_proto: 99, - ipv4_src: {1, 2, 3, 4}, - ipv4_dst: {1, 2, 3, 4}, - tcp_src: 8080, - tcp_dst: 18_080, - udp_src: 28_080, - udp_dst: 55_936, - sctp_src: 48_080, - sctp_dst: 59_328, - icmpv4_type: 100, - icmpv4_code: 101, - arp_op: 1, - arp_spa: {10, 0, 0, 1}, - arp_tpa: {10, 0, 0, 3}, - arp_sha: "f20ba47df8ea", - arp_tha: "000000000000", - ipv6_src: {65152, 0, 0, 0, 61451, 42239, 65096, 10405}, - ipv6_dst: {65152, 0, 0, 0, 61451, 42239, 65029, 47068}, - ipv6_flabel: 541_473, - icmpv6_type: 200, - icmpv6_code: 201, - ipv6_nd_target: {65152, 0, 0, 0, 2656, 28415, 65151, 29927}, - ipv6_nd_sll: "00000000029a", - ipv6_nd_tll: "00000000022b", - mpls_label: 624_485, - mpls_tc: 5, - mpls_bos: 1, - pbb_isid: 11_259_375, - tunnel_id: 651061555542690057, - ipv6_exthdr: [:auth, :frag, :router, :hop, :unrep, :unseq], - onf_pbb_uca: 1, - tun_src: {1, 2, 3, 4}, - tun_dst: {1, 2, 3, 4} - ) + + assert fm.match == + Openflow.Match.new( + in_port: 84_281_096, + in_phy_port: 16_909_060, + metadata: 283_686_952_306_183, + eth_type: 2054, + eth_dst: "ffffffffffff", + eth_src: "f20ba47df8ea", + vlan_vid: 999, + ip_dscp: 9, + ip_ecn: 3, + ip_proto: 99, + ipv4_src: {1, 2, 3, 4}, + ipv4_dst: {1, 2, 3, 4}, + tcp_src: 8080, + tcp_dst: 18_080, + udp_src: 28_080, + udp_dst: 55_936, + sctp_src: 48_080, + sctp_dst: 59_328, + icmpv4_type: 100, + icmpv4_code: 101, + arp_op: 1, + arp_spa: {10, 0, 0, 1}, + arp_tpa: {10, 0, 0, 3}, + arp_sha: "f20ba47df8ea", + arp_tha: "000000000000", + ipv6_src: {65152, 0, 0, 0, 61451, 42239, 65096, 10405}, + ipv6_dst: {65152, 0, 0, 0, 61451, 42239, 65029, 47068}, + ipv6_flabel: 541_473, + icmpv6_type: 200, + icmpv6_code: 201, + ipv6_nd_target: {65152, 0, 0, 0, 2656, 28415, 65151, 29927}, + ipv6_nd_sll: "00000000029a", + ipv6_nd_tll: "00000000022b", + mpls_label: 624_485, + mpls_tc: 5, + mpls_bos: 1, + pbb_isid: 11_259_375, + tunnel_id: 651_061_555_542_690_057, + ipv6_exthdr: [:auth, :frag, :router, :hop, :unrep, :unseq], + onf_pbb_uca: 1, + tun_src: {1, 2, 3, 4}, + tun_dst: {1, 2, 3, 4} + ) + assert fm.instructions == [] assert Openflow.to_binary(fm) == binary end @@ -168,8 +175,8 @@ defmodule OfpFlowModTest do binary = File.read!(@flow_mod5) {:ok, fm, ""} = Openflow.read(binary) - assert fm.cookie == 0x123456789abcdef0 - assert fm.cookie_mask == 0xffffffffffffffff + assert fm.cookie == 0x123456789ABCDEF0 + assert fm.cookie_mask == 0xFFFFFFFFFFFFFFFF assert fm.table_id == 2 assert fm.command == :add assert fm.idle_timeout == 0 @@ -179,51 +186,59 @@ defmodule OfpFlowModTest do assert fm.out_port == 0 assert fm.out_group == 0 assert fm.flags == [] - assert fm.match == Openflow.Match.new( - in_port: 43981, - eth_dst: "aabbcc998877", - eth_type: 2048, - vlan_vid: 5095, - ipv4_dst: {192, 168, 2, 1}, - tunnel_id: 50_000, - tun_src: {192, 168, 2, 3}, - tun_dst: {192, 168, 2, 4} - ) + + assert fm.match == + Openflow.Match.new( + in_port: 43981, + eth_dst: "aabbcc998877", + eth_type: 2048, + vlan_vid: 5095, + ipv4_dst: {192, 168, 2, 1}, + tunnel_id: 50_000, + tun_src: {192, 168, 2, 3}, + tun_dst: {192, 168, 2, 4} + ) + assert fm.instructions == [ - Openflow.Instruction.ApplyActions.new([ - Openflow.Action.PopVlan.new, - Openflow.Action.SetField.new({:ipv4_dst, {192, 168, 2, 9}}), - Openflow.Action.NxLearn.new( - hard_timeout: 300, - priority: 1, - table_id: 99, - flow_specs: [ - Openflow.Action.NxFlowSpecMatch.new(src: :vlan_vid, dst: :vlan_vid, n_bits: 12), - Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), - Openflow.Action.NxFlowSpecLoad.new(src: 0, dst: :vlan_vid, n_bits: 12), - Openflow.Action.NxFlowSpecLoad.new(src: :tun_id, dst: :tun_id), - Openflow.Action.NxFlowSpecOutput.new(src: :in_port) - ] - ) - ]), - Openflow.Instruction.GotoTable.new(100) - ] + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.PopVlan.new(), + Openflow.Action.SetField.new({:ipv4_dst, {192, 168, 2, 9}}), + Openflow.Action.NxLearn.new( + hard_timeout: 300, + priority: 1, + table_id: 99, + flow_specs: [ + Openflow.Action.NxFlowSpecMatch.new( + src: :vlan_vid, + dst: :vlan_vid, + n_bits: 12 + ), + Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), + Openflow.Action.NxFlowSpecLoad.new(src: 0, dst: :vlan_vid, n_bits: 12), + Openflow.Action.NxFlowSpecLoad.new(src: :tun_id, dst: :tun_id), + Openflow.Action.NxFlowSpecOutput.new(src: :in_port) + ] + ) + ]), + Openflow.Instruction.GotoTable.new(100) + ] + assert Openflow.to_binary(fm) == binary end - test "with OFP_FLOW_MOD packet(6)" do\ + test "with OFP_FLOW_MOD packet(6)" do {:error, :binary_too_small} = @flow_mod6 - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() end test "with OFP_FLOW_MOD packet(7)" do binary = File.read!(@flow_mod7) {:ok, fm, ""} = Openflow.read(binary) - assert fm.cookie == 0x123456789abcdef0 - assert fm.cookie_mask == 0xffffffffffffffff + assert fm.cookie == 0x123456789ABCDEF0 + assert fm.cookie_mask == 0xFFFFFFFFFFFFFFFF assert fm.table_id == 4 assert fm.command == :add assert fm.idle_timeout == 0 @@ -233,21 +248,25 @@ defmodule OfpFlowModTest do assert fm.out_port == 0 assert fm.out_group == 0 assert fm.flags == [] - assert fm.match == Openflow.Match.new( - in_port: 43981, - eth_dst: "aabbcc998877", - eth_type: 2048, - vlan_vid: 5095, - ipv4_dst: {192, 168, 2, 1}, - tunnel_id: 50_000, - tun_src: {192, 168, 2, 3}, - tun_dst: {192, 168, 2, 4} - ) + + assert fm.match == + Openflow.Match.new( + in_port: 43981, + eth_dst: "aabbcc998877", + eth_type: 2048, + vlan_vid: 5095, + ipv4_dst: {192, 168, 2, 1}, + tunnel_id: 50_000, + tun_src: {192, 168, 2, 3}, + tun_dst: {192, 168, 2, 4} + ) + assert fm.instructions == [ - Openflow.Instruction.ApplyActions.new([ - Openflow.Action.NxConjunction.new(clause: 1, id: 0xabcdef, n_clauses: 2) - ]) - ] + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.NxConjunction.new(clause: 1, id: 0xABCDEF, n_clauses: 2) + ]) + ] + assert Openflow.to_binary(fm) == binary end @@ -255,8 +274,8 @@ defmodule OfpFlowModTest do binary = File.read!(@flow_mod8) {:ok, fm, ""} = Openflow.read(binary) - assert fm.cookie == 0x123456789abcdef0 - assert fm.cookie_mask == 0xffffffffffffffff + assert fm.cookie == 0x123456789ABCDEF0 + assert fm.cookie_mask == 0xFFFFFFFFFFFFFFFF assert fm.table_id == 3 assert fm.command == :add assert fm.idle_timeout == 0 @@ -266,14 +285,16 @@ defmodule OfpFlowModTest do assert fm.out_port == 0 assert fm.out_group == 0 assert fm.flags == [] - assert fm.match == Openflow.Match.new(conj_id: 0xabcdef) + assert fm.match == Openflow.Match.new(conj_id: 0xABCDEF) + assert fm.instructions == [ - Openflow.Instruction.ApplyActions.new([ - Openflow.Action.PopVlan.new, - Openflow.Action.SetField.new({:ipv4_dst, {192, 168, 2, 9}}) - ]), - Openflow.Instruction.GotoTable.new(100) - ] + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.PopVlan.new(), + Openflow.Action.SetField.new({:ipv4_dst, {192, 168, 2, 9}}) + ]), + Openflow.Instruction.GotoTable.new(100) + ] + assert Openflow.to_binary(fm) == binary end end diff --git a/test/ofp_flow_removed_test.exs b/test/ofp_flow_removed_test.exs index 4a01473..056f78f 100644 --- a/test/ofp_flow_removed_test.exs +++ b/test/ofp_flow_removed_test.exs @@ -6,13 +6,13 @@ defmodule OfpFlowRemovedTest do test "with OFP_FLOW_REMOVED packet(with a match field)" do {:ok, flow_removed, ""} = "test/packet_data/4-40-ofp_flow_removed.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert flow_removed.version == 4 assert flow_removed.xid == 0 assert flow_removed.cookie == 0 - assert flow_removed.priority == 0xffff + assert flow_removed.priority == 0xFFFF assert flow_removed.reason == :idle_timeout assert flow_removed.table_id == 0 assert flow_removed.duration_sec == 3 @@ -27,12 +27,12 @@ defmodule OfpFlowRemovedTest do test "with OFP_FLOW_REMOVED packet(with match fields)" do {:ok, flow_removed, ""} = "test/packet_data/libofproto-OFP13-flow_removed.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert flow_removed.version == 4 assert flow_removed.xid == 0 - assert flow_removed.cookie == 0x123456789abcdef0 + assert flow_removed.cookie == 0x123456789ABCDEF0 assert flow_removed.priority == 100 assert flow_removed.reason == :idle_timeout assert flow_removed.table_id == 1 @@ -42,16 +42,17 @@ defmodule OfpFlowRemovedTest do assert flow_removed.hard_timeout == 300 assert flow_removed.packet_count == 200 assert flow_removed.byte_count == 100 + assert flow_removed.match == [ - in_port: 43_981, - eth_dst: "aabbcc998877", - eth_type: 2048, - vlan_vid: 5095, - ipv4_dst: {192, 168, 2, 1}, - tunnel_id: 50_000, - tun_src: {192, 168, 2, 3}, - tun_dst: {192, 168, 2, 4} - ] + in_port: 43_981, + eth_dst: "aabbcc998877", + eth_type: 2048, + vlan_vid: 5095, + ipv4_dst: {192, 168, 2, 1}, + tunnel_id: 50_000, + tun_src: {192, 168, 2, 3}, + tun_dst: {192, 168, 2, 4} + ] end end end diff --git a/test/ofp_get_config_test.exs b/test/ofp_get_config_test.exs index 524e99f..9c51812 100644 --- a/test/ofp_get_config_test.exs +++ b/test/ofp_get_config_test.exs @@ -6,8 +6,9 @@ defmodule OfpGetConfigTest do test "with OFP_GET_CONFIG_REQUEST packet" do {:ok, %Openflow.GetConfig.Request{} = config, ""} = "test/packet_data/ofp_get_config_request.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert config.version == 4 assert config.xid == 0 end @@ -15,8 +16,9 @@ defmodule OfpGetConfigTest do test "with OFP_GET_CONFIG_REPLY packet" do {:ok, %Openflow.GetConfig.Reply{} = config, ""} = "test/packet_data/ofp_get_config_reply.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert config.version == 4 assert config.xid == 0 assert config.flags == [] @@ -30,9 +32,11 @@ defmodule OfpGetConfigTest do version: 4, xid: 0 } + expect = "test/packet_data/ofp_get_config_request.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(config) == expect end @@ -43,9 +47,11 @@ defmodule OfpGetConfigTest do flags: [], miss_send_len: 128 } + expect = "test/packet_data/ofp_get_config_reply.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(config) == expect end end diff --git a/test/ofp_group_mod_test.exs b/test/ofp_group_mod_test.exs index cdf7e04..7081095 100644 --- a/test/ofp_group_mod_test.exs +++ b/test/ofp_group_mod_test.exs @@ -12,14 +12,16 @@ defmodule OfpGroupModTest do assert group_mod.command == :add assert group_mod.type == :all assert group_mod.group_id == 1 + assert group_mod.buckets == [ - Openflow.Bucket.new( - weight: 1, - watch_port: 1, - watch_group: 1, - actions: [Openflow.Action.Output.new(2)] - ) - ] + Openflow.Bucket.new( + weight: 1, + watch_port: 1, + watch_group: 1, + actions: [Openflow.Action.Output.new(2)] + ) + ] + assert Openflow.to_binary(group_mod) == binary end end diff --git a/test/ofp_hello_test.exs b/test/ofp_hello_test.exs index 0fd4b1e..5d47026 100644 --- a/test/ofp_hello_test.exs +++ b/test/ofp_hello_test.exs @@ -6,8 +6,9 @@ defmodule OfpHelloTest do test "with OFP_HELLO packet" do {:ok, hello, ""} = "test/packet_data/ofp_hello.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert hello.version == 4 assert hello.xid == 0 assert hello.elements == [versionbitmap: [30, 10, 9, 3, 2, 1]] @@ -17,9 +18,11 @@ defmodule OfpHelloTest do describe "Openflow.to_binary/1" do test "with %Openflow.Hello{}" do hello = Openflow.Hello.new([30, 10, 9, 3, 2, 1]) + expect = "test/packet_data/ofp_hello.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(hello) == expect end end diff --git a/test/ofp_packet_in_test.exs b/test/ofp_packet_in_test.exs index a59e22e..b39a9a8 100644 --- a/test/ofp_packet_in_test.exs +++ b/test/ofp_packet_in_test.exs @@ -6,8 +6,8 @@ defmodule OfpPacketInTest do test "with OFP_PACKET_IN packet(with simple matches)" do {:ok, pktin, ""} = "test/packet_data/4-4-ofp_packet_in.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert pktin.version == 4 assert pktin.xid == 0 @@ -15,73 +15,75 @@ defmodule OfpPacketInTest do assert pktin.table_id == 1 assert pktin.reason == :action assert pktin.in_port == 6 + assert pktin.match == [ - eth_type: 2054, - eth_dst: "ffffffffffff", - eth_src: "f20ba47df8ea", - arp_op: 1, - arp_spa: {10, 0, 0, 1}, - arp_tpa: {10, 0, 0, 3}, - arp_sha: "f20ba47df8ea", - arp_tha: "000000000000" - ] + eth_type: 2054, + eth_dst: "ffffffffffff", + eth_src: "f20ba47df8ea", + arp_op: 1, + arp_spa: {10, 0, 0, 1}, + arp_tpa: {10, 0, 0, 3}, + arp_sha: "f20ba47df8ea", + arp_tha: "000000000000" + ] end test "with OFP_PACKET_IN packet(with complex matches)" do {:ok, pktin, ""} = "test/packet_data/4-59-ofp_packet_in.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert pktin.version == 4 assert pktin.xid == 0 assert pktin.total_len == 0 assert pktin.table_id == 200 assert pktin.reason == :no_match - assert pktin.in_port == 84281096 + assert pktin.in_port == 84_281_096 + assert pktin.match == [ - in_phy_port: 16909060, - metadata: 283686952306183, - eth_type: 2054, - eth_dst: "ffffffffffff", - eth_src: "f20ba47df8ea", - vlan_vid: 999, - ip_dscp: 9, - ip_ecn: 3, - ip_proto: 99, - ipv4_src: {1, 2, 3, 4}, - ipv4_dst: {1, 2, 3, 4}, - tcp_src: 8080, - tcp_dst: 18080, - udp_src: 28080, - udp_dst: 55936, - sctp_src: 48080, - sctp_dst: 59328, - icmpv4_type: 100, - icmpv4_code: 101, - arp_op: 1, - arp_spa: {10, 0, 0, 1}, - arp_tpa: {10, 0, 0, 3}, - arp_sha: "f20ba47df8ea", - arp_tha: "000000000000", - ipv6_src: {65152, 0, 0, 0, 61451, 42239, 65096, 10405}, - ipv6_dst: {65152, 0, 0, 0, 61451, 42239, 65029, 47068}, - ipv6_flabel: 541473, - icmpv6_type: 200, - icmpv6_code: 201, - ipv6_nd_target: {65152, 0, 0, 0, 2656, 28415, 65151, 29927}, - ipv6_nd_sll: "00000000029a", - ipv6_nd_tll: "00000000022b", - mpls_label: 624485, - mpls_tc: 5, - mpls_bos: 1, - pbb_isid: 11259375, - tunnel_id: 651061555542690057, - ipv6_exthdr: [:auth, :frag, :router, :hop, :unrep, :unseq], - onf_pbb_uca: 1, - tun_src: {1, 2, 3, 4}, - tun_dst: {1, 2, 3, 4} - ] + in_phy_port: 16_909_060, + metadata: 283_686_952_306_183, + eth_type: 2054, + eth_dst: "ffffffffffff", + eth_src: "f20ba47df8ea", + vlan_vid: 999, + ip_dscp: 9, + ip_ecn: 3, + ip_proto: 99, + ipv4_src: {1, 2, 3, 4}, + ipv4_dst: {1, 2, 3, 4}, + tcp_src: 8080, + tcp_dst: 18080, + udp_src: 28080, + udp_dst: 55936, + sctp_src: 48080, + sctp_dst: 59328, + icmpv4_type: 100, + icmpv4_code: 101, + arp_op: 1, + arp_spa: {10, 0, 0, 1}, + arp_tpa: {10, 0, 0, 3}, + arp_sha: "f20ba47df8ea", + arp_tha: "000000000000", + ipv6_src: {65152, 0, 0, 0, 61451, 42239, 65096, 10405}, + ipv6_dst: {65152, 0, 0, 0, 61451, 42239, 65029, 47068}, + ipv6_flabel: 541_473, + icmpv6_type: 200, + icmpv6_code: 201, + ipv6_nd_target: {65152, 0, 0, 0, 2656, 28415, 65151, 29927}, + ipv6_nd_sll: "00000000029a", + ipv6_nd_tll: "00000000022b", + mpls_label: 624_485, + mpls_tc: 5, + mpls_bos: 1, + pbb_isid: 11_259_375, + tunnel_id: 651_061_555_542_690_057, + ipv6_exthdr: [:auth, :frag, :router, :hop, :unrep, :unseq], + onf_pbb_uca: 1, + tun_src: {1, 2, 3, 4}, + tun_dst: {1, 2, 3, 4} + ] end end end diff --git a/test/ofp_packet_out_test.exs b/test/ofp_packet_out_test.exs index 332ba10..07075da 100644 --- a/test/ofp_packet_out_test.exs +++ b/test/ofp_packet_out_test.exs @@ -3,27 +3,112 @@ defmodule OfpPacketOutTest do doctest Openflow @packet << - 0xf2, 0x0b, 0xa4, 0xd0, 0x3f, 0x70, 0xf2, 0x0b, - 0xa4, 0x7d, 0xf8, 0xea, 0x08, 0x00, 0x45, 0x00, - 0x00, 0x54, 0xf8, 0x1a, 0x00, 0x00, 0xff, 0x01, - 0xaf, 0x8b, 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, - 0x00, 0x02, 0x08, 0x00, 0x02, 0x08, 0xf7, 0x60, - 0x00, 0x00, 0x31, 0xd6, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xab, 0x8d, 0x2d, 0x31, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, - 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 + 0xF2, + 0x0B, + 0xA4, + 0xD0, + 0x3F, + 0x70, + 0xF2, + 0x0B, + 0xA4, + 0x7D, + 0xF8, + 0xEA, + 0x08, + 0x00, + 0x45, + 0x00, + 0x00, + 0x54, + 0xF8, + 0x1A, + 0x00, + 0x00, + 0xFF, + 0x01, + 0xAF, + 0x8B, + 0x0A, + 0x00, + 0x00, + 0x01, + 0x0A, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x02, + 0x08, + 0xF7, + 0x60, + 0x00, + 0x00, + 0x31, + 0xD6, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xAB, + 0x8D, + 0x2D, + 0x31, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x18, + 0x19, + 0x1A, + 0x1B, + 0x1C, + 0x1D, + 0x1E, + 0x1F, + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, + 0x26, + 0x27, + 0x28, + 0x29, + 0x2A, + 0x2B, + 0x2C, + 0x2D, + 0x2E, + 0x2F, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 >> describe "Openflow.read/1" do test "with OFP_PACKET_OUT packet" do {:ok, pktout, ""} = "test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert pktout.version == 4 assert pktout.xid == 0 @@ -37,12 +122,12 @@ defmodule OfpPacketOutTest do describe "Openflow.to_binary/1" do pktout = %Openflow.PacketOut{ actions: [Openflow.Action.Output.new(port_number: :all)], - data: @packet + data: @packet } expect = "test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet" - |> File.read! + |> File.read!() assert Openflow.to_binary(pktout) == expect end diff --git a/test/ofp_port_status_test.exs b/test/ofp_port_status_test.exs index fa6b5ea..0c667b1 100644 --- a/test/ofp_port_status_test.exs +++ b/test/ofp_port_status_test.exs @@ -6,8 +6,8 @@ defmodule OfpPortStatusTest do test "with OFP_PORT_STATUS packet" do {:ok, port_status, ""} = "test/packet_data/libofproto-OFP13-port_status.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert port_status.version == 4 assert port_status.xid == 0 @@ -27,8 +27,8 @@ defmodule OfpPortStatusTest do test "with OFP_PORT_STATUS packet(with kanji port name)" do {:ok, port_status, ""} = "test/packet_data/4-39-ofp_port_status.packet" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() assert port_status.version == 4 assert port_status.xid == 0 diff --git a/test/ofp_set_config_test.exs b/test/ofp_set_config_test.exs index 7266c6f..fd7b7e6 100644 --- a/test/ofp_set_config_test.exs +++ b/test/ofp_set_config_test.exs @@ -6,8 +6,9 @@ defmodule OfpSetConfigTest do test "with OFP_SET_CONFIG packet" do {:ok, %Openflow.SetConfig{} = config, ""} = "test/packet_data/ofp_set_config.raw" - |> File.read! - |> Openflow.read + |> File.read!() + |> Openflow.read() + assert config.version == 4 assert config.xid == 0 assert config.flags == [] @@ -23,9 +24,11 @@ defmodule OfpSetConfigTest do flags: [], miss_send_len: 128 } + expect = "test/packet_data/ofp_set_config.raw" - |> File.read! + |> File.read!() + assert Openflow.to_binary(config) == expect end end diff --git a/test/pf.ex b/test/pf.ex index 6257408..e96109c 100644 --- a/test/pf.ex +++ b/test/pf.ex @@ -8,11 +8,9 @@ defmodule Pf do end defmodule State do - defstruct [ - ifname: nil, - pcap_ref: nil, - tester_pid: nil - ] + defstruct ifname: nil, + pcap_ref: nil, + tester_pid: nil end def inject!(pid, packet, payload \\ "") do @@ -33,24 +31,28 @@ defmodule Pf do end def handle_cast({:inject, {headers, payload}}, state) do - headers_bin = for header <- headers do - case header do - ether() -> :pkt.ether(header) - {:"802.1q", _, _, _, _} = vlan -> :pkt_802_1q.codec(vlan) - arp() -> :pkt.arp(header) - ipv4() -> :pkt.ipv4(header) - lldp() -> :pkt.lldp(header) - udp() -> :pkt.udp(header) - tcp() -> :pkt.tcp(header) + headers_bin = + for header <- headers do + case header do + ether() -> :pkt.ether(header) + {:"802.1q", _, _, _, _} = vlan -> :pkt_802_1q.codec(vlan) + arp() -> :pkt.arp(header) + ipv4() -> :pkt.ipv4(header) + lldp() -> :pkt.lldp(header) + udp() -> :pkt.udp(header) + tcp() -> :pkt.tcp(header) + end end - end + binary = Enum.join(headers_bin, "") :epcap.send(state.pcap_ref, <>) {:noreply, state} end + def handle_cast(:stop, state) do {:stop, :normal, state} end + def handle_cast(_req, state) do {:noreply, state} end @@ -61,6 +63,7 @@ defmodule Pf do send(state.tester_pid, {to_string(state.ifname), Enum.take(packet, packet_len - 1)}) {:noreply, state} end + def handle_info(_info, state) do {:noreply, state} end