Compare commits

...

17 commits

Author SHA1 Message Date
Eishun Kondoh
1e3e7f78ba
tres/controller: Refactored to split aliases into actions and instructions respectively (#18) 2019-09-24 18:00:34 +09:00
Eishun Kondoh
715bead2ff Merge tag '0.1.3' into develop
Release v0.1.3
2019-07-31 20:38:47 +09:00
Eishun Kondoh
613e7d6d86 Merge branch 'release/0.1.3' 2019-07-31 20:38:39 +09:00
Eishun Kondoh
479e85439a Version bump 2019-07-31 20:38:31 +09:00
Eishun Kondoh
d8a17d2d94 openflow/field: Fix broken NXOXM/ONFOXM fields 2019-07-31 20:35:17 +09:00
Eishun Kondoh
c81cf9e8ba openflow/field: Add support for OXM_OF_PACKET_TYPE 2019-07-31 18:37:22 +09:00
Eishun Kondoh
ca02fe7ed7 openflow/actions: Improve readability of experimenter action codec 2019-07-24 02:39:08 +09:00
Eishun Kondoh
6dc3cfd500 openflow/learn_flow_spec: Fix to use src field if dst field is omitted, as dst field. 2019-07-24 02:24:37 +09:00
Eishun Kondoh
6ce014ea91
openflow/actions: Add nx_check_pkt_larger (#17)
this action available since post-2.11
2019-07-22 20:14:42 +09:00
Eishun Kondoh
ccb420cbce quality/travis: bump into OTP-22.x 2019-07-09 12:14:02 +09:00
Eishun Kondoh
0aa894a21c Merge tag '0.1.2' into develop
Release 0.1.2
2019-07-09 12:01:18 +09:00
Eishun Kondoh
2a6623445a Merge branch 'release/0.1.2' 2019-07-09 12:01:04 +09:00
Eishun Kondoh
da4165b670 mix: Version bump 2019-07-09 12:00:58 +09:00
Eishun Kondoh
9ddd82fcab openflow/match: Refactored 2019-07-09 11:58:23 +09:00
Eishun Kondoh
e65bf77a3c Better badges 2019-06-15 12:06:22 +09:00
Eishun Kondoh
8c2484e683 README 2019-06-15 11:03:35 +09:00
Eishun Kondoh
f385374f82 Merge tag '0.1.1' into develop
Minor fixes
2019-06-15 11:02:10 +09:00
38 changed files with 1666 additions and 2053 deletions

View file

@ -4,7 +4,7 @@ language: elixir
elixir:
- "1.8.1"
otp_release:
- "21.3.6"
- "22.0.5"
before_install:
- sudo apt-get install -y wget curl gdebi debhelper unbound

View file

@ -4,7 +4,7 @@
[![codecov](https://img.shields.io/codecov/c/github/shun159/tres/develop.svg?style=flat-square)](https://codecov.io/gh/shun159/tres)
[![Supported OTP version](https://img.shields.io/badge/erlang-22.x-blue.svg?style=flat-square)](http://erlang.org/)
[![LICENSE](https://img.shields.io/badge/license-SUSHI--WARE%F0%9F%8D%A3-blue.svg?style=flat-square)](https://github.com/MakeNowJust/sushi-ware)
[![hex version](https://img.shields.io/badge/hex-0.1.0-yellow.svg?style=flat-square)](https://hex.pm/packages/tres/0.1.0)
[![Hex Version](https://img.shields.io/hexpm/v/tres.svg?style=flat-square)](https://hex.pm/packages/tres)
## Overview
@ -17,7 +17,7 @@ Tres is a framework and set of helper libraries to develop OpenFlow controllers
```elixir
def deps do
[
{:tres, "~> 0.1.0"}
{:tres, "~> 0.1.2"}
]
end
```

View file

@ -11,7 +11,7 @@ config :tres,
callback_args: []
config :logger,
level: :debug,
level: :info,
format: "$date $time [$level] $message\n",
metadata: [],
handle_otp_reports: true

View file

@ -11,9 +11,9 @@ defmodule LearningSwitch.Ofctl do
@aging_time 180
@mcast {"010000000000", "110000000000"}
@bcast "ffffffffffff"
@ipv6_mcast {"333300000000", "ffff00000000"}
@mcast {<<0x010000000000::48>>, <<0x110000000000::48>>}
@bcast <<0xffffffffffff::48>>
@ipv6_mcast {<<0x333300000000::48>>, <<0xffff00000000::48>>}
defmodule State do
defstruct [

View file

@ -56,29 +56,7 @@ defmodule NxLearningSwitch do
send_flow_mod_add(
datapath_id,
table_id: 0,
instructions: ApplyActions.new([
NxLearn.new(
table_id: 1,
priority: 2,
hard_timeout: 10,
flow_specs: [
NxFlowSpecMatch.new(
src: :nx_eth_src,
dst: :nx_eth_dst
),
NxFlowSpecMatch.new(
src: :nx_vlan_tci,
dst: :nx_vlan_tci,
offset: 0,
n_bits: 12
),
NxFlowSpecOutput.new(
src: :nx_in_port
)
]
),
NxResubmitTable.new(1)
])
instructions: l2_learning_instr()
)
end
@ -90,4 +68,28 @@ defmodule NxLearningSwitch do
instructions: ApplyActions.new(Output.new(:flood))
)
end
defp l2_learning_instr do
ApplyActions.new([
l2_learning_action(),
NxResubmitTable.new(1)
])
end
defp l2_learning_action do
NxLearn.new(
table_id: 1,
priority: 2,
hard_timeout: 10,
flow_specs: l2_learning_flow_specs()
)
end
defp l2_learning_flow_specs do
[
NxFlowSpecMatch.new(src: :eth_src, dst: :eth_dst),
NxFlowSpecMatch.new(src: :vlan_vid, n_bits: 12),
NxFlowSpecOutput.new(src: :nx_in_port)
]
end
end

View file

@ -1,7 +1,7 @@
defmodule SimpleRouter.Config do
@moduledoc false
alias Tres.IPv4Address
alias SimpleRouter.IPv4Address
@spec interfaces() :: %{String.t() => map()}
def interfaces do
@ -24,7 +24,7 @@ defmodule SimpleRouter.Config do
entry =
%{
mac_address: String.replace(mac, ~r/:/, ""),
mac_address: mac_to_bin(mac),
ip_address: ipaddr,
subnet_mask: mask,
network_address: IPv4Address.to_network({ipaddr, mask}),
@ -50,6 +50,13 @@ defmodule SimpleRouter.Config do
end
end
defp mac_to_bin(mac) do
mac
|> String.replace(~r/:/, "")
|> String.to_integer(16)
|> :binary.encode_unsigned(:big)
end
defp get_env(key, default),
do: Application.get_env(:simple_router, key, default)
end

View file

@ -0,0 +1,120 @@
defmodule SimpleRouter.IPv4Address do
@moduledoc """
IP Address Utils
"""
use Bitwise
@typep in_addr :: {byte, byte, byte, byte}
@typep in_addr_str :: String.t()
@doc """
iex> {{192, 168, 0, 1}, {255, 255, 255, 255}} = IPv4Address.parse(<<192, 168, 0, 1>>)
iex> {{192, 168, 0, 1}, {255, 255, 255, 255}} = IPv4Address.parse("192.168.0.1")
iex> {{192, 168, 0, 1}, {255, 255, 255, 0}} = IPv4Address.parse("192.168.0.1/24")
"""
@spec parse(in_addr_str | binary()) :: {in_addr, in_addr}
def parse(<<a1, a2, a3, a4>>), do: {{a1, a2, a3, a4}, {255, 255, 255, 255}}
def parse(addr) do
case String.split(addr, ~r/\//) do
[^addr] ->
{:ok, ipaddr} = addr |> to_charlist |> :inet.parse_address()
{ipaddr, {255, 255, 255, 255}}
[netaddr, cidr_str] ->
cidr = String.to_integer(cidr_str)
mask = 0xFFFFFFFF >>> (32 - cidr) <<< (32 - cidr)
<<m1, m2, m3, m4>> = <<mask::32>>
{:ok, ipaddr} = netaddr |> to_charlist |> :inet.parse_address()
{ipaddr, {m1, m2, m3, m4}}
end
end
@doc """
iex> addr = IPv4Address.parse("192.168.10.1/24")
iex> {192, 168, 10, 0} = IPv4Address.to_network(addr)
"""
@spec to_network({in_addr(), in_addr()}) :: in_addr()
def to_network({{a1, a2, a3, a4}, {m1, m2, m3, m4}}) do
addr_int = :binary.decode_unsigned(<<a1, a2, a3, a4>>, :big)
mask_int = :binary.decode_unsigned(<<m1, m2, m3, m4>>, :big)
<<n1, n2, n3, n4>> = <<addr_int &&& mask_int::32>>
{n1, n2, n3, n4}
end
@doc """
iex> "192.168.0.1" = IPv4Address.to_str({192, 168, 0, 1})
"""
@spec to_str(in_addr | in_addr_str) :: in_addr_str
def to_str(addr) when is_binary(addr) do
addr
end
def to_str(addr) when is_tuple(addr) do
"#{:inet.ntoa(addr)}"
end
@doc """
iex> 0xc0a80001 = IPv4Address.to_int({192, 168, 0, 1})
"""
@spec to_int(in_addr) :: 0..0xFFFFFFFF
def to_int({a, b, c, d}) do
<<a, b, c, d>> |> :binary.decode_unsigned(:big)
end
@doc """
iex> true = IPv4Address.is_private?({192, 168, 0, 1})
"""
@spec is_private?(in_addr) :: boolean
def is_private?(addr) do
ipaddr_int = to_int(addr)
priv_class_a?(ipaddr_int) or priv_class_b?(ipaddr_int) or priv_class_c?(ipaddr_int)
end
@doc """
iex> false = IPv4Address.is_loopback?({192, 168, 0, 1})
iex> true = IPv4Address.is_loopback?({127, 0, 0, 1})
"""
@spec is_loopback?(in_addr) :: boolean
def is_loopback?({127, _, _, _}), do: true
def is_loopback?({_, _, _, _}), do: false
@doc """
iex> false = IPv4Address.is_multicast?({192, 168, 0, 1})
iex> true = IPv4Address.is_multicast?({224, 0, 0, 1})
"""
@spec is_multicast?(in_addr) :: boolean
def is_multicast?(in_addr) do
in_addr
|> to_int
|> mcast_class_d?
end
@doc """
iex> false = IPv4Address.is_broadcast?({192, 168, 0, 1})
iex> true = IPv4Address.is_broadcast?({255, 255, 255, 255})
"""
@spec is_broadcast?(in_addr) :: boolean
def is_broadcast?({255, _, _, _}), do: true
def is_broadcast?({_, _, _, _}), do: false
# private functions
@class_a_subnet 0xFF000000
@class_b_subnet 0xFFF00000
@class_c_subnet 0xFFFF0000
@class_d_subnet 0xE0000000
@class_a_start_addr 167_772_160
@class_b_start_addr 2_886_729_728
@class_c_start_addr 3_232_235_520
defp priv_class_a?(ipaddr_int), do: (ipaddr_int &&& @class_a_subnet) == @class_a_start_addr
defp priv_class_b?(ipaddr_int), do: (ipaddr_int &&& @class_b_subnet) == @class_b_start_addr
defp priv_class_c?(ipaddr_int), do: (ipaddr_int &&& @class_c_subnet) == @class_c_start_addr
defp mcast_class_d?(ipaddr_int), do: (ipaddr_int &&& @class_d_subnet) == @class_d_subnet
end

View file

@ -0,0 +1,87 @@
defmodule SimpleRouter.MacAddress do
@moduledoc """
MAC Address Utils
"""
use Bitwise
@mac_addr_pattern ~r/^(?:[0-9a-fA-F][0-9a-fA-F]){6}$/
@spec bin_to_str(<<_::48>>) :: String.t()
def bin_to_str(<<_::6-bytes>> = mac) do
mac
|> :erlang.binary_to_list()
|> Enum.reduce("", &to_hex/2)
|> String.downcase()
end
@spec to_a(String.t()) :: [non_neg_integer()]
def to_a(mac) do
mac
|> check_format()
|> to_a([])
rescue
_e in ArgumentError ->
{:error, :invalid_format}
end
@spec to_i(String.t()) :: non_neg_integer()
def to_i(mac) do
mac
|> check_format()
|> String.to_integer(16)
rescue
_e in ArgumentError ->
{:error, :invalid_format}
end
@spec is_broadcast?(String.t()) :: boolean()
def is_broadcast?(mac) do
mac
|> check_format()
|> to_a()
|> Enum.at(0)
|> Kernel.==(0xFF)
rescue
_e in ArgumentError ->
{:error, :invalid_format}
end
@spec is_multicast?(String.t()) :: boolean()
def is_multicast?(mac) do
mac
|> check_format()
|> to_a()
|> Enum.at(0)
|> Bitwise.&&&(1)
|> Kernel.==(1)
rescue
_e in ArgumentError ->
{:error, :invalid_format}
end
# private functions
defp to_a(<<>>, acc), do: Enum.reverse(acc)
defp to_a(<<octet::2-bytes, rest::bytes>>, acc) do
to_a(rest, [String.to_integer(octet, 16) | acc])
end
@spec to_hex(0..0xFF, String.t()) :: String.t()
defp to_hex(int, acc), do: "#{acc}#{to_hex(int)}"
@spec to_hex(0..0xFF) :: String.t()
defp to_hex(int) do
int
|> Integer.to_string(16)
|> String.pad_leading(2, "0")
end
@spec check_format(String.t()) :: String.t() | none()
defp check_format(mac) when is_binary(mac) do
if String.match?(mac, @mac_addr_pattern),
do: mac,
else: raise(ArgumentError, message: "MAC address should be 12 letters hex string format")
end
end

View file

@ -5,8 +5,7 @@ defmodule SimpleRouter.Openflow.FlowTables do
use Tres.Controller
alias Tres.IPv4Address
alias Tres.MacAddress
alias SimpleRouter.IPv4Address
@classifier_table_id 0
@arp_handler_table_id 1
@ -219,7 +218,7 @@ defmodule SimpleRouter.Openflow.FlowTables do
defp arp_packet(iface) do
ether_header = <<
0xffffffffffff::48, # destination ethernet address
(MacAddress.to_i(iface.mac_address))::48, # source ethernet address
iface.mac_address::48-bits, # source ethernet address
0x0806::16 # ethernet type
>>
@ -230,7 +229,7 @@ defmodule SimpleRouter.Openflow.FlowTables do
6::8, # hardware address length
4::8, # protocol address length
1::16, # ARPOP_REQUEST
(MacAddress.to_i(iface.mac_address))::48, # Source Hardware Address
iface.mac_address::48-bits, # Source Hardware Address
(IPv4Address.to_int(iface.ip_address))::32, # Source Protocol Address
0x000000000000::48 # Target Hardware Address
>>

View file

@ -20,28 +20,32 @@ defmodule Openflow.Action.Experimenter do
@spec pack_exp_header(binary()) :: binary()
def pack_exp_header(exp_body) do
pad_length =
exp_body
|> Kernel.byte_size()
|> Kernel.+(4)
|> Openflow.Utils.padding(8)
pad_length = pad_length_of(exp_body)
length =
exp_body
|> byte_size()
|> Kernel.+(4)
|> Kernel.+(pad_length)
<<0xFFFF::16, length::16, exp_body::bytes, 0::size(pad_length)-unit(8)>>
<<
0xFFFF::16,
length_of(exp_body, pad_length)::16,
exp_body::bytes,
0::size(pad_length)-unit(8)
>>
end
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: <<exp_type::16, data::bytes>>}
def read(<<
0xFFFF::16,
_length::16,
exp_id::32,
exp_type::16,
data::bytes
>>) do
exp_id
|> Openflow.Utils.get_enum(:action_vendor)
|> read(exp_id, exp_type, data)
end
vendor when is_atom(vendor) ->
case Openflow.Utils.get_enum(exp_type, vendor) do
## private functions
defp read(vendor_id, exp_id, exp_type, <<data::bytes>>) when is_atom(vendor_id) do
case Openflow.Utils.get_enum(exp_type, vendor_id) do
codec when is_atom(codec) ->
codec.read(<<exp_id::32, exp_type::16, data::bytes>>)
@ -49,5 +53,21 @@ defmodule Openflow.Action.Experimenter do
%Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
end
end
defp read(vendor_id, exp_id, exp_type, <<data::bytes>>) when is_integer(vendor_id),
do: %Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
defp pad_length_of(<<exp_body::bytes>>) do
exp_body
|> Kernel.byte_size()
|> Kernel.+(4)
|> Openflow.Utils.padding(8)
end
defp length_of(<<exp_body::bytes>>, pad_length) do
exp_body
|> byte_size()
|> Kernel.+(4)
|> Kernel.+(pad_length)
end
end

View file

@ -53,7 +53,7 @@ defmodule Openflow.Action.NxBundleLoad do
) :: t()
def new(options \\ []) do
dst_field = options[:dst_field] || raise "dst_field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
default_n_bits = Openflow.Match.n_bits_of(dst_field)
slaves = options[:slaves] || []
%NxBundleLoad{

View file

@ -0,0 +1,46 @@
defmodule Openflow.Action.NxCheckPktLarger do
defstruct(
pkt_len: 0,
offset: 0,
dst_field: nil
)
@experimenter 0x00002320
@nxast 49
alias __MODULE__
alias Openflow.Action.Experimenter
@type t :: %NxCheckPktLarger{dst_field: atom(), pkt_len: 0..0xFFFF, offset: 0..0xFFFF}
@spec new(dst_field: atom(), pkt_len: 0..0xFFFF, offset: 0..0xFFFF) :: t()
def new(options \\ []) do
dst_field = options[:dst_field] || raise "dst_field must be specified"
pkt_len = options[:pkt_len] || raise "pkt_len must be specified"
ofs = Keyword.get(options, :offset, 0)
%NxCheckPktLarger{dst_field: dst_field, pkt_len: pkt_len, offset: ofs}
end
@spec to_binary(t()) :: binary()
def to_binary(%NxCheckPktLarger{} = pkt_larger) do
dst_field_bin = Openflow.Match.codec_header(pkt_larger.dst_field)
pkt_len = pkt_larger.pkt_len
ofs = pkt_larger.offset
Experimenter.pack_exp_header(<<
@experimenter::32,
@nxast::16,
pkt_len::16,
ofs::16,
dst_field_bin::4-bytes,
0::size(10)-unit(8)
>>)
end
@spec read(binary()) :: t()
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<pkt_len::16, ofs::16, dst_field_bin::4-bytes, _::bytes>> = body
dst_field = Openflow.Match.codec_header(dst_field_bin)
%NxCheckPktLarger{dst_field: dst_field, pkt_len: pkt_len, offset: ofs}
end
end

View file

@ -31,7 +31,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do
def new(options) do
dst = options[:dst] || raise(":dst must be specified")
src = options[:src] || raise(":src must be specified")
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst)
n_bits = options[:n_bits] || Openflow.Match.n_bits_of(dst)
%NxFlowSpecLoad{
src: src,
@ -90,7 +90,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do
binary
dst = Openflow.Match.codec_header(dst_bin)
src = Openflow.Match.Field.codec(src_bin, dst)
src = Openflow.Match.decode_value(src_bin, dst)
flow_spec = %NxFlowSpecLoad{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs}
{flow_spec, rest}
end
@ -103,7 +103,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do
end
defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do
src_bin = Openflow.Match.Field.codec(src, dst_field)
src_bin = Openflow.Match.encode_value(src, dst_field)
{@learn_src_immediate, src_bin}
end
end

View file

@ -29,9 +29,9 @@ defmodule Openflow.Action.NxFlowSpecMatch do
dst_offset: non_neg_integer()
) :: t()
def new(options \\ []) do
dst = options[:dst] || raise ":dst must be specified"
src = options[:src] || raise ":src must be specified"
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst)
dst = options[:dst] || src
n_bits = options[:n_bits] || Openflow.Match.n_bits_of(dst)
%NxFlowSpecMatch{
src: src,
@ -92,7 +92,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do
binary
dst = Openflow.Match.codec_header(dst_bin)
src = Openflow.Match.Field.codec(src_bin, dst)
src = Openflow.Match.decode_value(src_bin, dst)
flow_spec = %NxFlowSpecMatch{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs}
{flow_spec, rest}
end
@ -105,7 +105,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do
end
defp codec_src(%NxFlowSpecMatch{src: src, dst: dst_field}) do
src_bin = Openflow.Match.Field.codec(src, dst_field)
src_bin = Openflow.Match.encode_value(src, dst_field)
{@learn_src_immediate, src_bin}
end
end

View file

@ -19,7 +19,7 @@ defmodule Openflow.Action.NxFlowSpecOutput do
@spec new(src: atom(), n_bits: non_neg_integer(), src_offset: non_neg_integer()) :: t()
def new(options \\ []) do
src = options[:src] || raise ":src must be specified"
n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(src)
n_bits = options[:n_bits] || Openflow.Match.n_bits_of(src)
%NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: options[:src_offset] || 0}
end

View file

@ -21,7 +21,7 @@ defmodule Openflow.Action.NxMultipath do
@spec new(Keyword.t()) :: %NxMultipath{}
def new(options) do
dst_field = options[:dst_field] || raise "dst_field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
default_n_bits = Openflow.Match.n_bits_of(dst_field)
%NxMultipath{
hash_field: options[:hash_field] || :eth_src,

View file

@ -30,7 +30,7 @@ defmodule Openflow.Action.NxOutputReg do
) :: t()
def new(options) do
src_field = options[:src_field] || raise "src_field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(src_field)
default_n_bits = Openflow.Match.n_bits_of(src_field)
%NxOutputReg{
n_bits: options[:n_bits] || default_n_bits,

View file

@ -30,7 +30,7 @@ defmodule Openflow.Action.NxOutputReg2 do
) :: t()
def new(options) do
src_field = options[:src_field] || raise "src_field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(src_field)
default_n_bits = Openflow.Match.n_bits_of(src_field)
%NxOutputReg2{
n_bits: options[:n_bits] || default_n_bits,

View file

@ -45,7 +45,7 @@ defmodule Openflow.Action.NxRegLoad do
def new(options \\ []) do
dst_field = options[:dst_field] || raise "dst_field must be specified"
value = options[:value] || raise "value must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
default_n_bits = Openflow.Match.n_bits_of(dst_field)
%NxRegLoad{
n_bits: options[:n_bits] || default_n_bits,
@ -61,7 +61,7 @@ defmodule Openflow.Action.NxRegLoad do
value_int =
load.value
|> Openflow.Match.Field.codec(load.dst_field)
|> Openflow.Match.encode_value(load.dst_field)
|> :binary.decode_unsigned(:big)
Experimenter.pack_exp_header(<<
@ -76,7 +76,7 @@ defmodule Openflow.Action.NxRegLoad do
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
<<ofs::10, n_bits::6, dst_field_bin::4-bytes, value_bin::bytes>> = body
dst_field = Openflow.Match.codec_header(dst_field_bin)
value = Openflow.Match.Field.codec(value_bin, dst_field)
value = Openflow.Match.decode_value(value_bin, dst_field)
%NxRegLoad{n_bits: n_bits + 1, offset: ofs, dst_field: dst_field, value: value}
end
end

View file

@ -147,7 +147,7 @@ defmodule Openflow.Action.NxRegMove do
def new(options \\ []) do
src_field = options[:src_field] || raise "src_field must be specified"
dst_field = options[:dst_field] || raise "dst_field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
default_n_bits = Openflow.Match.n_bits_of(dst_field)
%NxRegMove{
n_bits: options[:n_bits] || default_n_bits,

View file

@ -13,7 +13,7 @@ defmodule Openflow.Action.NxStackPop do
def new(options) do
field = options[:field] || raise "field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(field)
default_n_bits = Openflow.Match.n_bits_of(field)
%NxStackPop{
n_bits: options[:n_bits] || default_n_bits,

View file

@ -13,7 +13,7 @@ defmodule Openflow.Action.NxStackPush do
def new(options) do
field = options[:field] || raise "field must be specified"
default_n_bits = Openflow.Match.Field.n_bits_of(field)
default_n_bits = Openflow.Match.n_bits_of(field)
%NxStackPush{
n_bits: options[:n_bits] || default_n_bits,

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,673 +0,0 @@
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
else
value0
end
end
formatting(value, type, format)
end
def codec(value, type) do
{type, format} = format_of(type)
formatting(value, type, format)
end
def n_bits_of(field) do
field
|> format_of
|> 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({:be128, _}), do: 128
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_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
# 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(: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
# 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
# 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_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
# HP Ext Match
def vendor_of(:hp_udp_src_port_range), do: :hp_ext_match
def vendor_of(:hp_udp_dst_port_range), do: :hp_ext_match
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
# 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
# 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}
# 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}
# 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}
# 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}
# 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}
# 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}
# ONF Ext Match
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}
# Formatting = decimal
def formatting(<<value::8>>, :u8, :decimal), do: value
def formatting(value, :u8, :decimal) when is_integer(value), do: <<value::8>>
def formatting(<<value::16>>, :be16, :decimal), do: value
def formatting(value, :be16, :decimal) when is_integer(value), do: <<value::16>>
def formatting(<<value::24>>, :u24, :decimal), do: value
def formatting(value, :u24, :decimal) when is_integer(value), do: <<value::24>>
def formatting(<<value::32>>, :be32, :decimal), do: value
def formatting(value, :be32, :decimal) when is_integer(value), do: <<value::32>>
def formatting(<<value::64>>, :be64, :decimal), do: value
def formatting(value, :be64, :decimal) when is_integer(value), do: <<value::64>>
def formatting(<<value::128>>, :be128, :decimal), do: value
def formatting(value, :be128, :decimal) when is_integer(value), do: <<value::128>>
# Formatting = hexadecimal
def formatting(<<value::16>>, :be16, :hexadecimal), do: value
def formatting(value, :be16, :hexadecimal) when is_integer(value), do: <<value::16>>
def formatting(<<value::24>>, :u24, :hexadecimal), do: value
def formatting(value, :u24, :hexadecimal) when is_integer(value), do: <<value::24>>
def formatting(<<value::32>>, :be32, :hexadecimal), do: value
def formatting(value, :be32, :hexadecimal) when is_integer(value), do: <<value::32>>
def formatting(<<value::64>>, :be64, :hexadecimal), do: value
def formatting(value, :be64, :hexadecimal) when is_integer(value), do: <<value::64>>
def formatting(<<value::128>>, :be128, :hexadecimal), do: value
def formatting(value, :be128, :hexadecimal) when is_integer(value), do: <<value::128>>
# Formatting = ethernet
def formatting(<<value::48-bits>>, :mac, :ethernet), do: Openflow.Utils.to_hex_string(value)
def formatting(value, :mac, :ethernet), do: <<String.to_integer(value, 16)::48>>
# Formatting = IPv4
def formatting(<<a1, a2, a3, a4>>, :be32, :ipv4), do: {a1, a2, a3, a4}
def formatting({a1, a2, a3, a4}, :be32, :ipv4), do: <<a1, a2, a3, a4>>
# Formatting = IPv6
def formatting(
<<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>,
:be128,
:ipv6
) do
{a1, a2, a3, a4, a5, a6, a7, a8}
end
def formatting({a1, a2, a3, a4, a5, a6, a7, a8}, :be128, :ipv6) do
<<a1::16, a2::16, a3::16, a4::16, a5::16, a6::16, a7::16, a8::16>>
end
# Formatting = OpenFlow 1.0 port
def formatting(<<value::16>>, :be16, :openflow10_port) do
try do
Openflow.Enums.to_atom(value, :openflow10_port_no)
catch
: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
end
<<port_no::16>>
end
# Formatting = OpenFlow 1.3 port
def formatting(<<value::32>>, :be32, :openflow13_port) do
try do
Openflow.Enums.to_atom(value, :openflow13_port_no)
catch
:bad_enum -> value
end
end
def formatting(value, :be32, :openflow13_port) do
port_no =
try do
Openflow.Enums.to_int(value, :openflow13_port_no)
catch
:bad_enum -> value
end
<<port_no::32>>
end
# TCP flags
def formatting(<<value::16>>, :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(<<value::32>>, :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(<<value::16>>, :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
def formatting(value, _, _) do
value
end
end

82
lib/tres/actions.ex Normal file
View file

@ -0,0 +1,82 @@
defmodule Tres.Actions do
@moduledoc """
Action aliases
"""
defmacro __using__(_) do
quote do
alias Openflow.Action.Output
alias Openflow.Action.CopyTtlOut
alias Openflow.Action.CopyTtlIn
alias Openflow.Action.SetMplsTtl
alias Openflow.Action.DecMplsTtl
alias Openflow.Action.PushVlan
alias Openflow.Action.PopVlan
alias Openflow.Action.PushMpls
alias Openflow.Action.PopMpls
alias Openflow.Action.SetQueue
alias Openflow.Action.Group
alias Openflow.Action.SetNwTtl
alias Openflow.Action.DecNwTtl
alias Openflow.Action.SetField
alias Openflow.Action.PushPbb
alias Openflow.Action.PopPbb
alias Openflow.Action.Encap
alias Openflow.Action.Decap
alias Openflow.Action.SetSequence
alias Openflow.Action.ValidateSequence
alias Openflow.Action.NxResubmit
alias Openflow.Action.NxSetTunnel
alias Openflow.Action.NxSetQueue
alias Openflow.Action.NxPopQueue
alias Openflow.Action.NxRegMove
alias Openflow.Action.NxRegLoad
alias Openflow.Action.NxNote
alias Openflow.Action.NxSetTunnel64
alias Openflow.Action.NxMultipath
alias Openflow.Action.NxBundle
alias Openflow.Action.NxBundleLoad
alias Openflow.Action.NxResubmitTable
alias Openflow.Action.NxOutputReg
alias Openflow.Action.NxLearn
alias Openflow.Action.NxExit
alias Openflow.Action.NxDecTtl
alias Openflow.Action.NxFinTimeout
alias Openflow.Action.NxController
alias Openflow.Action.NxDecTtlCntIds
alias Openflow.Action.NxWriteMetadata
alias Openflow.Action.NxPushMpls
alias Openflow.Action.NxPopMpls
alias Openflow.Action.NxSetMplsTtl
alias Openflow.Action.NxDecMplsTtl
alias Openflow.Action.NxStackPush
alias Openflow.Action.NxStackPop
alias Openflow.Action.NxSample
alias Openflow.Action.NxSetMplsLabel
alias Openflow.Action.NxSetMplsTc
alias Openflow.Action.NxOutputReg2
alias Openflow.Action.NxRegLoad2
alias Openflow.Action.NxConjunction
alias Openflow.Action.NxConntrack
alias Openflow.Action.NxNat
alias Openflow.Action.NxController2
alias Openflow.Action.NxSample2
alias Openflow.Action.NxOutputTrunc
alias Openflow.Action.NxGroup
alias Openflow.Action.NxSample3
alias Openflow.Action.NxClone
alias Openflow.Action.NxCtClear
alias Openflow.Action.NxResubmitTableCt
alias Openflow.Action.NxLearn2
alias Openflow.Action.NxEncap
alias Openflow.Action.NxDecap
alias Openflow.Action.NxDebugRecirc
alias Openflow.Action.NxCheckPktLarger
alias Openflow.Action.NxFlowSpecMatch
alias Openflow.Action.NxFlowSpecLoad
alias Openflow.Action.NxFlowSpecOutput
end
end
end

View file

@ -10,7 +10,9 @@ defmodule Tres.Controller do
get_current_xid: 1
]
use Tres.Actions
use Tres.Messages
use Tres.Instructions
use Tres.MessageHelper
def handler_spec(dpid) do

16
lib/tres/instructions.ex Normal file
View file

@ -0,0 +1,16 @@
defmodule Tres.Instructions do
@moduledoc """
Instruction Aliases
"""
defmacro __using__(_) do
quote do
alias Openflow.Instruction.GotoTable
alias Openflow.Instruction.WriteMetadata
alias Openflow.Instruction.WriteActions
alias Openflow.Instruction.ApplyActions
alias Openflow.Instruction.ClearActions
alias Openflow.Instruction.Meter
end
end
end

View file

@ -43,85 +43,6 @@ defmodule Tres.Messages do
alias Openflow.Multipart.TableFeatures
alias Openflow.Multipart.PortDesc
alias Openflow.Instruction.GotoTable
alias Openflow.Instruction.WriteMetadata
alias Openflow.Instruction.WriteActions
alias Openflow.Instruction.ApplyActions
alias Openflow.Instruction.ClearActions
alias Openflow.Instruction.Meter
alias Openflow.Action.Output
alias Openflow.Action.CopyTtlOut
alias Openflow.Action.CopyTtlIn
alias Openflow.Action.SetMplsTtl
alias Openflow.Action.DecMplsTtl
alias Openflow.Action.PushVlan
alias Openflow.Action.PopVlan
alias Openflow.Action.PushMpls
alias Openflow.Action.PopMpls
alias Openflow.Action.SetQueue
alias Openflow.Action.Group
alias Openflow.Action.SetNwTtl
alias Openflow.Action.DecNwTtl
alias Openflow.Action.SetField
alias Openflow.Action.PushPbb
alias Openflow.Action.PopPbb
alias Openflow.Action.Encap
alias Openflow.Action.Decap
alias Openflow.Action.SetSequence
alias Openflow.Action.ValidateSequence
alias Openflow.Action.NxResubmit
alias Openflow.Action.NxSetTunnel
alias Openflow.Action.NxSetQueue
alias Openflow.Action.NxPopQueue
alias Openflow.Action.NxRegMove
alias Openflow.Action.NxRegLoad
alias Openflow.Action.NxNote
alias Openflow.Action.NxSetTunnel64
alias Openflow.Action.NxMultipath
alias Openflow.Action.NxBundle
alias Openflow.Action.NxBundleLoad
alias Openflow.Action.NxResubmitTable
alias Openflow.Action.NxOutputReg
alias Openflow.Action.NxLearn
alias Openflow.Action.NxExit
alias Openflow.Action.NxDecTtl
alias Openflow.Action.NxFinTimeout
alias Openflow.Action.NxController
alias Openflow.Action.NxDecTtlCntIds
alias Openflow.Action.NxWriteMetadata
alias Openflow.Action.NxPushMpls
alias Openflow.Action.NxPopMpls
alias Openflow.Action.NxSetMplsTtl
alias Openflow.Action.NxDecMplsTtl
alias Openflow.Action.NxStackPush
alias Openflow.Action.NxStackPop
alias Openflow.Action.NxSample
alias Openflow.Action.NxSetMplsLabel
alias Openflow.Action.NxSetMplsTc
alias Openflow.Action.NxOutputReg2
alias Openflow.Action.NxRegLoad2
alias Openflow.Action.NxConjunction
alias Openflow.Action.NxConntrack
alias Openflow.Action.NxNat
alias Openflow.Action.NxController2
alias Openflow.Action.NxSample2
alias Openflow.Action.NxOutputTrunc
alias Openflow.Action.NxGroup
alias Openflow.Action.NxSample3
alias Openflow.Action.NxClone
alias Openflow.Action.NxCtClear
alias Openflow.Action.NxResubmitTableCt
alias Openflow.Action.NxLearn2
alias Openflow.Action.NxEncap
alias Openflow.Action.NxDecap
alias Openflow.Action.NxDebugRecirc
alias Openflow.Action.NxFlowSpecMatch
alias Openflow.Action.NxFlowSpecLoad
alias Openflow.Action.NxFlowSpecOutput
alias Tres.SwitchRegistry
end
end

View file

@ -8,7 +8,7 @@ defmodule Tres.Mixfile do
def project do
[
app: :tres,
version: "0.1.1",
version: "0.1.3",
description: @description,
elixir: "~> 1.8",
package: package(),

View file

@ -304,7 +304,8 @@ enums = [
no_buffer: 0xFFFF
],
experimenter_oxm_vendors: [
nicira_ext_match: 0x00002320,
nxoxm_nsh_match: 0x005AD650,
nxoxm_match: 0x00002320,
hp_ext_match: 0x00002428,
onf_ext_match: 0x4F4E4600
],
@ -508,39 +509,14 @@ enums = [
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,
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
packet_type: 44
],
vlan_id: [
present: 0x1000,
none: 0x0000
# Bit that indicate that a VLAN id is set.
vid_present: 0x1000,
# No VLAN id was set.
vid_none: 0x0000
],
ipv6exthdr_flags: [
nonext: 1 <<< 0,
@ -564,6 +540,10 @@ enums = [
cwr: 1 <<< 7,
ns: 1 <<< 8
],
tun_gbp_flags: [
policy_applied: 1 <<< 3,
dont_learn: 1 <<< 6
],
ct_state_flags: [
# Beginning of a new connection.
new: 1 <<< 0,
@ -592,7 +572,7 @@ enums = [
xreg6: 6,
xreg7: 7
],
nicira_ext_match: [
nxoxm_nsh_match: [
nsh_flags: 1,
nsh_mdtype: 2,
nsh_np: 3,
@ -601,29 +581,21 @@ enums = [
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_custom_match_type: [
l2_start: 1,
l3_start: 2,
l4_start: 3
nsh_c4: 9,
nsh_ttl: 10
],
onf_ext_match: [
onf_tcp_flags: 42,
onf_actset_output: 43,
onf_pbb_uca: 2560
],
nxoxm_match: [
nxoxm_dp_hash: 0,
tun_erspan_idx: 11,
tun_erspan_ver: 12,
tun_erspan_dir: 13,
tun_erspan_hwid: 14
],
buffer_id: [
no_buffer: 0xFFFFFFFF
],
@ -898,6 +870,7 @@ enums = [
{Openflow.Action.NxLearn2, 45},
{Openflow.Action.NxEncap, 46},
{Openflow.Action.NxDecap, 47},
{Openflow.Action.NxCheckPktLarger, 49},
{Openflow.Action.NxDebugRecirc, 0xFF}
],
nx_mp_algorithm: [

View file

@ -741,7 +741,7 @@ defmodule OfpActionTest do
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_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)
]
@ -773,7 +773,7 @@ defmodule OfpActionTest do
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_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)
]
@ -846,22 +846,21 @@ defmodule OfpActionTest do
end
test "with no option" do
assert_raise RuntimeError, ":dst must be specified", fn ->
assert_raise RuntimeError, ":src must be specified", fn ->
Openflow.Action.NxFlowSpecMatch.new()
end
end
test "with no dst option" do
assert_raise RuntimeError, ":dst must be specified", fn ->
Openflow.Action.NxFlowSpecMatch.new(src: :in_port)
end
end
test "with no src option" do
assert_raise RuntimeError, ":src must be specified", fn ->
Openflow.Action.NxFlowSpecMatch.new(dst: :reg0)
end
end
test "with no dst option" do
learn = Openflow.Action.NxFlowSpecMatch.new(src: :in_port)
assert learn.dst == :in_port
end
end
describe "Openflow.Action.NxFlowSpecLoad" do
@ -1017,6 +1016,37 @@ defmodule OfpActionTest do
end
end
describe "Openflow.Action.NxCheckPktLarger" do
test "with options: if the packet larger than 100 bytes, set mark to reg1" do
test_file = "test/packet_data/nx_check_pkt_larger.raw"
packet = File.read!(test_file)
actions = Openflow.Action.read(packet)
check_pkt_larger =
Openflow.Action.NxCheckPktLarger.new(
dst_field: :reg1,
offset: 0,
pkt_len: 100
)
actions_bin = Openflow.Action.to_binary(check_pkt_larger)
assert actions_bin == packet
assert actions == [check_pkt_larger]
end
test "with no dst_field option" do
assert_raise RuntimeError, "dst_field must be specified", fn ->
Openflow.Action.NxCheckPktLarger.new(pkt_len: 100)
end
end
test "with no pkt_len option" do
assert_raise RuntimeError, "pkt_len must be specified", fn ->
Openflow.Action.NxCheckPktLarger.new(dst_field: :reg1)
end
end
end
describe "Openflow.Action.NxRegMove" do
test "with options: move in_port value to vlan_tci field" do
test_file = "test/packet_data/nx_reg_move.raw"

View file

@ -12,62 +12,6 @@ defmodule OfpFlowModTest do
@flow_mod8 "test/packet_data/libofproto-OFP13-flow_mod_match_conj.packet"
describe "Openflow.read/1" do
test "with OFP_FLOW_MOD packet(1)" do
binary = File.read!(@flow_mod1)
fm =
binary
|> Openflow.read()
|> elem(1)
|> Map.to_list()
|> Openflow.FlowMod.new()
|> Openflow.to_binary()
|> Openflow.read()
|> elem(1)
assert fm.cookie == 0
assert fm.cookie_mask == 0
assert fm.table_id == 1
assert fm.command == :add
assert fm.idle_timeout == 0
assert fm.hard_timeout == 0
assert fm.priority == 123
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)
])
]
assert Openflow.to_binary(fm) == binary
end
test "with OFP_FLOW_MOD packet(2)" do
binary = File.read!(@flow_mod2)
{:ok, fm, ""} = Openflow.read(binary)
@ -84,7 +28,7 @@ defmodule OfpFlowModTest do
assert fm.out_port == :any
assert fm.out_group == :any
assert fm.flags == []
assert fm.match == Openflow.Match.new(in_port: 6, eth_src: "f20ba47df8ea")
assert fm.match == Openflow.Match.new(in_port: 6, eth_src: <<0xF20BA47DF8EA::48>>)
assert fm.instructions == [Openflow.Instruction.GotoTable.new(1)]
assert Openflow.to_binary(fm) == binary
end
@ -104,7 +48,7 @@ defmodule OfpFlowModTest do
assert fm.out_port == :any
assert fm.out_group == :any
assert fm.flags == []
assert fm.match == Openflow.Match.new(eth_dst: "f20ba47df8ea")
assert fm.match == Openflow.Match.new(eth_dst: <<0xF20BA47DF8EA::48>>)
assert fm.instructions == [
Openflow.Instruction.Meter.new(1),
@ -114,72 +58,6 @@ defmodule OfpFlowModTest do
assert Openflow.to_binary(fm) == binary
end
test "with OFP_FLOW_MOD packet(4)" do
binary = File.read!(@flow_mod4)
{:ok, fm, ""} = Openflow.read(binary)
assert fm.cookie == 0
assert fm.cookie_mask == 0
assert fm.table_id == 1
assert fm.command == :add
assert fm.idle_timeout == 0
assert fm.hard_timeout == 0
assert fm.priority == 123
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: 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
test "with OFP_FLOW_MOD packet(5)" do
binary = File.read!(@flow_mod5)
{:ok, fm, ""} = Openflow.read(binary)
@ -199,7 +77,7 @@ defmodule OfpFlowModTest do
assert fm.match ==
Openflow.Match.new(
in_port: 43981,
eth_dst: "aabbcc998877",
eth_dst: <<0xAABBCC998877::48>>,
eth_type: 2048,
vlan_vid: 5095,
ipv4_dst: {192, 168, 2, 1},
@ -223,7 +101,11 @@ defmodule OfpFlowModTest do
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: 0,
dst: :vlan_vid,
n_bits: 12
),
Openflow.Action.NxFlowSpecLoad.new(src: :tun_id, dst: :tun_id),
Openflow.Action.NxFlowSpecOutput.new(src: :in_port)
]
@ -261,7 +143,7 @@ defmodule OfpFlowModTest do
assert fm.match ==
Openflow.Match.new(
in_port: 43981,
eth_dst: "aabbcc998877",
eth_dst: <<0xAABBCC998877::48>>,
eth_type: 2048,
vlan_vid: 5095,
ipv4_dst: {192, 168, 2, 1},

View file

@ -21,7 +21,7 @@ defmodule OfpFlowRemovedTest do
assert flow_removed.hard_timeout == 0
assert flow_removed.packet_count == 1
assert flow_removed.byte_count == 86
assert flow_removed.match == [eth_dst: "f20ba47df8ea"]
assert flow_removed.match == [eth_dst: <<0xF20BA47DF8EA::48>>]
end
test "with OFP_FLOW_REMOVED packet(with match fields)" do
@ -45,7 +45,7 @@ defmodule OfpFlowRemovedTest do
assert flow_removed.match == [
in_port: 43_981,
eth_dst: "aabbcc998877",
eth_dst: <<0xAABBCC998877::48>>,
eth_type: 2048,
vlan_vid: 5095,
ipv4_dst: {192, 168, 2, 1},

View file

@ -20,122 +20,4 @@ defmodule OfpFlowStatsTest do
assert flow_stats.match == []
end
end
describe "Openflow.Multipart.Flow.Reply" do
test "with test packet_data" do
flow_stats =
"test/packet_data/4-12-ofp_flow_stats_reply.packet"
|> File.read!()
|> Openflow.read()
|> Kernel.elem(1)
%Openflow.Multipart.Flow.Reply{
aux_id: nil,
datapath_id: nil,
flags: [],
flows: [
%Openflow.Multipart.FlowStats{
byte_count: 0,
cookie: 0,
duration_nsec: 115_277_000,
duration_sec: 358,
flags: [],
hard_timeout: 0,
idle_timeout: 0,
instructions: [],
match: [],
packet_count: 0,
priority: 65535,
table_id: 0
},
%Openflow.Multipart.FlowStats{
byte_count: 0,
cookie: 0,
duration_nsec: 115_055_000,
duration_sec: 358,
flags: [],
hard_timeout: 0,
idle_timeout: 0,
instructions: [
%Openflow.Instruction.ApplyActions{
actions: [%Openflow.Action.Output{max_len: 0, port_number: :normal}]
}
],
match: [eth_type: 2054],
packet_count: 0,
priority: 65534,
table_id: 0
},
%Openflow.Multipart.FlowStats{
byte_count: 238,
cookie: 0,
duration_nsec: 511_582_000,
duration_sec: 316_220,
flags: [],
hard_timeout: 0,
idle_timeout: 0,
instructions: [%Openflow.Instruction.GotoTable{table_id: 1}],
match: [in_port: 6, eth_src: "f20ba47df8ea"],
packet_count: 3,
priority: 123,
table_id: 0
},
%Openflow.Multipart.FlowStats{
byte_count: 98,
cookie: 0,
duration_nsec: 980_901_000,
duration_sec: 313_499,
flags: [],
hard_timeout: 0,
idle_timeout: 0,
instructions: [
%Openflow.Instruction.WriteActions{
actions: [
%Openflow.Action.SetField{field: [vlan_vid: 258]},
%Openflow.Action.CopyTtlOut{},
%Openflow.Action.CopyTtlIn{},
%Openflow.Action.CopyTtlIn{},
%Openflow.Action.PopPbb{},
%Openflow.Action.PushPbb{ethertype: 4660},
%Openflow.Action.PopMpls{ethertype: 39030},
%Openflow.Action.PushMpls{ethertype: 34887},
%Openflow.Action.PopVlan{},
%Openflow.Action.PushVlan{ethertype: 33024},
%Openflow.Action.DecMplsTtl{},
%Openflow.Action.SetMplsTtl{ttl: 10},
%Openflow.Action.DecNwTtl{},
%Openflow.Action.SetNwTtl{ttl: 10},
%Openflow.Action.SetQueue{id: 3},
%Openflow.Action.Group{id: 99},
%Openflow.Action.Output{max_len: :no_buffer, port_number: 6},
%Openflow.Action.Experimenter{data: "exp_data", exp_id: 98_765_432},
%Openflow.Action.Experimenter{data: "exp_data", exp_id: 8992}
]
},
%Openflow.Instruction.ApplyActions{
actions: [
%Openflow.Action.SetField{field: [eth_src: "010203040506"]},
%Openflow.Action.SetField{field: [onf_pbb_uca: 1]}
]
},
%Openflow.Instruction.WriteActions{
actions: [
%Openflow.Action.Output{
max_len: :no_buffer,
port_number: :controller
}
]
}
],
match: [],
packet_count: 1,
priority: 0,
table_id: 0
}
],
version: 4,
xid: 0
} = flow_stats
end
end
end

View file

@ -18,71 +18,13 @@ defmodule OfpPacketInTest do
assert pktin.match == [
eth_type: 2054,
eth_dst: "ffffffffffff",
eth_src: "f20ba47df8ea",
eth_dst: <<0xFFFFFFFFFFFF::48>>,
eth_src: <<0xF20BA47DF8EA::48>>,
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()
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 == 84_281_096
assert pktin.match == [
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}
arp_sha: <<0xF20BA47DF8EA::48>>,
arp_tha: <<0x000000000000::48>>
]
end
end

View file

@ -25,7 +25,9 @@ defmodule OfpTableFeaturesTest do
"test/packet_data/4-56-ofp_table_features_reply.packet"
|> File.read!()
|> Openflow.read()
|> Kernel.elem(1)
|> Kernel.elem(0)
|> Kernel.==(:ok)
|> assert()
end
end
end

Binary file not shown.