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:
|
elixir:
|
||||||
- "1.8.1"
|
- "1.8.1"
|
||||||
otp_release:
|
otp_release:
|
||||||
- "21.3.6"
|
- "22.0.5"
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- sudo apt-get install -y wget curl gdebi debhelper unbound
|
- sudo apt-get install -y wget curl gdebi debhelper unbound
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
[](https://codecov.io/gh/shun159/tres)
|
[](https://codecov.io/gh/shun159/tres)
|
||||||
[](http://erlang.org/)
|
[](http://erlang.org/)
|
||||||
[](https://github.com/MakeNowJust/sushi-ware)
|
[](https://github.com/MakeNowJust/sushi-ware)
|
||||||
[](https://hex.pm/packages/tres/0.1.0)
|
[](https://hex.pm/packages/tres)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ Tres is a framework and set of helper libraries to develop OpenFlow controllers
|
||||||
```elixir
|
```elixir
|
||||||
def deps do
|
def deps do
|
||||||
[
|
[
|
||||||
{:tres, "~> 0.1.0"}
|
{:tres, "~> 0.1.2"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ config :tres,
|
||||||
callback_args: []
|
callback_args: []
|
||||||
|
|
||||||
config :logger,
|
config :logger,
|
||||||
level: :debug,
|
level: :info,
|
||||||
format: "$date $time [$level] $message\n",
|
format: "$date $time [$level] $message\n",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
handle_otp_reports: true
|
handle_otp_reports: true
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ defmodule LearningSwitch.Ofctl do
|
||||||
|
|
||||||
@aging_time 180
|
@aging_time 180
|
||||||
|
|
||||||
@mcast {"010000000000", "110000000000"}
|
@mcast {<<0x010000000000::48>>, <<0x110000000000::48>>}
|
||||||
@bcast "ffffffffffff"
|
@bcast <<0xffffffffffff::48>>
|
||||||
@ipv6_mcast {"333300000000", "ffff00000000"}
|
@ipv6_mcast {<<0x333300000000::48>>, <<0xffff00000000::48>>}
|
||||||
|
|
||||||
defmodule State do
|
defmodule State do
|
||||||
defstruct [
|
defstruct [
|
||||||
|
|
|
||||||
|
|
@ -56,29 +56,7 @@ defmodule NxLearningSwitch do
|
||||||
send_flow_mod_add(
|
send_flow_mod_add(
|
||||||
datapath_id,
|
datapath_id,
|
||||||
table_id: 0,
|
table_id: 0,
|
||||||
instructions: ApplyActions.new([
|
instructions: l2_learning_instr()
|
||||||
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)
|
|
||||||
])
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -90,4 +68,28 @@ defmodule NxLearningSwitch do
|
||||||
instructions: ApplyActions.new(Output.new(:flood))
|
instructions: ApplyActions.new(Output.new(:flood))
|
||||||
)
|
)
|
||||||
end
|
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
defmodule SimpleRouter.Config do
|
defmodule SimpleRouter.Config do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
alias Tres.IPv4Address
|
alias SimpleRouter.IPv4Address
|
||||||
|
|
||||||
@spec interfaces() :: %{String.t() => map()}
|
@spec interfaces() :: %{String.t() => map()}
|
||||||
def interfaces do
|
def interfaces do
|
||||||
|
|
@ -24,7 +24,7 @@ defmodule SimpleRouter.Config do
|
||||||
|
|
||||||
entry =
|
entry =
|
||||||
%{
|
%{
|
||||||
mac_address: String.replace(mac, ~r/:/, ""),
|
mac_address: mac_to_bin(mac),
|
||||||
ip_address: ipaddr,
|
ip_address: ipaddr,
|
||||||
subnet_mask: mask,
|
subnet_mask: mask,
|
||||||
network_address: IPv4Address.to_network({ipaddr, mask}),
|
network_address: IPv4Address.to_network({ipaddr, mask}),
|
||||||
|
|
@ -50,6 +50,13 @@ defmodule SimpleRouter.Config do
|
||||||
end
|
end
|
||||||
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),
|
defp get_env(key, default),
|
||||||
do: Application.get_env(:simple_router, key, default)
|
do: Application.get_env(:simple_router, key, default)
|
||||||
end
|
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
|
use Tres.Controller
|
||||||
|
|
||||||
alias Tres.IPv4Address
|
alias SimpleRouter.IPv4Address
|
||||||
alias Tres.MacAddress
|
|
||||||
|
|
||||||
@classifier_table_id 0
|
@classifier_table_id 0
|
||||||
@arp_handler_table_id 1
|
@arp_handler_table_id 1
|
||||||
|
|
@ -219,7 +218,7 @@ defmodule SimpleRouter.Openflow.FlowTables do
|
||||||
defp arp_packet(iface) do
|
defp arp_packet(iface) do
|
||||||
ether_header = <<
|
ether_header = <<
|
||||||
0xffffffffffff::48, # destination ethernet address
|
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
|
0x0806::16 # ethernet type
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
|
@ -230,7 +229,7 @@ defmodule SimpleRouter.Openflow.FlowTables do
|
||||||
6::8, # hardware address length
|
6::8, # hardware address length
|
||||||
4::8, # protocol address length
|
4::8, # protocol address length
|
||||||
1::16, # ARPOP_REQUEST
|
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
|
(IPv4Address.to_int(iface.ip_address))::32, # Source Protocol Address
|
||||||
0x000000000000::48 # Target Hardware Address
|
0x000000000000::48 # Target Hardware Address
|
||||||
>>
|
>>
|
||||||
|
|
|
||||||
|
|
@ -20,34 +20,54 @@ defmodule Openflow.Action.Experimenter do
|
||||||
|
|
||||||
@spec pack_exp_header(binary()) :: binary()
|
@spec pack_exp_header(binary()) :: binary()
|
||||||
def pack_exp_header(exp_body) do
|
def pack_exp_header(exp_body) do
|
||||||
pad_length =
|
pad_length = pad_length_of(exp_body)
|
||||||
exp_body
|
|
||||||
|> Kernel.byte_size()
|
|
||||||
|> Kernel.+(4)
|
|
||||||
|> Openflow.Utils.padding(8)
|
|
||||||
|
|
||||||
length =
|
<<
|
||||||
exp_body
|
0xFFFF::16,
|
||||||
|> byte_size()
|
length_of(exp_body, pad_length)::16,
|
||||||
|> Kernel.+(4)
|
exp_body::bytes,
|
||||||
|> Kernel.+(pad_length)
|
0::size(pad_length)-unit(8)
|
||||||
|
>>
|
||||||
<<0xFFFF::16, length::16, exp_body::bytes, 0::size(pad_length)-unit(8)>>
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def read(<<0xFFFF::16, _length::16, exp_id::32, exp_type::16, data::bytes>>) do
|
def read(<<
|
||||||
case Openflow.Utils.get_enum(exp_id, :action_vendor) do
|
0xFFFF::16,
|
||||||
vendor_id when is_integer(vendor_id) ->
|
_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
|
||||||
|
|
||||||
|
## 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>>)
|
||||||
|
|
||||||
|
exp_type when is_integer(exp_type) ->
|
||||||
%Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
|
%Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
|
||||||
|
|
||||||
vendor when is_atom(vendor) ->
|
|
||||||
case Openflow.Utils.get_enum(exp_type, vendor) do
|
|
||||||
codec when is_atom(codec) ->
|
|
||||||
codec.read(<<exp_id::32, exp_type::16, data::bytes>>)
|
|
||||||
|
|
||||||
exp_type when is_integer(exp_type) ->
|
|
||||||
%Experimenter{exp_id: exp_id, data: <<exp_type::16, data::bytes>>}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ defmodule Openflow.Action.NxBundleLoad do
|
||||||
) :: t()
|
) :: t()
|
||||||
def new(options \\ []) do
|
def new(options \\ []) do
|
||||||
dst_field = options[:dst_field] || raise "dst_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)
|
||||||
slaves = options[:slaves] || []
|
slaves = options[:slaves] || []
|
||||||
|
|
||||||
%NxBundleLoad{
|
%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
|
def new(options) do
|
||||||
dst = options[:dst] || raise(":dst must be specified")
|
dst = options[:dst] || raise(":dst must be specified")
|
||||||
src = options[:src] || raise(":src 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{
|
%NxFlowSpecLoad{
|
||||||
src: src,
|
src: src,
|
||||||
|
|
@ -90,7 +90,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do
|
||||||
binary
|
binary
|
||||||
|
|
||||||
dst = Openflow.Match.codec_header(dst_bin)
|
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 = %NxFlowSpecLoad{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs}
|
||||||
{flow_spec, rest}
|
{flow_spec, rest}
|
||||||
end
|
end
|
||||||
|
|
@ -103,7 +103,7 @@ defmodule Openflow.Action.NxFlowSpecLoad do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do
|
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}
|
{@learn_src_immediate, src_bin}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ defmodule Openflow.Action.NxFlowSpecMatch do
|
||||||
dst_offset: non_neg_integer()
|
dst_offset: non_neg_integer()
|
||||||
) :: t()
|
) :: t()
|
||||||
def new(options \\ []) do
|
def new(options \\ []) do
|
||||||
dst = options[:dst] || raise ":dst must be specified"
|
|
||||||
src = options[:src] || raise ":src 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{
|
%NxFlowSpecMatch{
|
||||||
src: src,
|
src: src,
|
||||||
|
|
@ -92,7 +92,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do
|
||||||
binary
|
binary
|
||||||
|
|
||||||
dst = Openflow.Match.codec_header(dst_bin)
|
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 = %NxFlowSpecMatch{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs}
|
||||||
{flow_spec, rest}
|
{flow_spec, rest}
|
||||||
end
|
end
|
||||||
|
|
@ -105,7 +105,7 @@ defmodule Openflow.Action.NxFlowSpecMatch do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp codec_src(%NxFlowSpecMatch{src: src, dst: dst_field}) do
|
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}
|
{@learn_src_immediate, src_bin}
|
||||||
end
|
end
|
||||||
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()
|
@spec new(src: atom(), n_bits: non_neg_integer(), src_offset: non_neg_integer()) :: t()
|
||||||
def new(options \\ []) do
|
def new(options \\ []) do
|
||||||
src = options[:src] || raise ":src must be specified"
|
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}
|
%NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: options[:src_offset] || 0}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ defmodule Openflow.Action.NxMultipath do
|
||||||
@spec new(Keyword.t()) :: %NxMultipath{}
|
@spec new(Keyword.t()) :: %NxMultipath{}
|
||||||
def new(options) do
|
def new(options) do
|
||||||
dst_field = options[:dst_field] || raise "dst_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)
|
||||||
|
|
||||||
%NxMultipath{
|
%NxMultipath{
|
||||||
hash_field: options[:hash_field] || :eth_src,
|
hash_field: options[:hash_field] || :eth_src,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ defmodule Openflow.Action.NxOutputReg do
|
||||||
) :: t()
|
) :: t()
|
||||||
def new(options) do
|
def new(options) do
|
||||||
src_field = options[:src_field] || raise "src_field must be specified"
|
src_field = options[:src_field] || raise "src_field must be specified"
|
||||||
default_n_bits = Openflow.Match.Field.n_bits_of(src_field)
|
default_n_bits = Openflow.Match.n_bits_of(src_field)
|
||||||
|
|
||||||
%NxOutputReg{
|
%NxOutputReg{
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
n_bits: options[:n_bits] || default_n_bits,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ defmodule Openflow.Action.NxOutputReg2 do
|
||||||
) :: t()
|
) :: t()
|
||||||
def new(options) do
|
def new(options) do
|
||||||
src_field = options[:src_field] || raise "src_field must be specified"
|
src_field = options[:src_field] || raise "src_field must be specified"
|
||||||
default_n_bits = Openflow.Match.Field.n_bits_of(src_field)
|
default_n_bits = Openflow.Match.n_bits_of(src_field)
|
||||||
|
|
||||||
%NxOutputReg2{
|
%NxOutputReg2{
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
n_bits: options[:n_bits] || default_n_bits,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ defmodule Openflow.Action.NxRegLoad do
|
||||||
def new(options \\ []) do
|
def new(options \\ []) do
|
||||||
dst_field = options[:dst_field] || raise "dst_field must be specified"
|
dst_field = options[:dst_field] || raise "dst_field must be specified"
|
||||||
value = options[:value] || raise "value 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{
|
%NxRegLoad{
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
n_bits: options[:n_bits] || default_n_bits,
|
||||||
|
|
@ -61,7 +61,7 @@ defmodule Openflow.Action.NxRegLoad do
|
||||||
|
|
||||||
value_int =
|
value_int =
|
||||||
load.value
|
load.value
|
||||||
|> Openflow.Match.Field.codec(load.dst_field)
|
|> Openflow.Match.encode_value(load.dst_field)
|
||||||
|> :binary.decode_unsigned(:big)
|
|> :binary.decode_unsigned(:big)
|
||||||
|
|
||||||
Experimenter.pack_exp_header(<<
|
Experimenter.pack_exp_header(<<
|
||||||
|
|
@ -76,7 +76,7 @@ defmodule Openflow.Action.NxRegLoad do
|
||||||
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
|
def read(<<@experimenter::32, @nxast::16, body::bytes>>) do
|
||||||
<<ofs::10, n_bits::6, dst_field_bin::4-bytes, value_bin::bytes>> = body
|
<<ofs::10, n_bits::6, dst_field_bin::4-bytes, value_bin::bytes>> = body
|
||||||
dst_field = Openflow.Match.codec_header(dst_field_bin)
|
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}
|
%NxRegLoad{n_bits: n_bits + 1, offset: ofs, dst_field: dst_field, value: value}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ defmodule Openflow.Action.NxRegMove do
|
||||||
def new(options \\ []) do
|
def new(options \\ []) do
|
||||||
src_field = options[:src_field] || raise "src_field must be specified"
|
src_field = options[:src_field] || raise "src_field must be specified"
|
||||||
dst_field = options[:dst_field] || raise "dst_field must be specified"
|
dst_field = options[:dst_field] || raise "dst_field must be specified"
|
||||||
default_n_bits = Openflow.Match.Field.n_bits_of(dst_field)
|
default_n_bits = Openflow.Match.n_bits_of(dst_field)
|
||||||
|
|
||||||
%NxRegMove{
|
%NxRegMove{
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
n_bits: options[:n_bits] || default_n_bits,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ defmodule Openflow.Action.NxStackPop do
|
||||||
|
|
||||||
def new(options) do
|
def new(options) do
|
||||||
field = options[:field] || raise "field must be specified"
|
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{
|
%NxStackPop{
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
n_bits: options[:n_bits] || default_n_bits,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ defmodule Openflow.Action.NxStackPush do
|
||||||
|
|
||||||
def new(options) do
|
def new(options) do
|
||||||
field = options[:field] || raise "field must be specified"
|
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{
|
%NxStackPush{
|
||||||
n_bits: options[:n_bits] || default_n_bits,
|
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
|
get_current_xid: 1
|
||||||
]
|
]
|
||||||
|
|
||||||
|
use Tres.Actions
|
||||||
use Tres.Messages
|
use Tres.Messages
|
||||||
|
use Tres.Instructions
|
||||||
use Tres.MessageHelper
|
use Tres.MessageHelper
|
||||||
|
|
||||||
def handler_spec(dpid) do
|
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.TableFeatures
|
||||||
alias Openflow.Multipart.PortDesc
|
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
|
alias Tres.SwitchRegistry
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
2
mix.exs
2
mix.exs
|
|
@ -8,7 +8,7 @@ defmodule Tres.Mixfile do
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :tres,
|
app: :tres,
|
||||||
version: "0.1.1",
|
version: "0.1.3",
|
||||||
description: @description,
|
description: @description,
|
||||||
elixir: "~> 1.8",
|
elixir: "~> 1.8",
|
||||||
package: package(),
|
package: package(),
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,8 @@ enums = [
|
||||||
no_buffer: 0xFFFF
|
no_buffer: 0xFFFF
|
||||||
],
|
],
|
||||||
experimenter_oxm_vendors: [
|
experimenter_oxm_vendors: [
|
||||||
nicira_ext_match: 0x00002320,
|
nxoxm_nsh_match: 0x005AD650,
|
||||||
|
nxoxm_match: 0x00002320,
|
||||||
hp_ext_match: 0x00002428,
|
hp_ext_match: 0x00002428,
|
||||||
onf_ext_match: 0x4F4E4600
|
onf_ext_match: 0x4F4E4600
|
||||||
],
|
],
|
||||||
|
|
@ -508,39 +509,14 @@ enums = [
|
||||||
pbb_isid: 37,
|
pbb_isid: 37,
|
||||||
tunnel_id: 38,
|
tunnel_id: 38,
|
||||||
ipv6_exthdr: 39,
|
ipv6_exthdr: 39,
|
||||||
|
|
||||||
# Lagopus extended match fields
|
|
||||||
pbb_uca: 41,
|
pbb_uca: 41,
|
||||||
packet_type: 42,
|
packet_type: 44
|
||||||
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
|
|
||||||
],
|
],
|
||||||
vlan_id: [
|
vlan_id: [
|
||||||
present: 0x1000,
|
# Bit that indicate that a VLAN id is set.
|
||||||
none: 0x0000
|
vid_present: 0x1000,
|
||||||
|
# No VLAN id was set.
|
||||||
|
vid_none: 0x0000
|
||||||
],
|
],
|
||||||
ipv6exthdr_flags: [
|
ipv6exthdr_flags: [
|
||||||
nonext: 1 <<< 0,
|
nonext: 1 <<< 0,
|
||||||
|
|
@ -564,6 +540,10 @@ enums = [
|
||||||
cwr: 1 <<< 7,
|
cwr: 1 <<< 7,
|
||||||
ns: 1 <<< 8
|
ns: 1 <<< 8
|
||||||
],
|
],
|
||||||
|
tun_gbp_flags: [
|
||||||
|
policy_applied: 1 <<< 3,
|
||||||
|
dont_learn: 1 <<< 6
|
||||||
|
],
|
||||||
ct_state_flags: [
|
ct_state_flags: [
|
||||||
# Beginning of a new connection.
|
# Beginning of a new connection.
|
||||||
new: 1 <<< 0,
|
new: 1 <<< 0,
|
||||||
|
|
@ -592,7 +572,7 @@ enums = [
|
||||||
xreg6: 6,
|
xreg6: 6,
|
||||||
xreg7: 7
|
xreg7: 7
|
||||||
],
|
],
|
||||||
nicira_ext_match: [
|
nxoxm_nsh_match: [
|
||||||
nsh_flags: 1,
|
nsh_flags: 1,
|
||||||
nsh_mdtype: 2,
|
nsh_mdtype: 2,
|
||||||
nsh_np: 3,
|
nsh_np: 3,
|
||||||
|
|
@ -601,29 +581,21 @@ enums = [
|
||||||
nsh_c1: 6,
|
nsh_c1: 6,
|
||||||
nsh_c2: 7,
|
nsh_c2: 7,
|
||||||
nsh_c3: 8,
|
nsh_c3: 8,
|
||||||
nsh_c4: 9
|
nsh_c4: 9,
|
||||||
],
|
nsh_ttl: 10
|
||||||
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
|
|
||||||
],
|
],
|
||||||
onf_ext_match: [
|
onf_ext_match: [
|
||||||
onf_tcp_flags: 42,
|
onf_tcp_flags: 42,
|
||||||
onf_actset_output: 43,
|
onf_actset_output: 43,
|
||||||
onf_pbb_uca: 2560
|
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: [
|
buffer_id: [
|
||||||
no_buffer: 0xFFFFFFFF
|
no_buffer: 0xFFFFFFFF
|
||||||
],
|
],
|
||||||
|
|
@ -898,6 +870,7 @@ enums = [
|
||||||
{Openflow.Action.NxLearn2, 45},
|
{Openflow.Action.NxLearn2, 45},
|
||||||
{Openflow.Action.NxEncap, 46},
|
{Openflow.Action.NxEncap, 46},
|
||||||
{Openflow.Action.NxDecap, 47},
|
{Openflow.Action.NxDecap, 47},
|
||||||
|
{Openflow.Action.NxCheckPktLarger, 49},
|
||||||
{Openflow.Action.NxDebugRecirc, 0xFF}
|
{Openflow.Action.NxDebugRecirc, 0xFF}
|
||||||
],
|
],
|
||||||
nx_mp_algorithm: [
|
nx_mp_algorithm: [
|
||||||
|
|
|
||||||
|
|
@ -741,7 +741,7 @@ defmodule OfpActionTest do
|
||||||
fin_idle_timeout: 2,
|
fin_idle_timeout: 2,
|
||||||
fin_hard_timeout: 4,
|
fin_hard_timeout: 4,
|
||||||
flow_specs: [
|
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.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst),
|
||||||
Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port)
|
Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port)
|
||||||
]
|
]
|
||||||
|
|
@ -773,7 +773,7 @@ defmodule OfpActionTest do
|
||||||
result_dst: :reg0,
|
result_dst: :reg0,
|
||||||
result_dst_offset: 8,
|
result_dst_offset: 8,
|
||||||
flow_specs: [
|
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.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst),
|
||||||
Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port)
|
Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port)
|
||||||
]
|
]
|
||||||
|
|
@ -846,22 +846,21 @@ defmodule OfpActionTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with no option" do
|
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()
|
Openflow.Action.NxFlowSpecMatch.new()
|
||||||
end
|
end
|
||||||
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
|
test "with no src option" do
|
||||||
assert_raise RuntimeError, ":src must be specified", fn ->
|
assert_raise RuntimeError, ":src must be specified", fn ->
|
||||||
Openflow.Action.NxFlowSpecMatch.new(dst: :reg0)
|
Openflow.Action.NxFlowSpecMatch.new(dst: :reg0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "with no dst option" do
|
||||||
|
learn = Openflow.Action.NxFlowSpecMatch.new(src: :in_port)
|
||||||
|
assert learn.dst == :in_port
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Openflow.Action.NxFlowSpecLoad" do
|
describe "Openflow.Action.NxFlowSpecLoad" do
|
||||||
|
|
@ -1017,6 +1016,37 @@ defmodule OfpActionTest do
|
||||||
end
|
end
|
||||||
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
|
describe "Openflow.Action.NxRegMove" do
|
||||||
test "with options: move in_port value to vlan_tci field" do
|
test "with options: move in_port value to vlan_tci field" do
|
||||||
test_file = "test/packet_data/nx_reg_move.raw"
|
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"
|
@flow_mod8 "test/packet_data/libofproto-OFP13-flow_mod_match_conj.packet"
|
||||||
|
|
||||||
describe "Openflow.read/1" do
|
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
|
test "with OFP_FLOW_MOD packet(2)" do
|
||||||
binary = File.read!(@flow_mod2)
|
binary = File.read!(@flow_mod2)
|
||||||
{:ok, fm, ""} = Openflow.read(binary)
|
{:ok, fm, ""} = Openflow.read(binary)
|
||||||
|
|
@ -84,7 +28,7 @@ defmodule OfpFlowModTest do
|
||||||
assert fm.out_port == :any
|
assert fm.out_port == :any
|
||||||
assert fm.out_group == :any
|
assert fm.out_group == :any
|
||||||
assert fm.flags == []
|
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 fm.instructions == [Openflow.Instruction.GotoTable.new(1)]
|
||||||
assert Openflow.to_binary(fm) == binary
|
assert Openflow.to_binary(fm) == binary
|
||||||
end
|
end
|
||||||
|
|
@ -104,7 +48,7 @@ defmodule OfpFlowModTest do
|
||||||
assert fm.out_port == :any
|
assert fm.out_port == :any
|
||||||
assert fm.out_group == :any
|
assert fm.out_group == :any
|
||||||
assert fm.flags == []
|
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 == [
|
assert fm.instructions == [
|
||||||
Openflow.Instruction.Meter.new(1),
|
Openflow.Instruction.Meter.new(1),
|
||||||
|
|
@ -114,72 +58,6 @@ defmodule OfpFlowModTest do
|
||||||
assert Openflow.to_binary(fm) == binary
|
assert Openflow.to_binary(fm) == binary
|
||||||
end
|
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
|
test "with OFP_FLOW_MOD packet(5)" do
|
||||||
binary = File.read!(@flow_mod5)
|
binary = File.read!(@flow_mod5)
|
||||||
{:ok, fm, ""} = Openflow.read(binary)
|
{:ok, fm, ""} = Openflow.read(binary)
|
||||||
|
|
@ -199,7 +77,7 @@ defmodule OfpFlowModTest do
|
||||||
assert fm.match ==
|
assert fm.match ==
|
||||||
Openflow.Match.new(
|
Openflow.Match.new(
|
||||||
in_port: 43981,
|
in_port: 43981,
|
||||||
eth_dst: "aabbcc998877",
|
eth_dst: <<0xAABBCC998877::48>>,
|
||||||
eth_type: 2048,
|
eth_type: 2048,
|
||||||
vlan_vid: 5095,
|
vlan_vid: 5095,
|
||||||
ipv4_dst: {192, 168, 2, 1},
|
ipv4_dst: {192, 168, 2, 1},
|
||||||
|
|
@ -223,7 +101,11 @@ defmodule OfpFlowModTest do
|
||||||
n_bits: 12
|
n_bits: 12
|
||||||
),
|
),
|
||||||
Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst),
|
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.NxFlowSpecLoad.new(src: :tun_id, dst: :tun_id),
|
||||||
Openflow.Action.NxFlowSpecOutput.new(src: :in_port)
|
Openflow.Action.NxFlowSpecOutput.new(src: :in_port)
|
||||||
]
|
]
|
||||||
|
|
@ -261,7 +143,7 @@ defmodule OfpFlowModTest do
|
||||||
assert fm.match ==
|
assert fm.match ==
|
||||||
Openflow.Match.new(
|
Openflow.Match.new(
|
||||||
in_port: 43981,
|
in_port: 43981,
|
||||||
eth_dst: "aabbcc998877",
|
eth_dst: <<0xAABBCC998877::48>>,
|
||||||
eth_type: 2048,
|
eth_type: 2048,
|
||||||
vlan_vid: 5095,
|
vlan_vid: 5095,
|
||||||
ipv4_dst: {192, 168, 2, 1},
|
ipv4_dst: {192, 168, 2, 1},
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ defmodule OfpFlowRemovedTest do
|
||||||
assert flow_removed.hard_timeout == 0
|
assert flow_removed.hard_timeout == 0
|
||||||
assert flow_removed.packet_count == 1
|
assert flow_removed.packet_count == 1
|
||||||
assert flow_removed.byte_count == 86
|
assert flow_removed.byte_count == 86
|
||||||
assert flow_removed.match == [eth_dst: "f20ba47df8ea"]
|
assert flow_removed.match == [eth_dst: <<0xF20BA47DF8EA::48>>]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with OFP_FLOW_REMOVED packet(with match fields)" do
|
test "with OFP_FLOW_REMOVED packet(with match fields)" do
|
||||||
|
|
@ -45,7 +45,7 @@ defmodule OfpFlowRemovedTest do
|
||||||
|
|
||||||
assert flow_removed.match == [
|
assert flow_removed.match == [
|
||||||
in_port: 43_981,
|
in_port: 43_981,
|
||||||
eth_dst: "aabbcc998877",
|
eth_dst: <<0xAABBCC998877::48>>,
|
||||||
eth_type: 2048,
|
eth_type: 2048,
|
||||||
vlan_vid: 5095,
|
vlan_vid: 5095,
|
||||||
ipv4_dst: {192, 168, 2, 1},
|
ipv4_dst: {192, 168, 2, 1},
|
||||||
|
|
|
||||||
|
|
@ -20,122 +20,4 @@ defmodule OfpFlowStatsTest do
|
||||||
assert flow_stats.match == []
|
assert flow_stats.match == []
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
|
||||||
|
|
@ -18,71 +18,13 @@ defmodule OfpPacketInTest do
|
||||||
|
|
||||||
assert pktin.match == [
|
assert pktin.match == [
|
||||||
eth_type: 2054,
|
eth_type: 2054,
|
||||||
eth_dst: "ffffffffffff",
|
eth_dst: <<0xFFFFFFFFFFFF::48>>,
|
||||||
eth_src: "f20ba47df8ea",
|
eth_src: <<0xF20BA47DF8EA::48>>,
|
||||||
arp_op: 1,
|
arp_op: 1,
|
||||||
arp_spa: {10, 0, 0, 1},
|
arp_spa: {10, 0, 0, 1},
|
||||||
arp_tpa: {10, 0, 0, 3},
|
arp_tpa: {10, 0, 0, 3},
|
||||||
arp_sha: "f20ba47df8ea",
|
arp_sha: <<0xF20BA47DF8EA::48>>,
|
||||||
arp_tha: "000000000000"
|
arp_tha: <<0x000000000000::48>>
|
||||||
]
|
|
||||||
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}
|
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ defmodule OfpTableFeaturesTest do
|
||||||
"test/packet_data/4-56-ofp_table_features_reply.packet"
|
"test/packet_data/4-56-ofp_table_features_reply.packet"
|
||||||
|> File.read!()
|
|> File.read!()
|
||||||
|> Openflow.read()
|
|> Openflow.read()
|
||||||
|> Kernel.elem(1)
|
|> Kernel.elem(0)
|
||||||
|
|> Kernel.==(:ok)
|
||||||
|
|> assert()
|
||||||
end
|
end
|
||||||
end
|
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