diff --git a/lib/openflow/actions/copy_ttl_in.ex b/lib/openflow/actions/copy_ttl_in.ex index 83347b4..6b4fd2c 100644 --- a/lib/openflow/actions/copy_ttl_in.ex +++ b/lib/openflow/actions/copy_ttl_in.ex @@ -1,18 +1,37 @@ defmodule Openflow.Action.CopyTtlIn do + @moduledoc """ + Copy the TTL from next-to-outermost to outermost header with TTL.\\ + Copy can be IP-to-IP, MPLS-to-MPLS, or IP-to-MPLS. + """ + defstruct([]) alias __MODULE__ + @type t :: %CopyTtlIn{} + + @spec ofpat() :: 12 def ofpat, do: 12 + @doc """ + Create a copy_ttl_in action struct + + ## Example: + ```elixir + iex> %CopyTtlIn{} = Openflow.Action.CopyTtlIn.new() + ``` + """ + @spec new() :: CopyTtlIn.t() def new do %CopyTtlIn{} end + @spec to_binary(CopyTtlIn.t()) :: <<_::16, _::_*8>> def to_binary(%CopyTtlIn{}) do <<12::16, 8::16, 0::size(4)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: CopyTtlIn.t() def read(<<12::16, 8::16, _::size(4)-unit(8)>>) do %CopyTtlIn{} end diff --git a/lib/openflow/actions/copy_ttl_out.ex b/lib/openflow/actions/copy_ttl_out.ex index 759c0ad..7ce6dcf 100644 --- a/lib/openflow/actions/copy_ttl_out.ex +++ b/lib/openflow/actions/copy_ttl_out.ex @@ -1,18 +1,38 @@ defmodule Openflow.Action.CopyTtlOut do + @moduledoc """ + Copy the TTL from outermost to next-to-outermost header with TTL.\\ + Copy can be IP-to-IP, MPLS-to-MPLS, or MPLS-to-IP. + """ + defstruct([]) alias __MODULE__ + @type t :: %CopyTtlOut{} + + @spec ofpat() :: 11 def ofpat, do: 11 + @doc """ + Create a copy_ttl_out action structure + + ## Example + + ```elixir + iex> %CopyTtlOut{} = Openflow.Action.CopyTtlOut.new() + ``` + """ + @spec new() :: CopyTtlOut.t() def new do %CopyTtlOut{} end + @spec to_binary(CopyTtlIn.t()) :: <<_::16, _::_*8>> def to_binary(%CopyTtlOut{}) do <<11::16, 8::16, 0::size(4)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: CopyTtlOut.t() def read(<<11::16, 8::16, _::size(4)-unit(8)>>) do %CopyTtlOut{} end diff --git a/lib/openflow/actions/dec_mpls_ttl.ex b/lib/openflow/actions/dec_mpls_ttl.ex index 2931954..d3309cd 100644 --- a/lib/openflow/actions/dec_mpls_ttl.ex +++ b/lib/openflow/actions/dec_mpls_ttl.ex @@ -1,18 +1,39 @@ defmodule Openflow.Action.DecMplsTtl do + @moduledoc """ + Decrement MPLS TTL action + """ + defstruct([]) alias __MODULE__ + @type t :: %DecMplsTtl{} + + @spec ofpat() :: 16 def ofpat, do: 16 + @doc """ + Create a new dec_mpls_ttl action struct. + + Note: Need to be specified the one of `ETH_P_MPLS_*` on `eth_type` match field when using this action. + + ## Example: + + ````elixir + iex> %DecMplsTtl{} = DecMplsTtl.new() + ```` + """ + @spec new() :: t() def new do %DecMplsTtl{} end + @spec to_binary(t()) :: <<_::16, _::_*8>> def to_binary(%DecMplsTtl{}) do <<16::16, 8::16, 0::size(4)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: t() def read(<<16::16, 8::16, _::size(4)-unit(8)>>) do %DecMplsTtl{} end diff --git a/lib/openflow/actions/dec_nw_ttl.ex b/lib/openflow/actions/dec_nw_ttl.ex index 6d23b5d..30c6b0d 100644 --- a/lib/openflow/actions/dec_nw_ttl.ex +++ b/lib/openflow/actions/dec_nw_ttl.ex @@ -1,4 +1,7 @@ defmodule Openflow.Action.DecNwTtl do + @moduledoc """ + """ + defstruct([]) alias __MODULE__ diff --git a/lib/openflow/actions/output.ex b/lib/openflow/actions/output.ex index 96e52c5..e0c0bfd 100644 --- a/lib/openflow/actions/output.ex +++ b/lib/openflow/actions/output.ex @@ -1,31 +1,67 @@ defmodule Openflow.Action.Output do - defstruct( - port_number: 0, - max_len: :no_buffer - ) + @moduledoc """ + Action for sends packets out `port_number`. + """ + + defstruct port_number: 0, + max_len: :no_buffer alias __MODULE__ + @type port_no :: + 0..0xFFFFFFFF + | :max + | :in_port + | :table + | :normal + | :flood + | :all + | :controller + | :local + | :any + + @type max_len :: 0..0xFFFFFFFF | :no_buffer | :max + + @type t :: %Output{port_number: port_no(), max_len: max_len()} + + @spec ofpat() :: 0 def ofpat, do: 0 + @doc """ + Create a new output action structure + + ## Options: + - `port_number`: port number that sends a packet from + - `max_len`: byte length of the packet that sends to the controller + + ## Example + + ```elixir + iex> %Output{port_number: 1, max_len: :no_buffer} = Output.new(1) + ``` + """ + @spec new([port_number: port_no, max_len: max_len()] | port_no()) :: Output.t() def new(options \\ []) - def new(port) when not is_list(port) do - new(port_number: port) - end + @spec new(port :: port_no()) :: Output.t() + def new(port) when is_atom(port) or is_integer(port), + do: new(port_number: port) + @spec new(options :: [port_number: port_no(), max_len: max_len()]) :: Output.t() def new(options) when is_list(options) do port_no = options[:port_number] || raise "port_number must be specified" max_len = options[:max_len] || :no_buffer %Output{port_number: port_no, max_len: max_len} end + @spec to_binary(Output.t()) :: <<_::16, _::_*8>> def to_binary(%Output{port_number: port_no, max_len: max_len}) do port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) <<0::16, 16::16, port_no_int::32, max_len::16, 0::size(6)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: Output.t() def read(<<0::16, 16::16, port_no_int::32, max_len::16, _pad::size(6)-unit(8)>>) do port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) diff --git a/lib/openflow/actions/pop_mpls.ex b/lib/openflow/actions/pop_mpls.ex index 91f6eaa..3d82f6e 100644 --- a/lib/openflow/actions/pop_mpls.ex +++ b/lib/openflow/actions/pop_mpls.ex @@ -1,12 +1,34 @@ defmodule Openflow.Action.PopMpls do + @moduledoc """ + Pop the out MPLS label + + note: The one of ETH__P_MPLS_* is needed to be specified to eth_type field + + send_flow_mod_add( + datapath_id, + match: Match.new(0x8847), + instructions: ApplyActions.new(PopMpls.new()) + ) + """ + defstruct(ethertype: 0x8847) alias __MODULE__ + @type t :: %PopMpls{} + @eth_p_mpls_uc 0x8847 + @spec ofpat() :: 20 def ofpat, do: 20 + @doc """ + Create a new pop_mpls action struct + + 0x8847(ETH_P_MPLS_UC) as default value. + """ + @spec new() :: t() + @spec new(ethertype :: 0..0xFFFF) :: t() def new(ethertype \\ @eth_p_mpls_uc) do %PopMpls{ethertype: ethertype} end diff --git a/lib/openflow/actions/pop_vlan.ex b/lib/openflow/actions/pop_vlan.ex index 8ea4f26..5ad96c9 100644 --- a/lib/openflow/actions/pop_vlan.ex +++ b/lib/openflow/actions/pop_vlan.ex @@ -1,18 +1,38 @@ defmodule Openflow.Action.PopVlan do + @moduledoc """ + Pop the outer VLAN tag. + + note: The one of ETH__P_802_* is needed to be specified to eth_type field + send_flow_mod_add( + datapath_id, + match: Match.new(eth_type: 0x8100), + instructions: ApplyActions.new(PopVlan.new()) + ) + """ + defstruct([]) alias __MODULE__ + @type t() :: %PopVlan{} + + @spec ofpat() :: 18 def ofpat, do: 18 + @doc """ + Create a new pop_vlan action struct + """ + @spec new() :: t() def new do %PopVlan{} end + @spec to_binary(t()) :: <<_::16, _::_*8>> def to_binary(%PopVlan{}) do <<18::16, 8::16, 0::size(4)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: t() def read(<<18::16, 8::16, _::size(4)-unit(8)>>) do %PopVlan{} end diff --git a/lib/openflow/actions/push_mpls.ex b/lib/openflow/actions/push_mpls.ex index 9d55a28..caa2141 100644 --- a/lib/openflow/actions/push_mpls.ex +++ b/lib/openflow/actions/push_mpls.ex @@ -1,20 +1,43 @@ defmodule Openflow.Action.PushMpls do + @moduledoc """ + Push a new MPLS label + + send_flow_mod_add( + datapath_id, + match: Match.new(), + instruction: ApplyActions.new(PushMpls.new()) + ) + """ + defstruct(ethertype: 0x8847) @eth_p_mpls_uc 0x8847 alias __MODULE__ + @type t :: %PushMpls{ethertype: 0..0xFFFF} + + @spec ofpat() :: 19 def ofpat, do: 19 + @doc """ + Create a new push_mpls action struct\\ + 0x8847(ETH_P_MPLS_UC) as a default value. + + iex> %PushMpls{ethertype: 0x8847} = PushMpls.new() + """ + @spec new() :: t() + @spec new(ethertype :: 0..0xFFFF) :: t() def new(ethertype \\ @eth_p_mpls_uc) do %PushMpls{ethertype: ethertype} end + @spec to_binary(t()) :: <<_::16, _::_*8>> def to_binary(%PushMpls{ethertype: ethertype}) do <<19::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: t() def read(<<19::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do %PushMpls{ethertype: ethertype} end diff --git a/lib/openflow/actions/push_vlan.ex b/lib/openflow/actions/push_vlan.ex index 8c8ca39..25221ac 100644 --- a/lib/openflow/actions/push_vlan.ex +++ b/lib/openflow/actions/push_vlan.ex @@ -1,18 +1,39 @@ defmodule Openflow.Action.PushVlan do + @moduledoc """ + Push a new VLAN tag + + send_flow_mod_add( + datapath_id, + instructions: ApplyActions.new(PushVlan.new()) + ) + """ + defstruct(ethertype: 0x8100) alias __MODULE__ + @type t :: %PushVlan{ethertype: 0..0xFFFF} + @spec ofpat() :: 17 def ofpat, do: 17 + @doc """ + Create a new push_vlan action struct.\\ + 0x8100 is a default value. + + iex> %PushVlan{ethertype: 0x8100} = PushVlan.new() + """ + @spec new() :: t() + @spec new(ethertype :: 0..0xFFFF) :: t() def new(ethertype \\ 0x8100) do %PushVlan{ethertype: ethertype} end + @spec to_binary(t()) :: <<_::16, _::_*8>> def to_binary(%PushVlan{ethertype: ethertype}) do <<17::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: t() def read(<<17::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do %PushVlan{ethertype: ethertype} end diff --git a/lib/openflow/actions/set_mpls_ttl.ex b/lib/openflow/actions/set_mpls_ttl.ex index a82a0ec..84cfcfb 100644 --- a/lib/openflow/actions/set_mpls_ttl.ex +++ b/lib/openflow/actions/set_mpls_ttl.ex @@ -1,18 +1,38 @@ defmodule Openflow.Action.SetMplsTtl do + @moduledoc """ + Replace the existing MPLS TTL.\\ + Only applies to the packets with an existing MPLS shim header. + """ + defstruct(ttl: 0) alias __MODULE__ + @type t :: %SetMplsTtl{ttl: 0..0xFF} + + @spec ofpat() :: 15 def ofpat, do: 15 + @doc """ + Create a set_mpls_ttl action structure + + ## Example: + ```elixir + iex> %SetMplsTtl{ttl: 64} = Openflow.Action.SetMplsTtl.new(64) + ``` + """ + @deprecated "OFPAT_SET_MPLS_TTL is deprecated in OpenFlow13, use SetField" + @spec new(0..0xFF) :: SetMplsTtl.t() def new(ttl) do %SetMplsTtl{ttl: ttl} end + @spec to_binary(SetMplsTtl.t()) :: <<_::16, _::_*8>> def to_binary(%SetMplsTtl{ttl: ttl}) do <<15::16, 8::16, ttl::8, 0::size(3)-unit(8)>> end + @spec read(<<_::16, _::_*8>>) :: SetMplsTtl.t() def read(<<15::16, 8::16, ttl::8, _::size(3)-unit(8)>>) do %SetMplsTtl{ttl: ttl} end diff --git a/mix.exs b/mix.exs index 1062030..c7d4380 100644 --- a/mix.exs +++ b/mix.exs @@ -36,13 +36,13 @@ defmodule Tres.Mixfile do defp docs do [ groups_for_modules: groups_for_modules(), - formatters: ["html"], + formatters: ["html"] ] end defp groups_for_modules do [ - "Actions": [ + Actions: [ Openflow.Action.Output, Openflow.Action.CopyTtlOut, Openflow.Action.CopyTtlIn,