add documents

This commit is contained in:
Eishun Kondoh 2019-03-28 18:17:01 +09:00
parent 22e62d32ae
commit 1cb687433c
14 changed files with 377 additions and 27 deletions

View file

@ -1,21 +1,35 @@
defmodule Openflow.Action.DecNwTtl do defmodule Openflow.Action.DecNwTtl do
@moduledoc """ @moduledoc """
Decrement IP TTL
""" """
defstruct([]) defstruct([])
alias __MODULE__ alias __MODULE__
@type t :: %DecNwTtl{}
@spec ofpat() :: 24
def ofpat, do: 24 def ofpat, do: 24
@doc """
Create a new dec_nw_ttl action struct
```elixir
iex> %DecNwTtl{} = DecNwTtl.new()
```
"""
@spec new() :: t()
def new do def new do
%DecNwTtl{} %DecNwTtl{}
end end
@spec to_binary(t()) :: <<_::16, _::_*8>>
def to_binary(%DecNwTtl{}) do def to_binary(%DecNwTtl{}) do
<<24::16, 8::16, 0::size(4)-unit(8)>> <<24::16, 8::16, 0::size(4)-unit(8)>>
end end
@spec read(<<_::16, _::_*8>>) :: t()
def read(<<24::16, 8::16, _::size(4)-unit(8)>>) do def read(<<24::16, 8::16, _::size(4)-unit(8)>>) do
%DecNwTtl{} %DecNwTtl{}
end end

View file

@ -1,18 +1,38 @@
defmodule Openflow.Action.Group do defmodule Openflow.Action.Group do
@moduledoc """
Apply Group
"""
defstruct(id: 0) defstruct(id: 0)
alias __MODULE__ alias __MODULE__
@type t :: %Group{id: 0..0xFFFFFFFF}
@spec ofpat() :: 22
def ofpat, do: 22 def ofpat, do: 22
@doc """
Create a new group action struct
## Options
- id: Group identifier
```elixir
iex> %Group{id: 10} = Group.new(10)
```
"""
@spec new(0..0xFFFFFFFF) :: t()
def new(id) do def new(id) do
%Group{id: id} %Group{id: id}
end end
@spec to_binary(t()) :: <<_::16, _::_*8>>
def to_binary(%Group{id: id}) do def to_binary(%Group{id: id}) do
<<22::16, 8::16, id::32>> <<22::16, 8::16, id::32>>
end end
@spec read(<<_::16, _::_*8>>) :: t()
def read(<<22::16, 8::16, id::32>>) do def read(<<22::16, 8::16, id::32>>) do
%Group{id: id} %Group{id: id}
end end

View file

@ -1,4 +1,32 @@
defmodule Openflow.Action.NxRegLoad do defmodule Openflow.Action.NxRegLoad do
@moduledoc """
Copies value[0:n_bits] to dst[ofs:ofs+n_bits], where a[b:c] denotes the bits
within 'a' numbered 'b' through 'c' (not including bit 'c'). Bit numbering
starts at 0 for the least-significant bit, 1 for the next most significant
bit, and so on.
'dst' is an nxm_header with nxm_hasmask=0. See the documentation for
NXAST_REG_MOVE, above, for the permitted fields and for the side effects of
loading them.
The 'ofs' and 'n_bits' fields are combined into a single 'ofs_nbits' field
to avoid enlarging the structure by another 8 bytes. To allow 'n_bits' to
take a value between 1 and 64 (inclusive) while taking up only 6 bits, it is
also stored as one less than its true value:
```
15 6 5 0
+------------------------------+------------------+
| ofs | n_bits - 1 |
+------------------------------+------------------+
```
The switch will reject actions for which ofs+n_bits is greater than the
width of 'dst', or in which any bits in 'value' with value 2n_bits or
greater are set to 1, with error type OFPET_BAD_ACTION, code
OFPBAC_BAD_ARGUMENT.
"""
import Bitwise import Bitwise
defstruct( defstruct(

View file

@ -1,4 +1,94 @@
defmodule Openflow.Action.NxRegMove do defmodule Openflow.Action.NxRegMove do
@moduledoc """
Copies src[src_ofs:src_ofs+n_bits] to dst[dst_ofs:dst_ofs+n_bits], where
a[b:c] denotes the bits within 'a' numbered 'b' through 'c' (not including
bit 'c'). Bit numbering starts at 0 for the least-significant bit, 1 for
the next most significant bit, and so on.
The following nxm_header values are potentially acceptable as 'src':
- `:in_port`
- `:eth_dst`
- `:eth_src`
- `:eth_type`
- `:vlan_tci`
- `:ip_tos`
- `:ip_proto`
- `:ip_src`
- `:ip_dst`
- `:tcp_src`
- `:tcp_dst`
- `:udp_src`
- `:udp_dst`
- `:icmp_type`
- `:icmp_code`
- `:arp_op`
- `:arp_spa`
- `:arp_tpa`
- `:tun_id`
- `:arp_sha`
- `:arp_tha`
- `:icmpv6_type`
- `:icmpv6_code`
- `:nd_sll`
- `:nd_tll`
- `:reg(idx)` for idx in the switch's accepted range.
- `:pkt_mark`
- `:tun_ipv4_src`
- `:tun_ipv4_dst`
The following nxm_header values are potentially acceptable as 'dst':
- `:eth_dst`
- `:eth_src`
- `:ip_tos`
- `:ip_src`
- `:ip_dst`
- `:tcp_src`
- `:tcp_dst`
- `:udp_src`
- `:udp_dst`
- `:icmp_type`
- `:icmp_code`
- `:icmpv6_type`
- `:icmpv6_code`
- `:arp_sha`
- `:arp_tha`
- `:arp_op`
- `:arp_spa`
- `:arp_tpa`
Modifying any of the above fields changes the corresponding packet header.
- `:in_port`
- `:reg(idx)` for idx in the switch's accepted range.
- `:pkt_mark`
- `:vlan_tci`. Modifying this field's value has side effects on the
packet's 802.1Q header. Setting a value with CFI=0 removes the 802.1Q
header (if any), ignoring the other bits. Setting a value with CFI=1
adds or modifies the 802.1Q header appropriately, setting the TCI field
to the field's new value (with the CFI bit masked out).
- `:tun_id`, `:tun_ipv4_src`, `:tun_ipv4_dst`. Modifying
any of these values modifies the corresponding tunnel header field used
for the packet's next tunnel encapsulation, if allowed by the
configuration of the output tunnel port.
A given nxm_header value may be used as 'src' or 'dst' only on a flow whose
nx_match satisfies its prerequisites. For example, NXM_OF_IP_TOS may be
used only if the flow's nx_match includes an nxm_entry that specifies
nxm_type=NXM_OF_ETH_TYPE, nxm_hasmask=0, and nxm_value=0x0800.
The switch will reject actions for which src_ofs+n_bits is greater than the
width of 'src' or dst_ofs+n_bits is greater than the width of 'dst' with
error type OFPET_BAD_ACTION, code OFPBAC_BAD_ARGUMENT.
This action behaves properly when 'src' overlaps with 'dst', that is, it
behaves as if 'src' were copied out to a temporary buffer, then the
temporary buffer copied to 'dst'.
"""
defstruct( defstruct(
n_bits: 0, n_bits: 0,
src_offset: 0, src_offset: 0,
@ -13,6 +103,47 @@ defmodule Openflow.Action.NxRegMove do
alias __MODULE__ alias __MODULE__
alias Openflow.Action.Experimenter alias Openflow.Action.Experimenter
@type t :: %NxRegMove{
n_bits: 0..0xFFFF,
src_offset: 0..0xFFFF,
dst_offset: 0..0xFFFF,
src_field: atom(),
dst_field: atom()
}
@doc """
Creates a new reg_move action struct
## Options:
- n_bits: Number of bits
- src_offset: Starting bit offset in source
- dst_offset: Starting bit offset in destination
- src_field: oxm/nxm field name for source field
- dst_field: oxm/nxm field name for destination field
## Example
```elixir
# 1. move:NXM_OF_IN_PORT[]->NXM_OF_VLAN_TCI[]
iex> NxRegMove.new(src_field: :nx_in_port, :nx_vlan_tci)
# 2. move:NXM_NX_TUN_ID[40..57]->NXM_NX_REG1[0..17]
iex> NxRegMove.new(
iex> src_field: :tun_id,
iex> src_offset: 40,
iex> dst_field: :reg1
iex> dst_offset: 0,
iex> n_bits: 18
iex> )
```
"""
@spec new(
n_bits: 0..0xFFFF,
src_offset: 0..0xFFFF,
dst_offset: 0..0xFFFF,
src_field: atom(),
dst_field: atom()
) :: t()
def new(options \\ []) do def new(options \\ []) do
src_field = options[:src_field] || raise "src_field must be specified" src_field = options[:src_field] || raise "src_field must be specified"
dst_field = options[:dst_field] || raise "dst_field must be specified" dst_field = options[:dst_field] || raise "dst_field must be specified"
@ -27,6 +158,7 @@ defmodule Openflow.Action.NxRegMove do
} }
end end
@spec to_binary(t()) :: binary()
def to_binary(%NxRegMove{} = move) do def to_binary(%NxRegMove{} = move) do
src_field_bin = Openflow.Match.codec_header(move.src_field) src_field_bin = Openflow.Match.codec_header(move.src_field)
dst_field_bin = Openflow.Match.codec_header(move.dst_field) dst_field_bin = Openflow.Match.codec_header(move.dst_field)
@ -42,6 +174,7 @@ defmodule Openflow.Action.NxRegMove do
>>) >>)
end end
@spec read(binary()) :: t()
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<n_bits::16, src_ofs::16, dst_ofs::16, src_field_bin::4-bytes, dst_field_bin::4-bytes>> = <<n_bits::16, src_ofs::16, dst_ofs::16, src_field_bin::4-bytes, dst_field_bin::4-bytes>> =
body body

View file

@ -1,4 +1,16 @@
defmodule Openflow.Action.NxResubmit do defmodule Openflow.Action.NxResubmit do
@moduledoc """
Searches the flow table again, using a flow that is slightly modified from the original lookup:
Following the lookup, the original in_port is restored.
If the modified flow matched in the flow table, then the corresponding
actions are executed. Afterward, actions following NXAST_RESUBMIT in
the original set of actions, if any, are executed; any changes made to
the packet (e.g. changes to VLAN) by secondary actions persist when
those actions are executed, although the original in_port is restored.
"""
defstruct(in_port: :in_port) defstruct(in_port: :in_port)
@experimenter 0x00002320 @experimenter 0x00002320
@ -7,10 +19,46 @@ defmodule Openflow.Action.NxResubmit do
alias __MODULE__ alias __MODULE__
alias Openflow.Action.Experimenter alias Openflow.Action.Experimenter
@type t :: %{in_port: port_no()}
@type port_no ::
:max
| :in_port
| :table
| :normal
| :flood
| :all
| :controller
| :local
| :none
| 1..0xFFFF
@doc """
Creates a new nx_resubmit action struct
## Options:
- in_port: New in_port for checking flow table in the one of the `port_no()` type
## Note:
If the modified flow matchd in the flow table, then the corresponding actions are executed,\\
Afterward, actions following the resubmit in the original set of actions, if any, are executed;\\
any changes made to the packet by secondary actions persist when those actions are executed,
although the original in_port is restored
## Example:
```elixir
iex> %NxResubmit{in_port: :in_port} = NxResubmit.new()
iex> %NxResubmit{in_port: 1} = NxResubmit.new(1)
```
"""
@spec new(port_no()) :: t()
def new(in_port \\ :in_port) do def new(in_port \\ :in_port) do
%NxResubmit{in_port: in_port} %NxResubmit{in_port: in_port}
end end
@spec to_binary(t()) :: binary()
def to_binary(%NxResubmit{in_port: in_port}) do def to_binary(%NxResubmit{in_port: in_port}) do
in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no) in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no)
@ -22,6 +70,7 @@ defmodule Openflow.Action.NxResubmit do
>>) >>)
end end
@spec read(binary()) :: t()
def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do
in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no) in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no)
%NxResubmit{in_port: in_port} %NxResubmit{in_port: in_port}

View file

@ -1,4 +1,8 @@
defmodule Openflow.Action.NxSetTunnel do defmodule Openflow.Action.NxSetTunnel do
@moduledoc """
Set encapsulating tunnel ID.
"""
defstruct(tunnel_id: 0) defstruct(tunnel_id: 0)
@experimenter 0x00002320 @experimenter 0x00002320
@ -7,10 +11,23 @@ defmodule Openflow.Action.NxSetTunnel do
alias __MODULE__ alias __MODULE__
alias Openflow.Action.Experimenter alias Openflow.Action.Experimenter
@type tunnel_id :: 0..0xFFFFFFFF
@type t :: %NxSetTunnel{tunnel_id: tunnel_id()}
@doc """
Creates a new set_tunnel action struct
## Example:
```elixir
iex> %NxSetTunnel{tunnel_id: 1} = NxSetTunnel.new(1)
```
"""
@spec new(tunnel_id()) :: t()
def new(tunnel_id) do def new(tunnel_id) do
%NxSetTunnel{tunnel_id: tunnel_id} %NxSetTunnel{tunnel_id: tunnel_id}
end end
@spec to_binary(t()) :: binary()
def to_binary(%NxSetTunnel{tunnel_id: tunnel_id}) do def to_binary(%NxSetTunnel{tunnel_id: tunnel_id}) do
Experimenter.pack_exp_header(<< Experimenter.pack_exp_header(<<
@experimenter::32, @experimenter::32,
@ -20,6 +37,7 @@ defmodule Openflow.Action.NxSetTunnel do
>>) >>)
end end
@spec read(binary()) :: t()
def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do
%NxSetTunnel{tunnel_id: tunnel_id} %NxSetTunnel{tunnel_id: tunnel_id}
end end

View file

@ -31,8 +31,8 @@ defmodule Openflow.Action.Output do
Create a new output action structure Create a new output action structure
## Options: ## Options:
- `port_number`: port number that sends a packet from - `port_number`: Output port
- `max_len`: byte length of the packet that sends to the controller - `max_len`: Max length to send to controller
## Example ## Example

View file

@ -3,12 +3,6 @@ defmodule Openflow.Action.PopMpls do
Pop the out MPLS label Pop the out MPLS label
note: The one of ETH__P_MPLS_* is needed to be specified to eth_type field 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) defstruct(ethertype: 0x8847)
@ -25,7 +19,11 @@ defmodule Openflow.Action.PopMpls do
@doc """ @doc """
Create a new pop_mpls action struct Create a new pop_mpls action struct
0x8847(ETH_P_MPLS_UC) as default value. note: 0x8847(ETH_P_MPLS_UC) as default value.
```elixir
iex> %PopMpls{ethertype: 0x8847} = PopMpls.new()
```
""" """
@spec new() :: t() @spec new() :: t()
@spec new(ethertype :: 0..0xFFFF) :: t() @spec new(ethertype :: 0..0xFFFF) :: t()
@ -33,10 +31,12 @@ defmodule Openflow.Action.PopMpls do
%PopMpls{ethertype: ethertype} %PopMpls{ethertype: ethertype}
end end
@spec to_binary(t()) :: <<_::16, _::_*8>>
def to_binary(%PopMpls{ethertype: ethertype}) do def to_binary(%PopMpls{ethertype: ethertype}) do
<<20::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> <<20::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>
end end
@spec read(<<_::16, _::_*8>>) :: t()
def read(<<20::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do def read(<<20::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do
%PopMpls{ethertype: ethertype} %PopMpls{ethertype: ethertype}
end end

View file

@ -1,13 +1,6 @@
defmodule Openflow.Action.PopVlan do defmodule Openflow.Action.PopVlan do
@moduledoc """ @moduledoc """
Pop the outer VLAN tag. 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([]) defstruct([])
@ -21,6 +14,10 @@ defmodule Openflow.Action.PopVlan do
@doc """ @doc """
Create a new pop_vlan action struct Create a new pop_vlan action struct
````elixir
iex> %PopVlan{} = PopVlan.new()
````
""" """
@spec new() :: t() @spec new() :: t()
def new do def new do

View file

@ -1,12 +1,6 @@
defmodule Openflow.Action.PushMpls do defmodule Openflow.Action.PushMpls do
@moduledoc """ @moduledoc """
Push a new MPLS label Push a new MPLS label
send_flow_mod_add(
datapath_id,
match: Match.new(),
instruction: ApplyActions.new(PushMpls.new())
)
""" """
defstruct(ethertype: 0x8847) defstruct(ethertype: 0x8847)

View file

@ -1,11 +1,6 @@
defmodule Openflow.Action.PushVlan do defmodule Openflow.Action.PushVlan do
@moduledoc """ @moduledoc """
Push a new VLAN tag Push a new VLAN tag
send_flow_mod_add(
datapath_id,
instructions: ApplyActions.new(PushVlan.new())
)
""" """
defstruct(ethertype: 0x8100) defstruct(ethertype: 0x8100)

View file

@ -1,12 +1,74 @@
defmodule Openflow.Action.SetField do defmodule Openflow.Action.SetField do
@moduledoc """
Set a header field using OXM TLV format.
"""
defstruct(field: nil) defstruct(field: nil)
alias __MODULE__ alias __MODULE__
@type t :: %SetField{field: Keyword.t()}
@set_field_size 8 @set_field_size 8
def ofpat, do: 25 def ofpat, do: 25
@doc """
Create a new set_field action struct
note: The following oxm(nxm)_header values are potentially acceptable as `field`:
- :tun_id
- :tun_ipv4_src
- :tun_ipv4_dst
- :tun_ipv6_src
- :tun_ipv6_dst
- :tun_flags
- :tun_gbp_id
- :tun_gbp_flags
- :tun_metadata{0..63}
- :in_port
- :pkt_mark
- :ct_mark
- :ct_label
- :reg{0..15}
- :xreg{0..8}
- :xxreg{0..4}
- :eth_src
- :eth_dst
- :vlan_tci
- :mpls_ttl
- :ip_src
- :ip_dst
- :ipv6_src
- :ipv6_dst
- :ipv6_label
- :ip_tos
- :ip_ecn
- :ip_ttl
- :arp_op
- :arp_spa
- :arp_tpa
- :arp_sha
- :arp_tha
- :tcp_src
- :tcp_dst
- :udp_src
- :udp_dst
- :icmp_type
- :icmp_code
- :icmpv6_type
- :icmpv6_code
- :nd_target
- :nd_sll
- :nd_tll
- :metadata
```elixir
iex> %SetField{field: [reg1: 10]} = SetField.new(reg1: 10)
```
"""
@spec new(Keyword.t()) :: t()
def new([{_field, _value}] = oxm_field) do def new([{_field, _value}] = oxm_field) do
%SetField{field: oxm_field} %SetField{field: oxm_field}
end end

View file

@ -1,18 +1,38 @@
defmodule Openflow.Action.SetNwTtl do defmodule Openflow.Action.SetNwTtl do
@moduledoc """
Set IP TTL
"""
defstruct(ttl: 0) defstruct(ttl: 0)
alias __MODULE__ alias __MODULE__
@type t :: %SetNwTtl{ttl: 0..0xFF}
@spec ofpat() :: 23
def ofpat, do: 23 def ofpat, do: 23
@doc """
Create a new set_nw_ttl action struct
## Options:
- IP TTL
```elixir
iex> %SetNwTtl{ttl: 64} = SetNwTtl.new(_ttl = 64)
```
"""
@spec new(ttl :: 0..0xFF) :: t()
def new(ttl) do def new(ttl) do
%SetNwTtl{ttl: ttl} %SetNwTtl{ttl: ttl}
end end
@spec to_binary(t()) :: <<_::16, _::_*8>>
def to_binary(%SetNwTtl{ttl: ttl}) do def to_binary(%SetNwTtl{ttl: ttl}) do
<<23::16, 8::16, ttl::8, 0::size(3)-unit(8)>> <<23::16, 8::16, ttl::8, 0::size(3)-unit(8)>>
end end
@spec read(<<_::16, _::_*8>>) :: t()
def read(<<23::16, 8::16, ttl::8, _::size(3)-unit(8)>>) do def read(<<23::16, 8::16, ttl::8, _::size(3)-unit(8)>>) do
%SetNwTtl{ttl: ttl} %SetNwTtl{ttl: ttl}
end end

View file

@ -1,18 +1,38 @@
defmodule Openflow.Action.SetQueue do defmodule Openflow.Action.SetQueue do
@moduledoc """
Set queue id when outputting to a port
"""
defstruct(id: 0) defstruct(id: 0)
alias __MODULE__ alias __MODULE__
@type t :: %SetQueue{id: 0..0xFFFFFFFF}
@spec ofpat() :: 21
def ofpat, do: 21 def ofpat, do: 21
@doc """
Create a new set_queue action struct
## Options:
- Queue id for the packets
```elixir
iex> %SetQueue{id: 1} = SetQueue.new(_id = 1)
```
"""
@spec new(id :: 0..0xFFFFFFFF) :: t()
def new(id) do def new(id) do
%SetQueue{id: id} %SetQueue{id: id}
end end
@spec to_binary(t()) :: <<_::16, _::_*8>>
def to_binary(%SetQueue{id: id}) do def to_binary(%SetQueue{id: id}) do
<<21::16, 8::16, id::32>> <<21::16, 8::16, id::32>>
end end
@spec read(<<_::16, _::_*8>>) :: t()
def read(<<21::16, 8::16, id::32>>) do def read(<<21::16, 8::16, id::32>>) do
%SetQueue{id: id} %SetQueue{id: id}
end end