Compare commits
17 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e3e7f78ba | ||
|
|
715bead2ff | ||
|
|
613e7d6d86 | ||
|
|
479e85439a | ||
|
|
d8a17d2d94 | ||
|
|
c81cf9e8ba | ||
|
|
ca02fe7ed7 | ||
|
|
6dc3cfd500 | ||
|
|
6ce014ea91 | ||
|
|
ccb420cbce | ||
|
|
0aa894a21c | ||
|
|
2a6623445a | ||
|
|
da4165b670 | ||
|
|
9ddd82fcab | ||
|
|
e65bf77a3c | ||
|
|
8c2484e683 | ||
|
|
f385374f82 |
38 changed files with 1666 additions and 2053 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
[](https://codecov.io/gh/shun159/tres)
|
||||
[](http://erlang.org/)
|
||||
[](https://github.com/MakeNowJust/sushi-ware)
|
||||
[](https://hex.pm/packages/tres/0.1.0)
|
||||
[](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
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 [
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
120
examples/simple_router/lib/simple_router/ipv4_address.ex
Normal file
120
examples/simple_router/lib/simple_router/ipv4_address.ex
Normal 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
|
||||
87
examples/simple_router/lib/simple_router/mac_address.ex
Normal file
87
examples/simple_router/lib/simple_router/mac_address.ex
Normal 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
|
||||
|
|
@ -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
|
||||
>>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
46
lib/openflow/actions/nx_check_pkt_larger.ex
Normal file
46
lib/openflow/actions/nx_check_pkt_larger.ex
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
82
lib/tres/actions.ex
Normal 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
|
||||
|
|
@ -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
16
lib/tres/instructions.ex
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
2
mix.exs
2
mix.exs
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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: [
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
BIN
test/packet_data/nx_check_pkt_larger.raw
Normal file
BIN
test/packet_data/nx_check_pkt_larger.raw
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue