diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..b874ba3 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,18 @@ +[ + inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"], + + locals_without_parens: [ + # Formatter tests + assert_format: 2, + assert_format: 3, + assert_same: 1, + assert_same: 2, + + # Errors tests + assert_eval_raise: 3, + + # Mix tests + in_fixture: 2, + in_tmp: 2 + ] +] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..674fc49 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Examples +*/polaris/* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ea5a6eb --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright [2018] [Eishun Kondoh] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..69efd9b --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# Tres - an Elixir OpenFlow development platform + +## Overview + +Tres is a framework and set of helper libraries to develop OpenFlow controllers in Elixir. + +## How to build your own controller application + +### Installation + +```elixir +def deps do + [ + {:tres, github: "shun159/tres", branch: "develop"} + ] +end +``` + +### callbacks + +```elixir +config :tres, + callback_module: Tres.ExampleHandler, + callback_args: [] +``` + +To use `Tres.Controller` with your code, set the handler callback_module to your callback module. +This module must implement the `Module.start_link/2` that returns `on_start`. + +Set the callback_args to the terms you want pass to the `start_link/2` callback function. + +``` +% cat lib/sample.ex +defmodule Sample do + use GenServer + use Tres.Controller + + def start_link(datapath_id, _start_args) do + GenServer.start_link(__MODULE__, [datapath_id]) + end + + def init([datapath_id]) do + # As an example create a flow to receive all packet_ins from port 1 + redirect_action = Output.new(:controller) + apply_ins = ApplyActions.new(redirect_action) + match = Match.new(in_port: 1) + :ok = send_flow_mod_add(datapath_id, + priority: 1, + match: match, + instructions: [apply_ins]) + {:ok, datapath_id} + end + + def handle_info(%PacketIn{} = packet_in, datapath_id) do + # print the packet_in message struct + IO.inspect(packet_in) + {:noreply, datapath_id} + end +end +``` + +## To run the controller + +```bash +$ iex -S mix +``` + +## Examples + +- learning-switch: Simple Layer2 switch +- leader-example: Simple election based multiple controller using Ulf Wiger's Locks Leader +- patch\_panel: inteligent patch\_panel example + +License +------- +Tres is released under the Apache license Version 2.0: + +* https://www.apache.org/licenses/LICENSE-2.0 diff --git a/bin/enum_gen b/bin/enum_gen new file mode 100755 index 0000000..6390ace Binary files /dev/null and b/bin/enum_gen differ diff --git a/config/config.exs b/config/config.exs new file mode 100644 index 0000000..40896b3 --- /dev/null +++ b/config/config.exs @@ -0,0 +1,17 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +config :tres, + protocol: :tcp, + port: 6653, + max_connections: 10, + num_acceptors: 10, + callback_module: Tres.ExampleHandler, + callback_args: [] + +config :logger, + level: :info, + format: "$date $time [$level] $metadata$message\n", + metadata: [:application], + handle_otp_reports: true diff --git a/examples/leader_example/.formatter.exs b/examples/leader_example/.formatter.exs new file mode 100644 index 0000000..525446d --- /dev/null +++ b/examples/leader_example/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/examples/leader_example/.gitignore b/examples/leader_example/.gitignore new file mode 100644 index 0000000..28bf3b2 --- /dev/null +++ b/examples/leader_example/.gitignore @@ -0,0 +1,24 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +leader_example-*.tar + diff --git a/examples/leader_example/README.md b/examples/leader_example/README.md new file mode 100644 index 0000000..dfed475 --- /dev/null +++ b/examples/leader_example/README.md @@ -0,0 +1,21 @@ +# LeaderExample + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `leader_example` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:leader_example, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at [https://hexdocs.pm/leader_example](https://hexdocs.pm/leader_example). + diff --git a/examples/leader_example/config/config.exs b/examples/leader_example/config/config.exs new file mode 100644 index 0000000..ce42502 --- /dev/null +++ b/examples/leader_example/config/config.exs @@ -0,0 +1,21 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +config :libcluster, + topologies: [ + gossip_example: [ + strategy: Cluster.Strategy.Gossip, + config: [ + port: 45_892, + if_addr: {0, 0, 0, 0}, + multicast_addr: {230, 1, 1, 251}, + multicast_ttl: 1]]] + +config :logger, + level: :debug, + format: "$date $time [$level] $metadata$message\n", + metadata: [:application], + handle_otp_reports: true + +import_config "#{Mix.env}.exs" diff --git a/examples/leader_example/config/dev.exs b/examples/leader_example/config/dev.exs new file mode 100644 index 0000000..0d0917d --- /dev/null +++ b/examples/leader_example/config/dev.exs @@ -0,0 +1,3 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config diff --git a/examples/leader_example/config/node1.exs b/examples/leader_example/config/node1.exs new file mode 100644 index 0000000..52a9823 --- /dev/null +++ b/examples/leader_example/config/node1.exs @@ -0,0 +1,9 @@ +use Mix.Config + +config :tres, + protocol: :tcp, + port: 6653, + max_connections: 10, + num_acceptors: 10, + callback_module: LeaderExample.Leader, + callback_args: [] diff --git a/examples/leader_example/config/node2.exs b/examples/leader_example/config/node2.exs new file mode 100644 index 0000000..bbc9aef --- /dev/null +++ b/examples/leader_example/config/node2.exs @@ -0,0 +1,9 @@ +use Mix.Config + +config :tres, + protocol: :tcp, + port: 6633, + max_connections: 10, + num_acceptors: 10, + callback_module: LeaderExample.Leader, + callback_args: [] diff --git a/examples/leader_example/lib/leader_example/application.ex b/examples/leader_example/lib/leader_example/application.ex new file mode 100644 index 0000000..89c4ca6 --- /dev/null +++ b/examples/leader_example/lib/leader_example/application.ex @@ -0,0 +1,20 @@ +defmodule LeaderExample.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + def start(_type, _args) do + # List all child processes to be supervised + children = [ + # Starts a worker by calling: LeaderExample.Worker.start_link(arg) + # {LeaderExample.Worker, arg}, + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: LeaderExample.Supervisor] + Supervisor.start_link(children, opts) + end +end diff --git a/examples/leader_example/lib/leader_example/leader.ex b/examples/leader_example/lib/leader_example/leader.ex new file mode 100644 index 0000000..f895dc1 --- /dev/null +++ b/examples/leader_example/lib/leader_example/leader.ex @@ -0,0 +1,77 @@ +defmodule LeaderExample.Leader do + use Tres.Controller + + @behaviour :locks_leader + + require Logger + + def start_link(datapath_id, args) do + :locks_leader.start_link(__MODULE__, [datapath_id, args], []) + end + + def init([{datapath_id, _aux_id}, _args]) do + :ok = Logger.debug("Switch Ready: datapath_id: #{inspect(datapath_id)}") + :ok = send_role_request(datapath_id, role: :slave, generation_id: 0) + {:ok, %{am_leader: false, gen_id: 0, datapath_id: datapath_id}} + end + + def elected(state, _info, _cand) do + :ok = Logger.info("Elected: #{inspect(Node.self)} for #{state.datapath_id} gen_id: #{state.gen_id}") + :ok = send_role_request(state.datapath_id, role: :master, generation_id: state.gen_id) + {:ok, {:elected, {Node.self(), state.gen_id + 1}}, %{state|am_leader: true}} + end + + def surrendered(%{am_leader: true} = state, {:elected, {_node, next_gen_id}}, _info) do + :ok = Logger.info("network split possible detected") + :ok = send_role_request(state.datapath_id, role: :slave, generation_id: state.gen_id) + {:ok, %{state|am_leader: false, gen_id: next_gen_id}} + end + + def surrendered(state, {:elected, {node, next_gen_id}}, _info) do + :ok = Logger.info("Surrendered: elected node is #{node} for #{state.datapath_id}") + :ok = send_role_request(state.datapath_id, role: :slave, generation_id: state.gen_id) + {:ok, %{state|am_leader: false, gen_id: next_gen_id}} + end + + def handle_DOWN(_pid, state, _info) do + :ok = Logger.warn("DOWN detected") + {:ok, state} + end + + def handle_leader_call(msg, from, state, _info) do + :ok = Logger.info("leader call with: #{inspect(msg)} from: #{inspect(from)} on #{Node.self()}") + {:reply, :ok, state} + end + + def handle_leader_cast(_msg, state, _info) do + {:ok, state} + end + + def from_leader(_from_leader, state, _info) do + {:ok, state} + end + + def handle_call(_msg, _from, state, _info) do + {:reply, :ok, state} + end + + def handle_cast(_msg, state, _info) do + {:noreply, state} + end + + def handle_info(%Role.Reply{datapath_id: dpid} = role, %{datapath_id: dpid} = state, _info) do + :ok = Logger.info("#{Node.self()} is on #{role.role} for #{dpid}") + {:noreply, state} + end + def handle_info(_msg, state, _info) do + {:noreply, state} + end + + def code_change(_from_vsn, state, _info, _extra) do + {:ok, state} + end + + def terminate(_reason, _state) do + :ok + end +end diff --git a/examples/leader_example/mix.exs b/examples/leader_example/mix.exs new file mode 100644 index 0000000..864f603 --- /dev/null +++ b/examples/leader_example/mix.exs @@ -0,0 +1,25 @@ +defmodule LeaderExample.MixProject do + use Mix.Project + + def project do + [ + app: :leader_example, + version: "0.1.0", + elixir: "~> 1.6", + deps: deps() + ] + end + + def application do + [ + extra_applications: [:logger, :libcluster, :locks, :tres], + mod: {LeaderExample.Application, []} + ] + end + + defp deps do + [{:locks, "~> 0.2.0"}, + {:libcluster, "~> 2.3.0"}, + {:tres, path: "../../../tres"}] + end +end diff --git a/examples/leader_example/mix.lock b/examples/leader_example/mix.lock new file mode 100644 index 0000000..6318ab4 --- /dev/null +++ b/examples/leader_example/mix.lock @@ -0,0 +1,10 @@ +%{ + "eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]}, + "jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]}, + "libcluster": {:hex, :libcluster, "2.3.0", "d2fb8e8b2054a4a0c7faf7ced7c41dd13f7b49cce689590d37ecf30098e1b344", [:mix], [{:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, + "locks": {:hex, :locks, "0.2.0", "c8a5db52bdbfacfcc979b38920adb2ab8909fa7fb36015ddff6b753d1c950b92", [:rebar3], [{:plain_fsm, "1.4.1", [hex: :plain_fsm, repo: "hexpm", optional: false]}], "hexpm"}, + "plain_fsm": {:hex, :plain_fsm, "1.4.1", "47e9bf6ac9322fc7586fb6df8de7198391e93764571c75165f2c45b27acde1d0", [:rebar3], [], "hexpm"}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, + "ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [:rebar3], [], "hexpm"}, + "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}, +} diff --git a/examples/leader_example/test/leader_example_test.exs b/examples/leader_example/test/leader_example_test.exs new file mode 100644 index 0000000..e7d1d8d --- /dev/null +++ b/examples/leader_example/test/leader_example_test.exs @@ -0,0 +1,8 @@ +defmodule LeaderExampleTest do + use ExUnit.Case + doctest LeaderExample + + test "greets the world" do + assert LeaderExample.hello() == :world + end +end diff --git a/examples/leader_example/test/test_helper.exs b/examples/leader_example/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/examples/leader_example/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/examples/learning_switch/.gitignore b/examples/learning_switch/.gitignore new file mode 100644 index 0000000..12179ea --- /dev/null +++ b/examples/learning_switch/.gitignore @@ -0,0 +1,20 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez diff --git a/examples/learning_switch/README.md b/examples/learning_switch/README.md new file mode 100644 index 0000000..ca03145 --- /dev/null +++ b/examples/learning_switch/README.md @@ -0,0 +1,21 @@ +# LearningSwitch + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `learning_switch` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:learning_switch, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at [https://hexdocs.pm/learning_switch](https://hexdocs.pm/learning_switch). + diff --git a/examples/learning_switch/config/config.exs b/examples/learning_switch/config/config.exs new file mode 100644 index 0000000..a9393b7 --- /dev/null +++ b/examples/learning_switch/config/config.exs @@ -0,0 +1,17 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +config :tres, + protocol: :tcp, + port: 6653, + max_connections: 10, + num_acceptors: 10, + callback_module: LearningSwitch.Ofctl, + callback_args: [] + +config :logger, + level: :debug, + format: "$date $time [$level] $metadata$message\n", + metadata: [:application], + handle_otp_reports: true diff --git a/examples/learning_switch/lib/learning_switch.ex b/examples/learning_switch/lib/learning_switch.ex new file mode 100644 index 0000000..855e031 --- /dev/null +++ b/examples/learning_switch/lib/learning_switch.ex @@ -0,0 +1,18 @@ +defmodule LearningSwitch do + @moduledoc """ + Documentation for LearningSwitch. + """ + + @doc """ + Hello world. + + ## Examples + + iex> LearningSwitch.hello + :world + + """ + def hello do + :world + end +end diff --git a/examples/learning_switch/lib/learning_switch/application.ex b/examples/learning_switch/lib/learning_switch/application.ex new file mode 100644 index 0000000..fa4dab3 --- /dev/null +++ b/examples/learning_switch/lib/learning_switch/application.ex @@ -0,0 +1,20 @@ +defmodule LearningSwitch.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + def start(_type, _args) do + # List all child processes to be supervised + children = [ + # Starts a worker by calling: LearningSwitch.Worker.start_link(arg) + # {LearningSwitch.Worker, arg}, + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: LearningSwitch.Supervisor] + Supervisor.start_link(children, opts) + end +end diff --git a/examples/learning_switch/lib/learning_switch/fdb.ex b/examples/learning_switch/lib/learning_switch/fdb.ex new file mode 100644 index 0000000..dcc46e7 --- /dev/null +++ b/examples/learning_switch/lib/learning_switch/fdb.ex @@ -0,0 +1,66 @@ +defmodule LearningSwitch.FDB do + use Agent + + defmodule Entry do + defstruct [ + mac: nil, + port_no: nil, + age_max: 0, + last_update: 0 + ] + + def new(mac, port_no, age_max \\ 180) do + %Entry{ + mac: mac, + port_no: port_no, + age_max: age_max, + last_update: :os.timestamp + } + end + + def update(self, port_no) do + %{self|port_no: port_no, last_update: :os.timestamp} + end + + def aged_out?(self) do + :timer.now_diff(:os.timestamp, self.last_update) > (1000 * self.age_max) + end + end + + def start_link do + Agent.start_link(&Map.new/0) + end + + def lookup(self, mac) do + entry = Agent.get(self, &Map.get(&1, mac)) + entry && entry.port_no + end + + def learn(self, mac, port_no) do + entry = Agent.get(self, &Map.get(&1, mac)) + entry = if entry do + Entry.update(entry, port_no) + else + Entry.new(mac, port_no) + end + Agent.update(self, &Map.put(&1, mac, entry)) + end + + def age(self) do + mac_addrs = Agent.get(self, &find_aged_entries(&1)) + for mac <- mac_addrs do + Agent.update(self, &Map.delete(&1, mac)) + end + end + + # private function + + defp find_aged_entries(map) do + Enum.flat_map(map, fn({mac, entry}) -> + case Entry.aged_out?(entry) do + true -> [mac] + false -> [] + end + end) + end +end diff --git a/examples/learning_switch/lib/learning_switch/ofctl.ex b/examples/learning_switch/lib/learning_switch/ofctl.ex new file mode 100644 index 0000000..21b123f --- /dev/null +++ b/examples/learning_switch/lib/learning_switch/ofctl.ex @@ -0,0 +1,137 @@ +defmodule LearningSwitch.Ofctl do + use GenServer + use Tres.Controller + + import Logger + + alias LearningSwitch.FDB + + @ingress_filtering_table_id 0 + @forwarding_table_id 1 + + @aging_time 180 + + @mcast {"010000000000", "110000000000"} + @bcast "ffffffffffff" + @ipv6_mcast {"333300000000", "ffff00000000"} + + defmodule State do + defstruct [ + datapath_id: nil, + fdb_pid: nil + ] + end + + def start_link(datapath_id, args) do + GenServer.start_link(__MODULE__, [datapath_id, args]) + end + + def init([{datapath_id, _aux_id}, _args]) do + :ok = debug("Switch Ready: datapath_id: #{inspect(datapath_id)}") + {:ok, pid} = FDB.start_link + init_datapath(datapath_id) + state = %State{ + datapath_id: datapath_id, + fdb_pid: pid + } + {:ok, state} + end + + def handle_info(%PacketIn{} = packet_in, state) do + <<_dhost::6-bytes, shost::6-bytes, _rest::bytes>> = packet_in.data + eth_src = Openflow.Utils.to_hex_string(shost) + FDB.learn(state.fdb_pid, eth_src, packet_in.in_port) + add_forwarding_flow_and_packet_out(packet_in, state) + :ok = debug("PacketIn: eth_src: #{eth_src} datapath_id: #{inspect(state.datapath_id)}") + {:noreply, state} + end + def handle_info({:switch_disconnected, reason}, state) do + :ok = warn("[#{__MODULE__}] Switch Disconnected: datapath_id: #{state.datapath_id} by #{reason}") + {:stop, :normal, state} + end + def handle_info(info, state) do + :ok = warn("Unhandled message #{inspect(info)}: #{inspect(state.datapath_id)}") + {:noreply, state} + end + + # private functions + + defp init_datapath(datapath_id) do + SetConfig.new(miss_send_len: :no_buffer) + |> send_message(datapath_id) + init_flow_tables(datapath_id) + end + + defp init_flow_tables(datapath_id) do + for flow_options <- [ + add_default_broadcast_flow_entry(), + add_default_flooding_flow_entry(), + add_multicast_mac_drop_flow_entry(), + add_ipv6_multicast_mac_drop_flow_entry(), + add_default_forwarding_flow_entry()] do + send_flow_mod_add(datapath_id, flow_options) + end + end + + defp add_forwarding_flow_and_packet_out(packet_in, state) do + <> = packet_in.data + eth_dst = Openflow.Utils.to_hex_string(dhost) + port_no = FDB.lookup(state.fdb_pid, eth_dst) + add_forwarding_flow_entry(packet_in, port_no) + packet_out(packet_in, port_no || :flood) + end + + defp packet_out(%PacketIn{datapath_id: datapath_id, data: data}, port_no) do + send_packet_out( + datapath_id, + data: data, + actions: [Output.new(port_no)] + ) + end + + defp add_forwarding_flow_entry(_packet_in, nil), do: :noop + defp add_forwarding_flow_entry(%PacketIn{datapath_id: datapath_id, data: data} = packet_in, port_no) do + <> = data + send_flow_mod_add( + datapath_id, + idle_timeout: @aging_time, + priority: 2, + match: Match.new( + in_port: packet_in.in_port, + eth_dst: Openflow.Utils.to_hex_string(dhost), + eth_src: Openflow.Utils.to_hex_string(shost)), + instructions: [ApplyActions.new(Output.new(port_no))] + ) + end + + defp add_default_broadcast_flow_entry do + [table_id: @forwarding_table_id, + priority: 3, + match: Match.new(eth_dst: @bcast), + instructions: [ApplyActions.new(Output.new(:flood))]] + end + + defp add_default_flooding_flow_entry do + [table_id: @forwarding_table_id, + priority: 1, + instructions: [ApplyActions.new(Output.new(:controller))]] + end + + defp add_multicast_mac_drop_flow_entry do + [table_id: @ingress_filtering_table_id, + priority: 2, + match: Match.new(eth_dst: @mcast)] + end + + defp add_ipv6_multicast_mac_drop_flow_entry do + [table_id: @ingress_filtering_table_id, + priority: 2, + match: Match.new(eth_dst: @ipv6_mcast)] + end + + defp add_default_forwarding_flow_entry do + [table_id: @ingress_filtering_table_id, + priority: 1, + instructions: [GotoTable.new(@forwarding_table_id)]] + end +end diff --git a/examples/learning_switch/mix.exs b/examples/learning_switch/mix.exs new file mode 100644 index 0000000..97e36d2 --- /dev/null +++ b/examples/learning_switch/mix.exs @@ -0,0 +1,23 @@ +defmodule LearningSwitch.Mixfile do + use Mix.Project + + def project do + [ + app: :learning_switch, + version: "0.1.0", + elixir: "~> 1.5", + start_permanent: Mix.env == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [extra_applications: [:logger, :tres], + mod: {LearningSwitch.Application, []}] + end + + defp deps do + [{:tres, path: "../../../tres"}] + end +end diff --git a/examples/learning_switch/mix.lock b/examples/learning_switch/mix.lock new file mode 100644 index 0000000..cbc80d1 --- /dev/null +++ b/examples/learning_switch/mix.lock @@ -0,0 +1,7 @@ +%{ + "binpp": {:git, "https://github.com/jtendo/binpp.git", "64bd68d215d1a6cd35871e7c134d7fe2e46214ea", [branch: "master"]}, + "eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]}, + "jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]}, + "ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [], [], "hexpm"}, + "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}, +} diff --git a/examples/learning_switch/test/learning_switch_test.exs b/examples/learning_switch/test/learning_switch_test.exs new file mode 100644 index 0000000..095aaad --- /dev/null +++ b/examples/learning_switch/test/learning_switch_test.exs @@ -0,0 +1,8 @@ +defmodule LearningSwitchTest do + use ExUnit.Case + doctest LearningSwitch + + test "greets the world" do + assert LearningSwitch.hello() == :world + end +end diff --git a/examples/learning_switch/test/test_helper.exs b/examples/learning_switch/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/examples/learning_switch/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/examples/patch_panel/.formatter.exs b/examples/patch_panel/.formatter.exs new file mode 100644 index 0000000..525446d --- /dev/null +++ b/examples/patch_panel/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/examples/patch_panel/.gitignore b/examples/patch_panel/.gitignore new file mode 100644 index 0000000..b22822d --- /dev/null +++ b/examples/patch_panel/.gitignore @@ -0,0 +1,24 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +patch_panel-*.tar + diff --git a/examples/patch_panel/README.md b/examples/patch_panel/README.md new file mode 100644 index 0000000..ce2181c --- /dev/null +++ b/examples/patch_panel/README.md @@ -0,0 +1,16 @@ +# PatchPanel + +openflow controller that emulates a software patch panel + +## prerequisites + + - Erlang 20 or higher + - Elixir 1.6.1 or higher + - OpenFlow switch supports version 1.3 + +```iex +# To add a patch link +iex > :ok = PatchPanel.Openflow.Controller.create_patch("de780562fb45, 1, 2) +# To delete a patch link +iex > :ok = PatchPanel.Openflow.Controller.delete_patch("de780562fb45, 1, 2) +``` diff --git a/examples/patch_panel/config/config.exs b/examples/patch_panel/config/config.exs new file mode 100644 index 0000000..ce4f069 --- /dev/null +++ b/examples/patch_panel/config/config.exs @@ -0,0 +1,7 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Mix.Config module. +use Mix.Config + +config :tres, + callback_module: PatchPanel.Openflow.Controller, + callback_args: [] diff --git a/examples/patch_panel/lib/patch_panel.ex b/examples/patch_panel/lib/patch_panel.ex new file mode 100644 index 0000000..f6e0dbe --- /dev/null +++ b/examples/patch_panel/lib/patch_panel.ex @@ -0,0 +1,18 @@ +defmodule PatchPanel do + @moduledoc """ + Documentation for PatchPanel. + """ + + @doc """ + Hello world. + + ## Examples + + iex> PatchPanel.hello + :world + + """ + def hello do + :world + end +end diff --git a/examples/patch_panel/lib/patch_panel/application.ex b/examples/patch_panel/lib/patch_panel/application.ex new file mode 100644 index 0000000..b156391 --- /dev/null +++ b/examples/patch_panel/lib/patch_panel/application.ex @@ -0,0 +1,20 @@ +defmodule PatchPanel.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + alias PatchPanel.Openflow + + def start(_type, _args) do + import Supervisor.Spec + + children = [ + worker(Registry, [[keys: :unique, name: Openflow.Registry]], id: Openflow.Registry), + ] + + opts = [strategy: :one_for_one, name: PatchPanel.Supervisor] + Supervisor.start_link(children, opts) + end +end diff --git a/examples/patch_panel/lib/patch_panel/openflow/controller.ex b/examples/patch_panel/lib/patch_panel/openflow/controller.ex new file mode 100644 index 0000000..bbecf04 --- /dev/null +++ b/examples/patch_panel/lib/patch_panel/openflow/controller.ex @@ -0,0 +1,81 @@ +defmodule PatchPanel.Openflow.Controller do + use GenServer + use Tres.Controller + + import Logger + + defmodule State do + defstruct [:datapath_id] + end + + def create_patch(datapath_id, port_a, port_b) do + case PatchPanel.Openflow.Registry.lookup_pid(datapath_id) do + nil -> + {:error, :not_found} + pid when is_pid(pid) -> + GenServer.call(pid, {:create, port_a, port_b}) + end + end + + def delete_patch(datapath_id, port_a, port_b) do + case PatchPanel.Openflow.Registry.lookup_pid(datapath_id) do + nil -> + {:error, :not_found} + pid when is_pid(pid) -> + GenServer.call(pid, {:delete, port_a, port_b}) + end + end + + def start_link({datapath_id, _aux_id}, _start_args) do + GenServer.start_link(__MODULE__, [datapath_id]) + end + + def init([datapath_id]) do + :ok = info("Switch Connected: datapath_id = #{datapath_id}") + {:ok, _} = PatchPanel.Openflow.Registry.register(datapath_id) + {:ok, %State{datapath_id: datapath_id}} + end + + def handle_call({:create, port_a, port_b}, _from, %State{datapath_id: datapath_id} = state) do + :ok = add_flow_entries(datapath_id, port_a, port_b) + {:reply, :ok, state} + end + def handle_call({:delete, port_a, port_b}, _from, %State{datapath_id: datapath_id} = state) do + :ok = del_flow_entries(datapath_id, port_a, port_b) + {:reply, :ok, state} + end + + def handle_info({:switch_disconnected, reason}, %State{datapath_id: datapath_id} = state) do + :ok = warn("#{datapath_id} disconnected: reason = #{inspect(reason)}") + :ok = PatchPanel.Openflow.Registry.unregister(datapath_id) + {:stop, :normal, state} + end + def handle_info(_info, state) do + {:noreply, state} + end + + def terminate(reason, state) do + {reason, state} + end + + # private functions + + defp add_flow_entries(datapath_id, port_a, port_b) do + :ok = send_flow_mod_add( + datapath_id, + match: Match.new(in_port: port_a), + instructions: [ApplyActions.new(Output.new(port_b))] + ) + + :ok = send_flow_mod_add( + datapath_id, + match: Match.new(in_port: port_b), + instructions: [ApplyActions.new(Output.new(port_a))] + ) + end + + defp del_flow_entries(datapath_id, port_a, port_b) do + :ok = send_flow_mod_delete(datapath_id, match: Match.new(in_port: port_a)) + :ok = send_flow_mod_delete(datapath_id, match: Match.new(in_port: port_b)) + end +end diff --git a/examples/patch_panel/lib/patch_panel/openflow/registry.ex b/examples/patch_panel/lib/patch_panel/openflow/registry.ex new file mode 100644 index 0000000..a24ba0b --- /dev/null +++ b/examples/patch_panel/lib/patch_panel/openflow/registry.ex @@ -0,0 +1,16 @@ +defmodule PatchPanel.Openflow.Registry do + def register(datapath_id) do + {:ok, _} = Registry.register(__MODULE__, datapath_id, []) + end + + def unregister(datapath_id) do + :ok = Registry.unregister(__MODULE__, datapath_id) + end + + def lookup_pid(datapath_id) do + case Registry.lookup(__MODULE__, datapath_id) do + [{pid, _}] -> pid + [] -> nil + end + end +end diff --git a/examples/patch_panel/mix.exs b/examples/patch_panel/mix.exs new file mode 100644 index 0000000..91b4af6 --- /dev/null +++ b/examples/patch_panel/mix.exs @@ -0,0 +1,26 @@ +defmodule PatchPanel.MixProject do + use Mix.Project + + def project do + [ + app: :patch_panel, + version: "0.1.0", + elixir: "~> 1.6", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger], + mod: {PatchPanel.Application, []} + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [{:tres, path: "../../../tres"}] + end +end diff --git a/examples/patch_panel/mix.lock b/examples/patch_panel/mix.lock new file mode 100644 index 0000000..b51b792 --- /dev/null +++ b/examples/patch_panel/mix.lock @@ -0,0 +1,6 @@ +%{ + "eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]}, + "jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]}, + "ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [:rebar3], [], "hexpm"}, + "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}, +} diff --git a/examples/patch_panel/test/patch_panel_test.exs b/examples/patch_panel/test/patch_panel_test.exs new file mode 100644 index 0000000..d6f8a89 --- /dev/null +++ b/examples/patch_panel/test/patch_panel_test.exs @@ -0,0 +1,8 @@ +defmodule PatchPanelTest do + use ExUnit.Case + doctest PatchPanel + + test "greets the world" do + assert PatchPanel.hello() == :world + end +end diff --git a/examples/patch_panel/test/test_helper.exs b/examples/patch_panel/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/examples/patch_panel/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start() diff --git a/images/tres_inside.png b/images/tres_inside.png new file mode 100644 index 0000000..dc58075 Binary files /dev/null and b/images/tres_inside.png differ diff --git a/lib/openflow.ex b/lib/openflow.ex new file mode 100644 index 0000000..ac30ab8 --- /dev/null +++ b/lib/openflow.ex @@ -0,0 +1,72 @@ +defmodule Openflow do + @moduledoc "OpenFlow Protocol format codec" + + @ofp_header_size 8 + + @spec read(binary()) :: {:ok, map()} | {:error, :binary_too_small} + def read(binary) + when byte_size(binary) < @ofp_header_size do + {:error, :binary_too_small} + end + + def read(<<_v::8, _t::8, len::16, _x::32, _r::bytes>> = binary) + when byte_size(binary) < len do + {:error, :binary_too_small} + end + + def read(<>) do + body_len = len - @ofp_header_size + <> = binary2 + + result = + type + |> Openflow.Enums.to_atom(:openflow_codec) + |> do_read(body_bin) + + case result do + {:ok, struct} -> {:ok, %{struct | version: ver, xid: xid}, rest} + {:error, reason} -> {:error, reason} + end + end + + def to_binary(messages) when is_list(messages) do + binaries = for message <- messages, do: to_binary(message) + Enum.join(binaries, "") + end + + def to_binary(%{__struct__: encoder, version: version, xid: xid} = msg) do + case encoder.to_binary(msg) do + body_bin when is_binary(body_bin) -> + length = @ofp_header_size + byte_size(body_bin) + <> + + {:error, reason} -> + {:error, reason} + end + end + + def append_body(nil, message), do: message + + def append_body(message, continue) do + mod = message.__struct__ + + if function_exported?(mod, :append_body, 2) do + mod.append_body(message, continue) + else + message + end + end + + # private functions + + defp do_read({:error, reason}, _) do + {:error, reason} + end + + defp do_read(decoder, body_bin) do + case decoder.read(body_bin) do + {:error, reason} -> {:error, reason} + result when is_map(result) -> {:ok, result} + end + end +end diff --git a/lib/openflow/action.ex b/lib/openflow/action.ex new file mode 100644 index 0000000..6ffbe57 --- /dev/null +++ b/lib/openflow/action.ex @@ -0,0 +1,31 @@ +defmodule Openflow.Action do + def read(action_bin) do + do_read([], action_bin) + end + + def to_binary(actions) when is_list(actions) do + to_binary(<<>>, actions) + end + + def to_binary(action) do + to_binary([action]) + end + + # private functions + + defp do_read(acc, <<>>), do: Enum.reverse(acc) + defp do_read(acc, <<0::32, _::bytes>>), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + codec = Openflow.Enums.to_atom(type, :action_type) + do_read([codec.read(action_bin) | acc], rest) + end + + defp to_binary(acc, []), do: acc + + defp to_binary(acc, [action | rest]) do + codec = action.__struct__ + to_binary(<>, rest) + end +end diff --git a/lib/openflow/actions/copy_ttl_in.ex b/lib/openflow/actions/copy_ttl_in.ex new file mode 100644 index 0000000..83347b4 --- /dev/null +++ b/lib/openflow/actions/copy_ttl_in.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.CopyTtlIn do + defstruct([]) + + alias __MODULE__ + + def ofpat, do: 12 + + def new do + %CopyTtlIn{} + end + + def to_binary(%CopyTtlIn{}) do + <<12::16, 8::16, 0::size(4)-unit(8)>> + end + + def read(<<12::16, 8::16, _::size(4)-unit(8)>>) do + %CopyTtlIn{} + end +end diff --git a/lib/openflow/actions/copy_ttl_out.ex b/lib/openflow/actions/copy_ttl_out.ex new file mode 100644 index 0000000..759c0ad --- /dev/null +++ b/lib/openflow/actions/copy_ttl_out.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.CopyTtlOut do + defstruct([]) + + alias __MODULE__ + + def ofpat, do: 11 + + def new do + %CopyTtlOut{} + end + + def to_binary(%CopyTtlOut{}) do + <<11::16, 8::16, 0::size(4)-unit(8)>> + end + + def read(<<11::16, 8::16, _::size(4)-unit(8)>>) do + %CopyTtlOut{} + end +end diff --git a/lib/openflow/actions/dec_mpls_ttl.ex b/lib/openflow/actions/dec_mpls_ttl.ex new file mode 100644 index 0000000..2931954 --- /dev/null +++ b/lib/openflow/actions/dec_mpls_ttl.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.DecMplsTtl do + defstruct([]) + + alias __MODULE__ + + def ofpat, do: 16 + + def new do + %DecMplsTtl{} + end + + def to_binary(%DecMplsTtl{}) do + <<16::16, 8::16, 0::size(4)-unit(8)>> + end + + def read(<<16::16, 8::16, _::size(4)-unit(8)>>) do + %DecMplsTtl{} + end +end diff --git a/lib/openflow/actions/dec_nw_ttl.ex b/lib/openflow/actions/dec_nw_ttl.ex new file mode 100644 index 0000000..6d23b5d --- /dev/null +++ b/lib/openflow/actions/dec_nw_ttl.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.DecNwTtl do + defstruct([]) + + alias __MODULE__ + + def ofpat, do: 24 + + def new do + %DecNwTtl{} + end + + def to_binary(%DecNwTtl{}) do + <<24::16, 8::16, 0::size(4)-unit(8)>> + end + + def read(<<24::16, 8::16, _::size(4)-unit(8)>>) do + %DecNwTtl{} + end +end diff --git a/lib/openflow/actions/experimenter.ex b/lib/openflow/actions/experimenter.ex new file mode 100644 index 0000000..b2b7e99 --- /dev/null +++ b/lib/openflow/actions/experimenter.ex @@ -0,0 +1,34 @@ +defmodule Openflow.Action.Experimenter do + defstruct(exp_id: 0, data: "") + + alias __MODULE__ + + @experimter_size 8 + + def ofpat, do: 0xFFFF + + def new(exp_id, data \\ "") do + %Experimenter{exp_id: exp_id, data: data} + end + + def to_binary(%Experimenter{exp_id: exp_id, data: data}) do + length = @experimter_size + byte_size(data) + <<0xFFFF::16, length::16, exp_id::32, data::bytes>> + end + + def read(<<0xFFFF::16, _length::16, exp_id::32, exp_type::16, data::bytes>>) do + case Openflow.Utils.get_enum(exp_id, :action_vendor) do + vendor_id when is_integer(vendor_id) -> + %Experimenter{exp_id: exp_id, data: <>} + + vendor when is_atom(vendor) -> + case Openflow.Utils.get_enum(exp_type, vendor) do + codec when is_atom(codec) -> + codec.read(<>) + + exp_type when is_integer(exp_type) -> + %Experimenter{exp_id: exp_id, data: <>} + end + end + end +end diff --git a/lib/openflow/actions/group.ex b/lib/openflow/actions/group.ex new file mode 100644 index 0000000..ff2d756 --- /dev/null +++ b/lib/openflow/actions/group.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.Group do + defstruct(id: 0) + + alias __MODULE__ + + def ofpat, do: 22 + + def new(id) do + %Group{id: id} + end + + def to_binary(%Group{id: id}) do + <<22::16, 8::16, id::32>> + end + + def read(<<22::16, 8::16, id::32>>) do + %Group{id: id} + end +end diff --git a/lib/openflow/actions/nx_bundle.ex b/lib/openflow/actions/nx_bundle.ex new file mode 100644 index 0000000..da16230 --- /dev/null +++ b/lib/openflow/actions/nx_bundle.ex @@ -0,0 +1,91 @@ +defmodule Openflow.Action.NxBundle do + defstruct( + algorithm: :active_backup, + hash_field: :eth_src, + basis: 0, + slave_type: :nx_in_port, + n_slaves: 0, + slaves: [] + ) + + @experimenter 0x00002320 + @nxast 12 + + alias __MODULE__ + + def new(options) do + slaves = options[:slaves] || [] + + %NxBundle{ + algorithm: options[:algorithm] || :active_backup, + hash_field: options[:hash_field] || :eth_src, + basis: options[:basis] || 0, + n_slaves: length(slaves), + slaves: slaves + } + end + + def to_binary(%NxBundle{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves + }) do + hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) + alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm) + slave_type_bin = Openflow.Match.codec_header(slave_type) + slaves_bin = codec_slaves(slaves) + + body = + <> + + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + + slave_len = n_slaves * 2 + <> = rest + alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm) + hash_field = Openflow.Enums.to_atom(hash_field_int, :nx_hash_fields) + slave_type = Openflow.Match.codec_header(slave_type_bin) + slaves = codec_slaves(slaves_bin) + n_slaves = length(slaves) + + %NxBundle{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves + } + end + + # private functions + + defp codec_slaves(slaves) when is_list(slaves) do + slaves1 = + for slave <- slaves do + slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) + <> + end + + Enum.join(slaves1, "") + end + + defp codec_slaves(slaves) when is_binary(slaves) do + for <> do + Openflow.Utils.get_enum(slave_int, :openflow10_port_no) + end + end +end diff --git a/lib/openflow/actions/nx_bundle_load.ex b/lib/openflow/actions/nx_bundle_load.ex new file mode 100644 index 0000000..f213fe0 --- /dev/null +++ b/lib/openflow/actions/nx_bundle_load.ex @@ -0,0 +1,110 @@ +defmodule Openflow.Action.NxBundleLoad do + import Bitwise + + defstruct( + algorithm: :active_backup, + hash_field: :eth_src, + basis: 0, + slave_type: :nx_in_port, + n_slaves: 0, + slaves: [], + offset: 0, + n_bits: 0, + dst_field: nil + ) + + @experimenter 0x00002320 + @nxast 13 + + alias __MODULE__ + + def new(options) do + dst_field = options[:dst_field] + default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) + slaves = options[:slaves] || [] + + %NxBundleLoad{ + algorithm: options[:algorithm] || :active_backup, + hash_field: options[:hash_field] || :eth_src, + basis: options[:basis] || 0, + n_slaves: length(slaves), + slaves: slaves, + offset: options[:offset] || 0, + n_bits: options[:n_bits] || default_n_bits, + dst_field: options[:dst_field] + } + end + + def to_binary(%NxBundleLoad{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves, + offset: ofs, + n_bits: n_bits, + dst_field: dst_field + }) do + hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) + alg_int = Openflow.Enums.to_int(alg, :nx_bd_algorithm) + slave_type_bin = Openflow.Match.codec_header(slave_type) + slaves_bin = codec_slaves(slaves) + ofs_nbits = ofs <<< 6 ||| n_bits - 1 + dst_field_bin = Openflow.Match.codec_header(dst_field) + + body = + <> + + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + + slave_len = n_slaves * 2 + <> = rest + alg = Openflow.Enums.to_atom(alg_int, :nx_bd_algorithm) + hash_field = Openflow.Enums.to_atom(hash_field_int, :nx_hash_fields) + slave_type = Openflow.Match.codec_header(slave_type_bin) + slaves = codec_slaves(slaves_bin) + n_slaves = length(slaves) + dst_field = Openflow.Match.codec_header(dst_field_bin) + + %NxBundleLoad{ + algorithm: alg, + hash_field: hash_field, + basis: basis, + slave_type: slave_type, + n_slaves: n_slaves, + slaves: slaves, + offset: ofs, + n_bits: n_bits + 1, + dst_field: dst_field + } + end + + # private functions + + defp codec_slaves(slaves) when is_list(slaves) do + slaves1 = + for slave <- slaves do + slave_int = Openflow.Utils.get_enum(slave, :openflow10_port_no) + <> + end + + Enum.join(slaves1, "") + end + + defp codec_slaves(slaves) when is_binary(slaves) do + for <> do + Openflow.Utils.get_enum(slave_int, :openflow10_port_no) + end + end +end diff --git a/lib/openflow/actions/nx_clone.ex b/lib/openflow/actions/nx_clone.ex new file mode 100644 index 0000000..971721b --- /dev/null +++ b/lib/openflow/actions/nx_clone.ex @@ -0,0 +1,26 @@ +defmodule Openflow.Action.NxClone do + defstruct(actions: []) + + @experimenter 0x00002320 + @nxast 42 + + alias __MODULE__ + + def new(actions \\ []) do + %NxClone{actions: actions} + end + + def to_binary(%NxClone{actions: actions}) do + actions_bin = Openflow.Action.to_binary(actions) + exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), actions_bin::bytes>>) do + actions = Openflow.Action.read(actions_bin) + %NxClone{actions: actions} + end +end diff --git a/lib/openflow/actions/nx_conjunction.ex b/lib/openflow/actions/nx_conjunction.ex new file mode 100644 index 0000000..be33f2a --- /dev/null +++ b/lib/openflow/actions/nx_conjunction.ex @@ -0,0 +1,29 @@ +defmodule Openflow.Action.NxConjunction do + defstruct( + clause: 0, + n_clauses: 0, + id: 0 + ) + + @experimenter 0x00002320 + @nxast 34 + + alias __MODULE__ + + def new(options) do + %NxConjunction{ + clause: options[:clause] || 0, + n_clauses: options[:n_clauses] || 0, + id: options[:id] || 0 + } + end + + def to_binary(%NxConjunction{clause: clause, n_clauses: n_clauses, id: id}) do + exp_body = <<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>> + <<0xFFFF::16, 16::16, exp_body::bytes>> + end + + def read(<<@experimenter::32, @nxast::16, clause::8, n_clauses::8, id::32>>) do + %NxConjunction{clause: clause, n_clauses: n_clauses, id: id} + end +end diff --git a/lib/openflow/actions/nx_conntrack.ex b/lib/openflow/actions/nx_conntrack.ex new file mode 100644 index 0000000..7844221 --- /dev/null +++ b/lib/openflow/actions/nx_conntrack.ex @@ -0,0 +1,90 @@ +defmodule Openflow.Action.NxConntrack do + import Bitwise + + defstruct( + flags: [], + zone_src: nil, + zone_imm: 0, + zone_offset: nil, + zone_n_bits: nil, + recirc_table: 255, + alg: 0, + exec: [] + ) + + @experimenter 0x00002320 + @nxast 35 + + alias __MODULE__ + + def new(options \\ []) do + %NxConntrack{ + flags: options[:flags] || [], + zone_src: options[:zone_src], + zone_imm: options[:zone_imm] || 0, + zone_offset: options[:zone_offset], + zone_n_bits: options[:zone_n_bits], + recirc_table: options[:recirc_table] || 255, + alg: options[:alg] || 0, + exec: options[:exec] || [] + } + end + + def to_binary(%NxConntrack{ + flags: flags, + zone_src: zone_src, + zone_offset: zone_ofs, + zone_n_bits: zone_n_bits, + zone_imm: zone_imm, + recirc_table: recirc_table, + alg: alg, + exec: exec + }) do + flags_int = Openflow.Enums.flags_to_int(flags, :nx_conntrack_flags) + + {src_bin, ofs_nbits} = + if not is_nil(zone_src) do + zone_src_bin = Openflow.Match.codec_header(zone_src) + {zone_src_bin, zone_ofs <<< 6 ||| zone_n_bits - 1} + else + {<<0::32>>, zone_imm} + end + + exec_bin = Openflow.Action.to_binary(exec) + + exp_body = + <<@experimenter::32, @nxast::16, flags_int::16, src_bin::bytes, ofs_nbits::16, + recirc_table::8, 0::size(3)-unit(8), alg::16, exec_bin::bytes>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, flags_int::16, src_bin::4-bytes, ofs_nbits::16-bits, + recirc_table::8, _::size(3)-unit(8), alg::16, exec_bin::bytes>> + ) do + flags = Openflow.Enums.int_to_flags(flags_int, :nx_conntrack_flags) + exec = Openflow.Action.read(exec_bin) + + ct = %NxConntrack{ + flags: flags, + recirc_table: recirc_table, + alg: alg, + exec: exec + } + + case src_bin do + <<0::32>> -> + <> = ofs_nbits + %{ct | zone_imm: zone_imm} + + binary when is_binary(binary) -> + zone_src = Openflow.Match.codec_header(binary) + <> = ofs_nbits + %{ct | zone_src: zone_src, zone_offset: ofs, zone_n_bits: n_bits + 1} + end + end +end diff --git a/lib/openflow/actions/nx_controller.ex b/lib/openflow/actions/nx_controller.ex new file mode 100644 index 0000000..2f2d1fc --- /dev/null +++ b/lib/openflow/actions/nx_controller.ex @@ -0,0 +1,39 @@ +defmodule Openflow.Action.NxController do + defstruct( + max_len: :no_buffer, + id: 0, + reason: :action + ) + + @experimenter 0x00002320 + @nxast 20 + + alias __MODULE__ + + def new(options) do + %NxController{ + max_len: options[:max_len] || :no_buffer, + id: options[:id] || 0, + reason: options[:reason] || :action + } + end + + def to_binary(%NxController{max_len: max_len, id: controller_id, reason: reason}) do + max_len_int = Openflow.Utils.get_enum(max_len, :controller_max_len) + reason_int = Openflow.Enums.to_int(reason, :packet_in_reason) + + exp_body = + <<@experimenter::32, @nxast::16, max_len_int::16, controller_id::16, reason_int::8, 0::8>> + + <<0xFFFF::16, 16::16, exp_body::bytes>> + end + + def read( + <<@experimenter::32, @nxast::16, max_len_int::16, controller_id::16, reason_int::8, + _::bytes>> + ) do + max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len) + reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason) + %NxController{max_len: max_len, id: controller_id, reason: reason} + end +end diff --git a/lib/openflow/actions/nx_controller2.ex b/lib/openflow/actions/nx_controller2.ex new file mode 100644 index 0000000..78fb9d5 --- /dev/null +++ b/lib/openflow/actions/nx_controller2.ex @@ -0,0 +1,140 @@ +defmodule Openflow.Action.NxController2 do + defstruct( + max_len: :no_buffer, + id: 0, + reason: :action, + userdata: "", + pause: false + ) + + @experimenter 0x00002320 + @nxast 37 + + @prop_header_size 4 + + @prop_max_len 0 + @prop_ctl_id 1 + @prop_reason 2 + @prop_userdata 3 + @prop_pause 4 + + alias __MODULE__ + + def new(options) do + %NxController2{ + max_len: options[:max_len] || :no_buffer, + id: options[:id] || 0, + reason: options[:reason] || :action, + userdata: options[:userdata], + pause: options[:pause] || false + } + end + + def to_binary(%NxController2{} = ctl) do + ext_header = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>> + prop_keys = get_prop_key(ctl) + props_bin = encode_prop("", prop_keys, ctl) + exp_body = <> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes>> + end + + def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), body::bytes>>) do + %NxController2{} + |> decode_prop(body) + end + + # private functions + + defp get_prop_key(ctl) do + ctl + |> Map.from_struct() + |> Enum.map(fn {k, v} -> if(not is_nil(v), do: k, else: nil) end) + |> Enum.filter(fn v -> not is_nil(v) end) + end + + defp encode_prop(acc, [], _ctl), do: acc + + defp encode_prop(acc, [prop | rest], ctl) do + value = Map.get(ctl, prop) + + prop_bin = + cond do + prop == :max_len and (value != :no_buffer or value < 0xFFFF) -> + padding_length = 2 + prop_length = @prop_header_size + 2 + padding_length + max_len_int = Openflow.Utils.get_enum(value, :controller_max_len) + <<@prop_max_len::16, prop_length::16, max_len_int::16, 0::size(padding_length)-unit(8)>> + + prop == :id -> + padding_length = 2 + prop_length = @prop_header_size + 2 + padding_length + <<@prop_ctl_id::16, prop_length::16, value::16, 0::size(padding_length)-unit(8)>> + + prop == :reason and value != :action -> + padding_length = 3 + prop_length = @prop_header_size + 1 + padding_length + reason_int = Openflow.Utils.get_enum(value, :packet_in_reason) + <<@prop_reason::16, prop_length::16, reason_int::8, 0::size(padding_length)-unit(8)>> + + prop == :userdata and byte_size(value) > 0 -> + prop_length = @prop_header_size + byte_size(value) + padding_length = Openflow.Utils.padding(prop_length, 8) + <<@prop_userdata::16, prop_length::16, value::bytes, 0::size(padding_length)-unit(8)>> + + prop == :pause and value == true -> + padding_length = 4 + prop_length = @prop_header_size + padding_length + <<@prop_pause::16, prop_length::16, 0::size(padding_length)-unit(8)>> + + true -> + "" + end + + encode_prop(<>, rest, ctl) + end + + defp decode_prop(ctl, ""), do: ctl + + defp decode_prop(ctl, <> = bin) do + prop_type = Openflow.Enums.to_atom(prop_type_int, :nx_action_controller2_prop_type) + + case prop_type do + :max_len -> + <<@prop_max_len::16, _prop_length::16, max_len_int::16, _::size(2)-unit(8), rest::bytes>> = + bin + + max_len = Openflow.Utils.get_enum(max_len_int, :controller_max_len) + decode_prop(struct(ctl, %{max_len: max_len}), rest) + + :controller_id -> + <<@prop_ctl_id::16, _prop_length::16, controller_id::16, _::size(2)-unit(8), rest::bytes>> = + bin + + decode_prop(struct(ctl, %{controller_id: controller_id}), rest) + + :reason -> + <<@prop_reason::16, _prop_length::16, reason_int::8, _::size(3)-unit(8), rest::bytes>> = + bin + + reason = Openflow.Utils.get_enum(reason_int, :packet_in_reason) + decode_prop(struct(ctl, %{reason: reason}), rest) + + :userdata -> + <<@prop_userdata::16, prop_length::16, remains::bytes>> = bin + userdata_len = prop_length - 4 + padding_length = Openflow.Utils.padding(prop_length, 8) + + <> = + remains + + decode_prop(struct(ctl, %{userdata: userdata}), rest) + + :pause -> + <<@prop_pause::16, _::16, 0::size(4)-unit(8), rest::bytes>> = bin + decode_prop(struct(ctl, %{pause: true}), rest) + end + end +end diff --git a/lib/openflow/actions/nx_ct_clear.ex b/lib/openflow/actions/nx_ct_clear.ex new file mode 100644 index 0000000..f58d3b3 --- /dev/null +++ b/lib/openflow/actions/nx_ct_clear.ex @@ -0,0 +1,21 @@ +defmodule Openflow.Action.NxCtClear do + defstruct([]) + + @experimenter 0x00002320 + @nxast 43 + + alias __MODULE__ + + def new do + %NxCtClear{} + end + + def to_binary(%NxCtClear{}) do + exp_body = <<@experimenter::32, @nxast::16, 0::16, 0::size(4)-unit(8)>> + <<0xFFFF::16, 16::16, exp_body::bytes>> + end + + def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do + %NxCtClear{} + end +end diff --git a/lib/openflow/actions/nx_dec_mpls_ttl.ex b/lib/openflow/actions/nx_dec_mpls_ttl.ex new file mode 100644 index 0000000..6b5744d --- /dev/null +++ b/lib/openflow/actions/nx_dec_mpls_ttl.ex @@ -0,0 +1,21 @@ +defmodule Openflow.Action.NxDecMplsTtl do + defstruct([]) + + @experimenter 0x00002320 + @nxast 26 + + alias __MODULE__ + + def new do + %NxDecMplsTtl{} + end + + def to_binary(%NxDecMplsTtl{}) do + exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>> + <<0xFFFF::16, 16::16, exp_body::bytes>> + end + + def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8)>>) do + %NxDecMplsTtl{} + end +end diff --git a/lib/openflow/actions/nx_dec_ttl.ex b/lib/openflow/actions/nx_dec_ttl.ex new file mode 100644 index 0000000..de6b088 --- /dev/null +++ b/lib/openflow/actions/nx_dec_ttl.ex @@ -0,0 +1,21 @@ +defmodule Openflow.Action.NxDecTtl do + defstruct([]) + + @experimenter 0x00002320 + @nxast 18 + + alias __MODULE__ + + def new do + %NxDecTtl{} + end + + def to_binary(%NxDecTtl{}) do + exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>> + <<0xFFFF::16, 16::16, exp_body::bytes>> + end + + def read(<<@experimenter::32, @nxast::16, _::16, _::size(4)-unit(8)>>) do + %NxDecTtl{} + end +end diff --git a/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex b/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex new file mode 100644 index 0000000..729b705 --- /dev/null +++ b/lib/openflow/actions/nx_dec_ttl_cnt_ids.ex @@ -0,0 +1,34 @@ +defmodule Openflow.Action.NxDecTtlCntIds do + defstruct(ids: []) + + @experimenter 0x00002320 + @nxast 21 + + alias __MODULE__ + + def new(ids) do + %NxDecTtlCntIds{ids: ids} + end + + def to_binary(%NxDecTtlCntIds{ids: ids}) do + n_controllers = length(ids) + ids_bin = Enum.join(for(id <- ids, do: <>), "") + padding = Openflow.Utils.padding(n_controllers, 8) + + exp_body = + <<@experimenter::32, @nxast::16, n_controllers::16, 0::size(4)-unit(8), ids_bin::bytes, + 0::size(padding)-unit(8)>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, n_controllers::16, body::bitstring>>) do + n_controllers_len = n_controllers * 16 + <<0::size(4)-unit(8), ids_bin::size(n_controllers_len)-bits, _::bitstring>> = body + ids = for <>, do: id + %NxDecTtlCntIds{ids: ids} + end +end diff --git a/lib/openflow/actions/nx_exit.ex b/lib/openflow/actions/nx_exit.ex new file mode 100644 index 0000000..cc9786b --- /dev/null +++ b/lib/openflow/actions/nx_exit.ex @@ -0,0 +1,21 @@ +defmodule Openflow.Action.NxExit do + defstruct([]) + + @experimenter 0x00002320 + @nxast 17 + + alias __MODULE__ + + def new do + %NxExit{} + end + + def to_binary(%NxExit{}) do + exp_body = <<@experimenter::32, @nxast::16, 0::48>> + <<0xFFFF::16, 16::16, exp_body::bytes>> + end + + def read(<<@experimenter::32, @nxast::16, 0::48>>) do + %NxExit{} + end +end diff --git a/lib/openflow/actions/nx_fin_timeout.ex b/lib/openflow/actions/nx_fin_timeout.ex new file mode 100644 index 0000000..8f8e005 --- /dev/null +++ b/lib/openflow/actions/nx_fin_timeout.ex @@ -0,0 +1,27 @@ +defmodule Openflow.Action.NxFinTimeout do + defstruct( + idle_timeout: 0, + hard_timeout: 0 + ) + + @experimenter 0x00002320 + @nxast 19 + + alias __MODULE__ + + def new(options) do + %NxFinTimeout{ + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0 + } + end + + def to_binary(%NxFinTimeout{idle_timeout: fin_idle, hard_timeout: fin_hard}) do + exp_body = <<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16>> + <<0xFFFF::16, 16::16, exp_body::bytes, 0::size(2)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, fin_idle::16, fin_hard::16, _::size(2)-unit(8)>>) do + %NxFinTimeout{idle_timeout: fin_idle, hard_timeout: fin_hard} + end +end diff --git a/lib/openflow/actions/nx_flow_spec.ex b/lib/openflow/actions/nx_flow_spec.ex new file mode 100644 index 0000000..b865cc7 --- /dev/null +++ b/lib/openflow/actions/nx_flow_spec.ex @@ -0,0 +1,31 @@ +defmodule Openflow.Action.NxFlowSpec do + def read(flow_spec_bin) do + do_read([], flow_spec_bin) + end + + def to_binary(flow_specs) when is_list(flow_specs) do + to_binary(<<>>, flow_specs) + end + + def to_binary(flow_spec) do + to_binary([flow_spec]) + end + + # private functions + + defp do_read(acc, <<>>), do: Enum.reverse(acc) + defp do_read(acc, <<0::16, _::bitstring>>), do: Enum.reverse(acc) + + defp do_read(acc, <<_::2, _::1, type::2, _::bitstring>> = binary) do + codec = Openflow.Enums.to_atom(type, :nx_flow_spec_type) + {flow_spec, rest} = codec.read(binary) + do_read([flow_spec | acc], rest) + end + + defp to_binary(acc, []), do: acc + + defp to_binary(acc, [flow_spec | rest]) do + codec = flow_spec.__struct__ + to_binary(<>, rest) + end +end diff --git a/lib/openflow/actions/nx_flow_spec_load.ex b/lib/openflow/actions/nx_flow_spec_load.ex new file mode 100644 index 0000000..dcdbf86 --- /dev/null +++ b/lib/openflow/actions/nx_flow_spec_load.ex @@ -0,0 +1,93 @@ +defmodule Openflow.Action.NxFlowSpecLoad do + defstruct( + src: nil, + dst: nil, + n_bits: 0, + src_offset: 0, + dst_offset: 0 + ) + + @learn_src_field 0 + @learn_src_immediate 1 + @learn_dst 1 + + alias __MODULE__ + + def new(options) do + dst = options[:dst] + n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) + + %NxFlowSpecLoad{ + src: options[:src], + dst: dst, + n_bits: n_bits, + src_offset: options[:src_offset] || 0, + dst_offset: options[:dst_offset] || 0 + } + end + + def to_binary(%NxFlowSpecLoad{} = fsm) do + %NxFlowSpecLoad{ + dst: dst_field, + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs + } = fsm + + {src_code, src_bin} = codec_src(fsm) + dst_bin = Openflow.Match.codec_header(dst_field) + + case src_code do + @learn_src_immediate -> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, dst_bin::4-bytes, + dst_ofs::16>> + + @learn_src_field -> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, + dst_bin::4-bytes, dst_ofs::16>> + end + end + + def read( + <<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, + dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> + ) do + src = Openflow.Match.codec_header(src_bin) + dst = Openflow.Match.codec_header(dst_bin) + + flow_spec = %NxFlowSpecLoad{ + src: src, + dst: dst, + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs + } + + {flow_spec, rest} + end + + def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do + rounded_up_len = Openflow.Utils.pad_length(n_bits, 8) + rounded_up_nbits = n_bits + rounded_up_len + + <> = + binary + + dst = Openflow.Match.codec_header(dst_bin) + src = Openflow.Match.Field.codec(src_bin, dst) + flow_spec = %NxFlowSpecLoad{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs} + {flow_spec, rest} + end + + # private functions + + defp codec_src(%NxFlowSpecLoad{src: src_field}) when is_atom(src_field) do + src_bin = Openflow.Match.codec_header(src_field) + {@learn_src_field, src_bin} + end + + defp codec_src(%NxFlowSpecLoad{src: src, dst: dst_field}) do + src_bin = Openflow.Match.Field.codec(src, dst_field) + {@learn_src_immediate, src_bin} + end +end diff --git a/lib/openflow/actions/nx_flow_spec_match.ex b/lib/openflow/actions/nx_flow_spec_match.ex new file mode 100644 index 0000000..feae23d --- /dev/null +++ b/lib/openflow/actions/nx_flow_spec_match.ex @@ -0,0 +1,93 @@ +defmodule Openflow.Action.NxFlowSpecMatch do + defstruct( + src: nil, + dst: nil, + n_bits: 0, + src_offset: 0, + dst_offset: 0 + ) + + @learn_src_field 0 + @learn_src_immediate 1 + @learn_dst 0 + + alias __MODULE__ + + def new(options) do + dst = options[:dst] + n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(dst) + + %NxFlowSpecMatch{ + src: options[:src], + dst: dst, + n_bits: n_bits, + src_offset: options[:src_offset] || 0, + dst_offset: options[:dst_offset] || 0 + } + end + + def to_binary(%NxFlowSpecMatch{} = fsm) do + %NxFlowSpecMatch{ + dst: dst_field, + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs + } = fsm + + {src_code, src_bin} = codec_src(fsm) + dst_bin = Openflow.Match.codec_header(dst_field) + + case src_code do + @learn_src_immediate -> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, dst_bin::4-bytes, + dst_ofs::16>> + + @learn_src_field -> + <<0::2, src_code::1, @learn_dst::2, n_bits::11, src_bin::bytes, src_ofs::16, + dst_bin::4-bytes, dst_ofs::16>> + end + end + + def read( + <<_::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, + dst_bin::4-bytes, dst_ofs::16, rest::bitstring>> + ) do + src = Openflow.Match.codec_header(src_bin) + dst = Openflow.Match.codec_header(dst_bin) + + flow_spec = %NxFlowSpecMatch{ + src: src, + dst: dst, + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs + } + + {flow_spec, rest} + end + + def read(<<_::2, @learn_src_immediate::1, @learn_dst::2, n_bits::11, binary::bitstring>>) do + rounded_up_len = Openflow.Utils.pad_length(n_bits, 8) + rounded_up_nbits = n_bits + rounded_up_len + + <> = + binary + + dst = Openflow.Match.codec_header(dst_bin) + src = Openflow.Match.Field.codec(src_bin, dst) + flow_spec = %NxFlowSpecMatch{src: src, dst: dst, n_bits: n_bits, dst_offset: dst_ofs} + {flow_spec, rest} + end + + # private functions + + defp codec_src(%NxFlowSpecMatch{src: src_field}) when is_atom(src_field) do + src_bin = Openflow.Match.codec_header(src_field) + {@learn_src_field, src_bin} + end + + defp codec_src(%NxFlowSpecMatch{src: src, dst: dst_field}) do + src_bin = Openflow.Match.Field.codec(src, dst_field) + {@learn_src_immediate, src_bin} + end +end diff --git a/lib/openflow/actions/nx_flow_spec_output.ex b/lib/openflow/actions/nx_flow_spec_output.ex new file mode 100644 index 0000000..7f0500b --- /dev/null +++ b/lib/openflow/actions/nx_flow_spec_output.ex @@ -0,0 +1,32 @@ +defmodule Openflow.Action.NxFlowSpecOutput do + defstruct( + n_bits: 0, + src: nil, + src_offset: 0 + ) + + @learn_src_field 0 + @learn_dst 2 + + alias __MODULE__ + + def new(options) do + src = options[:src] + n_bits = options[:n_bits] || Openflow.Match.Field.n_bits_of(src) + %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: options[:src_offset] || 0} + end + + def to_binary(%NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs}) do + src_bin = Openflow.Match.codec_header(src) + <<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16>> + end + + def read( + <<0::2, @learn_src_field::1, @learn_dst::2, n_bits::11, src_bin::4-bytes, src_ofs::16, + rest::bitstring>> + ) do + src = Openflow.Match.codec_header(src_bin) + flow_spec = %NxFlowSpecOutput{n_bits: n_bits, src: src, src_offset: src_ofs} + {flow_spec, rest} + end +end diff --git a/lib/openflow/actions/nx_learn.ex b/lib/openflow/actions/nx_learn.ex new file mode 100644 index 0000000..04b6cf3 --- /dev/null +++ b/lib/openflow/actions/nx_learn.ex @@ -0,0 +1,76 @@ +defmodule Openflow.Action.NxLearn do + defstruct( + idle_timeout: 0, + hard_timeout: 0, + priority: 0, + cookie: 0, + flags: [], + table_id: 0, + fin_idle_timeout: 0, + fin_hard_timeout: 0, + flow_specs: [] + ) + + @experimenter 0x00002320 + @nxast 16 + + alias __MODULE__ + + def new(options) do + %NxLearn{ + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0, + priority: options[:priority] || 0, + cookie: options[:cookie] || 0, + flags: options[:flags] || [], + table_id: options[:table_id] || 0xFF, + fin_idle_timeout: options[:fin_idle_timeout] || 0, + fin_hard_timeout: options[:fin_hard_timeout] || 0, + flow_specs: options[:flow_specs] || [] + } + end + + def to_binary(%NxLearn{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + flow_specs: flow_specs + }) do + flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag) + flow_specs_bin = Openflow.Action.NxFlowSpec.to_binary(flow_specs) + + exp_body = + <<@experimenter::32, @nxast::16, idle::16, hard::16, prio::16, cookie::64, flags_int::16, + table_id::8, 0::size(1)-unit(8), fin_idle::16, fin_hard::16, flow_specs_bin::bitstring>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bitstring>>) do + <> = body + + flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag) + flow_specs = Openflow.Action.NxFlowSpec.read(flow_specs_bin) + + %NxLearn{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + flow_specs: flow_specs + } + end +end diff --git a/lib/openflow/actions/nx_learn2.ex b/lib/openflow/actions/nx_learn2.ex new file mode 100644 index 0000000..ea3a49d --- /dev/null +++ b/lib/openflow/actions/nx_learn2.ex @@ -0,0 +1,106 @@ +defmodule Openflow.Action.NxLearn2 do + defstruct( + idle_timeout: 0, + hard_timeout: 0, + priority: 0, + cookie: 0, + flags: [], + table_id: 0, + fin_idle_timeout: 0, + fin_hard_timeout: 0, + limit: 0, + result_dst_offset: 0, + result_dst: nil, + flow_specs: [] + ) + + @experimenter 0x00002320 + @nxast 45 + + alias __MODULE__ + + def new(options) do + %NxLearn2{ + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0, + priority: options[:priority] || 0, + cookie: options[:cookie] || 0, + flags: options[:flags] || [], + table_id: options[:table_id] || 0xFF, + fin_idle_timeout: options[:fin_idle_timeout] || 0, + fin_hard_timeout: options[:fin_hard_timeout] || 0, + limit: options[:limit] || 0, + result_dst_offset: options[:result_dst_offset] || 0, + result_dst: options[:result_dst], + flow_specs: options[:flow_specs] || [] + } + end + + def to_binary(%NxLearn2{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + limit: limit, + result_dst_offset: result_dst_ofs, + result_dst: result_dst, + flow_specs: flow_specs + }) do + flags_int = Openflow.Enums.flags_to_int(flags, :nx_learn_flag) + + result_dst_bin = + if :write_result in flags do + Openflow.Match.codec_header(result_dst) + else + "" + end + + flow_specs_bin = Openflow.Action.NxFlowSpec.to_binary(flow_specs) + + exp_body = + <<@experimenter::32, @nxast::16, idle::16, hard::16, prio::16, cookie::64, flags_int::16, + table_id::8, 0::size(1)-unit(8), fin_idle::16, fin_hard::16, limit::32, + result_dst_ofs::16, 0::size(2)-unit(8), result_dst_bin::bytes, flow_specs_bin::bitstring>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + + flags = Openflow.Enums.int_to_flags(flags_int, :nx_learn_flag) + + learn = %NxLearn2{ + idle_timeout: idle, + hard_timeout: hard, + priority: prio, + cookie: cookie, + flags: flags, + table_id: table_id, + fin_idle_timeout: fin_idle, + fin_hard_timeout: fin_hard, + limit: limit, + result_dst_offset: result_dst_ofs + } + + if :write_result in flags do + header_size = Openflow.Match.header_size(rest) + <> = rest + result_dst = Openflow.Match.codec_header(result_dst_bin) + flow_specs = Openflow.Action.NxFlowSpec.read(flow_specs_bin) + struct(learn, %{result_dst: result_dst, flow_specs: flow_specs}) + else + <> = rest + flow_specs = Openflow.Action.NxFlowSpec.read(flow_specs_bin) + struct(learn, %{flow_specs: flow_specs}) + end + end +end diff --git a/lib/openflow/actions/nx_multipath.ex b/lib/openflow/actions/nx_multipath.ex new file mode 100644 index 0000000..72975e0 --- /dev/null +++ b/lib/openflow/actions/nx_multipath.ex @@ -0,0 +1,88 @@ +defmodule Openflow.Action.NxMultipath do + import Bitwise + + defstruct( + hash_field: :eth_src, + basis: 0, + algorithm: :modulo_n, + max_link: 0, + argument: 0, + offset: 0, + n_bits: 0, + dst_field: nil + ) + + @experimenter 0x00002320 + @nxast 10 + + alias __MODULE__ + + def new(options) do + hash_field = Keyword.get(options, :hash_field, :eth_src) + basis = Keyword.get(options, :basis, 0) + alg = Keyword.get(options, :algorithm, :modulo_n) + max_link = Keyword.get(options, :max_link, 0) + arg = Keyword.get(options, :argument, 0) + dst_field = Keyword.get(options, :dst_field) + default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + ofs = Keyword.get(options, :offset, 0) + + %NxMultipath{ + hash_field: hash_field, + basis: basis, + algorithm: alg, + max_link: max_link, + offset: ofs, + n_bits: n_bits, + argument: arg, + dst_field: dst_field + } + end + + def to_binary(%NxMultipath{ + hash_field: hash_field, + basis: basis, + algorithm: alg, + max_link: max_link, + argument: arg, + offset: ofs, + n_bits: n_bits, + dst_field: dst_field + }) do + hash_field_int = Openflow.Enums.to_int(hash_field, :nx_hash_fields) + alg_int = Openflow.Enums.to_int(alg, :nx_mp_algorithm) + dst_field_bin = Openflow.Match.codec_header(dst_field) + ofs_nbits = ofs <<< 6 ||| n_bits - 1 + + body = + <> + + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + + hash_field = Openflow.Enums.to_atom(hash_field_int, :nx_hash_fields) + alg = Openflow.Enums.to_atom(alg_int, :nx_mp_algorithm) + dst_field = Openflow.Match.codec_header(dst_field_bin) + + %NxMultipath{ + hash_field: hash_field, + basis: basis, + algorithm: alg, + max_link: max_link, + argument: arg, + offset: ofs, + n_bits: n_bits + 1, + dst_field: dst_field + } + end +end diff --git a/lib/openflow/actions/nx_nat.ex b/lib/openflow/actions/nx_nat.ex new file mode 100644 index 0000000..921d5f1 --- /dev/null +++ b/lib/openflow/actions/nx_nat.ex @@ -0,0 +1,145 @@ +defmodule Openflow.Action.NxNat do + defstruct( + flags: [], + ipv4_min: nil, + ipv4_max: nil, + ipv6_min: nil, + ipv6_max: nil, + proto_min: nil, + proto_max: nil + ) + + @experimenter 0x00002320 + @nxast 36 + + alias __MODULE__ + + def new(options \\ []) do + flags = Keyword.get(options, :flags, []) + ipv4_min = Keyword.get(options, :ipv4_min) + ipv4_max = Keyword.get(options, :ipv4_max) + ipv6_min = Keyword.get(options, :ipv6_min) + ipv6_max = Keyword.get(options, :ipv6_max) + proto_min = Keyword.get(options, :proto_min) + proto_max = Keyword.get(options, :proto_max) + + %NxNat{ + flags: flags, + ipv4_min: ipv4_min, + ipv4_max: ipv4_max, + ipv6_min: ipv6_min, + ipv6_max: ipv6_max, + proto_min: proto_min, + proto_max: proto_max + } + end + + def to_binary(%NxNat{flags: flags} = nat) do + flags_int = Openflow.Enums.flags_to_int(flags, :nx_nat_flags) + + range_flags = + nat + |> get_ranges + |> Openflow.Enums.flags_to_int(:nx_nat_range) + |> Openflow.Enums.int_to_flags(:nx_nat_range) + + ranges_bin = encode_ranges("", range_flags, nat) + range_flags_int = Openflow.Enums.flags_to_int(range_flags, :nx_nat_range) + + exp_body = + <<@experimenter::32, @nxast::16, 0::size(2)-unit(8), flags_int::16, range_flags_int::16, + ranges_bin::bytes>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <<0::size(2)-unit(8), flags_int::16, range_flags_int::16, ranges_bin::bytes>> = body + flags = Openflow.Enums.int_to_flags(flags_int, :nx_nat_flags) + range_flags = Openflow.Enums.int_to_flags(range_flags_int, :nx_nat_range) + decode_ranges(%NxNat{flags: flags}, range_flags, ranges_bin) + end + + # private functions + + defp get_ranges(nat) do + nat + |> Map.from_struct() + |> Map.delete(:flags) + |> Enum.map(fn {k, v} -> if(not is_nil(v), do: k, else: nil) end) + |> Enum.filter(fn v -> not is_nil(v) end) + end + + defp encode_ranges(acc, [], _nat), do: acc + + defp encode_ranges(acc, [range | rest], nat) do + cond do + range == :ipv4_min or range == :ipv4_max -> + case Map.get(nat, range) do + {a1, a2, a3, a4} -> + encode_ranges(<>, rest, nat) + + "" -> + encode_ranges(<>, rest, nat) + end + + range == :ipv6_min or range == :ipv6_max -> + case Map.get(nat, range) do + {a1, a2, a3, a4, a5, a6, a7, a8} -> + encode_ranges( + <>, + rest, + nat + ) + + "" -> + encode_ranges(<>, rest, nat) + end + + range == :proto_min or range == :proto_max -> + case Map.get(nat, range) do + proto when is_integer(proto) and proto in 1..0xFFFF -> + encode_ranges(<>, rest, nat) + + _ -> + encode_ranges(<>, rest, nat) + end + end + end + + defp decode_ranges(nat, [], _), do: nat + + defp decode_ranges(nat, [range | ranges], bin) do + cond do + range == :ipv4_min or range == :ipv4_max -> + case bin do + <> -> + decode_ranges(struct(nat, %{range => {a1, a2, a3, a4}}), ranges, rest) + + rest -> + decode_ranges(struct(nat, %{range => ""}), ranges, rest) + end + + range == :ipv6_min or range == :ipv6_max -> + case bin do + <> -> + decode_ranges(struct(nat, %{range => {a1, a2, a3, a4, a5, a6, a7, a8}}), ranges, rest) + + rest -> + decode_ranges(struct(nat, %{range => ""}), ranges, rest) + end + + range == :proto_min or range == :proto_max -> + case bin do + <> when proto in 1..0xFFFF -> + decode_ranges(struct(nat, %{range => proto}), ranges, rest) + + rest -> + decode_ranges(struct(nat, %{range => ""}), ranges, rest) + end + end + end +end diff --git a/lib/openflow/actions/nx_note.ex b/lib/openflow/actions/nx_note.ex new file mode 100644 index 0000000..b96847d --- /dev/null +++ b/lib/openflow/actions/nx_note.ex @@ -0,0 +1,26 @@ +defmodule Openflow.Action.NxNote do + defstruct(note: "") + + @experimenter 0x00002320 + @nxast 8 + + alias __MODULE__ + + def new(note) do + %NxNote{note: note} + end + + def to_binary(%NxNote{note: note}) do + padding = Openflow.Utils.padding(byte_size(note) + 2, 8) + exp_body = <<@experimenter::32, @nxast::16, note::bytes, 0::size(padding)-unit(8)>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, note_bin::bytes>>) do + note = Openflow.Utils.decode_string(note_bin) + %NxNote{note: note} + end +end diff --git a/lib/openflow/actions/nx_output_reg.ex b/lib/openflow/actions/nx_output_reg.ex new file mode 100644 index 0000000..852358a --- /dev/null +++ b/lib/openflow/actions/nx_output_reg.ex @@ -0,0 +1,43 @@ +defmodule Openflow.Action.NxOutputReg do + import Bitwise + + defstruct( + n_bits: 0, + offset: 0, + src_field: nil, + max_len: :no_buffer + ) + + @experimenter 0x00002320 + @nxast 15 + + alias __MODULE__ + + def new(options) do + src_field = Keyword.get(options, :src_field) + default_n_bits = Openflow.Match.Field.n_bits_of(src_field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + ofs = Keyword.get(options, :offset, 0) + max_len = Keyword.get(options, :max_len, :no_buffer) + %NxOutputReg{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len} + end + + def to_binary(%NxOutputReg{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}) do + src_field_bin = Openflow.Match.codec_header(src_field) + ofs_nbits = ofs <<< 6 ||| n_bits - 1 + max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) + body = <> + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + src_field = Openflow.Match.codec_header(src_field_bin) + max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) + %NxOutputReg{n_bits: n_bits + 1, offset: ofs, src_field: src_field, max_len: max_len} + end +end diff --git a/lib/openflow/actions/nx_output_reg2.ex b/lib/openflow/actions/nx_output_reg2.ex new file mode 100644 index 0000000..e254cf3 --- /dev/null +++ b/lib/openflow/actions/nx_output_reg2.ex @@ -0,0 +1,54 @@ +defmodule Openflow.Action.NxOutputReg2 do + import Bitwise + + defstruct( + n_bits: 0, + offset: 0, + src_field: nil, + max_len: :no_buffer + ) + + @experimenter 0x00002320 + @nxast 32 + + alias __MODULE__ + + def new(options) do + src_field = Keyword.get(options, :src_field) + default_n_bits = Openflow.Match.Field.n_bits_of(src_field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + ofs = Keyword.get(options, :offset, 0) + max_len = Keyword.get(options, :max_len, :no_buffer) + %NxOutputReg2{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len} + end + + def to_binary(%NxOutputReg2{n_bits: n_bits, offset: ofs, src_field: src_field, max_len: max_len}) do + src_field_bin = Openflow.Match.codec_header(src_field) + ofs_nbits = ofs <<< 6 ||| n_bits - 1 + max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) + padding = Openflow.Utils.padding(byte_size(src_field_bin), 10) + body = <> + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + exp_size = match_header_size(oxm_header) - 4 + <> = rest + + src_field = + Openflow.Match.codec_header(<>) + + max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) + %NxOutputReg2{n_bits: n_bits + 1, offset: ofs, src_field: src_field, max_len: max_len} + end + + # private functions + + defp match_header_size(<<0xFFFF::16, _::bytes>>), do: 8 + defp match_header_size(<<_::16, _::bytes>>), do: 4 +end diff --git a/lib/openflow/actions/nx_output_trunc.ex b/lib/openflow/actions/nx_output_trunc.ex new file mode 100644 index 0000000..98b3c6e --- /dev/null +++ b/lib/openflow/actions/nx_output_trunc.ex @@ -0,0 +1,31 @@ +defmodule Openflow.Action.NxOutputTrunc do + defstruct( + port_number: 0, + max_len: :no_buffer + ) + + @experimenter 0x00002320 + @nxast 39 + + alias __MODULE__ + + def new(options) do + port_no = Keyword.get(options, :port_number) + max_len = Keyword.get(options, :max_len) + %NxOutputTrunc{port_number: port_no, max_len: max_len} + end + + def to_binary(%NxOutputTrunc{port_number: port_no, max_len: max_len}) do + port_no_int = Openflow.Utils.get_enum(port_no, :openflow10_port_no) + exp_body = <<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, port_no_int::16, max_len::32>>) do + port_no = Openflow.Utils.get_enum(port_no_int, :openflow10_port_no) + %NxOutputTrunc{port_number: port_no, max_len: max_len} + end +end diff --git a/lib/openflow/actions/nx_pop_mpls.ex b/lib/openflow/actions/nx_pop_mpls.ex new file mode 100644 index 0000000..f14f863 --- /dev/null +++ b/lib/openflow/actions/nx_pop_mpls.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxPopMpls do + defstruct(ethertype: 0x8847) + + @experimenter 0x00002320 + @nxast 24 + + alias __MODULE__ + + def new(ethertype \\ 0x8847) do + %NxPopMpls{ethertype: ethertype} + end + + def to_binary(%NxPopMpls{ethertype: ethertype}) do + exp_body = <<@experimenter::32, @nxast::16, ethertype::16, 0::size(4)-unit(8)>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do + %NxPopMpls{ethertype: ethertype} + end +end diff --git a/lib/openflow/actions/nx_pop_queue.ex b/lib/openflow/actions/nx_pop_queue.ex new file mode 100644 index 0000000..4821cd3 --- /dev/null +++ b/lib/openflow/actions/nx_pop_queue.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxPopQueue do + defstruct([]) + + @experimenter 0x00002320 + @nxast 5 + + alias __MODULE__ + + def new do + %NxPopQueue{} + end + + def to_binary(%NxPopQueue{}) do + exp_body = <<@experimenter::32, @nxast::16, 0::48>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8)>>) do + %NxPopQueue{} + end +end diff --git a/lib/openflow/actions/nx_push_mpls.ex b/lib/openflow/actions/nx_push_mpls.ex new file mode 100644 index 0000000..4db52b0 --- /dev/null +++ b/lib/openflow/actions/nx_push_mpls.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxPushMpls do + defstruct(ethertype: 0x8847) + + @experimenter 0x00002320 + @nxast 23 + + alias __MODULE__ + + def new(ethertype \\ 0x8847) do + %NxPushMpls{ethertype: ethertype} + end + + def to_binary(%NxPushMpls{ethertype: ethertype}) do + exp_body = <<@experimenter::32, @nxast::16, ethertype::16, 0::size(4)-unit(8)>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, ethertype::16, _::size(4)-unit(8)>>) do + %NxPushMpls{ethertype: ethertype} + end +end diff --git a/lib/openflow/actions/nx_reg_load.ex b/lib/openflow/actions/nx_reg_load.ex new file mode 100644 index 0000000..1ee7da5 --- /dev/null +++ b/lib/openflow/actions/nx_reg_load.ex @@ -0,0 +1,45 @@ +defmodule Openflow.Action.NxRegLoad do + import Bitwise + + defstruct( + n_bits: 0, + offset: 0, + dst_field: nil, + value: nil + ) + + @experimenter 0x00002320 + @nxast 7 + + alias __MODULE__ + + def new(options) do + dst_field = Keyword.get(options, :dst_field) + default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + ofs = Keyword.get(options, :offset, 0) + value = Keyword.get(options, :value) + %NxRegLoad{n_bits: n_bits, offset: ofs, dst_field: dst_field, value: value} + end + + def to_binary(%NxRegLoad{n_bits: n_bits, offset: ofs, dst_field: dst_field, value: value}) do + dst_field_bin = Openflow.Match.codec_header(dst_field) + value_bin0 = Openflow.Match.Field.codec(value, dst_field) + tmp_value = :binary.decode_unsigned(value_bin0, :big) + value_bin = <> + ofs_nbits = ofs <<< 6 ||| n_bits - 1 + body = <> + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = body + dst_field = Openflow.Match.codec_header(dst_field_bin) + value = Openflow.Match.Field.codec(value_bin, dst_field) + %NxRegLoad{n_bits: n_bits + 1, offset: ofs, dst_field: dst_field, value: value} + end +end diff --git a/lib/openflow/actions/nx_reg_load2.ex b/lib/openflow/actions/nx_reg_load2.ex new file mode 100644 index 0000000..0c1510e --- /dev/null +++ b/lib/openflow/actions/nx_reg_load2.ex @@ -0,0 +1,44 @@ +defmodule Openflow.Action.NxRegLoad2 do + defstruct( + dst_field: nil, + value: nil + ) + + @experimenter 0x00002320 + @nxast 33 + + alias __MODULE__ + + def new(options) do + dst_field = Keyword.get(options, :dst_field) + value = Keyword.get(options, :value) + %NxRegLoad2{dst_field: dst_field, value: value} + end + + def to_binary(%NxRegLoad2{dst_field: dst_field, value: value}) do + match_bin = + [{dst_field, value}] + |> Openflow.Match.new() + |> Openflow.Match.to_binary() + + <<1::16, _length::16, padded_field::bytes>> = match_bin + patial_len = 4 + 4 + 2 + 6 + byte_size(padded_field) + padding = Openflow.Utils.padding(patial_len, 8) + + exp_body = + <<@experimenter::32, @nxast::16, 0::48, padded_field::bytes, 0::size(padding)-unit(8)>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, _::48, match_field_bin::bytes>>) do + <<_class::16, _field::7, _hm::1, flen::8, _rest::bytes>> = match_field_bin + match_len = 4 + 4 + flen + match_bin = <<1::16, match_len::16, match_field_bin::bytes, 0::size(4)-unit(8)>> + {[{dst_field, value} | _], _rest} = Openflow.Match.read(match_bin) + %NxRegLoad2{dst_field: dst_field, value: value} + end +end diff --git a/lib/openflow/actions/nx_reg_move.ex b/lib/openflow/actions/nx_reg_move.ex new file mode 100644 index 0000000..309fd38 --- /dev/null +++ b/lib/openflow/actions/nx_reg_move.ex @@ -0,0 +1,67 @@ +defmodule Openflow.Action.NxRegMove do + defstruct( + n_bits: 0, + src_offset: 0, + dst_offset: 0, + src_field: nil, + dst_field: nil + ) + + @experimenter 0x00002320 + @nxast 6 + + alias __MODULE__ + + def new(options) do + src_field = Keyword.get(options, :src_field) + dst_field = Keyword.get(options, :dst_field) + default_n_bits = Openflow.Match.Field.n_bits_of(dst_field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + src_ofs = Keyword.get(options, :src_offset, 0) + dst_ofs = Keyword.get(options, :dst_offset, 0) + + %NxRegMove{ + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs, + src_field: src_field, + dst_field: dst_field + } + end + + def to_binary(%NxRegMove{ + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs, + src_field: src_field, + dst_field: dst_field + }) do + src_field_bin = Openflow.Match.codec_header(src_field) + dst_field_bin = Openflow.Match.codec_header(dst_field) + + body = + <> + + exp_body = <<@experimenter::32, @nxast::16, body::bytes>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, body::bytes>>) do + <> = + body + + src_field = Openflow.Match.codec_header(src_field_bin) + dst_field = Openflow.Match.codec_header(dst_field_bin) + + %NxRegMove{ + n_bits: n_bits, + src_offset: src_ofs, + dst_offset: dst_ofs, + src_field: src_field, + dst_field: dst_field + } + end +end diff --git a/lib/openflow/actions/nx_resubmit.ex b/lib/openflow/actions/nx_resubmit.ex new file mode 100644 index 0000000..9ed1623 --- /dev/null +++ b/lib/openflow/actions/nx_resubmit.ex @@ -0,0 +1,26 @@ +defmodule Openflow.Action.NxResubmit do + defstruct(in_port: :in_port) + + @experimenter 0x00002320 + @nxast 1 + + alias __MODULE__ + + def new(in_port \\ :in_port) do + %NxResubmit{in_port: in_port} + end + + def to_binary(%NxResubmit{in_port: in_port}) do + in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no) + exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, 0::size(4)-unit(8)>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, in_port_int::16, _::size(4)-unit(8)>>) do + in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no) + %NxResubmit{in_port: in_port} + end +end diff --git a/lib/openflow/actions/nx_resubmit_table.ex b/lib/openflow/actions/nx_resubmit_table.ex new file mode 100644 index 0000000..04bbba8 --- /dev/null +++ b/lib/openflow/actions/nx_resubmit_table.ex @@ -0,0 +1,36 @@ +defmodule Openflow.Action.NxResubmitTable do + defstruct(in_port: :in_port, table_id: :all) + + @experimenter 0x00002320 + @nxast 14 + + alias __MODULE__ + + def new(table_id) when is_atom(table_id) or is_integer(table_id) do + new(table_id: table_id) + end + + def new(options) do + in_port = Keyword.get(options, :in_port, :in_port) + table_id = Keyword.get(options, :table_id, :all) + %NxResubmitTable{in_port: in_port, table_id: table_id} + end + + def to_binary(%NxResubmitTable{in_port: in_port, table_id: table_id}) do + in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no) + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::24>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::size(3)-unit(8)>> + ) do + in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no) + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + %NxResubmitTable{in_port: in_port, table_id: table_id} + end +end diff --git a/lib/openflow/actions/nx_resubmit_table_ct.ex b/lib/openflow/actions/nx_resubmit_table_ct.ex new file mode 100644 index 0000000..849640e --- /dev/null +++ b/lib/openflow/actions/nx_resubmit_table_ct.ex @@ -0,0 +1,32 @@ +defmodule Openflow.Action.NxResubmitTableCt do + defstruct(in_port: :in_port, table_id: :all) + + @experimenter 0x00002320 + @nxast 44 + + alias __MODULE__ + + def new(options) do + in_port = Keyword.get(options, :in_port, :in_port) + table_id = Keyword.get(options, :table_id, :all) + %NxResubmitTableCt{in_port: in_port, table_id: table_id} + end + + def to_binary(%NxResubmitTableCt{in_port: in_port, table_id: table_id}) do + in_port_int = Openflow.Utils.get_enum(in_port, :openflow10_port_no) + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + exp_body = <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::24>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, in_port_int::16, table_id_int::8, 0::size(3)-unit(8)>> + ) do + in_port = Openflow.Utils.get_enum(in_port_int, :openflow10_port_no) + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + %NxResubmitTableCt{in_port: in_port, table_id: table_id} + end +end diff --git a/lib/openflow/actions/nx_sample.ex b/lib/openflow/actions/nx_sample.ex new file mode 100644 index 0000000..206c0ed --- /dev/null +++ b/lib/openflow/actions/nx_sample.ex @@ -0,0 +1,55 @@ +defmodule Openflow.Action.NxSample do + defstruct( + probability: 0, + collector_set_id: 0, + obs_domain_id: 0, + obs_point_id: 0 + ) + + @experimenter 0x00002320 + @nxast 29 + + alias __MODULE__ + + def new(options) do + probability = Keyword.get(options, :probability, 0) + collector_set_id = Keyword.get(options, :collector_set_id, 0) + obs_domain_id = Keyword.get(options, :obs_domain_id, 0) + obs_point_id = Keyword.get(options, :obs_point_id, 0) + + %NxSample{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id + } + end + + def to_binary(%NxSample{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id + }) do + exp_body = + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32>> + ) do + %NxSample{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id + } + end +end diff --git a/lib/openflow/actions/nx_sample2.ex b/lib/openflow/actions/nx_sample2.ex new file mode 100644 index 0000000..271a3c6 --- /dev/null +++ b/lib/openflow/actions/nx_sample2.ex @@ -0,0 +1,60 @@ +defmodule Openflow.Action.NxSample2 do + defstruct( + probability: 0, + collector_set_id: 0, + obs_domain_id: 0, + obs_point_id: 0, + sampling_port: 0 + ) + + @experimenter 0x00002320 + @nxast 38 + + alias __MODULE__ + + def new(options) do + probability = Keyword.get(options, :probability, 0) + collector_set_id = Keyword.get(options, :collector_set_id, 0) + obs_domain_id = Keyword.get(options, :obs_domain_id, 0) + obs_point_id = Keyword.get(options, :obs_point_id, 0) + sampling_port = Keyword.get(options, :sampling_port, 0) + + %NxSample2{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port + } + end + + def to_binary(%NxSample2{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port + }) do + exp_body = + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32, sampling_port::16, 0::size(6)-unit(8)>> + ) do + %NxSample2{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port + } + end +end diff --git a/lib/openflow/actions/nx_sample3.ex b/lib/openflow/actions/nx_sample3.ex new file mode 100644 index 0000000..bb1c531 --- /dev/null +++ b/lib/openflow/actions/nx_sample3.ex @@ -0,0 +1,69 @@ +defmodule Openflow.Action.NxSample3 do + defstruct( + probability: 0, + collector_set_id: 0, + obs_domain_id: 0, + obs_point_id: 0, + sampling_port: 0, + direction: :default + ) + + @experimenter 0x00002320 + @nxast 41 + + alias __MODULE__ + + def new(options) do + probability = Keyword.get(options, :probability, 0) + collector_set_id = Keyword.get(options, :collector_set_id, 0) + obs_domain_id = Keyword.get(options, :obs_domain_id, 0) + obs_point_id = Keyword.get(options, :obs_point_id, 0) + sampling_port = Keyword.get(options, :sampling_port, 0) + direction = Keyword.get(options, :direction, :default) + + %NxSample3{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port, + direction: direction + } + end + + def to_binary(%NxSample3{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port, + direction: direction + }) do + direction_int = Openflow.Enums.to_int(direction, :nx_action_sample_direction) + + exp_body = + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32, sampling_port::16, direction_int::8, 0::size(5)-unit(8)>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, probability::16, collector_set_id::32, obs_domain_id::32, + obs_point_id::32, sampling_port::16, direction_int::8, 0::size(5)-unit(8)>> + ) do + direction = Openflow.Enums.to_atom(direction_int, :nx_action_sample_direction) + + %NxSample3{ + probability: probability, + collector_set_id: collector_set_id, + obs_domain_id: obs_domain_id, + obs_point_id: obs_point_id, + sampling_port: sampling_port, + direction: direction + } + end +end diff --git a/lib/openflow/actions/nx_set_mpls_label.ex b/lib/openflow/actions/nx_set_mpls_label.ex new file mode 100644 index 0000000..9fdcf04 --- /dev/null +++ b/lib/openflow/actions/nx_set_mpls_label.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxSetMplsLabel do + defstruct(label: 0) + + @experimenter 0x00002320 + @nxast 30 + + alias __MODULE__ + + def new(label) do + %NxSetMplsLabel{label: label} + end + + def to_binary(%NxSetMplsLabel{label: label}) do + exp_body = <<@experimenter::32, @nxast::16, 0::16, label::32>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, _::16, label::32>>) do + %NxSetMplsLabel{label: label} + end +end diff --git a/lib/openflow/actions/nx_set_mpls_tc.ex b/lib/openflow/actions/nx_set_mpls_tc.ex new file mode 100644 index 0000000..9392558 --- /dev/null +++ b/lib/openflow/actions/nx_set_mpls_tc.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxSetMplsTc do + defstruct(tc: 0) + + @experimenter 0x00002320 + @nxast 31 + + alias __MODULE__ + + def new(tc) do + %NxSetMplsTc{tc: tc} + end + + def to_binary(%NxSetMplsTc{tc: tc}) do + exp_body = <<@experimenter::32, @nxast::16, tc::8, 0::size(5)-unit(8)>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, tc::8, _::size(5)-unit(8)>>) do + %NxSetMplsTc{tc: tc} + end +end diff --git a/lib/openflow/actions/nx_set_mpls_ttl.ex b/lib/openflow/actions/nx_set_mpls_ttl.ex new file mode 100644 index 0000000..cd932af --- /dev/null +++ b/lib/openflow/actions/nx_set_mpls_ttl.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxSetMplsTtl do + defstruct(ttl: 0) + + @experimenter 0x00002320 + @nxast 25 + + alias __MODULE__ + + def new(ttl) do + %NxSetMplsTtl{ttl: ttl} + end + + def to_binary(%NxSetMplsTtl{ttl: ttl}) do + exp_body = <<@experimenter::32, @nxast::16, ttl::8, 0::size(5)-unit(8)>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, ttl::8, _::size(5)-unit(8)>>) do + %NxSetMplsTtl{ttl: ttl} + end +end diff --git a/lib/openflow/actions/nx_set_queue.ex b/lib/openflow/actions/nx_set_queue.ex new file mode 100644 index 0000000..845c494 --- /dev/null +++ b/lib/openflow/actions/nx_set_queue.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxSetQueue do + defstruct(queue_id: 0) + + @experimenter 0x00002320 + @nxast 4 + + alias __MODULE__ + + def new(queue_id) do + %NxSetQueue{queue_id: queue_id} + end + + def to_binary(%NxSetQueue{queue_id: queue_id}) do + exp_body = <<@experimenter::32, @nxast::16, 0::16, queue_id::32>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, 0::size(2)-unit(8), queue_id::32>>) do + %NxSetQueue{queue_id: queue_id} + end +end diff --git a/lib/openflow/actions/nx_set_tunnel.ex b/lib/openflow/actions/nx_set_tunnel.ex new file mode 100644 index 0000000..661114b --- /dev/null +++ b/lib/openflow/actions/nx_set_tunnel.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxSetTunnel do + defstruct(tunnel_id: 0) + + @experimenter 0x00002320 + @nxast 2 + + alias __MODULE__ + + def new(tunnel_id) do + %NxSetTunnel{tunnel_id: tunnel_id} + end + + def to_binary(%NxSetTunnel{tunnel_id: tunnel_id}) do + exp_body = <<@experimenter::32, @nxast::16, 0::16, tunnel_id::32>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, _::16, tunnel_id::32>>) do + %NxSetTunnel{tunnel_id: tunnel_id} + end +end diff --git a/lib/openflow/actions/nx_set_tunnel64.ex b/lib/openflow/actions/nx_set_tunnel64.ex new file mode 100644 index 0000000..d729689 --- /dev/null +++ b/lib/openflow/actions/nx_set_tunnel64.ex @@ -0,0 +1,24 @@ +defmodule Openflow.Action.NxSetTunnel64 do + defstruct(tunnel_id: 0) + + @experimenter 0x00002320 + @nxast 9 + + alias __MODULE__ + + def new(tunnel_id) do + %NxSetTunnel64{tunnel_id: tunnel_id} + end + + def to_binary(%NxSetTunnel64{tunnel_id: tunnel_id}) do + exp_body = <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>> + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, 0::size(6)-unit(8), tunnel_id::64>>) do + %NxSetTunnel64{tunnel_id: tunnel_id} + end +end diff --git a/lib/openflow/actions/nx_stack_pop.ex b/lib/openflow/actions/nx_stack_pop.ex new file mode 100644 index 0000000..479932c --- /dev/null +++ b/lib/openflow/actions/nx_stack_pop.ex @@ -0,0 +1,41 @@ +defmodule Openflow.Action.NxStackPop do + defstruct( + n_bits: 0, + offset: 0, + field: nil + ) + + @experimenter 0x00002320 + @nxast 28 + + alias __MODULE__ + + def new(options) do + field = Keyword.get(options, :field) + default_n_bits = Openflow.Match.Field.n_bits_of(field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + ofs = Keyword.get(options, :offset, 0) + %NxStackPop{n_bits: n_bits, offset: ofs, field: field} + end + + def to_binary(%NxStackPop{n_bits: n_bits, offset: ofs, field: field}) do + field_bin = Openflow.Match.codec_header(field) + + exp_body = + <<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16, + 0::size(6)-unit(8)>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16, + _::size(6)-unit(8)>> + ) do + field = Openflow.Match.codec_header(field_bin) + %NxStackPop{n_bits: n_bits, offset: ofs, field: field} + end +end diff --git a/lib/openflow/actions/nx_stack_push.ex b/lib/openflow/actions/nx_stack_push.ex new file mode 100644 index 0000000..aa33e71 --- /dev/null +++ b/lib/openflow/actions/nx_stack_push.ex @@ -0,0 +1,41 @@ +defmodule Openflow.Action.NxStackPush do + defstruct( + n_bits: 0, + offset: 0, + field: nil + ) + + @experimenter 0x00002320 + @nxast 27 + + alias __MODULE__ + + def new(options) do + field = Keyword.get(options, :field) + default_n_bits = Openflow.Match.Field.n_bits_of(field) + n_bits = Keyword.get(options, :n_bits, default_n_bits) + ofs = Keyword.get(options, :offset, 0) + %NxStackPush{n_bits: n_bits, offset: ofs, field: field} + end + + def to_binary(%NxStackPush{n_bits: n_bits, offset: ofs, field: field}) do + field_bin = Openflow.Match.codec_header(field) + + exp_body = + <<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16, + 0::size(6)-unit(8)>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read( + <<@experimenter::32, @nxast::16, ofs::16, field_bin::4-bytes, n_bits::16, + _::size(6)-unit(8)>> + ) do + field = Openflow.Match.codec_header(field_bin) + %NxStackPush{n_bits: n_bits, offset: ofs, field: field} + end +end diff --git a/lib/openflow/actions/nx_write_metadata.ex b/lib/openflow/actions/nx_write_metadata.ex new file mode 100644 index 0000000..4396d6a --- /dev/null +++ b/lib/openflow/actions/nx_write_metadata.ex @@ -0,0 +1,35 @@ +defmodule Openflow.Action.NxWriteMetadata do + defstruct( + metadata: 0, + metadata_mask: 0xFFFFFFFFFFFFFFFF + ) + + @experimenter 0x00002320 + @nxast 22 + + alias __MODULE__ + + def new(metadata) when is_integer(metadata) do + new(metadata: metadata) + end + + def new(options) when is_list(options) do + metadata = Keyword.get(options, :metadata, 0) + metadata_mask = Keyword.get(options, :metadata_mask, 0xFFFFFFFFFFFFFFFF) + %NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask} + end + + def to_binary(%NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask}) do + exp_body = + <<@experimenter::32, @nxast::16, 0::size(6)-unit(8), metadata::64, metadata_mask::64>> + + exp_body_size = byte_size(exp_body) + padding_length = Openflow.Utils.padding(4 + exp_body_size, 8) + length = 4 + exp_body_size + padding_length + <<0xFFFF::16, length::16, exp_body::bytes, 0::size(padding_length)-unit(8)>> + end + + def read(<<@experimenter::32, @nxast::16, _::size(6)-unit(8), metadata::64, metadata_mask::64>>) do + %NxWriteMetadata{metadata: metadata, metadata_mask: metadata_mask} + end +end diff --git a/lib/openflow/actions/output.ex b/lib/openflow/actions/output.ex new file mode 100644 index 0000000..070b123 --- /dev/null +++ b/lib/openflow/actions/output.ex @@ -0,0 +1,32 @@ +defmodule Openflow.Action.Output do + defstruct( + port_number: 0, + max_len: :no_buffer + ) + + alias __MODULE__ + + def ofpat, do: 0 + + def new(port) when not is_list(port) do + new(port_number: port) + end + + def new(options) when is_list(options) do + port_no = Keyword.get(options, :port_number) + max_len = Keyword.get(options, :max_len, :no_buffer) + %Output{port_number: port_no, max_len: max_len} + end + + def to_binary(%Output{port_number: port_no, max_len: max_len}) do + port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no) + max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) + <<0::16, 16::16, port_no_int::32, max_len::16, 0::size(6)-unit(8)>> + end + + def read(<<0::16, 16::16, port_no_int::32, max_len::16, _pad::size(6)-unit(8)>>) do + port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) + max_len = Openflow.Utils.get_enum(max_len, :controller_max_len) + %Output{port_number: port_no, max_len: max_len} + end +end diff --git a/lib/openflow/actions/pop_mpls.ex b/lib/openflow/actions/pop_mpls.ex new file mode 100644 index 0000000..7ea7950 --- /dev/null +++ b/lib/openflow/actions/pop_mpls.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.PopMpls do + defstruct(ethertype: 0x8847) + + alias __MODULE__ + + def ofpat, do: 20 + + def new(ethertype) do + %PopMpls{ethertype: ethertype} + end + + def to_binary(%PopMpls{ethertype: ethertype}) do + <<20::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> + end + + def read(<<20::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do + %PopMpls{ethertype: ethertype} + end +end diff --git a/lib/openflow/actions/pop_pbb.ex b/lib/openflow/actions/pop_pbb.ex new file mode 100644 index 0000000..d2e4c0d --- /dev/null +++ b/lib/openflow/actions/pop_pbb.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.PopPbb do + defstruct([]) + + alias __MODULE__ + + def ofpat, do: 27 + + def new do + %PopPbb{} + end + + def to_binary(%PopPbb{}) do + <<27::16, 8::16, 0::size(4)-unit(8)>> + end + + def read(<<27::16, 8::16, _::size(4)-unit(8)>>) do + %PopPbb{} + end +end diff --git a/lib/openflow/actions/pop_vlan.ex b/lib/openflow/actions/pop_vlan.ex new file mode 100644 index 0000000..8ea4f26 --- /dev/null +++ b/lib/openflow/actions/pop_vlan.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.PopVlan do + defstruct([]) + + alias __MODULE__ + + def ofpat, do: 18 + + def new do + %PopVlan{} + end + + def to_binary(%PopVlan{}) do + <<18::16, 8::16, 0::size(4)-unit(8)>> + end + + def read(<<18::16, 8::16, _::size(4)-unit(8)>>) do + %PopVlan{} + end +end diff --git a/lib/openflow/actions/push_mpls.ex b/lib/openflow/actions/push_mpls.ex new file mode 100644 index 0000000..f9c7fe0 --- /dev/null +++ b/lib/openflow/actions/push_mpls.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.PushMpls do + defstruct(ethertype: 0x8847) + + alias __MODULE__ + + def ofpat, do: 19 + + def new(ethertype) do + %PushMpls{ethertype: ethertype} + end + + def to_binary(%PushMpls{ethertype: ethertype}) do + <<19::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> + end + + def read(<<19::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do + %PushMpls{ethertype: ethertype} + end +end diff --git a/lib/openflow/actions/push_pbb.ex b/lib/openflow/actions/push_pbb.ex new file mode 100644 index 0000000..4a7d0ae --- /dev/null +++ b/lib/openflow/actions/push_pbb.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.PushPbb do + defstruct(ethertype: 0x88E7) + + alias __MODULE__ + + def ofpat, do: 26 + + def new(ethertype) do + %PushPbb{ethertype: ethertype} + end + + def to_binary(%PushPbb{ethertype: ethertype}) do + <<26::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> + end + + def read(<<26::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do + %PushPbb{ethertype: ethertype} + end +end diff --git a/lib/openflow/actions/push_vlan.ex b/lib/openflow/actions/push_vlan.ex new file mode 100644 index 0000000..8c8ca39 --- /dev/null +++ b/lib/openflow/actions/push_vlan.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.PushVlan do + defstruct(ethertype: 0x8100) + + alias __MODULE__ + + def ofpat, do: 17 + + def new(ethertype \\ 0x8100) do + %PushVlan{ethertype: ethertype} + end + + def to_binary(%PushVlan{ethertype: ethertype}) do + <<17::16, 8::16, ethertype::16, 0::size(2)-unit(8)>> + end + + def read(<<17::16, 8::16, ethertype::16, 0::size(2)-unit(8)>>) do + %PushVlan{ethertype: ethertype} + end +end diff --git a/lib/openflow/actions/set_field.ex b/lib/openflow/actions/set_field.ex new file mode 100644 index 0000000..79b4070 --- /dev/null +++ b/lib/openflow/actions/set_field.ex @@ -0,0 +1,34 @@ +defmodule Openflow.Action.SetField do + defstruct(field: nil) + + alias __MODULE__ + + @set_field_size 8 + + def ofpat, do: 25 + + def new({_field, _value} = oxm_field) do + %SetField{field: oxm_field} + end + + def to_binary(%SetField{field: {field, value}}) do + match_bin = + [{field, value}] + |> Openflow.Match.new() + |> Openflow.Match.to_binary() + + <<1::16, _length::16, padded_field::bytes>> = match_bin + patial_len = @set_field_size - 4 + byte_size(padded_field) + padding = Openflow.Utils.padding(patial_len, 8) + length = patial_len + padding + <<25::16, length::16, padded_field::bytes, 0::size(padding)-unit(8)>> + end + + def read(<<25::16, _length::16, match_field_bin::bytes>>) do + <<_class::16, _field::7, _hm::1, flen::8, _rest::bytes>> = match_field_bin + match_len = 4 + 4 + flen + match_bin = <<1::16, match_len::16, match_field_bin::bytes>> + {[field | _], _rest} = Openflow.Match.read(match_bin) + %SetField{field: field} + end +end diff --git a/lib/openflow/actions/set_mpls_ttl.ex b/lib/openflow/actions/set_mpls_ttl.ex new file mode 100644 index 0000000..a82a0ec --- /dev/null +++ b/lib/openflow/actions/set_mpls_ttl.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.SetMplsTtl do + defstruct(ttl: 0) + + alias __MODULE__ + + def ofpat, do: 15 + + def new(ttl) do + %SetMplsTtl{ttl: ttl} + end + + def to_binary(%SetMplsTtl{ttl: ttl}) do + <<15::16, 8::16, ttl::8, 0::size(3)-unit(8)>> + end + + def read(<<15::16, 8::16, ttl::8, _::size(3)-unit(8)>>) do + %SetMplsTtl{ttl: ttl} + end +end diff --git a/lib/openflow/actions/set_nw_ttl.ex b/lib/openflow/actions/set_nw_ttl.ex new file mode 100644 index 0000000..48a296a --- /dev/null +++ b/lib/openflow/actions/set_nw_ttl.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.SetNwTtl do + defstruct(ttl: 0) + + alias __MODULE__ + + def ofpat, do: 23 + + def new(ttl) do + %SetNwTtl{ttl: ttl} + end + + def to_binary(%SetNwTtl{ttl: ttl}) do + <<23::16, 8::16, ttl::8, 0::size(3)-unit(8)>> + end + + def read(<<23::16, 8::16, ttl::8, _::size(3)-unit(8)>>) do + %SetNwTtl{ttl: ttl} + end +end diff --git a/lib/openflow/actions/set_queue.ex b/lib/openflow/actions/set_queue.ex new file mode 100644 index 0000000..001f4ff --- /dev/null +++ b/lib/openflow/actions/set_queue.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Action.SetQueue do + defstruct(id: 0) + + alias __MODULE__ + + def ofpat, do: 21 + + def new(id) do + %SetQueue{id: id} + end + + def to_binary(%SetQueue{id: id}) do + <<21::16, 8::16, id::32>> + end + + def read(<<21::16, 8::16, id::32>>) do + %SetQueue{id: id} + end +end diff --git a/lib/openflow/barrier/reply.ex b/lib/openflow/barrier/reply.ex new file mode 100644 index 0000000..59f7f68 --- /dev/null +++ b/lib/openflow/barrier/reply.ex @@ -0,0 +1,26 @@ +defmodule Openflow.Barrier.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 21 + + def new do + %Reply{} + end + + def read(_) do + %Reply{} + end + + def to_binary(%Reply{}) do + <<>> + end +end diff --git a/lib/openflow/barrier/request.ex b/lib/openflow/barrier/request.ex new file mode 100644 index 0000000..346270c --- /dev/null +++ b/lib/openflow/barrier/request.ex @@ -0,0 +1,26 @@ +defmodule Openflow.Barrier.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 20 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read(_) do + %Request{} + end + + def to_binary(%Request{}) do + <<>> + end +end diff --git a/lib/openflow/buckets.ex b/lib/openflow/buckets.ex new file mode 100644 index 0000000..005db35 --- /dev/null +++ b/lib/openflow/buckets.ex @@ -0,0 +1,71 @@ +defmodule Openflow.Bucket do + defstruct( + weight: 0, + watch_port: 0, + watch_group: 0, + actions: [] + ) + + alias __MODULE__ + + @header_size 16 + + def new(options) do + weight = Keyword.get(options, :weight, 0) + watch_port = Keyword.get(options, :watch_port, :any) + watch_group = Keyword.get(options, :watch_group, :any) + actions = Keyword.get(options, :actions, []) + %Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} + end + + def read(buckets_bin) do + do_read([], buckets_bin) + end + + def to_binary(buckets) do + to_binary("", buckets) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read( + acc, + <> + ) do + actions_len = length - @header_size + <> = binary + watch_port = Openflow.Utils.get_enum(watch_port_int, :openflow13_port_no) + watch_group = Openflow.Utils.get_enum(watch_group_int, :group_id) + actions = Openflow.Action.read(actions_bin) + + bucket = %Bucket{ + weight: weight, + watch_port: watch_port, + watch_group: watch_group, + actions: actions + } + + do_read([bucket | acc], rest) + end + + defp to_binary(acc, []), do: acc + + defp to_binary(acc, [bucket | rest]) do + %Bucket{weight: weight, watch_port: watch_port, watch_group: watch_group, actions: actions} = + bucket + + watch_port_int = Openflow.Utils.get_enum(watch_port, :openflow13_port_no) + watch_group_int = Openflow.Utils.get_enum(watch_group, :group_id) + actions_bin = Openflow.Action.to_binary(actions) + length = byte_size(actions_bin) + @header_size + + bucket_bin = + <> + + to_binary(<>, rest) + end +end diff --git a/lib/openflow/echo.ex b/lib/openflow/echo.ex new file mode 100644 index 0000000..d0cea11 --- /dev/null +++ b/lib/openflow/echo.ex @@ -0,0 +1,2 @@ +defmodule Openflow.Echo do +end diff --git a/lib/openflow/echo/reply.ex b/lib/openflow/echo/reply.ex new file mode 100644 index 0000000..9b0b2d8 --- /dev/null +++ b/lib/openflow/echo/reply.ex @@ -0,0 +1,34 @@ +defmodule Openflow.Echo.Reply do + defstruct( + version: 4, + xid: 0, + data: "", + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 3 + + def new(options) when is_list(options) do + %Reply{ + xid: options[:xid] || 0, + data: options[:data] || "" + } + end + + def new(data) when is_binary(data) do + %Reply{data: data} + end + + def read(data) do + %Reply{data: data} + end + + def to_binary(%Reply{data: data}) do + data + end +end diff --git a/lib/openflow/echo/request.ex b/lib/openflow/echo/request.ex new file mode 100644 index 0000000..a1684d6 --- /dev/null +++ b/lib/openflow/echo/request.ex @@ -0,0 +1,34 @@ +defmodule Openflow.Echo.Request do + defstruct( + version: 4, + xid: 0, + data: "", + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 2 + + def new(options) when is_list(options) do + %Request{ + xid: options[:xid] || 0, + data: options[:data] || "" + } + end + + def new(data) when is_binary(data) do + %Request{data: data} + end + + def read(data) do + %Request{data: data} + end + + def to_binary(%Request{data: data}) do + data + end +end diff --git a/lib/openflow/enum_gen.ex b/lib/openflow/enum_gen.ex new file mode 100644 index 0000000..1c2f023 --- /dev/null +++ b/lib/openflow/enum_gen.ex @@ -0,0 +1,1122 @@ +defmodule Openflow.EnumGen do + import Bitwise + + @enums [ + openflow_codec: [ + {Openflow.Hello, 0}, + {Openflow.ErrorMsg, 1}, + {Openflow.Echo.Request, 2}, + {Openflow.Echo.Reply, 3}, + {Openflow.Experimenter, 4}, + {Openflow.Features.Request, 5}, + {Openflow.Features.Reply, 6}, + {Openflow.GetConfig.Request, 7}, + {Openflow.GetConfig.Reply, 8}, + {Openflow.SetConfig, 9}, + {Openflow.PacketIn, 10}, + {Openflow.FlowRemoved, 11}, + {Openflow.PortStatus, 12}, + {Openflow.PacketOut, 13}, + {Openflow.FlowMod, 14}, + {Openflow.GroupMod, 15}, + {Openflow.PortMod, 16}, + {Openflow.TableMod, 17}, + {Openflow.Multipart.Request, 18}, + {Openflow.Multipart.Reply, 19}, + {Openflow.Barrier.Request, 20}, + {Openflow.Barrier.Reply, 21}, + {Openflow.Role.Request, 24}, + {Openflow.Role.Reply, 25}, + {Openflow.GetAsync.Request, 26}, + {Openflow.GetAsync.Reply, 27}, + {Openflow.SetAsync, 28}, + {Openflow.MeterMod, 29} + ], + experimenter_id: [ + nicira_ext_message: 0x00002320, + onf_ext_message: 0x4F4E4600 + ], + nicira_ext_message: [ + # {Openflow.NxRole.Request, 10}, /* Openflow 1.3 support role request/reply */ + # {Openflow.NxRole.Reply, 11}, + # {Openflow.NxSetFlowFormat, 12}, /* No special reason for implement this struct codec. */ + # {Openflow.NxFlowMod, 13}, /* Prefer use ofp_flow_mod to nx_flow_mod */ + # {Openflow.NxFlowRemoved, 14}, /* Prefer use ofp_flow_removed to nx_flow_removed */ + # {Openflow.NxSetFlowModTableId, 15}, /* OpenFlow 1.3 support multiple flow table. */ + {Openflow.NxSetPacketInFormat, 16}, + # {Openflow.NxPacketIn, 17}, /* No special reason for implement this struct codec. */ + # {Openflow.NxFlowAge, 18}, /* No special reason for implement this struct codec. */ + # {Openflow.NxSetAsyncConfig, 19}, /* Openflow 1.3 support async config. */ + {Openflow.NxSetControllerId, 20}, + {Openflow.NxFlowMonitor.Cancel, 21}, + {Openflow.NxFlowMonitor.Paused, 22}, + {Openflow.NxFlowMonitor.Resumed, 23}, + {Openflow.NxTLVTableMod, 24}, + {Openflow.NxTLVTable.Request, 25}, + {Openflow.NxTLVTable.Reply, 26}, + {Openflow.NxSetAsyncConfig2, 27}, + {Openflow.NxResume, 28}, + {Openflow.NxCtFlushZone, 29}, + {Openflow.NxPacketIn2, 30} + ], + onf_ext_message: [ + {Openflow.OnfBundleControl, 2300}, + {Openflow.OnfBundleAddMessage, 2301} + ], + multipart_request_flags: [ + more: 1 <<< 0 + ], + multipart_reply_flags: [ + more: 1 <<< 0 + ], + multipart_request_codec: [ + {Openflow.Multipart.Desc.Request, 0}, + {Openflow.Multipart.Flow.Request, 1}, + {Openflow.Multipart.Aggregate.Request, 2}, + {Openflow.Multipart.Table.Request, 3}, + {Openflow.Multipart.PortStats.Request, 4}, + {Openflow.Multipart.Queue.Request, 5}, + {Openflow.Multipart.Group.Request, 6}, + {Openflow.Multipart.GroupDesc.Request, 7}, + {Openflow.Multipart.GroupFeatures.Request, 8}, + {Openflow.Multipart.Meter.Request, 9}, + {Openflow.Multipart.MeterConfig.Request, 10}, + {Openflow.Multipart.MeterFeatures.Request, 11}, + {Openflow.Multipart.TableFeatures.Request, 12}, + {Openflow.Multipart.PortDesc.Request, 13}, + {Openflow.Multipart.Experimenter.Request, 0xFFFF} + ], + multipart_reply_codec: [ + {Openflow.Multipart.Desc.Reply, 0}, + {Openflow.Multipart.Flow.Reply, 1}, + {Openflow.Multipart.Aggregate.Reply, 2}, + {Openflow.Multipart.Table.Reply, 3}, + {Openflow.Multipart.PortStats.Reply, 4}, + {Openflow.Multipart.Queue.Reply, 5}, + {Openflow.Multipart.Group.Reply, 6}, + {Openflow.Multipart.GroupDesc.Reply, 7}, + {Openflow.Multipart.GroupFeatures.Reply, 8}, + {Openflow.Multipart.Meter.Reply, 9}, + {Openflow.Multipart.MeterConfig.Reply, 10}, + {Openflow.Multipart.MeterFeatures.Reply, 11}, + {Openflow.Multipart.TableFeatures.Reply, 12}, + {Openflow.Multipart.PortDesc.Reply, 13}, + {Openflow.Multipart.Experimenter.Reply, 0xFFFF} + ], + nicira_ext_stats: [ + {Openflow.Multipart.NxFlow, 0}, + {Openflow.Multipart.NxAggregate, 1}, + {Openflow.Multipart.NxFlowMonitor, 2}, + {Openflow.Multipart.NxIPFIXBridge, 3}, + {Openflow.Multipart.NxIPFIXFlow, 4} + ], + hello_elem: [ + versionbitmap: 1 + ], + error_type: [ + hello_failed: 0, + bad_request: 1, + bad_action: 2, + bad_instruction: 3, + bad_match: 4, + flow_mod_failed: 5, + group_mod_failed: 6, + port_mod_failed: 7, + table_mod_failed: 8, + queue_op_failed: 9, + switch_config_failed: 10, + role_request_failed: 11, + meter_mod_failed: 12, + table_features_failed: 13, + experimenter: 0xFFFF + ], + hello_failed: [ + inconpatible: 0, + eperm: 1 + ], + bad_request: [ + bad_version: 0, + bad_type: 1, + bad_multipart: 2, + bad_experimeter: 3, + bad_exp_type: 4, + eperm: 5, + bad_len: 6, + buffer_empty: 7, + buffer_unknown: 8, + bad_table_id: 9, + is_slave: 10, + bad_port: 11, + bad_packet: 12, + multipart_buffer_overflow: 13 + ], + bad_action: [ + bad_type: 0, + bad_len: 1, + bad_experimeter: 2, + bad_exp_type: 3, + bad_out_port: 4, + bad_argument: 5, + eperm: 6, + too_many: 7, + bad_queue: 8, + bad_out_group: 9, + match_inconsistent: 10, + unsupported_order: 11, + bad_tag: 12, + bad_set_type: 13, + bad_set_len: 14, + bad_set_argument: 15 + ], + bad_instruction: [ + unknown_instruction: 0, + unsupported_instruction: 1, + bad_table_id: 2, + unsupported_metadata: 3, + unsupported_metadata_mask: 4, + bad_experimeter: 5, + bad_exp_type: 6, + bad_len: 7, + eperm: 8 + ], + bad_match: [ + bad_type: 0, + bad_len: 1, + bad_tag: 2, + bad_dl_addr_mask: 3, + bad_nw_addr_mask: 4, + bad_wildcards: 5, + bad_field: 6, + bad_value: 7, + bad_mask: 8, + bad_prereq: 9, + dup_field: 10, + eperm: 11 + ], + flow_mod_failed: [ + unknown: 0, + table_full: 1, + bad_table_id: 2, + overlap: 3, + eperm: 4, + bad_timeout: 5, + bad_command: 6, + bad_flags: 7 + ], + group_mod_failed: [ + group_exists: 0, + invalid_group: 1, + weight_unsupported: 2, + out_of_groups: 3, + ouf_of_buckets: 4, + chaining_unsupported: 5, + watch_unsupported: 6, + loop: 7, + unknown_group: 8, + chained_group: 9, + bad_type: 10, + bad_command: 11, + bad_bucket: 12, + bad_watch: 13, + eperm: 14 + ], + port_mod_failed: [ + bad_port: 0, + bad_hw_addr: 1, + bad_config: 2, + bad_advertise: 3, + eperm: 4 + ], + table_mod_failed: [ + bad_table: 0, + bad_config: 1, + eperm: 2 + ], + queue_op_failed: [ + bad_port: 0, + bad_queue: 1, + eperm: 2 + ], + switch_config_failed: [ + bad_flags: 0, + bad_len: 1, + eperm: 2 + ], + role_request_failed: [ + stale: 0, + unsup: 1, + bad_role: 2 + ], + meter_mod_failed: [ + unknown: 0, + meter_exists: 1, + invalid_meter: 2, + unknown_meter: 3, + bad_command: 4, + bad_flags: 5, + bad_rate: 6, + bad_burst: 7, + bad_band: 8, + bad_band_value: 9, + out_of_meters: 10, + out_of_bands: 11 + ], + table_features_failed: [ + bad_table: 0, + bad_metadata: 1, + bad_type: 2, + bad_len: 3, + bad_argument: 4, + eperm: 5 + ], + switch_capabilities: [ + flow_stats: 1 <<< 0, + table_stats: 1 <<< 1, + port_stats: 1 <<< 2, + group_stats: 1 <<< 3, + ip_reasm: 1 <<< 5, + queue_stats: 1 <<< 6, + arp_match_ip: 1 <<< 7, + port_blocked: 1 <<< 8 + ], + config_flags: [ + drop: 1 <<< 0, + reasm: 1 <<< 1 + ], + controller_max_len: [ + max: 0xFFE5, + no_buffer: 0xFFFF + ], + experimenter_oxm_vendors: [ + nicira_ext_match: 0x00002320, + hp_ext_match: 0x00002428, + onf_ext_match: 0x4F4E4600 + ], + match_type: [ + standard: 0, + oxm: 1 + ], + oxm_class: [ + nxm_0: 0x0000, + nxm_1: 0x0001, + openflow_basic: 0x8000, + packet_register: 0x8001, + experimenter: 0xFFFF + ], + nxm_0: [ + nx_in_port: 0, + nx_eth_dst: 1, + nx_eth_src: 2, + nx_eth_type: 3, + nx_vlan_tci: 4, + nx_ip_tos: 5, + nx_ip_proto: 6, + nx_ipv4_src: 7, + nx_ipv4_dst: 8, + nx_tcp_src: 9, + nx_tcp_dst: 10, + nx_udp_src: 11, + nx_udp_dst: 12, + nx_icmpv4_type: 13, + nx_icmpv4_code: 14, + nx_arp_op: 15, + nx_arp_spa: 16, + nx_arp_tpa: 17, + nx_tcp_flags: 34 + ], + nxm_1: [ + reg0: 0, + reg1: 1, + reg2: 2, + reg3: 3, + reg4: 4, + reg5: 5, + reg6: 6, + reg7: 7, + reg8: 8, + reg9: 9, + reg10: 10, + reg11: 11, + reg12: 12, + reg13: 13, + reg14: 14, + reg15: 15, + tun_id: 16, + nx_arp_sha: 17, + nx_arp_tha: 18, + nx_ipv6_src: 19, + nx_ipv6_dst: 20, + nx_icmpv6_type: 21, + nx_icmpv6_code: 22, + nx_ipv6_nd_target: 23, + nx_ipv6_nd_sll: 24, + nx_ipv6_nd_tll: 25, + nx_ip_frag: 26, + nx_ipv6_label: 27, + nx_ip_ecn: 28, + nx_ip_ttl: 29, + nx_mpls_ttl: 30, + tun_src: 31, + tun_dst: 32, + pkt_mark: 33, + dp_hash: 35, + recirc_id: 36, + conj_id: 37, + tun_gbp_id: 38, + tun_gbp_flags: 39, + tun_metadata0: 40, + tun_metadata1: 41, + tun_metadata2: 42, + tun_metadata3: 43, + tun_metadata4: 44, + tun_metadata5: 45, + tun_metadata6: 46, + tun_metadata7: 47, + tun_metadata8: 48, + tun_metadata9: 49, + tun_metadata10: 50, + tun_metadata11: 51, + tun_metadata12: 52, + tun_metadata13: 53, + tun_metadata14: 54, + tun_metadata15: 55, + tun_metadata16: 56, + tun_metadata17: 57, + tun_metadata18: 58, + tun_metadata19: 59, + tun_metadata20: 60, + tun_metadata21: 61, + tun_metadata22: 62, + tun_metadata23: 63, + tun_metadata24: 64, + tun_metadata25: 65, + tun_metadata26: 66, + tun_metadata27: 67, + tun_metadata28: 68, + tun_metadata29: 69, + tun_metadata30: 70, + tun_metadata31: 71, + tun_metadata32: 72, + tun_metadata33: 73, + tun_metadata34: 74, + tun_metadata35: 75, + tun_metadata36: 76, + tun_metadata37: 77, + tun_metadata38: 78, + tun_metadata39: 79, + tun_metadata40: 80, + tun_metadata41: 81, + tun_metadata42: 82, + tun_metadata43: 83, + tun_metadata44: 84, + tun_metadata45: 85, + tun_metadata46: 86, + tun_metadata47: 87, + tun_metadata48: 88, + tun_metadata49: 89, + tun_metadata50: 90, + tun_metadata51: 91, + tun_metadata52: 92, + tun_metadata53: 93, + tun_metadata54: 94, + tun_metadata55: 95, + tun_metadata56: 96, + tun_metadata57: 97, + tun_metadata58: 98, + tun_metadata59: 99, + tun_metadata60: 100, + tun_metadata61: 101, + tun_metadata62: 102, + tun_metadata63: 103, + tun_flags: 104, + ct_state: 105, + ct_zone: 106, + ct_mark: 107, + ct_label: 108, + tun_ipv6_src: 109, + tun_ipv6_dst: 110, + xxreg0: 111, + xxreg1: 112, + xxreg2: 113, + xxreg3: 114, + xxreg4: 115, + xxreg5: 116, + xxreg6: 117, + xxreg7: 118, + ct_nw_proto: 119, + ct_nw_src: 120, + ct_nw_dst: 121, + ct_ipv6_src: 122, + ct_ipv6_dst: 123, + ct_tp_src: 124, + ct_tp_dst: 125 + ], + openflow_basic: [ + in_port: 0, + in_phy_port: 1, + metadata: 2, + eth_dst: 3, + eth_src: 4, + eth_type: 5, + vlan_vid: 6, + vlan_pcp: 7, + ip_dscp: 8, + ip_ecn: 9, + ip_proto: 10, + ipv4_src: 11, + ipv4_dst: 12, + tcp_src: 13, + tcp_dst: 14, + udp_src: 15, + udp_dst: 16, + sctp_src: 17, + sctp_dst: 18, + icmpv4_type: 19, + icmpv4_code: 20, + arp_op: 21, + arp_spa: 22, + arp_tpa: 23, + arp_sha: 24, + arp_tha: 25, + ipv6_src: 26, + ipv6_dst: 27, + ipv6_flabel: 28, + icmpv6_type: 29, + icmpv6_code: 30, + ipv6_nd_target: 31, + ipv6_nd_sll: 32, + ipv6_nd_tll: 33, + mpls_label: 34, + mpls_tc: 35, + mpls_bos: 36, + pbb_isid: 37, + tunnel_id: 38, + ipv6_exthdr: 39, + + # Lagopus extended match fields + pbb_uca: 41, + packet_type: 42, + gre_flags: 43, + gre_ver: 44, + gre_protocol: 45, + gre_key: 46, + gre_seqnum: 47, + lisp_flags: 48, + lisp_nonce: 49, + lisp_id: 50, + vxlan_flags: 51, + vxlan_vni: 52, + mpls_data_first_nibble: 53, + mpls_ach_version: 54, + mpls_ach_channel: 55, + mpls_pw_metadata: 56, + mpls_cw_flags: 57, + mpls_cw_fragment: 58, + mpls_cw_len: 59, + mpls_cw_seq_num: 60, + gtpu_flags: 61, + gtpu_ver: 62, + gtpu_msg_type: 63, + gtpu_teid: 64, + gtpu_extn_hdr: 65, + gtpu_extn_udp_port: 66, + gtpu_extn_sci: 67 + ], + vlan_id: [ + present: 0x1000, + none: 0x0000 + ], + ipv6exthdr_flags: [ + nonext: 1 <<< 0, + esp: 1 <<< 1, + auth: 1 <<< 2, + dest: 1 <<< 3, + frag: 1 <<< 4, + router: 1 <<< 5, + hop: 1 <<< 6, + unrep: 1 <<< 7, + unseq: 1 <<< 8 + ], + tcp_flags: [ + fin: 1 <<< 0, + syn: 1 <<< 1, + rst: 1 <<< 2, + psh: 1 <<< 3, + ack: 1 <<< 4, + urg: 1 <<< 5, + ece: 1 <<< 6, + cwr: 1 <<< 7, + ns: 1 <<< 8 + ], + ct_state_flags: [ + # Beginning of a new connection. + new: 1 <<< 0, + # Part of an existing connection. + est: 1 <<< 1, + # Related to an established connection. + rel: 1 <<< 2, + # Flow is in the reply direction. + rep: 1 <<< 3, + # Could not track connection. + inv: 1 <<< 4, + # Conntrack has occurred. + trk: 1 <<< 5, + # Packet's source address/port was mangled by NAT. + snat: 1 <<< 6, + # Packet's destination address/port was mangled by NAT. + dnat: 1 <<< 7 + ], + packet_register: [ + xreg0: 0, + xreg1: 1, + xreg2: 2, + xreg3: 3, + xreg4: 4, + xreg5: 5, + xreg6: 6, + xreg7: 7 + ], + nicira_ext_match: [ + nsh_flags: 1, + nsh_mdtype: 2, + nsh_np: 3, + nsh_spi: 4, + nsh_si: 5, + nsh_c1: 6, + nsh_c2: 7, + nsh_c3: 8, + nsh_c4: 9 + ], + hp_ext_match: [ + hp_udp_src_port_range: 0, + hp_udp_dst_port_range: 1, + hp_tcp_src_port_range: 2, + hp_tcp_dst_port_range: 3, + hp_tcp_flags: 4, + hp_custom_1: 5, + hp_custom_2: 6, + hp_custom_3: 7, + hp_custom_4: 8 + ], + hp_custom_match_type: [ + l2_start: 1, + l3_start: 2, + l4_start: 3 + ], + onf_ext_match: [ + onf_tcp_flags: 42, + onf_actset_output: 43, + onf_pbb_uca: 2560 + ], + buffer_id: [ + no_buffer: 0xFFFFFFFF + ], + port_config: [ + port_down: 1 <<< 0, + no_receive: 1 <<< 2, + no_forward: 1 <<< 5, + no_packet_in: 1 <<< 6 + ], + port_state: [ + link_down: 1 <<< 0, + blocked: 1 <<< 1, + live: 1 <<< 2 + ], + port_features: [ + {:"10mb_hd", 1 <<< 0}, + {:"10mb_fd", 1 <<< 1}, + {:"100mb_hd", 1 <<< 2}, + {:"100mb_fd", 1 <<< 3}, + {:"1gb_hd", 1 <<< 4}, + {:"1gb_fd", 1 <<< 5}, + {:"10gb_fd", 1 <<< 6}, + {:"40gb_fd", 1 <<< 7}, + {:"100gb_fd", 1 <<< 8}, + {:"1tb_fd", 1 <<< 9}, + {:other, 1 <<< 10}, + {:copper, 1 <<< 11}, + {:fiber, 1 <<< 12}, + {:autoneg, 1 <<< 13}, + {:pause, 1 <<< 14}, + {:pause_asym, 1 <<< 15} + ], + openflow10_port_no: [ + max: 0xFF00, + in_port: 0xFFF8, + table: 0xFFF9, + normal: 0xFFFA, + flood: 0xFFFB, + all: 0xFFFC, + controller: 0xFFFD, + local: 0xFFFE, + none: 0xFFFF + ], + openflow13_port_no: [ + max: 0xFFFFFF00, + in_port: 0xFFFFFFF8, + table: 0xFFFFFFF9, + normal: 0xFFFFFFFA, + flood: 0xFFFFFFFB, + all: 0xFFFFFFFC, + controller: 0xFFFFFFFD, + local: 0xFFFFFFFE, + any: 0xFFFFFFFF + ], + packet_in_reason: [ + no_match: 0, + action: 1, + invalid_ttl: 2, + action_set: 3, + group: 4, + packet_out: 5 + ], + flow_mod_command: [ + add: 0, + modify: 1, + modify_strict: 2, + delete: 3, + delete_strict: 4 + ], + flow_mod_flags: [ + send_flow_rem: 1 <<< 0, + check_overlap: 1 <<< 1, + reset_counts: 1 <<< 2, + no_packet_counts: 1 <<< 3, + no_byte_counts: 1 <<< 4 + ], + flow_removed_reason: [ + idle_timeout: 0, + hard_timeout: 1, + delete: 2, + group_delete: 3, + meter_delete: 4, + eviction: 5 + ], + port_reason: [ + add: 0, + delete: 1, + modify: 2 + ], + group_mod_command: [ + add: 0, + modify: 1, + delete: 2 + ], + group_type: [ + all: 0, + select: 1, + indirect: 2, + fast_failover: 3 + ], + group_id: [ + max: 0xFFFFFF00, + all: 0xFFFFFFFC, + any: 0xFFFFFFFF + ], + group_capabilities: [ + select_weight: 1 <<< 0, + select_liveness: 1 <<< 1, + chaining: 1 <<< 2, + chaining_checks: 1 <<< 3 + ], + table_id: [ + max: 0xFE, + all: 0xFF + ], + queue_id: [ + all: 0xFFFFFFFF + ], + meter_mod_command: [ + add: 0, + modify: 1, + delete: 2 + ], + meter_id: [ + max: 0xFFFF0000, + slowpath: 0xFFFFFFFD, + controller: 0xFFFFFFFE, + all: 0xFFFFFFFF + ], + meter_flags: [ + kbps: 1 <<< 0, + pktps: 1 <<< 1, + burst: 1 <<< 2, + stats: 1 <<< 3 + ], + meter_band_type: [ + {Openflow.MeterBand.Drop, 1}, + {Openflow.MeterBand.Remark, 2}, + {Openflow.MeterBand.Experimenter, 0xFFFF} + ], + table_config: [ + table_miss_controller: 0 <<< 0, + table_miss_continue: 1 <<< 0, + table_miss_drop: 2 <<< 0, + table_miss_mask: 3 <<< 0, + eviction: 1 <<< 2, + vacancy_events: 1 <<< 3 + ], + action_type: [ + {Openflow.Action.Output, 0}, + {Openflow.Action.CopyTtlOut, 11}, + {Openflow.Action.CopyTtlIn, 12}, + {Openflow.Action.SetMplsTtl, 15}, + {Openflow.Action.DecMplsTtl, 16}, + {Openflow.Action.PushVlan, 17}, + {Openflow.Action.PopVlan, 18}, + {Openflow.Action.PushMpls, 19}, + {Openflow.Action.PopMpls, 20}, + {Openflow.Action.SetQueue, 21}, + {Openflow.Action.Group, 22}, + {Openflow.Action.SetNwTtl, 23}, + {Openflow.Action.DecNwTtl, 24}, + {Openflow.Action.SetField, 25}, + {Openflow.Action.PushPbb, 26}, + {Openflow.Action.PopPbb, 27}, + {Openflow.Action.Encap, 28}, + {Openflow.Action.Decap, 29}, + {Openflow.Action.SetSequence, 30}, + {Openflow.Action.ValidateSequence, 31}, + {Openflow.Action.Experimenter, 0xFFFF} + ], + action_vendor: [ + nicira_ext_action: 0x00002320, + onf_ext_action: 0x4F4E4600 + ], + onf_ext_action: [ + {Openflow.Action.OnfCopyField, 3200} + ], + nicira_ext_action: [ + {Openflow.Action.NxResubmit, 1}, + {Openflow.Action.NxSetTunnel, 2}, + {Openflow.Action.NxSetQueue, 4}, + {Openflow.Action.NxPopQueue, 5}, + {Openflow.Action.NxRegMove, 6}, + {Openflow.Action.NxRegLoad, 7}, + {Openflow.Action.NxNote, 8}, + {Openflow.Action.NxSetTunnel64, 9}, + {Openflow.Action.NxMultipath, 10}, + {Openflow.Action.NxBundle, 12}, + {Openflow.Action.NxBundleLoad, 13}, + {Openflow.Action.NxResubmitTable, 14}, + {Openflow.Action.NxOutputReg, 15}, + {Openflow.Action.NxLearn, 16}, + {Openflow.Action.NxExit, 17}, + {Openflow.Action.NxDecTtl, 18}, + {Openflow.Action.NxFinTimeout, 19}, + {Openflow.Action.NxController, 20}, + {Openflow.Action.NxDecTtlCntIds, 21}, + {Openflow.Action.NxWriteMetadata, 22}, + {Openflow.Action.NxPushMpls, 23}, + {Openflow.Action.NxPopMpls, 24}, + {Openflow.Action.NxSetMplsTtl, 25}, + {Openflow.Action.NxDecMplsTtl, 26}, + {Openflow.Action.NxStackPush, 27}, + {Openflow.Action.NxStackPop, 28}, + {Openflow.Action.NxSample, 29}, + {Openflow.Action.NxSetMplsLabel, 30}, + {Openflow.Action.NxSetMplsTc, 31}, + {Openflow.Action.NxOutputReg2, 32}, + {Openflow.Action.NxRegLoad2, 33}, + {Openflow.Action.NxConjunction, 34}, + {Openflow.Action.NxConntrack, 35}, + {Openflow.Action.NxNat, 36}, + {Openflow.Action.NxController2, 37}, + {Openflow.Action.NxSample2, 38}, + {Openflow.Action.NxOutputTrunc, 39}, + {Openflow.Action.NxGroup, 40}, + {Openflow.Action.NxSample3, 41}, + {Openflow.Action.NxClone, 42}, + {Openflow.Action.NxCtClear, 43}, + {Openflow.Action.NxResubmitTableCt, 44}, + {Openflow.Action.NxLearn2, 45}, + {Openflow.Action.NxEncap, 46}, + {Openflow.Action.NxDecap, 47}, + {Openflow.Action.NxDebugRecirc, 0xFF} + ], + nx_mp_algorithm: [ + modulo_n: 0, + hash_threshold: 1, + highest_random_weight: 2, + iterative_hash: 3 + ], + nx_hash_fields: [ + eth_src: 0, + symmetric_l4: 1, + symmetric_l3l4: 2, + symmetric_l3l4_udp: 3, + nw_src: 4, + nw_dst: 5 + ], + nx_bd_algorithm: [ + active_backup: 0, + highest_random_weight: 1 + ], + nx_learn_flag: [ + send_flow_rem: 1 <<< 0, + delete_learned: 1 <<< 1, + write_result: 1 <<< 2 + ], + nx_conntrack_flags: [ + commit: 1 <<< 0, + force: 1 <<< 1 + ], + nx_nat_flags: [ + src: 1 <<< 0, + dst: 1 <<< 1, + persistent: 1 <<< 2, + protocol_hash: 1 <<< 3, + protocol_random: 1 <<< 4 + ], + nx_nat_range: [ + ipv4_min: 1 <<< 0, + ipv4_max: 1 <<< 1, + ipv6_min: 1 <<< 2, + ipv6_max: 1 <<< 3, + proto_min: 1 <<< 4, + proto_max: 1 <<< 5 + ], + nx_action_controller2_prop_type: [ + max_len: 0, + controller_id: 1, + reason: 2, + userdata: 3, + pause: 4 + ], + nx_action_sample_direction: [ + default: 0, + ingress: 1, + egress: 2 + ], + nx_flow_spec_type: [ + {Openflow.Action.NxFlowSpecMatch, 0}, + {Openflow.Action.NxFlowSpecLoad, 1}, + {Openflow.Action.NxFlowSpecOutput, 2} + ], + instruction_type: [ + {Openflow.Instruction.GotoTable, 1}, + {Openflow.Instruction.WriteMetadata, 2}, + {Openflow.Instruction.WriteActions, 3}, + {Openflow.Instruction.ApplyActions, 4}, + {Openflow.Instruction.ClearActions, 5}, + {Openflow.Instruction.Meter, 6}, + {Openflow.Instruction.Experimenter, 0xFFFF} + ], + controller_role: [ + nochange: 0, + equal: 1, + master: 2, + slave: 3 + ], + nx_role: [ + other: 0, + master: 1, + slave: 2 + ], + packet_in_format: [ + standard: 0, + nxt_packet_in: 1, + nxt_packet_in2: 2 + ], + flow_format: [ + openflow10: 0, + nxm: 1 + ], + packet_in2_prop_type: [ + packet: 0, + full_len: 1, + buffer_id: 2, + table_id: 3, + cookie: 4, + reason: 5, + metadata: 6, + userdata: 7, + continuation: 8 + ], + continuation_prop_type: [ + bridge: 0x8000, + stack: 0x8001, + mirrors: 0x8002, + conntracked: 0x8003, + table_id: 0x8004, + cookie: 0x8005, + actions: 0x8006, + action_set: 0x8007 + ], + flow_monitor_flag: [ + initial: 1 <<< 0, + add: 1 <<< 1, + delete: 1 <<< 2, + modify: 1 <<< 3, + actions: 1 <<< 4, + own: 1 <<< 5 + ], + flow_update_event: [ + added: 0, + deleted: 1, + modified: 2, + abbrev: 3 + ], + tlv_table_mod_command: [ + add: 0, + delete: 1, + clear: 2 + ], + table_feature_prop_type: [ + instructions: 0, + instructions_miss: 1, + next_tables: 2, + next_tables_miss: 3, + write_actions: 4, + write_actions_miss: 5, + apply_actions: 6, + apply_actions_miss: 7, + match: 8, + wildcards: 10, + write_setfield: 12, + write_setfield_miss: 13, + apply_setfield: 14, + apply_setfield_miss: 15, + experimenter: 0xFFFE, + experimenter_miss: 0xFFFF + ] + ] + + def main(_) do + File.write( + "lib/openflow/enums.ex", + """ + defmodule Openflow.Enums do + @moduledoc "auto generated code"\n + """, + [:binary] + ) + + for {enum_name, enum_def} <- @enums do + to_int_fn_name = :"#{enum_name}_to_int" + + for {key, _value} <- enum_def do + File.write( + "lib/openflow/enums.ex", + """ + def to_int(#{inspect(key)}, :#{enum_name}) do + #{to_int_fn_name}(#{inspect(key)}) + catch + _class, _reason -> #{inspect(key)} + end\n + """, + [:append, :binary] + ) + end + + File.write( + "lib/openflow/enums.ex", + """ + def to_int(_int, :#{enum_name}) do + throw(:bad_enum) + end\n + """, + [:append, :binary] + ) + end + + for {enum_name, enum_def} <- @enums do + to_atom_fn_name = :"#{enum_name}_to_atom" + + for {_key, value} <- enum_def do + File.write( + "lib/openflow/enums.ex", + """ + def to_atom(#{inspect(value, base: :hex)}, :#{enum_name}) do + #{to_atom_fn_name}(#{inspect(value, base: :hex)}) + catch + _class, _reason -> #{value} + end\n + """, + [:append, :binary] + ) + end + + File.write( + "lib/openflow/enums.ex", + """ + def to_atom(_, :#{enum_name}) do + throw(:bad_enum) + end\n + """, + [:append, :binary] + ) + end + + for {enum_name, enum_def} <- @enums do + to_int_fn_name = :"#{enum_name}_to_int" + to_atom_fn_name = :"#{enum_name}_to_atom" + + for {key, value} <- enum_def do + File.write( + "lib/openflow/enums.ex", + " def #{to_int_fn_name}(#{inspect(key)}), do: #{inspect(value, base: :hex)}\n", + [ + :append, + :binary + ] + ) + end + + File.write("lib/openflow/enums.ex", " def #{to_int_fn_name}(_), do: throw(:bad_enum)\n", [ + :append, + :binary + ]) + + for {key, value} <- enum_def do + File.write( + "lib/openflow/enums.ex", + " def #{to_atom_fn_name}(#{inspect(value, base: :hex)}), do: #{inspect(key)}\n", + [ + :append, + :binary + ] + ) + end + + File.write("lib/openflow/enums.ex", " def #{to_atom_fn_name}(_), do: throw(:bad_enum)\n", [ + :append, + :binary + ]) + end + + for {enum_name, _enum_def} <- @enums do + File.write( + "lib/openflow/enums.ex", + """ + def int_to_flags(int, :#{enum_name}) do + Openflow.Utils.int_to_flags([], int, enum_of(:#{enum_name})) + end\n + """, + [:append, :binary] + ) + end + + for {enum_name, _enum_def} <- @enums do + File.write( + "lib/openflow/enums.ex", + """ + def flags_to_int(flags, :#{enum_name}) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:#{enum_name})) + end\n + """, + [:append, :binary] + ) + end + + for {enum_name, enum_def} <- @enums do + File.write( + "lib/openflow/enums.ex", + " defp enum_of(:#{enum_name}), do: #{inspect(enum_def, pretty: true, limit: 100_000)}\n", + [:append, :binary] + ) + end + + File.write("lib/openflow/enums.ex", "end", [:append, :binary]) + end +end diff --git a/lib/openflow/enums.ex b/lib/openflow/enums.ex new file mode 100644 index 0000000..430fffa --- /dev/null +++ b/lib/openflow/enums.ex @@ -0,0 +1,13393 @@ +defmodule Openflow.Enums do + @moduledoc "auto generated code" + + def to_int(Openflow.Hello, :openflow_codec) do + openflow_codec_to_int(Openflow.Hello) + catch + _class, _reason -> Openflow.Hello + end + + def to_int(Openflow.ErrorMsg, :openflow_codec) do + openflow_codec_to_int(Openflow.ErrorMsg) + catch + _class, _reason -> Openflow.ErrorMsg + end + + def to_int(Openflow.Echo.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.Echo.Request) + catch + _class, _reason -> Openflow.Echo.Request + end + + def to_int(Openflow.Echo.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.Echo.Reply) + catch + _class, _reason -> Openflow.Echo.Reply + end + + def to_int(Openflow.Experimenter, :openflow_codec) do + openflow_codec_to_int(Openflow.Experimenter) + catch + _class, _reason -> Openflow.Experimenter + end + + def to_int(Openflow.Features.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.Features.Request) + catch + _class, _reason -> Openflow.Features.Request + end + + def to_int(Openflow.Features.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.Features.Reply) + catch + _class, _reason -> Openflow.Features.Reply + end + + def to_int(Openflow.GetConfig.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.GetConfig.Request) + catch + _class, _reason -> Openflow.GetConfig.Request + end + + def to_int(Openflow.GetConfig.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.GetConfig.Reply) + catch + _class, _reason -> Openflow.GetConfig.Reply + end + + def to_int(Openflow.SetConfig, :openflow_codec) do + openflow_codec_to_int(Openflow.SetConfig) + catch + _class, _reason -> Openflow.SetConfig + end + + def to_int(Openflow.PacketIn, :openflow_codec) do + openflow_codec_to_int(Openflow.PacketIn) + catch + _class, _reason -> Openflow.PacketIn + end + + def to_int(Openflow.FlowRemoved, :openflow_codec) do + openflow_codec_to_int(Openflow.FlowRemoved) + catch + _class, _reason -> Openflow.FlowRemoved + end + + def to_int(Openflow.PortStatus, :openflow_codec) do + openflow_codec_to_int(Openflow.PortStatus) + catch + _class, _reason -> Openflow.PortStatus + end + + def to_int(Openflow.PacketOut, :openflow_codec) do + openflow_codec_to_int(Openflow.PacketOut) + catch + _class, _reason -> Openflow.PacketOut + end + + def to_int(Openflow.FlowMod, :openflow_codec) do + openflow_codec_to_int(Openflow.FlowMod) + catch + _class, _reason -> Openflow.FlowMod + end + + def to_int(Openflow.GroupMod, :openflow_codec) do + openflow_codec_to_int(Openflow.GroupMod) + catch + _class, _reason -> Openflow.GroupMod + end + + def to_int(Openflow.PortMod, :openflow_codec) do + openflow_codec_to_int(Openflow.PortMod) + catch + _class, _reason -> Openflow.PortMod + end + + def to_int(Openflow.TableMod, :openflow_codec) do + openflow_codec_to_int(Openflow.TableMod) + catch + _class, _reason -> Openflow.TableMod + end + + def to_int(Openflow.Multipart.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.Multipart.Request) + catch + _class, _reason -> Openflow.Multipart.Request + end + + def to_int(Openflow.Multipart.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.Multipart.Reply) + catch + _class, _reason -> Openflow.Multipart.Reply + end + + def to_int(Openflow.Barrier.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.Barrier.Request) + catch + _class, _reason -> Openflow.Barrier.Request + end + + def to_int(Openflow.Barrier.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.Barrier.Reply) + catch + _class, _reason -> Openflow.Barrier.Reply + end + + def to_int(Openflow.Role.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.Role.Request) + catch + _class, _reason -> Openflow.Role.Request + end + + def to_int(Openflow.Role.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.Role.Reply) + catch + _class, _reason -> Openflow.Role.Reply + end + + def to_int(Openflow.GetAsync.Request, :openflow_codec) do + openflow_codec_to_int(Openflow.GetAsync.Request) + catch + _class, _reason -> Openflow.GetAsync.Request + end + + def to_int(Openflow.GetAsync.Reply, :openflow_codec) do + openflow_codec_to_int(Openflow.GetAsync.Reply) + catch + _class, _reason -> Openflow.GetAsync.Reply + end + + def to_int(Openflow.SetAsync, :openflow_codec) do + openflow_codec_to_int(Openflow.SetAsync) + catch + _class, _reason -> Openflow.SetAsync + end + + def to_int(Openflow.MeterMod, :openflow_codec) do + openflow_codec_to_int(Openflow.MeterMod) + catch + _class, _reason -> Openflow.MeterMod + end + + def to_int(_int, :openflow_codec) do + throw(:bad_enum) + end + + def to_int(:nicira_ext_message, :experimenter_id) do + experimenter_id_to_int(:nicira_ext_message) + catch + _class, _reason -> :nicira_ext_message + end + + def to_int(:onf_ext_message, :experimenter_id) do + experimenter_id_to_int(:onf_ext_message) + catch + _class, _reason -> :onf_ext_message + end + + def to_int(_int, :experimenter_id) do + throw(:bad_enum) + end + + def to_int(Openflow.NxSetPacketInFormat, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxSetPacketInFormat) + catch + _class, _reason -> Openflow.NxSetPacketInFormat + end + + def to_int(Openflow.NxSetControllerId, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxSetControllerId) + catch + _class, _reason -> Openflow.NxSetControllerId + end + + def to_int(Openflow.NxFlowMonitor.Cancel, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxFlowMonitor.Cancel) + catch + _class, _reason -> Openflow.NxFlowMonitor.Cancel + end + + def to_int(Openflow.NxFlowMonitor.Paused, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxFlowMonitor.Paused) + catch + _class, _reason -> Openflow.NxFlowMonitor.Paused + end + + def to_int(Openflow.NxFlowMonitor.Resumed, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxFlowMonitor.Resumed) + catch + _class, _reason -> Openflow.NxFlowMonitor.Resumed + end + + def to_int(Openflow.NxTLVTableMod, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxTLVTableMod) + catch + _class, _reason -> Openflow.NxTLVTableMod + end + + def to_int(Openflow.NxTLVTable.Request, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxTLVTable.Request) + catch + _class, _reason -> Openflow.NxTLVTable.Request + end + + def to_int(Openflow.NxTLVTable.Reply, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxTLVTable.Reply) + catch + _class, _reason -> Openflow.NxTLVTable.Reply + end + + def to_int(Openflow.NxSetAsyncConfig2, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxSetAsyncConfig2) + catch + _class, _reason -> Openflow.NxSetAsyncConfig2 + end + + def to_int(Openflow.NxResume, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxResume) + catch + _class, _reason -> Openflow.NxResume + end + + def to_int(Openflow.NxCtFlushZone, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxCtFlushZone) + catch + _class, _reason -> Openflow.NxCtFlushZone + end + + def to_int(Openflow.NxPacketIn2, :nicira_ext_message) do + nicira_ext_message_to_int(Openflow.NxPacketIn2) + catch + _class, _reason -> Openflow.NxPacketIn2 + end + + def to_int(_int, :nicira_ext_message) do + throw(:bad_enum) + end + + def to_int(Openflow.OnfBundleControl, :onf_ext_message) do + onf_ext_message_to_int(Openflow.OnfBundleControl) + catch + _class, _reason -> Openflow.OnfBundleControl + end + + def to_int(Openflow.OnfBundleAddMessage, :onf_ext_message) do + onf_ext_message_to_int(Openflow.OnfBundleAddMessage) + catch + _class, _reason -> Openflow.OnfBundleAddMessage + end + + def to_int(_int, :onf_ext_message) do + throw(:bad_enum) + end + + def to_int(:more, :multipart_request_flags) do + multipart_request_flags_to_int(:more) + catch + _class, _reason -> :more + end + + def to_int(_int, :multipart_request_flags) do + throw(:bad_enum) + end + + def to_int(:more, :multipart_reply_flags) do + multipart_reply_flags_to_int(:more) + catch + _class, _reason -> :more + end + + def to_int(_int, :multipart_reply_flags) do + throw(:bad_enum) + end + + def to_int(Openflow.Multipart.Desc.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Desc.Request) + catch + _class, _reason -> Openflow.Multipart.Desc.Request + end + + def to_int(Openflow.Multipart.Flow.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Flow.Request) + catch + _class, _reason -> Openflow.Multipart.Flow.Request + end + + def to_int(Openflow.Multipart.Aggregate.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Aggregate.Request) + catch + _class, _reason -> Openflow.Multipart.Aggregate.Request + end + + def to_int(Openflow.Multipart.Table.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Table.Request) + catch + _class, _reason -> Openflow.Multipart.Table.Request + end + + def to_int(Openflow.Multipart.PortStats.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.PortStats.Request) + catch + _class, _reason -> Openflow.Multipart.PortStats.Request + end + + def to_int(Openflow.Multipart.Queue.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Queue.Request) + catch + _class, _reason -> Openflow.Multipart.Queue.Request + end + + def to_int(Openflow.Multipart.Group.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Group.Request) + catch + _class, _reason -> Openflow.Multipart.Group.Request + end + + def to_int(Openflow.Multipart.GroupDesc.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.GroupDesc.Request) + catch + _class, _reason -> Openflow.Multipart.GroupDesc.Request + end + + def to_int(Openflow.Multipart.GroupFeatures.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.GroupFeatures.Request) + catch + _class, _reason -> Openflow.Multipart.GroupFeatures.Request + end + + def to_int(Openflow.Multipart.Meter.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Meter.Request) + catch + _class, _reason -> Openflow.Multipart.Meter.Request + end + + def to_int(Openflow.Multipart.MeterConfig.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.MeterConfig.Request) + catch + _class, _reason -> Openflow.Multipart.MeterConfig.Request + end + + def to_int(Openflow.Multipart.MeterFeatures.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.MeterFeatures.Request) + catch + _class, _reason -> Openflow.Multipart.MeterFeatures.Request + end + + def to_int(Openflow.Multipart.TableFeatures.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.TableFeatures.Request) + catch + _class, _reason -> Openflow.Multipart.TableFeatures.Request + end + + def to_int(Openflow.Multipart.PortDesc.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.PortDesc.Request) + catch + _class, _reason -> Openflow.Multipart.PortDesc.Request + end + + def to_int(Openflow.Multipart.Experimenter.Request, :multipart_request_codec) do + multipart_request_codec_to_int(Openflow.Multipart.Experimenter.Request) + catch + _class, _reason -> Openflow.Multipart.Experimenter.Request + end + + def to_int(_int, :multipart_request_codec) do + throw(:bad_enum) + end + + def to_int(Openflow.Multipart.Desc.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Desc.Reply) + catch + _class, _reason -> Openflow.Multipart.Desc.Reply + end + + def to_int(Openflow.Multipart.Flow.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Flow.Reply) + catch + _class, _reason -> Openflow.Multipart.Flow.Reply + end + + def to_int(Openflow.Multipart.Aggregate.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Aggregate.Reply) + catch + _class, _reason -> Openflow.Multipart.Aggregate.Reply + end + + def to_int(Openflow.Multipart.Table.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Table.Reply) + catch + _class, _reason -> Openflow.Multipart.Table.Reply + end + + def to_int(Openflow.Multipart.PortStats.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.PortStats.Reply) + catch + _class, _reason -> Openflow.Multipart.PortStats.Reply + end + + def to_int(Openflow.Multipart.Queue.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Queue.Reply) + catch + _class, _reason -> Openflow.Multipart.Queue.Reply + end + + def to_int(Openflow.Multipart.Group.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Group.Reply) + catch + _class, _reason -> Openflow.Multipart.Group.Reply + end + + def to_int(Openflow.Multipart.GroupDesc.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.GroupDesc.Reply) + catch + _class, _reason -> Openflow.Multipart.GroupDesc.Reply + end + + def to_int(Openflow.Multipart.GroupFeatures.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.GroupFeatures.Reply) + catch + _class, _reason -> Openflow.Multipart.GroupFeatures.Reply + end + + def to_int(Openflow.Multipart.Meter.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Meter.Reply) + catch + _class, _reason -> Openflow.Multipart.Meter.Reply + end + + def to_int(Openflow.Multipart.MeterConfig.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.MeterConfig.Reply) + catch + _class, _reason -> Openflow.Multipart.MeterConfig.Reply + end + + def to_int(Openflow.Multipart.MeterFeatures.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.MeterFeatures.Reply) + catch + _class, _reason -> Openflow.Multipart.MeterFeatures.Reply + end + + def to_int(Openflow.Multipart.TableFeatures.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.TableFeatures.Reply) + catch + _class, _reason -> Openflow.Multipart.TableFeatures.Reply + end + + def to_int(Openflow.Multipart.PortDesc.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.PortDesc.Reply) + catch + _class, _reason -> Openflow.Multipart.PortDesc.Reply + end + + def to_int(Openflow.Multipart.Experimenter.Reply, :multipart_reply_codec) do + multipart_reply_codec_to_int(Openflow.Multipart.Experimenter.Reply) + catch + _class, _reason -> Openflow.Multipart.Experimenter.Reply + end + + def to_int(_int, :multipart_reply_codec) do + throw(:bad_enum) + end + + def to_int(Openflow.Multipart.NxFlow, :nicira_ext_stats) do + nicira_ext_stats_to_int(Openflow.Multipart.NxFlow) + catch + _class, _reason -> Openflow.Multipart.NxFlow + end + + def to_int(Openflow.Multipart.NxAggregate, :nicira_ext_stats) do + nicira_ext_stats_to_int(Openflow.Multipart.NxAggregate) + catch + _class, _reason -> Openflow.Multipart.NxAggregate + end + + def to_int(Openflow.Multipart.NxFlowMonitor, :nicira_ext_stats) do + nicira_ext_stats_to_int(Openflow.Multipart.NxFlowMonitor) + catch + _class, _reason -> Openflow.Multipart.NxFlowMonitor + end + + def to_int(Openflow.Multipart.NxIPFIXBridge, :nicira_ext_stats) do + nicira_ext_stats_to_int(Openflow.Multipart.NxIPFIXBridge) + catch + _class, _reason -> Openflow.Multipart.NxIPFIXBridge + end + + def to_int(Openflow.Multipart.NxIPFIXFlow, :nicira_ext_stats) do + nicira_ext_stats_to_int(Openflow.Multipart.NxIPFIXFlow) + catch + _class, _reason -> Openflow.Multipart.NxIPFIXFlow + end + + def to_int(_int, :nicira_ext_stats) do + throw(:bad_enum) + end + + def to_int(:versionbitmap, :hello_elem) do + hello_elem_to_int(:versionbitmap) + catch + _class, _reason -> :versionbitmap + end + + def to_int(_int, :hello_elem) do + throw(:bad_enum) + end + + def to_int(:hello_failed, :error_type) do + error_type_to_int(:hello_failed) + catch + _class, _reason -> :hello_failed + end + + def to_int(:bad_request, :error_type) do + error_type_to_int(:bad_request) + catch + _class, _reason -> :bad_request + end + + def to_int(:bad_action, :error_type) do + error_type_to_int(:bad_action) + catch + _class, _reason -> :bad_action + end + + def to_int(:bad_instruction, :error_type) do + error_type_to_int(:bad_instruction) + catch + _class, _reason -> :bad_instruction + end + + def to_int(:bad_match, :error_type) do + error_type_to_int(:bad_match) + catch + _class, _reason -> :bad_match + end + + def to_int(:flow_mod_failed, :error_type) do + error_type_to_int(:flow_mod_failed) + catch + _class, _reason -> :flow_mod_failed + end + + def to_int(:group_mod_failed, :error_type) do + error_type_to_int(:group_mod_failed) + catch + _class, _reason -> :group_mod_failed + end + + def to_int(:port_mod_failed, :error_type) do + error_type_to_int(:port_mod_failed) + catch + _class, _reason -> :port_mod_failed + end + + def to_int(:table_mod_failed, :error_type) do + error_type_to_int(:table_mod_failed) + catch + _class, _reason -> :table_mod_failed + end + + def to_int(:queue_op_failed, :error_type) do + error_type_to_int(:queue_op_failed) + catch + _class, _reason -> :queue_op_failed + end + + def to_int(:switch_config_failed, :error_type) do + error_type_to_int(:switch_config_failed) + catch + _class, _reason -> :switch_config_failed + end + + def to_int(:role_request_failed, :error_type) do + error_type_to_int(:role_request_failed) + catch + _class, _reason -> :role_request_failed + end + + def to_int(:meter_mod_failed, :error_type) do + error_type_to_int(:meter_mod_failed) + catch + _class, _reason -> :meter_mod_failed + end + + def to_int(:table_features_failed, :error_type) do + error_type_to_int(:table_features_failed) + catch + _class, _reason -> :table_features_failed + end + + def to_int(:experimenter, :error_type) do + error_type_to_int(:experimenter) + catch + _class, _reason -> :experimenter + end + + def to_int(_int, :error_type) do + throw(:bad_enum) + end + + def to_int(:inconpatible, :hello_failed) do + hello_failed_to_int(:inconpatible) + catch + _class, _reason -> :inconpatible + end + + def to_int(:eperm, :hello_failed) do + hello_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :hello_failed) do + throw(:bad_enum) + end + + def to_int(:bad_version, :bad_request) do + bad_request_to_int(:bad_version) + catch + _class, _reason -> :bad_version + end + + def to_int(:bad_type, :bad_request) do + bad_request_to_int(:bad_type) + catch + _class, _reason -> :bad_type + end + + def to_int(:bad_multipart, :bad_request) do + bad_request_to_int(:bad_multipart) + catch + _class, _reason -> :bad_multipart + end + + def to_int(:bad_experimeter, :bad_request) do + bad_request_to_int(:bad_experimeter) + catch + _class, _reason -> :bad_experimeter + end + + def to_int(:bad_exp_type, :bad_request) do + bad_request_to_int(:bad_exp_type) + catch + _class, _reason -> :bad_exp_type + end + + def to_int(:eperm, :bad_request) do + bad_request_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(:bad_len, :bad_request) do + bad_request_to_int(:bad_len) + catch + _class, _reason -> :bad_len + end + + def to_int(:buffer_empty, :bad_request) do + bad_request_to_int(:buffer_empty) + catch + _class, _reason -> :buffer_empty + end + + def to_int(:buffer_unknown, :bad_request) do + bad_request_to_int(:buffer_unknown) + catch + _class, _reason -> :buffer_unknown + end + + def to_int(:bad_table_id, :bad_request) do + bad_request_to_int(:bad_table_id) + catch + _class, _reason -> :bad_table_id + end + + def to_int(:is_slave, :bad_request) do + bad_request_to_int(:is_slave) + catch + _class, _reason -> :is_slave + end + + def to_int(:bad_port, :bad_request) do + bad_request_to_int(:bad_port) + catch + _class, _reason -> :bad_port + end + + def to_int(:bad_packet, :bad_request) do + bad_request_to_int(:bad_packet) + catch + _class, _reason -> :bad_packet + end + + def to_int(:multipart_buffer_overflow, :bad_request) do + bad_request_to_int(:multipart_buffer_overflow) + catch + _class, _reason -> :multipart_buffer_overflow + end + + def to_int(_int, :bad_request) do + throw(:bad_enum) + end + + def to_int(:bad_type, :bad_action) do + bad_action_to_int(:bad_type) + catch + _class, _reason -> :bad_type + end + + def to_int(:bad_len, :bad_action) do + bad_action_to_int(:bad_len) + catch + _class, _reason -> :bad_len + end + + def to_int(:bad_experimeter, :bad_action) do + bad_action_to_int(:bad_experimeter) + catch + _class, _reason -> :bad_experimeter + end + + def to_int(:bad_exp_type, :bad_action) do + bad_action_to_int(:bad_exp_type) + catch + _class, _reason -> :bad_exp_type + end + + def to_int(:bad_out_port, :bad_action) do + bad_action_to_int(:bad_out_port) + catch + _class, _reason -> :bad_out_port + end + + def to_int(:bad_argument, :bad_action) do + bad_action_to_int(:bad_argument) + catch + _class, _reason -> :bad_argument + end + + def to_int(:eperm, :bad_action) do + bad_action_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(:too_many, :bad_action) do + bad_action_to_int(:too_many) + catch + _class, _reason -> :too_many + end + + def to_int(:bad_queue, :bad_action) do + bad_action_to_int(:bad_queue) + catch + _class, _reason -> :bad_queue + end + + def to_int(:bad_out_group, :bad_action) do + bad_action_to_int(:bad_out_group) + catch + _class, _reason -> :bad_out_group + end + + def to_int(:match_inconsistent, :bad_action) do + bad_action_to_int(:match_inconsistent) + catch + _class, _reason -> :match_inconsistent + end + + def to_int(:unsupported_order, :bad_action) do + bad_action_to_int(:unsupported_order) + catch + _class, _reason -> :unsupported_order + end + + def to_int(:bad_tag, :bad_action) do + bad_action_to_int(:bad_tag) + catch + _class, _reason -> :bad_tag + end + + def to_int(:bad_set_type, :bad_action) do + bad_action_to_int(:bad_set_type) + catch + _class, _reason -> :bad_set_type + end + + def to_int(:bad_set_len, :bad_action) do + bad_action_to_int(:bad_set_len) + catch + _class, _reason -> :bad_set_len + end + + def to_int(:bad_set_argument, :bad_action) do + bad_action_to_int(:bad_set_argument) + catch + _class, _reason -> :bad_set_argument + end + + def to_int(_int, :bad_action) do + throw(:bad_enum) + end + + def to_int(:unknown_instruction, :bad_instruction) do + bad_instruction_to_int(:unknown_instruction) + catch + _class, _reason -> :unknown_instruction + end + + def to_int(:unsupported_instruction, :bad_instruction) do + bad_instruction_to_int(:unsupported_instruction) + catch + _class, _reason -> :unsupported_instruction + end + + def to_int(:bad_table_id, :bad_instruction) do + bad_instruction_to_int(:bad_table_id) + catch + _class, _reason -> :bad_table_id + end + + def to_int(:unsupported_metadata, :bad_instruction) do + bad_instruction_to_int(:unsupported_metadata) + catch + _class, _reason -> :unsupported_metadata + end + + def to_int(:unsupported_metadata_mask, :bad_instruction) do + bad_instruction_to_int(:unsupported_metadata_mask) + catch + _class, _reason -> :unsupported_metadata_mask + end + + def to_int(:bad_experimeter, :bad_instruction) do + bad_instruction_to_int(:bad_experimeter) + catch + _class, _reason -> :bad_experimeter + end + + def to_int(:bad_exp_type, :bad_instruction) do + bad_instruction_to_int(:bad_exp_type) + catch + _class, _reason -> :bad_exp_type + end + + def to_int(:bad_len, :bad_instruction) do + bad_instruction_to_int(:bad_len) + catch + _class, _reason -> :bad_len + end + + def to_int(:eperm, :bad_instruction) do + bad_instruction_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :bad_instruction) do + throw(:bad_enum) + end + + def to_int(:bad_type, :bad_match) do + bad_match_to_int(:bad_type) + catch + _class, _reason -> :bad_type + end + + def to_int(:bad_len, :bad_match) do + bad_match_to_int(:bad_len) + catch + _class, _reason -> :bad_len + end + + def to_int(:bad_tag, :bad_match) do + bad_match_to_int(:bad_tag) + catch + _class, _reason -> :bad_tag + end + + def to_int(:bad_dl_addr_mask, :bad_match) do + bad_match_to_int(:bad_dl_addr_mask) + catch + _class, _reason -> :bad_dl_addr_mask + end + + def to_int(:bad_nw_addr_mask, :bad_match) do + bad_match_to_int(:bad_nw_addr_mask) + catch + _class, _reason -> :bad_nw_addr_mask + end + + def to_int(:bad_wildcards, :bad_match) do + bad_match_to_int(:bad_wildcards) + catch + _class, _reason -> :bad_wildcards + end + + def to_int(:bad_field, :bad_match) do + bad_match_to_int(:bad_field) + catch + _class, _reason -> :bad_field + end + + def to_int(:bad_value, :bad_match) do + bad_match_to_int(:bad_value) + catch + _class, _reason -> :bad_value + end + + def to_int(:bad_mask, :bad_match) do + bad_match_to_int(:bad_mask) + catch + _class, _reason -> :bad_mask + end + + def to_int(:bad_prereq, :bad_match) do + bad_match_to_int(:bad_prereq) + catch + _class, _reason -> :bad_prereq + end + + def to_int(:dup_field, :bad_match) do + bad_match_to_int(:dup_field) + catch + _class, _reason -> :dup_field + end + + def to_int(:eperm, :bad_match) do + bad_match_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :bad_match) do + throw(:bad_enum) + end + + def to_int(:unknown, :flow_mod_failed) do + flow_mod_failed_to_int(:unknown) + catch + _class, _reason -> :unknown + end + + def to_int(:table_full, :flow_mod_failed) do + flow_mod_failed_to_int(:table_full) + catch + _class, _reason -> :table_full + end + + def to_int(:bad_table_id, :flow_mod_failed) do + flow_mod_failed_to_int(:bad_table_id) + catch + _class, _reason -> :bad_table_id + end + + def to_int(:overlap, :flow_mod_failed) do + flow_mod_failed_to_int(:overlap) + catch + _class, _reason -> :overlap + end + + def to_int(:eperm, :flow_mod_failed) do + flow_mod_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(:bad_timeout, :flow_mod_failed) do + flow_mod_failed_to_int(:bad_timeout) + catch + _class, _reason -> :bad_timeout + end + + def to_int(:bad_command, :flow_mod_failed) do + flow_mod_failed_to_int(:bad_command) + catch + _class, _reason -> :bad_command + end + + def to_int(:bad_flags, :flow_mod_failed) do + flow_mod_failed_to_int(:bad_flags) + catch + _class, _reason -> :bad_flags + end + + def to_int(_int, :flow_mod_failed) do + throw(:bad_enum) + end + + def to_int(:group_exists, :group_mod_failed) do + group_mod_failed_to_int(:group_exists) + catch + _class, _reason -> :group_exists + end + + def to_int(:invalid_group, :group_mod_failed) do + group_mod_failed_to_int(:invalid_group) + catch + _class, _reason -> :invalid_group + end + + def to_int(:weight_unsupported, :group_mod_failed) do + group_mod_failed_to_int(:weight_unsupported) + catch + _class, _reason -> :weight_unsupported + end + + def to_int(:out_of_groups, :group_mod_failed) do + group_mod_failed_to_int(:out_of_groups) + catch + _class, _reason -> :out_of_groups + end + + def to_int(:ouf_of_buckets, :group_mod_failed) do + group_mod_failed_to_int(:ouf_of_buckets) + catch + _class, _reason -> :ouf_of_buckets + end + + def to_int(:chaining_unsupported, :group_mod_failed) do + group_mod_failed_to_int(:chaining_unsupported) + catch + _class, _reason -> :chaining_unsupported + end + + def to_int(:watch_unsupported, :group_mod_failed) do + group_mod_failed_to_int(:watch_unsupported) + catch + _class, _reason -> :watch_unsupported + end + + def to_int(:loop, :group_mod_failed) do + group_mod_failed_to_int(:loop) + catch + _class, _reason -> :loop + end + + def to_int(:unknown_group, :group_mod_failed) do + group_mod_failed_to_int(:unknown_group) + catch + _class, _reason -> :unknown_group + end + + def to_int(:chained_group, :group_mod_failed) do + group_mod_failed_to_int(:chained_group) + catch + _class, _reason -> :chained_group + end + + def to_int(:bad_type, :group_mod_failed) do + group_mod_failed_to_int(:bad_type) + catch + _class, _reason -> :bad_type + end + + def to_int(:bad_command, :group_mod_failed) do + group_mod_failed_to_int(:bad_command) + catch + _class, _reason -> :bad_command + end + + def to_int(:bad_bucket, :group_mod_failed) do + group_mod_failed_to_int(:bad_bucket) + catch + _class, _reason -> :bad_bucket + end + + def to_int(:bad_watch, :group_mod_failed) do + group_mod_failed_to_int(:bad_watch) + catch + _class, _reason -> :bad_watch + end + + def to_int(:eperm, :group_mod_failed) do + group_mod_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :group_mod_failed) do + throw(:bad_enum) + end + + def to_int(:bad_port, :port_mod_failed) do + port_mod_failed_to_int(:bad_port) + catch + _class, _reason -> :bad_port + end + + def to_int(:bad_hw_addr, :port_mod_failed) do + port_mod_failed_to_int(:bad_hw_addr) + catch + _class, _reason -> :bad_hw_addr + end + + def to_int(:bad_config, :port_mod_failed) do + port_mod_failed_to_int(:bad_config) + catch + _class, _reason -> :bad_config + end + + def to_int(:bad_advertise, :port_mod_failed) do + port_mod_failed_to_int(:bad_advertise) + catch + _class, _reason -> :bad_advertise + end + + def to_int(:eperm, :port_mod_failed) do + port_mod_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :port_mod_failed) do + throw(:bad_enum) + end + + def to_int(:bad_table, :table_mod_failed) do + table_mod_failed_to_int(:bad_table) + catch + _class, _reason -> :bad_table + end + + def to_int(:bad_config, :table_mod_failed) do + table_mod_failed_to_int(:bad_config) + catch + _class, _reason -> :bad_config + end + + def to_int(:eperm, :table_mod_failed) do + table_mod_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :table_mod_failed) do + throw(:bad_enum) + end + + def to_int(:bad_port, :queue_op_failed) do + queue_op_failed_to_int(:bad_port) + catch + _class, _reason -> :bad_port + end + + def to_int(:bad_queue, :queue_op_failed) do + queue_op_failed_to_int(:bad_queue) + catch + _class, _reason -> :bad_queue + end + + def to_int(:eperm, :queue_op_failed) do + queue_op_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :queue_op_failed) do + throw(:bad_enum) + end + + def to_int(:bad_flags, :switch_config_failed) do + switch_config_failed_to_int(:bad_flags) + catch + _class, _reason -> :bad_flags + end + + def to_int(:bad_len, :switch_config_failed) do + switch_config_failed_to_int(:bad_len) + catch + _class, _reason -> :bad_len + end + + def to_int(:eperm, :switch_config_failed) do + switch_config_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :switch_config_failed) do + throw(:bad_enum) + end + + def to_int(:stale, :role_request_failed) do + role_request_failed_to_int(:stale) + catch + _class, _reason -> :stale + end + + def to_int(:unsup, :role_request_failed) do + role_request_failed_to_int(:unsup) + catch + _class, _reason -> :unsup + end + + def to_int(:bad_role, :role_request_failed) do + role_request_failed_to_int(:bad_role) + catch + _class, _reason -> :bad_role + end + + def to_int(_int, :role_request_failed) do + throw(:bad_enum) + end + + def to_int(:unknown, :meter_mod_failed) do + meter_mod_failed_to_int(:unknown) + catch + _class, _reason -> :unknown + end + + def to_int(:meter_exists, :meter_mod_failed) do + meter_mod_failed_to_int(:meter_exists) + catch + _class, _reason -> :meter_exists + end + + def to_int(:invalid_meter, :meter_mod_failed) do + meter_mod_failed_to_int(:invalid_meter) + catch + _class, _reason -> :invalid_meter + end + + def to_int(:unknown_meter, :meter_mod_failed) do + meter_mod_failed_to_int(:unknown_meter) + catch + _class, _reason -> :unknown_meter + end + + def to_int(:bad_command, :meter_mod_failed) do + meter_mod_failed_to_int(:bad_command) + catch + _class, _reason -> :bad_command + end + + def to_int(:bad_flags, :meter_mod_failed) do + meter_mod_failed_to_int(:bad_flags) + catch + _class, _reason -> :bad_flags + end + + def to_int(:bad_rate, :meter_mod_failed) do + meter_mod_failed_to_int(:bad_rate) + catch + _class, _reason -> :bad_rate + end + + def to_int(:bad_burst, :meter_mod_failed) do + meter_mod_failed_to_int(:bad_burst) + catch + _class, _reason -> :bad_burst + end + + def to_int(:bad_band, :meter_mod_failed) do + meter_mod_failed_to_int(:bad_band) + catch + _class, _reason -> :bad_band + end + + def to_int(:bad_band_value, :meter_mod_failed) do + meter_mod_failed_to_int(:bad_band_value) + catch + _class, _reason -> :bad_band_value + end + + def to_int(:out_of_meters, :meter_mod_failed) do + meter_mod_failed_to_int(:out_of_meters) + catch + _class, _reason -> :out_of_meters + end + + def to_int(:out_of_bands, :meter_mod_failed) do + meter_mod_failed_to_int(:out_of_bands) + catch + _class, _reason -> :out_of_bands + end + + def to_int(_int, :meter_mod_failed) do + throw(:bad_enum) + end + + def to_int(:bad_table, :table_features_failed) do + table_features_failed_to_int(:bad_table) + catch + _class, _reason -> :bad_table + end + + def to_int(:bad_metadata, :table_features_failed) do + table_features_failed_to_int(:bad_metadata) + catch + _class, _reason -> :bad_metadata + end + + def to_int(:bad_type, :table_features_failed) do + table_features_failed_to_int(:bad_type) + catch + _class, _reason -> :bad_type + end + + def to_int(:bad_len, :table_features_failed) do + table_features_failed_to_int(:bad_len) + catch + _class, _reason -> :bad_len + end + + def to_int(:bad_argument, :table_features_failed) do + table_features_failed_to_int(:bad_argument) + catch + _class, _reason -> :bad_argument + end + + def to_int(:eperm, :table_features_failed) do + table_features_failed_to_int(:eperm) + catch + _class, _reason -> :eperm + end + + def to_int(_int, :table_features_failed) do + throw(:bad_enum) + end + + def to_int(:flow_stats, :switch_capabilities) do + switch_capabilities_to_int(:flow_stats) + catch + _class, _reason -> :flow_stats + end + + def to_int(:table_stats, :switch_capabilities) do + switch_capabilities_to_int(:table_stats) + catch + _class, _reason -> :table_stats + end + + def to_int(:port_stats, :switch_capabilities) do + switch_capabilities_to_int(:port_stats) + catch + _class, _reason -> :port_stats + end + + def to_int(:group_stats, :switch_capabilities) do + switch_capabilities_to_int(:group_stats) + catch + _class, _reason -> :group_stats + end + + def to_int(:ip_reasm, :switch_capabilities) do + switch_capabilities_to_int(:ip_reasm) + catch + _class, _reason -> :ip_reasm + end + + def to_int(:queue_stats, :switch_capabilities) do + switch_capabilities_to_int(:queue_stats) + catch + _class, _reason -> :queue_stats + end + + def to_int(:arp_match_ip, :switch_capabilities) do + switch_capabilities_to_int(:arp_match_ip) + catch + _class, _reason -> :arp_match_ip + end + + def to_int(:port_blocked, :switch_capabilities) do + switch_capabilities_to_int(:port_blocked) + catch + _class, _reason -> :port_blocked + end + + def to_int(_int, :switch_capabilities) do + throw(:bad_enum) + end + + def to_int(:drop, :config_flags) do + config_flags_to_int(:drop) + catch + _class, _reason -> :drop + end + + def to_int(:reasm, :config_flags) do + config_flags_to_int(:reasm) + catch + _class, _reason -> :reasm + end + + def to_int(_int, :config_flags) do + throw(:bad_enum) + end + + def to_int(:max, :controller_max_len) do + controller_max_len_to_int(:max) + catch + _class, _reason -> :max + end + + def to_int(:no_buffer, :controller_max_len) do + controller_max_len_to_int(:no_buffer) + catch + _class, _reason -> :no_buffer + end + + def to_int(_int, :controller_max_len) do + throw(:bad_enum) + end + + def to_int(:nicira_ext_match, :experimenter_oxm_vendors) do + experimenter_oxm_vendors_to_int(:nicira_ext_match) + catch + _class, _reason -> :nicira_ext_match + end + + def to_int(:hp_ext_match, :experimenter_oxm_vendors) do + experimenter_oxm_vendors_to_int(:hp_ext_match) + catch + _class, _reason -> :hp_ext_match + end + + def to_int(:onf_ext_match, :experimenter_oxm_vendors) do + experimenter_oxm_vendors_to_int(:onf_ext_match) + catch + _class, _reason -> :onf_ext_match + end + + def to_int(_int, :experimenter_oxm_vendors) do + throw(:bad_enum) + end + + def to_int(:standard, :match_type) do + match_type_to_int(:standard) + catch + _class, _reason -> :standard + end + + def to_int(:oxm, :match_type) do + match_type_to_int(:oxm) + catch + _class, _reason -> :oxm + end + + def to_int(_int, :match_type) do + throw(:bad_enum) + end + + def to_int(:nxm_0, :oxm_class) do + oxm_class_to_int(:nxm_0) + catch + _class, _reason -> :nxm_0 + end + + def to_int(:nxm_1, :oxm_class) do + oxm_class_to_int(:nxm_1) + catch + _class, _reason -> :nxm_1 + end + + def to_int(:openflow_basic, :oxm_class) do + oxm_class_to_int(:openflow_basic) + catch + _class, _reason -> :openflow_basic + end + + def to_int(:packet_register, :oxm_class) do + oxm_class_to_int(:packet_register) + catch + _class, _reason -> :packet_register + end + + def to_int(:experimenter, :oxm_class) do + oxm_class_to_int(:experimenter) + catch + _class, _reason -> :experimenter + end + + def to_int(_int, :oxm_class) do + throw(:bad_enum) + end + + def to_int(:nx_in_port, :nxm_0) do + nxm_0_to_int(:nx_in_port) + catch + _class, _reason -> :nx_in_port + end + + def to_int(:nx_eth_dst, :nxm_0) do + nxm_0_to_int(:nx_eth_dst) + catch + _class, _reason -> :nx_eth_dst + end + + def to_int(:nx_eth_src, :nxm_0) do + nxm_0_to_int(:nx_eth_src) + catch + _class, _reason -> :nx_eth_src + end + + def to_int(:nx_eth_type, :nxm_0) do + nxm_0_to_int(:nx_eth_type) + catch + _class, _reason -> :nx_eth_type + end + + def to_int(:nx_vlan_tci, :nxm_0) do + nxm_0_to_int(:nx_vlan_tci) + catch + _class, _reason -> :nx_vlan_tci + end + + def to_int(:nx_ip_tos, :nxm_0) do + nxm_0_to_int(:nx_ip_tos) + catch + _class, _reason -> :nx_ip_tos + end + + def to_int(:nx_ip_proto, :nxm_0) do + nxm_0_to_int(:nx_ip_proto) + catch + _class, _reason -> :nx_ip_proto + end + + def to_int(:nx_ipv4_src, :nxm_0) do + nxm_0_to_int(:nx_ipv4_src) + catch + _class, _reason -> :nx_ipv4_src + end + + def to_int(:nx_ipv4_dst, :nxm_0) do + nxm_0_to_int(:nx_ipv4_dst) + catch + _class, _reason -> :nx_ipv4_dst + end + + def to_int(:nx_tcp_src, :nxm_0) do + nxm_0_to_int(:nx_tcp_src) + catch + _class, _reason -> :nx_tcp_src + end + + def to_int(:nx_tcp_dst, :nxm_0) do + nxm_0_to_int(:nx_tcp_dst) + catch + _class, _reason -> :nx_tcp_dst + end + + def to_int(:nx_udp_src, :nxm_0) do + nxm_0_to_int(:nx_udp_src) + catch + _class, _reason -> :nx_udp_src + end + + def to_int(:nx_udp_dst, :nxm_0) do + nxm_0_to_int(:nx_udp_dst) + catch + _class, _reason -> :nx_udp_dst + end + + def to_int(:nx_icmpv4_type, :nxm_0) do + nxm_0_to_int(:nx_icmpv4_type) + catch + _class, _reason -> :nx_icmpv4_type + end + + def to_int(:nx_icmpv4_code, :nxm_0) do + nxm_0_to_int(:nx_icmpv4_code) + catch + _class, _reason -> :nx_icmpv4_code + end + + def to_int(:nx_arp_op, :nxm_0) do + nxm_0_to_int(:nx_arp_op) + catch + _class, _reason -> :nx_arp_op + end + + def to_int(:nx_arp_spa, :nxm_0) do + nxm_0_to_int(:nx_arp_spa) + catch + _class, _reason -> :nx_arp_spa + end + + def to_int(:nx_arp_tpa, :nxm_0) do + nxm_0_to_int(:nx_arp_tpa) + catch + _class, _reason -> :nx_arp_tpa + end + + def to_int(:nx_tcp_flags, :nxm_0) do + nxm_0_to_int(:nx_tcp_flags) + catch + _class, _reason -> :nx_tcp_flags + end + + def to_int(_int, :nxm_0) do + throw(:bad_enum) + end + + def to_int(:reg0, :nxm_1) do + nxm_1_to_int(:reg0) + catch + _class, _reason -> :reg0 + end + + def to_int(:reg1, :nxm_1) do + nxm_1_to_int(:reg1) + catch + _class, _reason -> :reg1 + end + + def to_int(:reg2, :nxm_1) do + nxm_1_to_int(:reg2) + catch + _class, _reason -> :reg2 + end + + def to_int(:reg3, :nxm_1) do + nxm_1_to_int(:reg3) + catch + _class, _reason -> :reg3 + end + + def to_int(:reg4, :nxm_1) do + nxm_1_to_int(:reg4) + catch + _class, _reason -> :reg4 + end + + def to_int(:reg5, :nxm_1) do + nxm_1_to_int(:reg5) + catch + _class, _reason -> :reg5 + end + + def to_int(:reg6, :nxm_1) do + nxm_1_to_int(:reg6) + catch + _class, _reason -> :reg6 + end + + def to_int(:reg7, :nxm_1) do + nxm_1_to_int(:reg7) + catch + _class, _reason -> :reg7 + end + + def to_int(:reg8, :nxm_1) do + nxm_1_to_int(:reg8) + catch + _class, _reason -> :reg8 + end + + def to_int(:reg9, :nxm_1) do + nxm_1_to_int(:reg9) + catch + _class, _reason -> :reg9 + end + + def to_int(:reg10, :nxm_1) do + nxm_1_to_int(:reg10) + catch + _class, _reason -> :reg10 + end + + def to_int(:reg11, :nxm_1) do + nxm_1_to_int(:reg11) + catch + _class, _reason -> :reg11 + end + + def to_int(:reg12, :nxm_1) do + nxm_1_to_int(:reg12) + catch + _class, _reason -> :reg12 + end + + def to_int(:reg13, :nxm_1) do + nxm_1_to_int(:reg13) + catch + _class, _reason -> :reg13 + end + + def to_int(:reg14, :nxm_1) do + nxm_1_to_int(:reg14) + catch + _class, _reason -> :reg14 + end + + def to_int(:reg15, :nxm_1) do + nxm_1_to_int(:reg15) + catch + _class, _reason -> :reg15 + end + + def to_int(:tun_id, :nxm_1) do + nxm_1_to_int(:tun_id) + catch + _class, _reason -> :tun_id + end + + def to_int(:nx_arp_sha, :nxm_1) do + nxm_1_to_int(:nx_arp_sha) + catch + _class, _reason -> :nx_arp_sha + end + + def to_int(:nx_arp_tha, :nxm_1) do + nxm_1_to_int(:nx_arp_tha) + catch + _class, _reason -> :nx_arp_tha + end + + def to_int(:nx_ipv6_src, :nxm_1) do + nxm_1_to_int(:nx_ipv6_src) + catch + _class, _reason -> :nx_ipv6_src + end + + def to_int(:nx_ipv6_dst, :nxm_1) do + nxm_1_to_int(:nx_ipv6_dst) + catch + _class, _reason -> :nx_ipv6_dst + end + + def to_int(:nx_icmpv6_type, :nxm_1) do + nxm_1_to_int(:nx_icmpv6_type) + catch + _class, _reason -> :nx_icmpv6_type + end + + def to_int(:nx_icmpv6_code, :nxm_1) do + nxm_1_to_int(:nx_icmpv6_code) + catch + _class, _reason -> :nx_icmpv6_code + end + + def to_int(:nx_ipv6_nd_target, :nxm_1) do + nxm_1_to_int(:nx_ipv6_nd_target) + catch + _class, _reason -> :nx_ipv6_nd_target + end + + def to_int(:nx_ipv6_nd_sll, :nxm_1) do + nxm_1_to_int(:nx_ipv6_nd_sll) + catch + _class, _reason -> :nx_ipv6_nd_sll + end + + def to_int(:nx_ipv6_nd_tll, :nxm_1) do + nxm_1_to_int(:nx_ipv6_nd_tll) + catch + _class, _reason -> :nx_ipv6_nd_tll + end + + def to_int(:nx_ip_frag, :nxm_1) do + nxm_1_to_int(:nx_ip_frag) + catch + _class, _reason -> :nx_ip_frag + end + + def to_int(:nx_ipv6_label, :nxm_1) do + nxm_1_to_int(:nx_ipv6_label) + catch + _class, _reason -> :nx_ipv6_label + end + + def to_int(:nx_ip_ecn, :nxm_1) do + nxm_1_to_int(:nx_ip_ecn) + catch + _class, _reason -> :nx_ip_ecn + end + + def to_int(:nx_ip_ttl, :nxm_1) do + nxm_1_to_int(:nx_ip_ttl) + catch + _class, _reason -> :nx_ip_ttl + end + + def to_int(:nx_mpls_ttl, :nxm_1) do + nxm_1_to_int(:nx_mpls_ttl) + catch + _class, _reason -> :nx_mpls_ttl + end + + def to_int(:tun_src, :nxm_1) do + nxm_1_to_int(:tun_src) + catch + _class, _reason -> :tun_src + end + + def to_int(:tun_dst, :nxm_1) do + nxm_1_to_int(:tun_dst) + catch + _class, _reason -> :tun_dst + end + + def to_int(:pkt_mark, :nxm_1) do + nxm_1_to_int(:pkt_mark) + catch + _class, _reason -> :pkt_mark + end + + def to_int(:dp_hash, :nxm_1) do + nxm_1_to_int(:dp_hash) + catch + _class, _reason -> :dp_hash + end + + def to_int(:recirc_id, :nxm_1) do + nxm_1_to_int(:recirc_id) + catch + _class, _reason -> :recirc_id + end + + def to_int(:conj_id, :nxm_1) do + nxm_1_to_int(:conj_id) + catch + _class, _reason -> :conj_id + end + + def to_int(:tun_gbp_id, :nxm_1) do + nxm_1_to_int(:tun_gbp_id) + catch + _class, _reason -> :tun_gbp_id + end + + def to_int(:tun_gbp_flags, :nxm_1) do + nxm_1_to_int(:tun_gbp_flags) + catch + _class, _reason -> :tun_gbp_flags + end + + def to_int(:tun_metadata0, :nxm_1) do + nxm_1_to_int(:tun_metadata0) + catch + _class, _reason -> :tun_metadata0 + end + + def to_int(:tun_metadata1, :nxm_1) do + nxm_1_to_int(:tun_metadata1) + catch + _class, _reason -> :tun_metadata1 + end + + def to_int(:tun_metadata2, :nxm_1) do + nxm_1_to_int(:tun_metadata2) + catch + _class, _reason -> :tun_metadata2 + end + + def to_int(:tun_metadata3, :nxm_1) do + nxm_1_to_int(:tun_metadata3) + catch + _class, _reason -> :tun_metadata3 + end + + def to_int(:tun_metadata4, :nxm_1) do + nxm_1_to_int(:tun_metadata4) + catch + _class, _reason -> :tun_metadata4 + end + + def to_int(:tun_metadata5, :nxm_1) do + nxm_1_to_int(:tun_metadata5) + catch + _class, _reason -> :tun_metadata5 + end + + def to_int(:tun_metadata6, :nxm_1) do + nxm_1_to_int(:tun_metadata6) + catch + _class, _reason -> :tun_metadata6 + end + + def to_int(:tun_metadata7, :nxm_1) do + nxm_1_to_int(:tun_metadata7) + catch + _class, _reason -> :tun_metadata7 + end + + def to_int(:tun_metadata8, :nxm_1) do + nxm_1_to_int(:tun_metadata8) + catch + _class, _reason -> :tun_metadata8 + end + + def to_int(:tun_metadata9, :nxm_1) do + nxm_1_to_int(:tun_metadata9) + catch + _class, _reason -> :tun_metadata9 + end + + def to_int(:tun_metadata10, :nxm_1) do + nxm_1_to_int(:tun_metadata10) + catch + _class, _reason -> :tun_metadata10 + end + + def to_int(:tun_metadata11, :nxm_1) do + nxm_1_to_int(:tun_metadata11) + catch + _class, _reason -> :tun_metadata11 + end + + def to_int(:tun_metadata12, :nxm_1) do + nxm_1_to_int(:tun_metadata12) + catch + _class, _reason -> :tun_metadata12 + end + + def to_int(:tun_metadata13, :nxm_1) do + nxm_1_to_int(:tun_metadata13) + catch + _class, _reason -> :tun_metadata13 + end + + def to_int(:tun_metadata14, :nxm_1) do + nxm_1_to_int(:tun_metadata14) + catch + _class, _reason -> :tun_metadata14 + end + + def to_int(:tun_metadata15, :nxm_1) do + nxm_1_to_int(:tun_metadata15) + catch + _class, _reason -> :tun_metadata15 + end + + def to_int(:tun_metadata16, :nxm_1) do + nxm_1_to_int(:tun_metadata16) + catch + _class, _reason -> :tun_metadata16 + end + + def to_int(:tun_metadata17, :nxm_1) do + nxm_1_to_int(:tun_metadata17) + catch + _class, _reason -> :tun_metadata17 + end + + def to_int(:tun_metadata18, :nxm_1) do + nxm_1_to_int(:tun_metadata18) + catch + _class, _reason -> :tun_metadata18 + end + + def to_int(:tun_metadata19, :nxm_1) do + nxm_1_to_int(:tun_metadata19) + catch + _class, _reason -> :tun_metadata19 + end + + def to_int(:tun_metadata20, :nxm_1) do + nxm_1_to_int(:tun_metadata20) + catch + _class, _reason -> :tun_metadata20 + end + + def to_int(:tun_metadata21, :nxm_1) do + nxm_1_to_int(:tun_metadata21) + catch + _class, _reason -> :tun_metadata21 + end + + def to_int(:tun_metadata22, :nxm_1) do + nxm_1_to_int(:tun_metadata22) + catch + _class, _reason -> :tun_metadata22 + end + + def to_int(:tun_metadata23, :nxm_1) do + nxm_1_to_int(:tun_metadata23) + catch + _class, _reason -> :tun_metadata23 + end + + def to_int(:tun_metadata24, :nxm_1) do + nxm_1_to_int(:tun_metadata24) + catch + _class, _reason -> :tun_metadata24 + end + + def to_int(:tun_metadata25, :nxm_1) do + nxm_1_to_int(:tun_metadata25) + catch + _class, _reason -> :tun_metadata25 + end + + def to_int(:tun_metadata26, :nxm_1) do + nxm_1_to_int(:tun_metadata26) + catch + _class, _reason -> :tun_metadata26 + end + + def to_int(:tun_metadata27, :nxm_1) do + nxm_1_to_int(:tun_metadata27) + catch + _class, _reason -> :tun_metadata27 + end + + def to_int(:tun_metadata28, :nxm_1) do + nxm_1_to_int(:tun_metadata28) + catch + _class, _reason -> :tun_metadata28 + end + + def to_int(:tun_metadata29, :nxm_1) do + nxm_1_to_int(:tun_metadata29) + catch + _class, _reason -> :tun_metadata29 + end + + def to_int(:tun_metadata30, :nxm_1) do + nxm_1_to_int(:tun_metadata30) + catch + _class, _reason -> :tun_metadata30 + end + + def to_int(:tun_metadata31, :nxm_1) do + nxm_1_to_int(:tun_metadata31) + catch + _class, _reason -> :tun_metadata31 + end + + def to_int(:tun_metadata32, :nxm_1) do + nxm_1_to_int(:tun_metadata32) + catch + _class, _reason -> :tun_metadata32 + end + + def to_int(:tun_metadata33, :nxm_1) do + nxm_1_to_int(:tun_metadata33) + catch + _class, _reason -> :tun_metadata33 + end + + def to_int(:tun_metadata34, :nxm_1) do + nxm_1_to_int(:tun_metadata34) + catch + _class, _reason -> :tun_metadata34 + end + + def to_int(:tun_metadata35, :nxm_1) do + nxm_1_to_int(:tun_metadata35) + catch + _class, _reason -> :tun_metadata35 + end + + def to_int(:tun_metadata36, :nxm_1) do + nxm_1_to_int(:tun_metadata36) + catch + _class, _reason -> :tun_metadata36 + end + + def to_int(:tun_metadata37, :nxm_1) do + nxm_1_to_int(:tun_metadata37) + catch + _class, _reason -> :tun_metadata37 + end + + def to_int(:tun_metadata38, :nxm_1) do + nxm_1_to_int(:tun_metadata38) + catch + _class, _reason -> :tun_metadata38 + end + + def to_int(:tun_metadata39, :nxm_1) do + nxm_1_to_int(:tun_metadata39) + catch + _class, _reason -> :tun_metadata39 + end + + def to_int(:tun_metadata40, :nxm_1) do + nxm_1_to_int(:tun_metadata40) + catch + _class, _reason -> :tun_metadata40 + end + + def to_int(:tun_metadata41, :nxm_1) do + nxm_1_to_int(:tun_metadata41) + catch + _class, _reason -> :tun_metadata41 + end + + def to_int(:tun_metadata42, :nxm_1) do + nxm_1_to_int(:tun_metadata42) + catch + _class, _reason -> :tun_metadata42 + end + + def to_int(:tun_metadata43, :nxm_1) do + nxm_1_to_int(:tun_metadata43) + catch + _class, _reason -> :tun_metadata43 + end + + def to_int(:tun_metadata44, :nxm_1) do + nxm_1_to_int(:tun_metadata44) + catch + _class, _reason -> :tun_metadata44 + end + + def to_int(:tun_metadata45, :nxm_1) do + nxm_1_to_int(:tun_metadata45) + catch + _class, _reason -> :tun_metadata45 + end + + def to_int(:tun_metadata46, :nxm_1) do + nxm_1_to_int(:tun_metadata46) + catch + _class, _reason -> :tun_metadata46 + end + + def to_int(:tun_metadata47, :nxm_1) do + nxm_1_to_int(:tun_metadata47) + catch + _class, _reason -> :tun_metadata47 + end + + def to_int(:tun_metadata48, :nxm_1) do + nxm_1_to_int(:tun_metadata48) + catch + _class, _reason -> :tun_metadata48 + end + + def to_int(:tun_metadata49, :nxm_1) do + nxm_1_to_int(:tun_metadata49) + catch + _class, _reason -> :tun_metadata49 + end + + def to_int(:tun_metadata50, :nxm_1) do + nxm_1_to_int(:tun_metadata50) + catch + _class, _reason -> :tun_metadata50 + end + + def to_int(:tun_metadata51, :nxm_1) do + nxm_1_to_int(:tun_metadata51) + catch + _class, _reason -> :tun_metadata51 + end + + def to_int(:tun_metadata52, :nxm_1) do + nxm_1_to_int(:tun_metadata52) + catch + _class, _reason -> :tun_metadata52 + end + + def to_int(:tun_metadata53, :nxm_1) do + nxm_1_to_int(:tun_metadata53) + catch + _class, _reason -> :tun_metadata53 + end + + def to_int(:tun_metadata54, :nxm_1) do + nxm_1_to_int(:tun_metadata54) + catch + _class, _reason -> :tun_metadata54 + end + + def to_int(:tun_metadata55, :nxm_1) do + nxm_1_to_int(:tun_metadata55) + catch + _class, _reason -> :tun_metadata55 + end + + def to_int(:tun_metadata56, :nxm_1) do + nxm_1_to_int(:tun_metadata56) + catch + _class, _reason -> :tun_metadata56 + end + + def to_int(:tun_metadata57, :nxm_1) do + nxm_1_to_int(:tun_metadata57) + catch + _class, _reason -> :tun_metadata57 + end + + def to_int(:tun_metadata58, :nxm_1) do + nxm_1_to_int(:tun_metadata58) + catch + _class, _reason -> :tun_metadata58 + end + + def to_int(:tun_metadata59, :nxm_1) do + nxm_1_to_int(:tun_metadata59) + catch + _class, _reason -> :tun_metadata59 + end + + def to_int(:tun_metadata60, :nxm_1) do + nxm_1_to_int(:tun_metadata60) + catch + _class, _reason -> :tun_metadata60 + end + + def to_int(:tun_metadata61, :nxm_1) do + nxm_1_to_int(:tun_metadata61) + catch + _class, _reason -> :tun_metadata61 + end + + def to_int(:tun_metadata62, :nxm_1) do + nxm_1_to_int(:tun_metadata62) + catch + _class, _reason -> :tun_metadata62 + end + + def to_int(:tun_metadata63, :nxm_1) do + nxm_1_to_int(:tun_metadata63) + catch + _class, _reason -> :tun_metadata63 + end + + def to_int(:tun_flags, :nxm_1) do + nxm_1_to_int(:tun_flags) + catch + _class, _reason -> :tun_flags + end + + def to_int(:ct_state, :nxm_1) do + nxm_1_to_int(:ct_state) + catch + _class, _reason -> :ct_state + end + + def to_int(:ct_zone, :nxm_1) do + nxm_1_to_int(:ct_zone) + catch + _class, _reason -> :ct_zone + end + + def to_int(:ct_mark, :nxm_1) do + nxm_1_to_int(:ct_mark) + catch + _class, _reason -> :ct_mark + end + + def to_int(:ct_label, :nxm_1) do + nxm_1_to_int(:ct_label) + catch + _class, _reason -> :ct_label + end + + def to_int(:tun_ipv6_src, :nxm_1) do + nxm_1_to_int(:tun_ipv6_src) + catch + _class, _reason -> :tun_ipv6_src + end + + def to_int(:tun_ipv6_dst, :nxm_1) do + nxm_1_to_int(:tun_ipv6_dst) + catch + _class, _reason -> :tun_ipv6_dst + end + + def to_int(:xxreg0, :nxm_1) do + nxm_1_to_int(:xxreg0) + catch + _class, _reason -> :xxreg0 + end + + def to_int(:xxreg1, :nxm_1) do + nxm_1_to_int(:xxreg1) + catch + _class, _reason -> :xxreg1 + end + + def to_int(:xxreg2, :nxm_1) do + nxm_1_to_int(:xxreg2) + catch + _class, _reason -> :xxreg2 + end + + def to_int(:xxreg3, :nxm_1) do + nxm_1_to_int(:xxreg3) + catch + _class, _reason -> :xxreg3 + end + + def to_int(:xxreg4, :nxm_1) do + nxm_1_to_int(:xxreg4) + catch + _class, _reason -> :xxreg4 + end + + def to_int(:xxreg5, :nxm_1) do + nxm_1_to_int(:xxreg5) + catch + _class, _reason -> :xxreg5 + end + + def to_int(:xxreg6, :nxm_1) do + nxm_1_to_int(:xxreg6) + catch + _class, _reason -> :xxreg6 + end + + def to_int(:xxreg7, :nxm_1) do + nxm_1_to_int(:xxreg7) + catch + _class, _reason -> :xxreg7 + end + + def to_int(:ct_nw_proto, :nxm_1) do + nxm_1_to_int(:ct_nw_proto) + catch + _class, _reason -> :ct_nw_proto + end + + def to_int(:ct_nw_src, :nxm_1) do + nxm_1_to_int(:ct_nw_src) + catch + _class, _reason -> :ct_nw_src + end + + def to_int(:ct_nw_dst, :nxm_1) do + nxm_1_to_int(:ct_nw_dst) + catch + _class, _reason -> :ct_nw_dst + end + + def to_int(:ct_ipv6_src, :nxm_1) do + nxm_1_to_int(:ct_ipv6_src) + catch + _class, _reason -> :ct_ipv6_src + end + + def to_int(:ct_ipv6_dst, :nxm_1) do + nxm_1_to_int(:ct_ipv6_dst) + catch + _class, _reason -> :ct_ipv6_dst + end + + def to_int(:ct_tp_src, :nxm_1) do + nxm_1_to_int(:ct_tp_src) + catch + _class, _reason -> :ct_tp_src + end + + def to_int(:ct_tp_dst, :nxm_1) do + nxm_1_to_int(:ct_tp_dst) + catch + _class, _reason -> :ct_tp_dst + end + + def to_int(_int, :nxm_1) do + throw(:bad_enum) + end + + def to_int(:in_port, :openflow_basic) do + openflow_basic_to_int(:in_port) + catch + _class, _reason -> :in_port + end + + def to_int(:in_phy_port, :openflow_basic) do + openflow_basic_to_int(:in_phy_port) + catch + _class, _reason -> :in_phy_port + end + + def to_int(:metadata, :openflow_basic) do + openflow_basic_to_int(:metadata) + catch + _class, _reason -> :metadata + end + + def to_int(:eth_dst, :openflow_basic) do + openflow_basic_to_int(:eth_dst) + catch + _class, _reason -> :eth_dst + end + + def to_int(:eth_src, :openflow_basic) do + openflow_basic_to_int(:eth_src) + catch + _class, _reason -> :eth_src + end + + def to_int(:eth_type, :openflow_basic) do + openflow_basic_to_int(:eth_type) + catch + _class, _reason -> :eth_type + end + + def to_int(:vlan_vid, :openflow_basic) do + openflow_basic_to_int(:vlan_vid) + catch + _class, _reason -> :vlan_vid + end + + def to_int(:vlan_pcp, :openflow_basic) do + openflow_basic_to_int(:vlan_pcp) + catch + _class, _reason -> :vlan_pcp + end + + def to_int(:ip_dscp, :openflow_basic) do + openflow_basic_to_int(:ip_dscp) + catch + _class, _reason -> :ip_dscp + end + + def to_int(:ip_ecn, :openflow_basic) do + openflow_basic_to_int(:ip_ecn) + catch + _class, _reason -> :ip_ecn + end + + def to_int(:ip_proto, :openflow_basic) do + openflow_basic_to_int(:ip_proto) + catch + _class, _reason -> :ip_proto + end + + def to_int(:ipv4_src, :openflow_basic) do + openflow_basic_to_int(:ipv4_src) + catch + _class, _reason -> :ipv4_src + end + + def to_int(:ipv4_dst, :openflow_basic) do + openflow_basic_to_int(:ipv4_dst) + catch + _class, _reason -> :ipv4_dst + end + + def to_int(:tcp_src, :openflow_basic) do + openflow_basic_to_int(:tcp_src) + catch + _class, _reason -> :tcp_src + end + + def to_int(:tcp_dst, :openflow_basic) do + openflow_basic_to_int(:tcp_dst) + catch + _class, _reason -> :tcp_dst + end + + def to_int(:udp_src, :openflow_basic) do + openflow_basic_to_int(:udp_src) + catch + _class, _reason -> :udp_src + end + + def to_int(:udp_dst, :openflow_basic) do + openflow_basic_to_int(:udp_dst) + catch + _class, _reason -> :udp_dst + end + + def to_int(:sctp_src, :openflow_basic) do + openflow_basic_to_int(:sctp_src) + catch + _class, _reason -> :sctp_src + end + + def to_int(:sctp_dst, :openflow_basic) do + openflow_basic_to_int(:sctp_dst) + catch + _class, _reason -> :sctp_dst + end + + def to_int(:icmpv4_type, :openflow_basic) do + openflow_basic_to_int(:icmpv4_type) + catch + _class, _reason -> :icmpv4_type + end + + def to_int(:icmpv4_code, :openflow_basic) do + openflow_basic_to_int(:icmpv4_code) + catch + _class, _reason -> :icmpv4_code + end + + def to_int(:arp_op, :openflow_basic) do + openflow_basic_to_int(:arp_op) + catch + _class, _reason -> :arp_op + end + + def to_int(:arp_spa, :openflow_basic) do + openflow_basic_to_int(:arp_spa) + catch + _class, _reason -> :arp_spa + end + + def to_int(:arp_tpa, :openflow_basic) do + openflow_basic_to_int(:arp_tpa) + catch + _class, _reason -> :arp_tpa + end + + def to_int(:arp_sha, :openflow_basic) do + openflow_basic_to_int(:arp_sha) + catch + _class, _reason -> :arp_sha + end + + def to_int(:arp_tha, :openflow_basic) do + openflow_basic_to_int(:arp_tha) + catch + _class, _reason -> :arp_tha + end + + def to_int(:ipv6_src, :openflow_basic) do + openflow_basic_to_int(:ipv6_src) + catch + _class, _reason -> :ipv6_src + end + + def to_int(:ipv6_dst, :openflow_basic) do + openflow_basic_to_int(:ipv6_dst) + catch + _class, _reason -> :ipv6_dst + end + + def to_int(:ipv6_flabel, :openflow_basic) do + openflow_basic_to_int(:ipv6_flabel) + catch + _class, _reason -> :ipv6_flabel + end + + def to_int(:icmpv6_type, :openflow_basic) do + openflow_basic_to_int(:icmpv6_type) + catch + _class, _reason -> :icmpv6_type + end + + def to_int(:icmpv6_code, :openflow_basic) do + openflow_basic_to_int(:icmpv6_code) + catch + _class, _reason -> :icmpv6_code + end + + def to_int(:ipv6_nd_target, :openflow_basic) do + openflow_basic_to_int(:ipv6_nd_target) + catch + _class, _reason -> :ipv6_nd_target + end + + def to_int(:ipv6_nd_sll, :openflow_basic) do + openflow_basic_to_int(:ipv6_nd_sll) + catch + _class, _reason -> :ipv6_nd_sll + end + + def to_int(:ipv6_nd_tll, :openflow_basic) do + openflow_basic_to_int(:ipv6_nd_tll) + catch + _class, _reason -> :ipv6_nd_tll + end + + def to_int(:mpls_label, :openflow_basic) do + openflow_basic_to_int(:mpls_label) + catch + _class, _reason -> :mpls_label + end + + def to_int(:mpls_tc, :openflow_basic) do + openflow_basic_to_int(:mpls_tc) + catch + _class, _reason -> :mpls_tc + end + + def to_int(:mpls_bos, :openflow_basic) do + openflow_basic_to_int(:mpls_bos) + catch + _class, _reason -> :mpls_bos + end + + def to_int(:pbb_isid, :openflow_basic) do + openflow_basic_to_int(:pbb_isid) + catch + _class, _reason -> :pbb_isid + end + + def to_int(:tunnel_id, :openflow_basic) do + openflow_basic_to_int(:tunnel_id) + catch + _class, _reason -> :tunnel_id + end + + def to_int(:ipv6_exthdr, :openflow_basic) do + openflow_basic_to_int(:ipv6_exthdr) + catch + _class, _reason -> :ipv6_exthdr + end + + def to_int(:pbb_uca, :openflow_basic) do + openflow_basic_to_int(:pbb_uca) + catch + _class, _reason -> :pbb_uca + end + + def to_int(:packet_type, :openflow_basic) do + openflow_basic_to_int(:packet_type) + catch + _class, _reason -> :packet_type + end + + def to_int(:gre_flags, :openflow_basic) do + openflow_basic_to_int(:gre_flags) + catch + _class, _reason -> :gre_flags + end + + def to_int(:gre_ver, :openflow_basic) do + openflow_basic_to_int(:gre_ver) + catch + _class, _reason -> :gre_ver + end + + def to_int(:gre_protocol, :openflow_basic) do + openflow_basic_to_int(:gre_protocol) + catch + _class, _reason -> :gre_protocol + end + + def to_int(:gre_key, :openflow_basic) do + openflow_basic_to_int(:gre_key) + catch + _class, _reason -> :gre_key + end + + def to_int(:gre_seqnum, :openflow_basic) do + openflow_basic_to_int(:gre_seqnum) + catch + _class, _reason -> :gre_seqnum + end + + def to_int(:lisp_flags, :openflow_basic) do + openflow_basic_to_int(:lisp_flags) + catch + _class, _reason -> :lisp_flags + end + + def to_int(:lisp_nonce, :openflow_basic) do + openflow_basic_to_int(:lisp_nonce) + catch + _class, _reason -> :lisp_nonce + end + + def to_int(:lisp_id, :openflow_basic) do + openflow_basic_to_int(:lisp_id) + catch + _class, _reason -> :lisp_id + end + + def to_int(:vxlan_flags, :openflow_basic) do + openflow_basic_to_int(:vxlan_flags) + catch + _class, _reason -> :vxlan_flags + end + + def to_int(:vxlan_vni, :openflow_basic) do + openflow_basic_to_int(:vxlan_vni) + catch + _class, _reason -> :vxlan_vni + end + + def to_int(:mpls_data_first_nibble, :openflow_basic) do + openflow_basic_to_int(:mpls_data_first_nibble) + catch + _class, _reason -> :mpls_data_first_nibble + end + + def to_int(:mpls_ach_version, :openflow_basic) do + openflow_basic_to_int(:mpls_ach_version) + catch + _class, _reason -> :mpls_ach_version + end + + def to_int(:mpls_ach_channel, :openflow_basic) do + openflow_basic_to_int(:mpls_ach_channel) + catch + _class, _reason -> :mpls_ach_channel + end + + def to_int(:mpls_pw_metadata, :openflow_basic) do + openflow_basic_to_int(:mpls_pw_metadata) + catch + _class, _reason -> :mpls_pw_metadata + end + + def to_int(:mpls_cw_flags, :openflow_basic) do + openflow_basic_to_int(:mpls_cw_flags) + catch + _class, _reason -> :mpls_cw_flags + end + + def to_int(:mpls_cw_fragment, :openflow_basic) do + openflow_basic_to_int(:mpls_cw_fragment) + catch + _class, _reason -> :mpls_cw_fragment + end + + def to_int(:mpls_cw_len, :openflow_basic) do + openflow_basic_to_int(:mpls_cw_len) + catch + _class, _reason -> :mpls_cw_len + end + + def to_int(:mpls_cw_seq_num, :openflow_basic) do + openflow_basic_to_int(:mpls_cw_seq_num) + catch + _class, _reason -> :mpls_cw_seq_num + end + + def to_int(:gtpu_flags, :openflow_basic) do + openflow_basic_to_int(:gtpu_flags) + catch + _class, _reason -> :gtpu_flags + end + + def to_int(:gtpu_ver, :openflow_basic) do + openflow_basic_to_int(:gtpu_ver) + catch + _class, _reason -> :gtpu_ver + end + + def to_int(:gtpu_msg_type, :openflow_basic) do + openflow_basic_to_int(:gtpu_msg_type) + catch + _class, _reason -> :gtpu_msg_type + end + + def to_int(:gtpu_teid, :openflow_basic) do + openflow_basic_to_int(:gtpu_teid) + catch + _class, _reason -> :gtpu_teid + end + + def to_int(:gtpu_extn_hdr, :openflow_basic) do + openflow_basic_to_int(:gtpu_extn_hdr) + catch + _class, _reason -> :gtpu_extn_hdr + end + + def to_int(:gtpu_extn_udp_port, :openflow_basic) do + openflow_basic_to_int(:gtpu_extn_udp_port) + catch + _class, _reason -> :gtpu_extn_udp_port + end + + def to_int(:gtpu_extn_sci, :openflow_basic) do + openflow_basic_to_int(:gtpu_extn_sci) + catch + _class, _reason -> :gtpu_extn_sci + end + + def to_int(_int, :openflow_basic) do + throw(:bad_enum) + end + + def to_int(:present, :vlan_id) do + vlan_id_to_int(:present) + catch + _class, _reason -> :present + end + + def to_int(:none, :vlan_id) do + vlan_id_to_int(:none) + catch + _class, _reason -> :none + end + + def to_int(_int, :vlan_id) do + throw(:bad_enum) + end + + def to_int(:nonext, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:nonext) + catch + _class, _reason -> :nonext + end + + def to_int(:esp, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:esp) + catch + _class, _reason -> :esp + end + + def to_int(:auth, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:auth) + catch + _class, _reason -> :auth + end + + def to_int(:dest, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:dest) + catch + _class, _reason -> :dest + end + + def to_int(:frag, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:frag) + catch + _class, _reason -> :frag + end + + def to_int(:router, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:router) + catch + _class, _reason -> :router + end + + def to_int(:hop, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:hop) + catch + _class, _reason -> :hop + end + + def to_int(:unrep, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:unrep) + catch + _class, _reason -> :unrep + end + + def to_int(:unseq, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_int(:unseq) + catch + _class, _reason -> :unseq + end + + def to_int(_int, :ipv6exthdr_flags) do + throw(:bad_enum) + end + + def to_int(:fin, :tcp_flags) do + tcp_flags_to_int(:fin) + catch + _class, _reason -> :fin + end + + def to_int(:syn, :tcp_flags) do + tcp_flags_to_int(:syn) + catch + _class, _reason -> :syn + end + + def to_int(:rst, :tcp_flags) do + tcp_flags_to_int(:rst) + catch + _class, _reason -> :rst + end + + def to_int(:psh, :tcp_flags) do + tcp_flags_to_int(:psh) + catch + _class, _reason -> :psh + end + + def to_int(:ack, :tcp_flags) do + tcp_flags_to_int(:ack) + catch + _class, _reason -> :ack + end + + def to_int(:urg, :tcp_flags) do + tcp_flags_to_int(:urg) + catch + _class, _reason -> :urg + end + + def to_int(:ece, :tcp_flags) do + tcp_flags_to_int(:ece) + catch + _class, _reason -> :ece + end + + def to_int(:cwr, :tcp_flags) do + tcp_flags_to_int(:cwr) + catch + _class, _reason -> :cwr + end + + def to_int(:ns, :tcp_flags) do + tcp_flags_to_int(:ns) + catch + _class, _reason -> :ns + end + + def to_int(_int, :tcp_flags) do + throw(:bad_enum) + end + + def to_int(:new, :ct_state_flags) do + ct_state_flags_to_int(:new) + catch + _class, _reason -> :new + end + + def to_int(:est, :ct_state_flags) do + ct_state_flags_to_int(:est) + catch + _class, _reason -> :est + end + + def to_int(:rel, :ct_state_flags) do + ct_state_flags_to_int(:rel) + catch + _class, _reason -> :rel + end + + def to_int(:rep, :ct_state_flags) do + ct_state_flags_to_int(:rep) + catch + _class, _reason -> :rep + end + + def to_int(:inv, :ct_state_flags) do + ct_state_flags_to_int(:inv) + catch + _class, _reason -> :inv + end + + def to_int(:trk, :ct_state_flags) do + ct_state_flags_to_int(:trk) + catch + _class, _reason -> :trk + end + + def to_int(:snat, :ct_state_flags) do + ct_state_flags_to_int(:snat) + catch + _class, _reason -> :snat + end + + def to_int(:dnat, :ct_state_flags) do + ct_state_flags_to_int(:dnat) + catch + _class, _reason -> :dnat + end + + def to_int(_int, :ct_state_flags) do + throw(:bad_enum) + end + + def to_int(:xreg0, :packet_register) do + packet_register_to_int(:xreg0) + catch + _class, _reason -> :xreg0 + end + + def to_int(:xreg1, :packet_register) do + packet_register_to_int(:xreg1) + catch + _class, _reason -> :xreg1 + end + + def to_int(:xreg2, :packet_register) do + packet_register_to_int(:xreg2) + catch + _class, _reason -> :xreg2 + end + + def to_int(:xreg3, :packet_register) do + packet_register_to_int(:xreg3) + catch + _class, _reason -> :xreg3 + end + + def to_int(:xreg4, :packet_register) do + packet_register_to_int(:xreg4) + catch + _class, _reason -> :xreg4 + end + + def to_int(:xreg5, :packet_register) do + packet_register_to_int(:xreg5) + catch + _class, _reason -> :xreg5 + end + + def to_int(:xreg6, :packet_register) do + packet_register_to_int(:xreg6) + catch + _class, _reason -> :xreg6 + end + + def to_int(:xreg7, :packet_register) do + packet_register_to_int(:xreg7) + catch + _class, _reason -> :xreg7 + end + + def to_int(_int, :packet_register) do + throw(:bad_enum) + end + + def to_int(:nsh_flags, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_flags) + catch + _class, _reason -> :nsh_flags + end + + def to_int(:nsh_mdtype, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_mdtype) + catch + _class, _reason -> :nsh_mdtype + end + + def to_int(:nsh_np, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_np) + catch + _class, _reason -> :nsh_np + end + + def to_int(:nsh_spi, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_spi) + catch + _class, _reason -> :nsh_spi + end + + def to_int(:nsh_si, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_si) + catch + _class, _reason -> :nsh_si + end + + def to_int(:nsh_c1, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_c1) + catch + _class, _reason -> :nsh_c1 + end + + def to_int(:nsh_c2, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_c2) + catch + _class, _reason -> :nsh_c2 + end + + def to_int(:nsh_c3, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_c3) + catch + _class, _reason -> :nsh_c3 + end + + def to_int(:nsh_c4, :nicira_ext_match) do + nicira_ext_match_to_int(:nsh_c4) + catch + _class, _reason -> :nsh_c4 + end + + def to_int(_int, :nicira_ext_match) do + throw(:bad_enum) + end + + def to_int(:hp_udp_src_port_range, :hp_ext_match) do + hp_ext_match_to_int(:hp_udp_src_port_range) + catch + _class, _reason -> :hp_udp_src_port_range + end + + def to_int(:hp_udp_dst_port_range, :hp_ext_match) do + hp_ext_match_to_int(:hp_udp_dst_port_range) + catch + _class, _reason -> :hp_udp_dst_port_range + end + + def to_int(:hp_tcp_src_port_range, :hp_ext_match) do + hp_ext_match_to_int(:hp_tcp_src_port_range) + catch + _class, _reason -> :hp_tcp_src_port_range + end + + def to_int(:hp_tcp_dst_port_range, :hp_ext_match) do + hp_ext_match_to_int(:hp_tcp_dst_port_range) + catch + _class, _reason -> :hp_tcp_dst_port_range + end + + def to_int(:hp_tcp_flags, :hp_ext_match) do + hp_ext_match_to_int(:hp_tcp_flags) + catch + _class, _reason -> :hp_tcp_flags + end + + def to_int(:hp_custom_1, :hp_ext_match) do + hp_ext_match_to_int(:hp_custom_1) + catch + _class, _reason -> :hp_custom_1 + end + + def to_int(:hp_custom_2, :hp_ext_match) do + hp_ext_match_to_int(:hp_custom_2) + catch + _class, _reason -> :hp_custom_2 + end + + def to_int(:hp_custom_3, :hp_ext_match) do + hp_ext_match_to_int(:hp_custom_3) + catch + _class, _reason -> :hp_custom_3 + end + + def to_int(:hp_custom_4, :hp_ext_match) do + hp_ext_match_to_int(:hp_custom_4) + catch + _class, _reason -> :hp_custom_4 + end + + def to_int(_int, :hp_ext_match) do + throw(:bad_enum) + end + + def to_int(:l2_start, :hp_custom_match_type) do + hp_custom_match_type_to_int(:l2_start) + catch + _class, _reason -> :l2_start + end + + def to_int(:l3_start, :hp_custom_match_type) do + hp_custom_match_type_to_int(:l3_start) + catch + _class, _reason -> :l3_start + end + + def to_int(:l4_start, :hp_custom_match_type) do + hp_custom_match_type_to_int(:l4_start) + catch + _class, _reason -> :l4_start + end + + def to_int(_int, :hp_custom_match_type) do + throw(:bad_enum) + end + + def to_int(:onf_tcp_flags, :onf_ext_match) do + onf_ext_match_to_int(:onf_tcp_flags) + catch + _class, _reason -> :onf_tcp_flags + end + + def to_int(:onf_actset_output, :onf_ext_match) do + onf_ext_match_to_int(:onf_actset_output) + catch + _class, _reason -> :onf_actset_output + end + + def to_int(:onf_pbb_uca, :onf_ext_match) do + onf_ext_match_to_int(:onf_pbb_uca) + catch + _class, _reason -> :onf_pbb_uca + end + + def to_int(_int, :onf_ext_match) do + throw(:bad_enum) + end + + def to_int(:no_buffer, :buffer_id) do + buffer_id_to_int(:no_buffer) + catch + _class, _reason -> :no_buffer + end + + def to_int(_int, :buffer_id) do + throw(:bad_enum) + end + + def to_int(:port_down, :port_config) do + port_config_to_int(:port_down) + catch + _class, _reason -> :port_down + end + + def to_int(:no_receive, :port_config) do + port_config_to_int(:no_receive) + catch + _class, _reason -> :no_receive + end + + def to_int(:no_forward, :port_config) do + port_config_to_int(:no_forward) + catch + _class, _reason -> :no_forward + end + + def to_int(:no_packet_in, :port_config) do + port_config_to_int(:no_packet_in) + catch + _class, _reason -> :no_packet_in + end + + def to_int(_int, :port_config) do + throw(:bad_enum) + end + + def to_int(:link_down, :port_state) do + port_state_to_int(:link_down) + catch + _class, _reason -> :link_down + end + + def to_int(:blocked, :port_state) do + port_state_to_int(:blocked) + catch + _class, _reason -> :blocked + end + + def to_int(:live, :port_state) do + port_state_to_int(:live) + catch + _class, _reason -> :live + end + + def to_int(_int, :port_state) do + throw(:bad_enum) + end + + def to_int(:"10mb_hd", :port_features) do + port_features_to_int(:"10mb_hd") + catch + _class, _reason -> :"10mb_hd" + end + + def to_int(:"10mb_fd", :port_features) do + port_features_to_int(:"10mb_fd") + catch + _class, _reason -> :"10mb_fd" + end + + def to_int(:"100mb_hd", :port_features) do + port_features_to_int(:"100mb_hd") + catch + _class, _reason -> :"100mb_hd" + end + + def to_int(:"100mb_fd", :port_features) do + port_features_to_int(:"100mb_fd") + catch + _class, _reason -> :"100mb_fd" + end + + def to_int(:"1gb_hd", :port_features) do + port_features_to_int(:"1gb_hd") + catch + _class, _reason -> :"1gb_hd" + end + + def to_int(:"1gb_fd", :port_features) do + port_features_to_int(:"1gb_fd") + catch + _class, _reason -> :"1gb_fd" + end + + def to_int(:"10gb_fd", :port_features) do + port_features_to_int(:"10gb_fd") + catch + _class, _reason -> :"10gb_fd" + end + + def to_int(:"40gb_fd", :port_features) do + port_features_to_int(:"40gb_fd") + catch + _class, _reason -> :"40gb_fd" + end + + def to_int(:"100gb_fd", :port_features) do + port_features_to_int(:"100gb_fd") + catch + _class, _reason -> :"100gb_fd" + end + + def to_int(:"1tb_fd", :port_features) do + port_features_to_int(:"1tb_fd") + catch + _class, _reason -> :"1tb_fd" + end + + def to_int(:other, :port_features) do + port_features_to_int(:other) + catch + _class, _reason -> :other + end + + def to_int(:copper, :port_features) do + port_features_to_int(:copper) + catch + _class, _reason -> :copper + end + + def to_int(:fiber, :port_features) do + port_features_to_int(:fiber) + catch + _class, _reason -> :fiber + end + + def to_int(:autoneg, :port_features) do + port_features_to_int(:autoneg) + catch + _class, _reason -> :autoneg + end + + def to_int(:pause, :port_features) do + port_features_to_int(:pause) + catch + _class, _reason -> :pause + end + + def to_int(:pause_asym, :port_features) do + port_features_to_int(:pause_asym) + catch + _class, _reason -> :pause_asym + end + + def to_int(_int, :port_features) do + throw(:bad_enum) + end + + def to_int(:max, :openflow10_port_no) do + openflow10_port_no_to_int(:max) + catch + _class, _reason -> :max + end + + def to_int(:in_port, :openflow10_port_no) do + openflow10_port_no_to_int(:in_port) + catch + _class, _reason -> :in_port + end + + def to_int(:table, :openflow10_port_no) do + openflow10_port_no_to_int(:table) + catch + _class, _reason -> :table + end + + def to_int(:normal, :openflow10_port_no) do + openflow10_port_no_to_int(:normal) + catch + _class, _reason -> :normal + end + + def to_int(:flood, :openflow10_port_no) do + openflow10_port_no_to_int(:flood) + catch + _class, _reason -> :flood + end + + def to_int(:all, :openflow10_port_no) do + openflow10_port_no_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(:controller, :openflow10_port_no) do + openflow10_port_no_to_int(:controller) + catch + _class, _reason -> :controller + end + + def to_int(:local, :openflow10_port_no) do + openflow10_port_no_to_int(:local) + catch + _class, _reason -> :local + end + + def to_int(:none, :openflow10_port_no) do + openflow10_port_no_to_int(:none) + catch + _class, _reason -> :none + end + + def to_int(_int, :openflow10_port_no) do + throw(:bad_enum) + end + + def to_int(:max, :openflow13_port_no) do + openflow13_port_no_to_int(:max) + catch + _class, _reason -> :max + end + + def to_int(:in_port, :openflow13_port_no) do + openflow13_port_no_to_int(:in_port) + catch + _class, _reason -> :in_port + end + + def to_int(:table, :openflow13_port_no) do + openflow13_port_no_to_int(:table) + catch + _class, _reason -> :table + end + + def to_int(:normal, :openflow13_port_no) do + openflow13_port_no_to_int(:normal) + catch + _class, _reason -> :normal + end + + def to_int(:flood, :openflow13_port_no) do + openflow13_port_no_to_int(:flood) + catch + _class, _reason -> :flood + end + + def to_int(:all, :openflow13_port_no) do + openflow13_port_no_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(:controller, :openflow13_port_no) do + openflow13_port_no_to_int(:controller) + catch + _class, _reason -> :controller + end + + def to_int(:local, :openflow13_port_no) do + openflow13_port_no_to_int(:local) + catch + _class, _reason -> :local + end + + def to_int(:any, :openflow13_port_no) do + openflow13_port_no_to_int(:any) + catch + _class, _reason -> :any + end + + def to_int(_int, :openflow13_port_no) do + throw(:bad_enum) + end + + def to_int(:no_match, :packet_in_reason) do + packet_in_reason_to_int(:no_match) + catch + _class, _reason -> :no_match + end + + def to_int(:action, :packet_in_reason) do + packet_in_reason_to_int(:action) + catch + _class, _reason -> :action + end + + def to_int(:invalid_ttl, :packet_in_reason) do + packet_in_reason_to_int(:invalid_ttl) + catch + _class, _reason -> :invalid_ttl + end + + def to_int(:action_set, :packet_in_reason) do + packet_in_reason_to_int(:action_set) + catch + _class, _reason -> :action_set + end + + def to_int(:group, :packet_in_reason) do + packet_in_reason_to_int(:group) + catch + _class, _reason -> :group + end + + def to_int(:packet_out, :packet_in_reason) do + packet_in_reason_to_int(:packet_out) + catch + _class, _reason -> :packet_out + end + + def to_int(_int, :packet_in_reason) do + throw(:bad_enum) + end + + def to_int(:add, :flow_mod_command) do + flow_mod_command_to_int(:add) + catch + _class, _reason -> :add + end + + def to_int(:modify, :flow_mod_command) do + flow_mod_command_to_int(:modify) + catch + _class, _reason -> :modify + end + + def to_int(:modify_strict, :flow_mod_command) do + flow_mod_command_to_int(:modify_strict) + catch + _class, _reason -> :modify_strict + end + + def to_int(:delete, :flow_mod_command) do + flow_mod_command_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(:delete_strict, :flow_mod_command) do + flow_mod_command_to_int(:delete_strict) + catch + _class, _reason -> :delete_strict + end + + def to_int(_int, :flow_mod_command) do + throw(:bad_enum) + end + + def to_int(:send_flow_rem, :flow_mod_flags) do + flow_mod_flags_to_int(:send_flow_rem) + catch + _class, _reason -> :send_flow_rem + end + + def to_int(:check_overlap, :flow_mod_flags) do + flow_mod_flags_to_int(:check_overlap) + catch + _class, _reason -> :check_overlap + end + + def to_int(:reset_counts, :flow_mod_flags) do + flow_mod_flags_to_int(:reset_counts) + catch + _class, _reason -> :reset_counts + end + + def to_int(:no_packet_counts, :flow_mod_flags) do + flow_mod_flags_to_int(:no_packet_counts) + catch + _class, _reason -> :no_packet_counts + end + + def to_int(:no_byte_counts, :flow_mod_flags) do + flow_mod_flags_to_int(:no_byte_counts) + catch + _class, _reason -> :no_byte_counts + end + + def to_int(_int, :flow_mod_flags) do + throw(:bad_enum) + end + + def to_int(:idle_timeout, :flow_removed_reason) do + flow_removed_reason_to_int(:idle_timeout) + catch + _class, _reason -> :idle_timeout + end + + def to_int(:hard_timeout, :flow_removed_reason) do + flow_removed_reason_to_int(:hard_timeout) + catch + _class, _reason -> :hard_timeout + end + + def to_int(:delete, :flow_removed_reason) do + flow_removed_reason_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(:group_delete, :flow_removed_reason) do + flow_removed_reason_to_int(:group_delete) + catch + _class, _reason -> :group_delete + end + + def to_int(:meter_delete, :flow_removed_reason) do + flow_removed_reason_to_int(:meter_delete) + catch + _class, _reason -> :meter_delete + end + + def to_int(:eviction, :flow_removed_reason) do + flow_removed_reason_to_int(:eviction) + catch + _class, _reason -> :eviction + end + + def to_int(_int, :flow_removed_reason) do + throw(:bad_enum) + end + + def to_int(:add, :port_reason) do + port_reason_to_int(:add) + catch + _class, _reason -> :add + end + + def to_int(:delete, :port_reason) do + port_reason_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(:modify, :port_reason) do + port_reason_to_int(:modify) + catch + _class, _reason -> :modify + end + + def to_int(_int, :port_reason) do + throw(:bad_enum) + end + + def to_int(:add, :group_mod_command) do + group_mod_command_to_int(:add) + catch + _class, _reason -> :add + end + + def to_int(:modify, :group_mod_command) do + group_mod_command_to_int(:modify) + catch + _class, _reason -> :modify + end + + def to_int(:delete, :group_mod_command) do + group_mod_command_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(_int, :group_mod_command) do + throw(:bad_enum) + end + + def to_int(:all, :group_type) do + group_type_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(:select, :group_type) do + group_type_to_int(:select) + catch + _class, _reason -> :select + end + + def to_int(:indirect, :group_type) do + group_type_to_int(:indirect) + catch + _class, _reason -> :indirect + end + + def to_int(:fast_failover, :group_type) do + group_type_to_int(:fast_failover) + catch + _class, _reason -> :fast_failover + end + + def to_int(_int, :group_type) do + throw(:bad_enum) + end + + def to_int(:max, :group_id) do + group_id_to_int(:max) + catch + _class, _reason -> :max + end + + def to_int(:all, :group_id) do + group_id_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(:any, :group_id) do + group_id_to_int(:any) + catch + _class, _reason -> :any + end + + def to_int(_int, :group_id) do + throw(:bad_enum) + end + + def to_int(:select_weight, :group_capabilities) do + group_capabilities_to_int(:select_weight) + catch + _class, _reason -> :select_weight + end + + def to_int(:select_liveness, :group_capabilities) do + group_capabilities_to_int(:select_liveness) + catch + _class, _reason -> :select_liveness + end + + def to_int(:chaining, :group_capabilities) do + group_capabilities_to_int(:chaining) + catch + _class, _reason -> :chaining + end + + def to_int(:chaining_checks, :group_capabilities) do + group_capabilities_to_int(:chaining_checks) + catch + _class, _reason -> :chaining_checks + end + + def to_int(_int, :group_capabilities) do + throw(:bad_enum) + end + + def to_int(:max, :table_id) do + table_id_to_int(:max) + catch + _class, _reason -> :max + end + + def to_int(:all, :table_id) do + table_id_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(_int, :table_id) do + throw(:bad_enum) + end + + def to_int(:all, :queue_id) do + queue_id_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(_int, :queue_id) do + throw(:bad_enum) + end + + def to_int(:add, :meter_mod_command) do + meter_mod_command_to_int(:add) + catch + _class, _reason -> :add + end + + def to_int(:modify, :meter_mod_command) do + meter_mod_command_to_int(:modify) + catch + _class, _reason -> :modify + end + + def to_int(:delete, :meter_mod_command) do + meter_mod_command_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(_int, :meter_mod_command) do + throw(:bad_enum) + end + + def to_int(:max, :meter_id) do + meter_id_to_int(:max) + catch + _class, _reason -> :max + end + + def to_int(:slowpath, :meter_id) do + meter_id_to_int(:slowpath) + catch + _class, _reason -> :slowpath + end + + def to_int(:controller, :meter_id) do + meter_id_to_int(:controller) + catch + _class, _reason -> :controller + end + + def to_int(:all, :meter_id) do + meter_id_to_int(:all) + catch + _class, _reason -> :all + end + + def to_int(_int, :meter_id) do + throw(:bad_enum) + end + + def to_int(:kbps, :meter_flags) do + meter_flags_to_int(:kbps) + catch + _class, _reason -> :kbps + end + + def to_int(:pktps, :meter_flags) do + meter_flags_to_int(:pktps) + catch + _class, _reason -> :pktps + end + + def to_int(:burst, :meter_flags) do + meter_flags_to_int(:burst) + catch + _class, _reason -> :burst + end + + def to_int(:stats, :meter_flags) do + meter_flags_to_int(:stats) + catch + _class, _reason -> :stats + end + + def to_int(_int, :meter_flags) do + throw(:bad_enum) + end + + def to_int(Openflow.MeterBand.Drop, :meter_band_type) do + meter_band_type_to_int(Openflow.MeterBand.Drop) + catch + _class, _reason -> Openflow.MeterBand.Drop + end + + def to_int(Openflow.MeterBand.Remark, :meter_band_type) do + meter_band_type_to_int(Openflow.MeterBand.Remark) + catch + _class, _reason -> Openflow.MeterBand.Remark + end + + def to_int(Openflow.MeterBand.Experimenter, :meter_band_type) do + meter_band_type_to_int(Openflow.MeterBand.Experimenter) + catch + _class, _reason -> Openflow.MeterBand.Experimenter + end + + def to_int(_int, :meter_band_type) do + throw(:bad_enum) + end + + def to_int(:table_miss_controller, :table_config) do + table_config_to_int(:table_miss_controller) + catch + _class, _reason -> :table_miss_controller + end + + def to_int(:table_miss_continue, :table_config) do + table_config_to_int(:table_miss_continue) + catch + _class, _reason -> :table_miss_continue + end + + def to_int(:table_miss_drop, :table_config) do + table_config_to_int(:table_miss_drop) + catch + _class, _reason -> :table_miss_drop + end + + def to_int(:table_miss_mask, :table_config) do + table_config_to_int(:table_miss_mask) + catch + _class, _reason -> :table_miss_mask + end + + def to_int(:eviction, :table_config) do + table_config_to_int(:eviction) + catch + _class, _reason -> :eviction + end + + def to_int(:vacancy_events, :table_config) do + table_config_to_int(:vacancy_events) + catch + _class, _reason -> :vacancy_events + end + + def to_int(_int, :table_config) do + throw(:bad_enum) + end + + def to_int(Openflow.Action.Output, :action_type) do + action_type_to_int(Openflow.Action.Output) + catch + _class, _reason -> Openflow.Action.Output + end + + def to_int(Openflow.Action.CopyTtlOut, :action_type) do + action_type_to_int(Openflow.Action.CopyTtlOut) + catch + _class, _reason -> Openflow.Action.CopyTtlOut + end + + def to_int(Openflow.Action.CopyTtlIn, :action_type) do + action_type_to_int(Openflow.Action.CopyTtlIn) + catch + _class, _reason -> Openflow.Action.CopyTtlIn + end + + def to_int(Openflow.Action.SetMplsTtl, :action_type) do + action_type_to_int(Openflow.Action.SetMplsTtl) + catch + _class, _reason -> Openflow.Action.SetMplsTtl + end + + def to_int(Openflow.Action.DecMplsTtl, :action_type) do + action_type_to_int(Openflow.Action.DecMplsTtl) + catch + _class, _reason -> Openflow.Action.DecMplsTtl + end + + def to_int(Openflow.Action.PushVlan, :action_type) do + action_type_to_int(Openflow.Action.PushVlan) + catch + _class, _reason -> Openflow.Action.PushVlan + end + + def to_int(Openflow.Action.PopVlan, :action_type) do + action_type_to_int(Openflow.Action.PopVlan) + catch + _class, _reason -> Openflow.Action.PopVlan + end + + def to_int(Openflow.Action.PushMpls, :action_type) do + action_type_to_int(Openflow.Action.PushMpls) + catch + _class, _reason -> Openflow.Action.PushMpls + end + + def to_int(Openflow.Action.PopMpls, :action_type) do + action_type_to_int(Openflow.Action.PopMpls) + catch + _class, _reason -> Openflow.Action.PopMpls + end + + def to_int(Openflow.Action.SetQueue, :action_type) do + action_type_to_int(Openflow.Action.SetQueue) + catch + _class, _reason -> Openflow.Action.SetQueue + end + + def to_int(Openflow.Action.Group, :action_type) do + action_type_to_int(Openflow.Action.Group) + catch + _class, _reason -> Openflow.Action.Group + end + + def to_int(Openflow.Action.SetNwTtl, :action_type) do + action_type_to_int(Openflow.Action.SetNwTtl) + catch + _class, _reason -> Openflow.Action.SetNwTtl + end + + def to_int(Openflow.Action.DecNwTtl, :action_type) do + action_type_to_int(Openflow.Action.DecNwTtl) + catch + _class, _reason -> Openflow.Action.DecNwTtl + end + + def to_int(Openflow.Action.SetField, :action_type) do + action_type_to_int(Openflow.Action.SetField) + catch + _class, _reason -> Openflow.Action.SetField + end + + def to_int(Openflow.Action.PushPbb, :action_type) do + action_type_to_int(Openflow.Action.PushPbb) + catch + _class, _reason -> Openflow.Action.PushPbb + end + + def to_int(Openflow.Action.PopPbb, :action_type) do + action_type_to_int(Openflow.Action.PopPbb) + catch + _class, _reason -> Openflow.Action.PopPbb + end + + def to_int(Openflow.Action.Encap, :action_type) do + action_type_to_int(Openflow.Action.Encap) + catch + _class, _reason -> Openflow.Action.Encap + end + + def to_int(Openflow.Action.Decap, :action_type) do + action_type_to_int(Openflow.Action.Decap) + catch + _class, _reason -> Openflow.Action.Decap + end + + def to_int(Openflow.Action.SetSequence, :action_type) do + action_type_to_int(Openflow.Action.SetSequence) + catch + _class, _reason -> Openflow.Action.SetSequence + end + + def to_int(Openflow.Action.ValidateSequence, :action_type) do + action_type_to_int(Openflow.Action.ValidateSequence) + catch + _class, _reason -> Openflow.Action.ValidateSequence + end + + def to_int(Openflow.Action.Experimenter, :action_type) do + action_type_to_int(Openflow.Action.Experimenter) + catch + _class, _reason -> Openflow.Action.Experimenter + end + + def to_int(_int, :action_type) do + throw(:bad_enum) + end + + def to_int(:nicira_ext_action, :action_vendor) do + action_vendor_to_int(:nicira_ext_action) + catch + _class, _reason -> :nicira_ext_action + end + + def to_int(:onf_ext_action, :action_vendor) do + action_vendor_to_int(:onf_ext_action) + catch + _class, _reason -> :onf_ext_action + end + + def to_int(_int, :action_vendor) do + throw(:bad_enum) + end + + def to_int(Openflow.Action.OnfCopyField, :onf_ext_action) do + onf_ext_action_to_int(Openflow.Action.OnfCopyField) + catch + _class, _reason -> Openflow.Action.OnfCopyField + end + + def to_int(_int, :onf_ext_action) do + throw(:bad_enum) + end + + def to_int(Openflow.Action.NxResubmit, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxResubmit) + catch + _class, _reason -> Openflow.Action.NxResubmit + end + + def to_int(Openflow.Action.NxSetTunnel, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSetTunnel) + catch + _class, _reason -> Openflow.Action.NxSetTunnel + end + + def to_int(Openflow.Action.NxSetQueue, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSetQueue) + catch + _class, _reason -> Openflow.Action.NxSetQueue + end + + def to_int(Openflow.Action.NxPopQueue, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxPopQueue) + catch + _class, _reason -> Openflow.Action.NxPopQueue + end + + def to_int(Openflow.Action.NxRegMove, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxRegMove) + catch + _class, _reason -> Openflow.Action.NxRegMove + end + + def to_int(Openflow.Action.NxRegLoad, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxRegLoad) + catch + _class, _reason -> Openflow.Action.NxRegLoad + end + + def to_int(Openflow.Action.NxNote, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxNote) + catch + _class, _reason -> Openflow.Action.NxNote + end + + def to_int(Openflow.Action.NxSetTunnel64, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSetTunnel64) + catch + _class, _reason -> Openflow.Action.NxSetTunnel64 + end + + def to_int(Openflow.Action.NxMultipath, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxMultipath) + catch + _class, _reason -> Openflow.Action.NxMultipath + end + + def to_int(Openflow.Action.NxBundle, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxBundle) + catch + _class, _reason -> Openflow.Action.NxBundle + end + + def to_int(Openflow.Action.NxBundleLoad, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxBundleLoad) + catch + _class, _reason -> Openflow.Action.NxBundleLoad + end + + def to_int(Openflow.Action.NxResubmitTable, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxResubmitTable) + catch + _class, _reason -> Openflow.Action.NxResubmitTable + end + + def to_int(Openflow.Action.NxOutputReg, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxOutputReg) + catch + _class, _reason -> Openflow.Action.NxOutputReg + end + + def to_int(Openflow.Action.NxLearn, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxLearn) + catch + _class, _reason -> Openflow.Action.NxLearn + end + + def to_int(Openflow.Action.NxExit, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxExit) + catch + _class, _reason -> Openflow.Action.NxExit + end + + def to_int(Openflow.Action.NxDecTtl, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxDecTtl) + catch + _class, _reason -> Openflow.Action.NxDecTtl + end + + def to_int(Openflow.Action.NxFinTimeout, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxFinTimeout) + catch + _class, _reason -> Openflow.Action.NxFinTimeout + end + + def to_int(Openflow.Action.NxController, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxController) + catch + _class, _reason -> Openflow.Action.NxController + end + + def to_int(Openflow.Action.NxDecTtlCntIds, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxDecTtlCntIds) + catch + _class, _reason -> Openflow.Action.NxDecTtlCntIds + end + + def to_int(Openflow.Action.NxWriteMetadata, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxWriteMetadata) + catch + _class, _reason -> Openflow.Action.NxWriteMetadata + end + + def to_int(Openflow.Action.NxPushMpls, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxPushMpls) + catch + _class, _reason -> Openflow.Action.NxPushMpls + end + + def to_int(Openflow.Action.NxPopMpls, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxPopMpls) + catch + _class, _reason -> Openflow.Action.NxPopMpls + end + + def to_int(Openflow.Action.NxSetMplsTtl, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSetMplsTtl) + catch + _class, _reason -> Openflow.Action.NxSetMplsTtl + end + + def to_int(Openflow.Action.NxDecMplsTtl, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxDecMplsTtl) + catch + _class, _reason -> Openflow.Action.NxDecMplsTtl + end + + def to_int(Openflow.Action.NxStackPush, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxStackPush) + catch + _class, _reason -> Openflow.Action.NxStackPush + end + + def to_int(Openflow.Action.NxStackPop, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxStackPop) + catch + _class, _reason -> Openflow.Action.NxStackPop + end + + def to_int(Openflow.Action.NxSample, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSample) + catch + _class, _reason -> Openflow.Action.NxSample + end + + def to_int(Openflow.Action.NxSetMplsLabel, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSetMplsLabel) + catch + _class, _reason -> Openflow.Action.NxSetMplsLabel + end + + def to_int(Openflow.Action.NxSetMplsTc, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSetMplsTc) + catch + _class, _reason -> Openflow.Action.NxSetMplsTc + end + + def to_int(Openflow.Action.NxOutputReg2, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxOutputReg2) + catch + _class, _reason -> Openflow.Action.NxOutputReg2 + end + + def to_int(Openflow.Action.NxRegLoad2, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxRegLoad2) + catch + _class, _reason -> Openflow.Action.NxRegLoad2 + end + + def to_int(Openflow.Action.NxConjunction, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxConjunction) + catch + _class, _reason -> Openflow.Action.NxConjunction + end + + def to_int(Openflow.Action.NxConntrack, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxConntrack) + catch + _class, _reason -> Openflow.Action.NxConntrack + end + + def to_int(Openflow.Action.NxNat, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxNat) + catch + _class, _reason -> Openflow.Action.NxNat + end + + def to_int(Openflow.Action.NxController2, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxController2) + catch + _class, _reason -> Openflow.Action.NxController2 + end + + def to_int(Openflow.Action.NxSample2, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSample2) + catch + _class, _reason -> Openflow.Action.NxSample2 + end + + def to_int(Openflow.Action.NxOutputTrunc, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxOutputTrunc) + catch + _class, _reason -> Openflow.Action.NxOutputTrunc + end + + def to_int(Openflow.Action.NxGroup, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxGroup) + catch + _class, _reason -> Openflow.Action.NxGroup + end + + def to_int(Openflow.Action.NxSample3, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxSample3) + catch + _class, _reason -> Openflow.Action.NxSample3 + end + + def to_int(Openflow.Action.NxClone, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxClone) + catch + _class, _reason -> Openflow.Action.NxClone + end + + def to_int(Openflow.Action.NxCtClear, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxCtClear) + catch + _class, _reason -> Openflow.Action.NxCtClear + end + + def to_int(Openflow.Action.NxResubmitTableCt, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxResubmitTableCt) + catch + _class, _reason -> Openflow.Action.NxResubmitTableCt + end + + def to_int(Openflow.Action.NxLearn2, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxLearn2) + catch + _class, _reason -> Openflow.Action.NxLearn2 + end + + def to_int(Openflow.Action.NxEncap, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxEncap) + catch + _class, _reason -> Openflow.Action.NxEncap + end + + def to_int(Openflow.Action.NxDecap, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxDecap) + catch + _class, _reason -> Openflow.Action.NxDecap + end + + def to_int(Openflow.Action.NxDebugRecirc, :nicira_ext_action) do + nicira_ext_action_to_int(Openflow.Action.NxDebugRecirc) + catch + _class, _reason -> Openflow.Action.NxDebugRecirc + end + + def to_int(_int, :nicira_ext_action) do + throw(:bad_enum) + end + + def to_int(:modulo_n, :nx_mp_algorithm) do + nx_mp_algorithm_to_int(:modulo_n) + catch + _class, _reason -> :modulo_n + end + + def to_int(:hash_threshold, :nx_mp_algorithm) do + nx_mp_algorithm_to_int(:hash_threshold) + catch + _class, _reason -> :hash_threshold + end + + def to_int(:highest_random_weight, :nx_mp_algorithm) do + nx_mp_algorithm_to_int(:highest_random_weight) + catch + _class, _reason -> :highest_random_weight + end + + def to_int(:iterative_hash, :nx_mp_algorithm) do + nx_mp_algorithm_to_int(:iterative_hash) + catch + _class, _reason -> :iterative_hash + end + + def to_int(_int, :nx_mp_algorithm) do + throw(:bad_enum) + end + + def to_int(:eth_src, :nx_hash_fields) do + nx_hash_fields_to_int(:eth_src) + catch + _class, _reason -> :eth_src + end + + def to_int(:symmetric_l4, :nx_hash_fields) do + nx_hash_fields_to_int(:symmetric_l4) + catch + _class, _reason -> :symmetric_l4 + end + + def to_int(:symmetric_l3l4, :nx_hash_fields) do + nx_hash_fields_to_int(:symmetric_l3l4) + catch + _class, _reason -> :symmetric_l3l4 + end + + def to_int(:symmetric_l3l4_udp, :nx_hash_fields) do + nx_hash_fields_to_int(:symmetric_l3l4_udp) + catch + _class, _reason -> :symmetric_l3l4_udp + end + + def to_int(:nw_src, :nx_hash_fields) do + nx_hash_fields_to_int(:nw_src) + catch + _class, _reason -> :nw_src + end + + def to_int(:nw_dst, :nx_hash_fields) do + nx_hash_fields_to_int(:nw_dst) + catch + _class, _reason -> :nw_dst + end + + def to_int(_int, :nx_hash_fields) do + throw(:bad_enum) + end + + def to_int(:active_backup, :nx_bd_algorithm) do + nx_bd_algorithm_to_int(:active_backup) + catch + _class, _reason -> :active_backup + end + + def to_int(:highest_random_weight, :nx_bd_algorithm) do + nx_bd_algorithm_to_int(:highest_random_weight) + catch + _class, _reason -> :highest_random_weight + end + + def to_int(_int, :nx_bd_algorithm) do + throw(:bad_enum) + end + + def to_int(:send_flow_rem, :nx_learn_flag) do + nx_learn_flag_to_int(:send_flow_rem) + catch + _class, _reason -> :send_flow_rem + end + + def to_int(:delete_learned, :nx_learn_flag) do + nx_learn_flag_to_int(:delete_learned) + catch + _class, _reason -> :delete_learned + end + + def to_int(:write_result, :nx_learn_flag) do + nx_learn_flag_to_int(:write_result) + catch + _class, _reason -> :write_result + end + + def to_int(_int, :nx_learn_flag) do + throw(:bad_enum) + end + + def to_int(:commit, :nx_conntrack_flags) do + nx_conntrack_flags_to_int(:commit) + catch + _class, _reason -> :commit + end + + def to_int(:force, :nx_conntrack_flags) do + nx_conntrack_flags_to_int(:force) + catch + _class, _reason -> :force + end + + def to_int(_int, :nx_conntrack_flags) do + throw(:bad_enum) + end + + def to_int(:src, :nx_nat_flags) do + nx_nat_flags_to_int(:src) + catch + _class, _reason -> :src + end + + def to_int(:dst, :nx_nat_flags) do + nx_nat_flags_to_int(:dst) + catch + _class, _reason -> :dst + end + + def to_int(:persistent, :nx_nat_flags) do + nx_nat_flags_to_int(:persistent) + catch + _class, _reason -> :persistent + end + + def to_int(:protocol_hash, :nx_nat_flags) do + nx_nat_flags_to_int(:protocol_hash) + catch + _class, _reason -> :protocol_hash + end + + def to_int(:protocol_random, :nx_nat_flags) do + nx_nat_flags_to_int(:protocol_random) + catch + _class, _reason -> :protocol_random + end + + def to_int(_int, :nx_nat_flags) do + throw(:bad_enum) + end + + def to_int(:ipv4_min, :nx_nat_range) do + nx_nat_range_to_int(:ipv4_min) + catch + _class, _reason -> :ipv4_min + end + + def to_int(:ipv4_max, :nx_nat_range) do + nx_nat_range_to_int(:ipv4_max) + catch + _class, _reason -> :ipv4_max + end + + def to_int(:ipv6_min, :nx_nat_range) do + nx_nat_range_to_int(:ipv6_min) + catch + _class, _reason -> :ipv6_min + end + + def to_int(:ipv6_max, :nx_nat_range) do + nx_nat_range_to_int(:ipv6_max) + catch + _class, _reason -> :ipv6_max + end + + def to_int(:proto_min, :nx_nat_range) do + nx_nat_range_to_int(:proto_min) + catch + _class, _reason -> :proto_min + end + + def to_int(:proto_max, :nx_nat_range) do + nx_nat_range_to_int(:proto_max) + catch + _class, _reason -> :proto_max + end + + def to_int(_int, :nx_nat_range) do + throw(:bad_enum) + end + + def to_int(:max_len, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_int(:max_len) + catch + _class, _reason -> :max_len + end + + def to_int(:controller_id, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_int(:controller_id) + catch + _class, _reason -> :controller_id + end + + def to_int(:reason, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_int(:reason) + catch + _class, _reason -> :reason + end + + def to_int(:userdata, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_int(:userdata) + catch + _class, _reason -> :userdata + end + + def to_int(:pause, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_int(:pause) + catch + _class, _reason -> :pause + end + + def to_int(_int, :nx_action_controller2_prop_type) do + throw(:bad_enum) + end + + def to_int(:default, :nx_action_sample_direction) do + nx_action_sample_direction_to_int(:default) + catch + _class, _reason -> :default + end + + def to_int(:ingress, :nx_action_sample_direction) do + nx_action_sample_direction_to_int(:ingress) + catch + _class, _reason -> :ingress + end + + def to_int(:egress, :nx_action_sample_direction) do + nx_action_sample_direction_to_int(:egress) + catch + _class, _reason -> :egress + end + + def to_int(_int, :nx_action_sample_direction) do + throw(:bad_enum) + end + + def to_int(Openflow.Action.NxFlowSpecMatch, :nx_flow_spec_type) do + nx_flow_spec_type_to_int(Openflow.Action.NxFlowSpecMatch) + catch + _class, _reason -> Openflow.Action.NxFlowSpecMatch + end + + def to_int(Openflow.Action.NxFlowSpecLoad, :nx_flow_spec_type) do + nx_flow_spec_type_to_int(Openflow.Action.NxFlowSpecLoad) + catch + _class, _reason -> Openflow.Action.NxFlowSpecLoad + end + + def to_int(Openflow.Action.NxFlowSpecOutput, :nx_flow_spec_type) do + nx_flow_spec_type_to_int(Openflow.Action.NxFlowSpecOutput) + catch + _class, _reason -> Openflow.Action.NxFlowSpecOutput + end + + def to_int(_int, :nx_flow_spec_type) do + throw(:bad_enum) + end + + def to_int(Openflow.Instruction.GotoTable, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.GotoTable) + catch + _class, _reason -> Openflow.Instruction.GotoTable + end + + def to_int(Openflow.Instruction.WriteMetadata, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.WriteMetadata) + catch + _class, _reason -> Openflow.Instruction.WriteMetadata + end + + def to_int(Openflow.Instruction.WriteActions, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.WriteActions) + catch + _class, _reason -> Openflow.Instruction.WriteActions + end + + def to_int(Openflow.Instruction.ApplyActions, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.ApplyActions) + catch + _class, _reason -> Openflow.Instruction.ApplyActions + end + + def to_int(Openflow.Instruction.ClearActions, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.ClearActions) + catch + _class, _reason -> Openflow.Instruction.ClearActions + end + + def to_int(Openflow.Instruction.Meter, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.Meter) + catch + _class, _reason -> Openflow.Instruction.Meter + end + + def to_int(Openflow.Instruction.Experimenter, :instruction_type) do + instruction_type_to_int(Openflow.Instruction.Experimenter) + catch + _class, _reason -> Openflow.Instruction.Experimenter + end + + def to_int(_int, :instruction_type) do + throw(:bad_enum) + end + + def to_int(:nochange, :controller_role) do + controller_role_to_int(:nochange) + catch + _class, _reason -> :nochange + end + + def to_int(:equal, :controller_role) do + controller_role_to_int(:equal) + catch + _class, _reason -> :equal + end + + def to_int(:master, :controller_role) do + controller_role_to_int(:master) + catch + _class, _reason -> :master + end + + def to_int(:slave, :controller_role) do + controller_role_to_int(:slave) + catch + _class, _reason -> :slave + end + + def to_int(_int, :controller_role) do + throw(:bad_enum) + end + + def to_int(:other, :nx_role) do + nx_role_to_int(:other) + catch + _class, _reason -> :other + end + + def to_int(:master, :nx_role) do + nx_role_to_int(:master) + catch + _class, _reason -> :master + end + + def to_int(:slave, :nx_role) do + nx_role_to_int(:slave) + catch + _class, _reason -> :slave + end + + def to_int(_int, :nx_role) do + throw(:bad_enum) + end + + def to_int(:standard, :packet_in_format) do + packet_in_format_to_int(:standard) + catch + _class, _reason -> :standard + end + + def to_int(:nxt_packet_in, :packet_in_format) do + packet_in_format_to_int(:nxt_packet_in) + catch + _class, _reason -> :nxt_packet_in + end + + def to_int(:nxt_packet_in2, :packet_in_format) do + packet_in_format_to_int(:nxt_packet_in2) + catch + _class, _reason -> :nxt_packet_in2 + end + + def to_int(_int, :packet_in_format) do + throw(:bad_enum) + end + + def to_int(:openflow10, :flow_format) do + flow_format_to_int(:openflow10) + catch + _class, _reason -> :openflow10 + end + + def to_int(:nxm, :flow_format) do + flow_format_to_int(:nxm) + catch + _class, _reason -> :nxm + end + + def to_int(_int, :flow_format) do + throw(:bad_enum) + end + + def to_int(:packet, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:packet) + catch + _class, _reason -> :packet + end + + def to_int(:full_len, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:full_len) + catch + _class, _reason -> :full_len + end + + def to_int(:buffer_id, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:buffer_id) + catch + _class, _reason -> :buffer_id + end + + def to_int(:table_id, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:table_id) + catch + _class, _reason -> :table_id + end + + def to_int(:cookie, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:cookie) + catch + _class, _reason -> :cookie + end + + def to_int(:reason, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:reason) + catch + _class, _reason -> :reason + end + + def to_int(:metadata, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:metadata) + catch + _class, _reason -> :metadata + end + + def to_int(:userdata, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:userdata) + catch + _class, _reason -> :userdata + end + + def to_int(:continuation, :packet_in2_prop_type) do + packet_in2_prop_type_to_int(:continuation) + catch + _class, _reason -> :continuation + end + + def to_int(_int, :packet_in2_prop_type) do + throw(:bad_enum) + end + + def to_int(:bridge, :continuation_prop_type) do + continuation_prop_type_to_int(:bridge) + catch + _class, _reason -> :bridge + end + + def to_int(:stack, :continuation_prop_type) do + continuation_prop_type_to_int(:stack) + catch + _class, _reason -> :stack + end + + def to_int(:mirrors, :continuation_prop_type) do + continuation_prop_type_to_int(:mirrors) + catch + _class, _reason -> :mirrors + end + + def to_int(:conntracked, :continuation_prop_type) do + continuation_prop_type_to_int(:conntracked) + catch + _class, _reason -> :conntracked + end + + def to_int(:table_id, :continuation_prop_type) do + continuation_prop_type_to_int(:table_id) + catch + _class, _reason -> :table_id + end + + def to_int(:cookie, :continuation_prop_type) do + continuation_prop_type_to_int(:cookie) + catch + _class, _reason -> :cookie + end + + def to_int(:actions, :continuation_prop_type) do + continuation_prop_type_to_int(:actions) + catch + _class, _reason -> :actions + end + + def to_int(:action_set, :continuation_prop_type) do + continuation_prop_type_to_int(:action_set) + catch + _class, _reason -> :action_set + end + + def to_int(_int, :continuation_prop_type) do + throw(:bad_enum) + end + + def to_int(:initial, :flow_monitor_flag) do + flow_monitor_flag_to_int(:initial) + catch + _class, _reason -> :initial + end + + def to_int(:add, :flow_monitor_flag) do + flow_monitor_flag_to_int(:add) + catch + _class, _reason -> :add + end + + def to_int(:delete, :flow_monitor_flag) do + flow_monitor_flag_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(:modify, :flow_monitor_flag) do + flow_monitor_flag_to_int(:modify) + catch + _class, _reason -> :modify + end + + def to_int(:actions, :flow_monitor_flag) do + flow_monitor_flag_to_int(:actions) + catch + _class, _reason -> :actions + end + + def to_int(:own, :flow_monitor_flag) do + flow_monitor_flag_to_int(:own) + catch + _class, _reason -> :own + end + + def to_int(_int, :flow_monitor_flag) do + throw(:bad_enum) + end + + def to_int(:added, :flow_update_event) do + flow_update_event_to_int(:added) + catch + _class, _reason -> :added + end + + def to_int(:deleted, :flow_update_event) do + flow_update_event_to_int(:deleted) + catch + _class, _reason -> :deleted + end + + def to_int(:modified, :flow_update_event) do + flow_update_event_to_int(:modified) + catch + _class, _reason -> :modified + end + + def to_int(:abbrev, :flow_update_event) do + flow_update_event_to_int(:abbrev) + catch + _class, _reason -> :abbrev + end + + def to_int(_int, :flow_update_event) do + throw(:bad_enum) + end + + def to_int(:add, :tlv_table_mod_command) do + tlv_table_mod_command_to_int(:add) + catch + _class, _reason -> :add + end + + def to_int(:delete, :tlv_table_mod_command) do + tlv_table_mod_command_to_int(:delete) + catch + _class, _reason -> :delete + end + + def to_int(:clear, :tlv_table_mod_command) do + tlv_table_mod_command_to_int(:clear) + catch + _class, _reason -> :clear + end + + def to_int(_int, :tlv_table_mod_command) do + throw(:bad_enum) + end + + def to_int(:instructions, :table_feature_prop_type) do + table_feature_prop_type_to_int(:instructions) + catch + _class, _reason -> :instructions + end + + def to_int(:instructions_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:instructions_miss) + catch + _class, _reason -> :instructions_miss + end + + def to_int(:next_tables, :table_feature_prop_type) do + table_feature_prop_type_to_int(:next_tables) + catch + _class, _reason -> :next_tables + end + + def to_int(:next_tables_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:next_tables_miss) + catch + _class, _reason -> :next_tables_miss + end + + def to_int(:write_actions, :table_feature_prop_type) do + table_feature_prop_type_to_int(:write_actions) + catch + _class, _reason -> :write_actions + end + + def to_int(:write_actions_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:write_actions_miss) + catch + _class, _reason -> :write_actions_miss + end + + def to_int(:apply_actions, :table_feature_prop_type) do + table_feature_prop_type_to_int(:apply_actions) + catch + _class, _reason -> :apply_actions + end + + def to_int(:apply_actions_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:apply_actions_miss) + catch + _class, _reason -> :apply_actions_miss + end + + def to_int(:match, :table_feature_prop_type) do + table_feature_prop_type_to_int(:match) + catch + _class, _reason -> :match + end + + def to_int(:wildcards, :table_feature_prop_type) do + table_feature_prop_type_to_int(:wildcards) + catch + _class, _reason -> :wildcards + end + + def to_int(:write_setfield, :table_feature_prop_type) do + table_feature_prop_type_to_int(:write_setfield) + catch + _class, _reason -> :write_setfield + end + + def to_int(:write_setfield_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:write_setfield_miss) + catch + _class, _reason -> :write_setfield_miss + end + + def to_int(:apply_setfield, :table_feature_prop_type) do + table_feature_prop_type_to_int(:apply_setfield) + catch + _class, _reason -> :apply_setfield + end + + def to_int(:apply_setfield_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:apply_setfield_miss) + catch + _class, _reason -> :apply_setfield_miss + end + + def to_int(:experimenter, :table_feature_prop_type) do + table_feature_prop_type_to_int(:experimenter) + catch + _class, _reason -> :experimenter + end + + def to_int(:experimenter_miss, :table_feature_prop_type) do + table_feature_prop_type_to_int(:experimenter_miss) + catch + _class, _reason -> :experimenter_miss + end + + def to_int(_int, :table_feature_prop_type) do + throw(:bad_enum) + end + + def to_atom(0x0, :openflow_codec) do + openflow_codec_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :openflow_codec) do + openflow_codec_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :openflow_codec) do + openflow_codec_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :openflow_codec) do + openflow_codec_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :openflow_codec) do + openflow_codec_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :openflow_codec) do + openflow_codec_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :openflow_codec) do + openflow_codec_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :openflow_codec) do + openflow_codec_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :openflow_codec) do + openflow_codec_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :openflow_codec) do + openflow_codec_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :openflow_codec) do + openflow_codec_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :openflow_codec) do + openflow_codec_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :openflow_codec) do + openflow_codec_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :openflow_codec) do + openflow_codec_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :openflow_codec) do + openflow_codec_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :openflow_codec) do + openflow_codec_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0x10, :openflow_codec) do + openflow_codec_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x11, :openflow_codec) do + openflow_codec_to_atom(0x11) + catch + _class, _reason -> 17 + end + + def to_atom(0x12, :openflow_codec) do + openflow_codec_to_atom(0x12) + catch + _class, _reason -> 18 + end + + def to_atom(0x13, :openflow_codec) do + openflow_codec_to_atom(0x13) + catch + _class, _reason -> 19 + end + + def to_atom(0x14, :openflow_codec) do + openflow_codec_to_atom(0x14) + catch + _class, _reason -> 20 + end + + def to_atom(0x15, :openflow_codec) do + openflow_codec_to_atom(0x15) + catch + _class, _reason -> 21 + end + + def to_atom(0x18, :openflow_codec) do + openflow_codec_to_atom(0x18) + catch + _class, _reason -> 24 + end + + def to_atom(0x19, :openflow_codec) do + openflow_codec_to_atom(0x19) + catch + _class, _reason -> 25 + end + + def to_atom(0x1A, :openflow_codec) do + openflow_codec_to_atom(0x1A) + catch + _class, _reason -> 26 + end + + def to_atom(0x1B, :openflow_codec) do + openflow_codec_to_atom(0x1B) + catch + _class, _reason -> 27 + end + + def to_atom(0x1C, :openflow_codec) do + openflow_codec_to_atom(0x1C) + catch + _class, _reason -> 28 + end + + def to_atom(0x1D, :openflow_codec) do + openflow_codec_to_atom(0x1D) + catch + _class, _reason -> 29 + end + + def to_atom(_, :openflow_codec) do + throw(:bad_enum) + end + + def to_atom(0x2320, :experimenter_id) do + experimenter_id_to_atom(0x2320) + catch + _class, _reason -> 8992 + end + + def to_atom(0x4F4E4600, :experimenter_id) do + experimenter_id_to_atom(0x4F4E4600) + catch + _class, _reason -> 1_330_529_792 + end + + def to_atom(_, :experimenter_id) do + throw(:bad_enum) + end + + def to_atom(0x10, :nicira_ext_message) do + nicira_ext_message_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x14, :nicira_ext_message) do + nicira_ext_message_to_atom(0x14) + catch + _class, _reason -> 20 + end + + def to_atom(0x15, :nicira_ext_message) do + nicira_ext_message_to_atom(0x15) + catch + _class, _reason -> 21 + end + + def to_atom(0x16, :nicira_ext_message) do + nicira_ext_message_to_atom(0x16) + catch + _class, _reason -> 22 + end + + def to_atom(0x17, :nicira_ext_message) do + nicira_ext_message_to_atom(0x17) + catch + _class, _reason -> 23 + end + + def to_atom(0x18, :nicira_ext_message) do + nicira_ext_message_to_atom(0x18) + catch + _class, _reason -> 24 + end + + def to_atom(0x19, :nicira_ext_message) do + nicira_ext_message_to_atom(0x19) + catch + _class, _reason -> 25 + end + + def to_atom(0x1A, :nicira_ext_message) do + nicira_ext_message_to_atom(0x1A) + catch + _class, _reason -> 26 + end + + def to_atom(0x1B, :nicira_ext_message) do + nicira_ext_message_to_atom(0x1B) + catch + _class, _reason -> 27 + end + + def to_atom(0x1C, :nicira_ext_message) do + nicira_ext_message_to_atom(0x1C) + catch + _class, _reason -> 28 + end + + def to_atom(0x1D, :nicira_ext_message) do + nicira_ext_message_to_atom(0x1D) + catch + _class, _reason -> 29 + end + + def to_atom(0x1E, :nicira_ext_message) do + nicira_ext_message_to_atom(0x1E) + catch + _class, _reason -> 30 + end + + def to_atom(_, :nicira_ext_message) do + throw(:bad_enum) + end + + def to_atom(0x8FC, :onf_ext_message) do + onf_ext_message_to_atom(0x8FC) + catch + _class, _reason -> 2300 + end + + def to_atom(0x8FD, :onf_ext_message) do + onf_ext_message_to_atom(0x8FD) + catch + _class, _reason -> 2301 + end + + def to_atom(_, :onf_ext_message) do + throw(:bad_enum) + end + + def to_atom(0x1, :multipart_request_flags) do + multipart_request_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :multipart_request_flags) do + throw(:bad_enum) + end + + def to_atom(0x1, :multipart_reply_flags) do + multipart_reply_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :multipart_reply_flags) do + throw(:bad_enum) + end + + def to_atom(0x0, :multipart_request_codec) do + multipart_request_codec_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :multipart_request_codec) do + multipart_request_codec_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :multipart_request_codec) do + multipart_request_codec_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :multipart_request_codec) do + multipart_request_codec_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :multipart_request_codec) do + multipart_request_codec_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :multipart_request_codec) do + multipart_request_codec_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :multipart_request_codec) do + multipart_request_codec_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :multipart_request_codec) do + multipart_request_codec_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :multipart_request_codec) do + multipart_request_codec_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :multipart_request_codec) do + multipart_request_codec_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :multipart_request_codec) do + multipart_request_codec_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :multipart_request_codec) do + multipart_request_codec_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :multipart_request_codec) do + multipart_request_codec_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :multipart_request_codec) do + multipart_request_codec_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xFFFF, :multipart_request_codec) do + multipart_request_codec_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :multipart_request_codec) do + throw(:bad_enum) + end + + def to_atom(0x0, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xFFFF, :multipart_reply_codec) do + multipart_reply_codec_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :multipart_reply_codec) do + throw(:bad_enum) + end + + def to_atom(0x0, :nicira_ext_stats) do + nicira_ext_stats_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nicira_ext_stats) do + nicira_ext_stats_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nicira_ext_stats) do + nicira_ext_stats_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nicira_ext_stats) do + nicira_ext_stats_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :nicira_ext_stats) do + nicira_ext_stats_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(_, :nicira_ext_stats) do + throw(:bad_enum) + end + + def to_atom(0x1, :hello_elem) do + hello_elem_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :hello_elem) do + throw(:bad_enum) + end + + def to_atom(0x0, :error_type) do + error_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :error_type) do + error_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :error_type) do + error_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :error_type) do + error_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :error_type) do + error_type_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :error_type) do + error_type_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :error_type) do + error_type_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :error_type) do + error_type_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :error_type) do + error_type_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :error_type) do + error_type_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :error_type) do + error_type_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :error_type) do + error_type_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :error_type) do + error_type_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :error_type) do + error_type_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xFFFF, :error_type) do + error_type_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :error_type) do + throw(:bad_enum) + end + + def to_atom(0x0, :hello_failed) do + hello_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :hello_failed) do + hello_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :hello_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :bad_request) do + bad_request_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :bad_request) do + bad_request_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :bad_request) do + bad_request_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :bad_request) do + bad_request_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :bad_request) do + bad_request_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :bad_request) do + bad_request_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :bad_request) do + bad_request_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :bad_request) do + bad_request_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :bad_request) do + bad_request_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :bad_request) do + bad_request_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :bad_request) do + bad_request_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :bad_request) do + bad_request_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :bad_request) do + bad_request_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :bad_request) do + bad_request_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(_, :bad_request) do + throw(:bad_enum) + end + + def to_atom(0x0, :bad_action) do + bad_action_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :bad_action) do + bad_action_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :bad_action) do + bad_action_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :bad_action) do + bad_action_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :bad_action) do + bad_action_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :bad_action) do + bad_action_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :bad_action) do + bad_action_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :bad_action) do + bad_action_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :bad_action) do + bad_action_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :bad_action) do + bad_action_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :bad_action) do + bad_action_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :bad_action) do + bad_action_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :bad_action) do + bad_action_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :bad_action) do + bad_action_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :bad_action) do + bad_action_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :bad_action) do + bad_action_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(_, :bad_action) do + throw(:bad_enum) + end + + def to_atom(0x0, :bad_instruction) do + bad_instruction_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :bad_instruction) do + bad_instruction_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :bad_instruction) do + bad_instruction_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :bad_instruction) do + bad_instruction_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :bad_instruction) do + bad_instruction_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :bad_instruction) do + bad_instruction_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :bad_instruction) do + bad_instruction_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :bad_instruction) do + bad_instruction_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :bad_instruction) do + bad_instruction_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(_, :bad_instruction) do + throw(:bad_enum) + end + + def to_atom(0x0, :bad_match) do + bad_match_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :bad_match) do + bad_match_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :bad_match) do + bad_match_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :bad_match) do + bad_match_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :bad_match) do + bad_match_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :bad_match) do + bad_match_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :bad_match) do + bad_match_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :bad_match) do + bad_match_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :bad_match) do + bad_match_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :bad_match) do + bad_match_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :bad_match) do + bad_match_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :bad_match) do + bad_match_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(_, :bad_match) do + throw(:bad_enum) + end + + def to_atom(0x0, :flow_mod_failed) do + flow_mod_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :flow_mod_failed) do + flow_mod_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :flow_mod_failed) do + flow_mod_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :flow_mod_failed) do + flow_mod_failed_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :flow_mod_failed) do + flow_mod_failed_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :flow_mod_failed) do + flow_mod_failed_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :flow_mod_failed) do + flow_mod_failed_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :flow_mod_failed) do + flow_mod_failed_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(_, :flow_mod_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :group_mod_failed) do + group_mod_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :group_mod_failed) do + group_mod_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :group_mod_failed) do + group_mod_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :group_mod_failed) do + group_mod_failed_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :group_mod_failed) do + group_mod_failed_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :group_mod_failed) do + group_mod_failed_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :group_mod_failed) do + group_mod_failed_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :group_mod_failed) do + group_mod_failed_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :group_mod_failed) do + group_mod_failed_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :group_mod_failed) do + group_mod_failed_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :group_mod_failed) do + group_mod_failed_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :group_mod_failed) do + group_mod_failed_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :group_mod_failed) do + group_mod_failed_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :group_mod_failed) do + group_mod_failed_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :group_mod_failed) do + group_mod_failed_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(_, :group_mod_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :port_mod_failed) do + port_mod_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :port_mod_failed) do + port_mod_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :port_mod_failed) do + port_mod_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :port_mod_failed) do + port_mod_failed_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :port_mod_failed) do + port_mod_failed_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(_, :port_mod_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :table_mod_failed) do + table_mod_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :table_mod_failed) do + table_mod_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :table_mod_failed) do + table_mod_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :table_mod_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :queue_op_failed) do + queue_op_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :queue_op_failed) do + queue_op_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :queue_op_failed) do + queue_op_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :queue_op_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :switch_config_failed) do + switch_config_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :switch_config_failed) do + switch_config_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :switch_config_failed) do + switch_config_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :switch_config_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :role_request_failed) do + role_request_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :role_request_failed) do + role_request_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :role_request_failed) do + role_request_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :role_request_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :meter_mod_failed) do + meter_mod_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :meter_mod_failed) do + meter_mod_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :meter_mod_failed) do + meter_mod_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :meter_mod_failed) do + meter_mod_failed_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :meter_mod_failed) do + meter_mod_failed_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :meter_mod_failed) do + meter_mod_failed_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :meter_mod_failed) do + meter_mod_failed_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :meter_mod_failed) do + meter_mod_failed_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :meter_mod_failed) do + meter_mod_failed_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :meter_mod_failed) do + meter_mod_failed_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :meter_mod_failed) do + meter_mod_failed_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :meter_mod_failed) do + meter_mod_failed_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(_, :meter_mod_failed) do + throw(:bad_enum) + end + + def to_atom(0x0, :table_features_failed) do + table_features_failed_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :table_features_failed) do + table_features_failed_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :table_features_failed) do + table_features_failed_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :table_features_failed) do + table_features_failed_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :table_features_failed) do + table_features_failed_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :table_features_failed) do + table_features_failed_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(_, :table_features_failed) do + throw(:bad_enum) + end + + def to_atom(0x1, :switch_capabilities) do + switch_capabilities_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :switch_capabilities) do + switch_capabilities_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :switch_capabilities) do + switch_capabilities_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :switch_capabilities) do + switch_capabilities_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x20, :switch_capabilities) do + switch_capabilities_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x40, :switch_capabilities) do + switch_capabilities_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x80, :switch_capabilities) do + switch_capabilities_to_atom(0x80) + catch + _class, _reason -> 128 + end + + def to_atom(0x100, :switch_capabilities) do + switch_capabilities_to_atom(0x100) + catch + _class, _reason -> 256 + end + + def to_atom(_, :switch_capabilities) do + throw(:bad_enum) + end + + def to_atom(0x1, :config_flags) do + config_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :config_flags) do + config_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :config_flags) do + throw(:bad_enum) + end + + def to_atom(0xFFE5, :controller_max_len) do + controller_max_len_to_atom(0xFFE5) + catch + _class, _reason -> 65509 + end + + def to_atom(0xFFFF, :controller_max_len) do + controller_max_len_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :controller_max_len) do + throw(:bad_enum) + end + + def to_atom(0x2320, :experimenter_oxm_vendors) do + experimenter_oxm_vendors_to_atom(0x2320) + catch + _class, _reason -> 8992 + end + + def to_atom(0x2428, :experimenter_oxm_vendors) do + experimenter_oxm_vendors_to_atom(0x2428) + catch + _class, _reason -> 9256 + end + + def to_atom(0x4F4E4600, :experimenter_oxm_vendors) do + experimenter_oxm_vendors_to_atom(0x4F4E4600) + catch + _class, _reason -> 1_330_529_792 + end + + def to_atom(_, :experimenter_oxm_vendors) do + throw(:bad_enum) + end + + def to_atom(0x0, :match_type) do + match_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :match_type) do + match_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :match_type) do + throw(:bad_enum) + end + + def to_atom(0x0, :oxm_class) do + oxm_class_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :oxm_class) do + oxm_class_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x8000, :oxm_class) do + oxm_class_to_atom(0x8000) + catch + _class, _reason -> 32768 + end + + def to_atom(0x8001, :oxm_class) do + oxm_class_to_atom(0x8001) + catch + _class, _reason -> 32769 + end + + def to_atom(0xFFFF, :oxm_class) do + oxm_class_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :oxm_class) do + throw(:bad_enum) + end + + def to_atom(0x0, :nxm_0) do + nxm_0_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nxm_0) do + nxm_0_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nxm_0) do + nxm_0_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nxm_0) do + nxm_0_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :nxm_0) do + nxm_0_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :nxm_0) do + nxm_0_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :nxm_0) do + nxm_0_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :nxm_0) do + nxm_0_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :nxm_0) do + nxm_0_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :nxm_0) do + nxm_0_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :nxm_0) do + nxm_0_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :nxm_0) do + nxm_0_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :nxm_0) do + nxm_0_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :nxm_0) do + nxm_0_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :nxm_0) do + nxm_0_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :nxm_0) do + nxm_0_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0x10, :nxm_0) do + nxm_0_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x11, :nxm_0) do + nxm_0_to_atom(0x11) + catch + _class, _reason -> 17 + end + + def to_atom(0x22, :nxm_0) do + nxm_0_to_atom(0x22) + catch + _class, _reason -> 34 + end + + def to_atom(_, :nxm_0) do + throw(:bad_enum) + end + + def to_atom(0x0, :nxm_1) do + nxm_1_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nxm_1) do + nxm_1_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nxm_1) do + nxm_1_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nxm_1) do + nxm_1_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :nxm_1) do + nxm_1_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :nxm_1) do + nxm_1_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :nxm_1) do + nxm_1_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :nxm_1) do + nxm_1_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :nxm_1) do + nxm_1_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :nxm_1) do + nxm_1_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :nxm_1) do + nxm_1_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :nxm_1) do + nxm_1_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :nxm_1) do + nxm_1_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :nxm_1) do + nxm_1_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :nxm_1) do + nxm_1_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :nxm_1) do + nxm_1_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0x10, :nxm_1) do + nxm_1_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x11, :nxm_1) do + nxm_1_to_atom(0x11) + catch + _class, _reason -> 17 + end + + def to_atom(0x12, :nxm_1) do + nxm_1_to_atom(0x12) + catch + _class, _reason -> 18 + end + + def to_atom(0x13, :nxm_1) do + nxm_1_to_atom(0x13) + catch + _class, _reason -> 19 + end + + def to_atom(0x14, :nxm_1) do + nxm_1_to_atom(0x14) + catch + _class, _reason -> 20 + end + + def to_atom(0x15, :nxm_1) do + nxm_1_to_atom(0x15) + catch + _class, _reason -> 21 + end + + def to_atom(0x16, :nxm_1) do + nxm_1_to_atom(0x16) + catch + _class, _reason -> 22 + end + + def to_atom(0x17, :nxm_1) do + nxm_1_to_atom(0x17) + catch + _class, _reason -> 23 + end + + def to_atom(0x18, :nxm_1) do + nxm_1_to_atom(0x18) + catch + _class, _reason -> 24 + end + + def to_atom(0x19, :nxm_1) do + nxm_1_to_atom(0x19) + catch + _class, _reason -> 25 + end + + def to_atom(0x1A, :nxm_1) do + nxm_1_to_atom(0x1A) + catch + _class, _reason -> 26 + end + + def to_atom(0x1B, :nxm_1) do + nxm_1_to_atom(0x1B) + catch + _class, _reason -> 27 + end + + def to_atom(0x1C, :nxm_1) do + nxm_1_to_atom(0x1C) + catch + _class, _reason -> 28 + end + + def to_atom(0x1D, :nxm_1) do + nxm_1_to_atom(0x1D) + catch + _class, _reason -> 29 + end + + def to_atom(0x1E, :nxm_1) do + nxm_1_to_atom(0x1E) + catch + _class, _reason -> 30 + end + + def to_atom(0x1F, :nxm_1) do + nxm_1_to_atom(0x1F) + catch + _class, _reason -> 31 + end + + def to_atom(0x20, :nxm_1) do + nxm_1_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x21, :nxm_1) do + nxm_1_to_atom(0x21) + catch + _class, _reason -> 33 + end + + def to_atom(0x23, :nxm_1) do + nxm_1_to_atom(0x23) + catch + _class, _reason -> 35 + end + + def to_atom(0x24, :nxm_1) do + nxm_1_to_atom(0x24) + catch + _class, _reason -> 36 + end + + def to_atom(0x25, :nxm_1) do + nxm_1_to_atom(0x25) + catch + _class, _reason -> 37 + end + + def to_atom(0x26, :nxm_1) do + nxm_1_to_atom(0x26) + catch + _class, _reason -> 38 + end + + def to_atom(0x27, :nxm_1) do + nxm_1_to_atom(0x27) + catch + _class, _reason -> 39 + end + + def to_atom(0x28, :nxm_1) do + nxm_1_to_atom(0x28) + catch + _class, _reason -> 40 + end + + def to_atom(0x29, :nxm_1) do + nxm_1_to_atom(0x29) + catch + _class, _reason -> 41 + end + + def to_atom(0x2A, :nxm_1) do + nxm_1_to_atom(0x2A) + catch + _class, _reason -> 42 + end + + def to_atom(0x2B, :nxm_1) do + nxm_1_to_atom(0x2B) + catch + _class, _reason -> 43 + end + + def to_atom(0x2C, :nxm_1) do + nxm_1_to_atom(0x2C) + catch + _class, _reason -> 44 + end + + def to_atom(0x2D, :nxm_1) do + nxm_1_to_atom(0x2D) + catch + _class, _reason -> 45 + end + + def to_atom(0x2E, :nxm_1) do + nxm_1_to_atom(0x2E) + catch + _class, _reason -> 46 + end + + def to_atom(0x2F, :nxm_1) do + nxm_1_to_atom(0x2F) + catch + _class, _reason -> 47 + end + + def to_atom(0x30, :nxm_1) do + nxm_1_to_atom(0x30) + catch + _class, _reason -> 48 + end + + def to_atom(0x31, :nxm_1) do + nxm_1_to_atom(0x31) + catch + _class, _reason -> 49 + end + + def to_atom(0x32, :nxm_1) do + nxm_1_to_atom(0x32) + catch + _class, _reason -> 50 + end + + def to_atom(0x33, :nxm_1) do + nxm_1_to_atom(0x33) + catch + _class, _reason -> 51 + end + + def to_atom(0x34, :nxm_1) do + nxm_1_to_atom(0x34) + catch + _class, _reason -> 52 + end + + def to_atom(0x35, :nxm_1) do + nxm_1_to_atom(0x35) + catch + _class, _reason -> 53 + end + + def to_atom(0x36, :nxm_1) do + nxm_1_to_atom(0x36) + catch + _class, _reason -> 54 + end + + def to_atom(0x37, :nxm_1) do + nxm_1_to_atom(0x37) + catch + _class, _reason -> 55 + end + + def to_atom(0x38, :nxm_1) do + nxm_1_to_atom(0x38) + catch + _class, _reason -> 56 + end + + def to_atom(0x39, :nxm_1) do + nxm_1_to_atom(0x39) + catch + _class, _reason -> 57 + end + + def to_atom(0x3A, :nxm_1) do + nxm_1_to_atom(0x3A) + catch + _class, _reason -> 58 + end + + def to_atom(0x3B, :nxm_1) do + nxm_1_to_atom(0x3B) + catch + _class, _reason -> 59 + end + + def to_atom(0x3C, :nxm_1) do + nxm_1_to_atom(0x3C) + catch + _class, _reason -> 60 + end + + def to_atom(0x3D, :nxm_1) do + nxm_1_to_atom(0x3D) + catch + _class, _reason -> 61 + end + + def to_atom(0x3E, :nxm_1) do + nxm_1_to_atom(0x3E) + catch + _class, _reason -> 62 + end + + def to_atom(0x3F, :nxm_1) do + nxm_1_to_atom(0x3F) + catch + _class, _reason -> 63 + end + + def to_atom(0x40, :nxm_1) do + nxm_1_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x41, :nxm_1) do + nxm_1_to_atom(0x41) + catch + _class, _reason -> 65 + end + + def to_atom(0x42, :nxm_1) do + nxm_1_to_atom(0x42) + catch + _class, _reason -> 66 + end + + def to_atom(0x43, :nxm_1) do + nxm_1_to_atom(0x43) + catch + _class, _reason -> 67 + end + + def to_atom(0x44, :nxm_1) do + nxm_1_to_atom(0x44) + catch + _class, _reason -> 68 + end + + def to_atom(0x45, :nxm_1) do + nxm_1_to_atom(0x45) + catch + _class, _reason -> 69 + end + + def to_atom(0x46, :nxm_1) do + nxm_1_to_atom(0x46) + catch + _class, _reason -> 70 + end + + def to_atom(0x47, :nxm_1) do + nxm_1_to_atom(0x47) + catch + _class, _reason -> 71 + end + + def to_atom(0x48, :nxm_1) do + nxm_1_to_atom(0x48) + catch + _class, _reason -> 72 + end + + def to_atom(0x49, :nxm_1) do + nxm_1_to_atom(0x49) + catch + _class, _reason -> 73 + end + + def to_atom(0x4A, :nxm_1) do + nxm_1_to_atom(0x4A) + catch + _class, _reason -> 74 + end + + def to_atom(0x4B, :nxm_1) do + nxm_1_to_atom(0x4B) + catch + _class, _reason -> 75 + end + + def to_atom(0x4C, :nxm_1) do + nxm_1_to_atom(0x4C) + catch + _class, _reason -> 76 + end + + def to_atom(0x4D, :nxm_1) do + nxm_1_to_atom(0x4D) + catch + _class, _reason -> 77 + end + + def to_atom(0x4E, :nxm_1) do + nxm_1_to_atom(0x4E) + catch + _class, _reason -> 78 + end + + def to_atom(0x4F, :nxm_1) do + nxm_1_to_atom(0x4F) + catch + _class, _reason -> 79 + end + + def to_atom(0x50, :nxm_1) do + nxm_1_to_atom(0x50) + catch + _class, _reason -> 80 + end + + def to_atom(0x51, :nxm_1) do + nxm_1_to_atom(0x51) + catch + _class, _reason -> 81 + end + + def to_atom(0x52, :nxm_1) do + nxm_1_to_atom(0x52) + catch + _class, _reason -> 82 + end + + def to_atom(0x53, :nxm_1) do + nxm_1_to_atom(0x53) + catch + _class, _reason -> 83 + end + + def to_atom(0x54, :nxm_1) do + nxm_1_to_atom(0x54) + catch + _class, _reason -> 84 + end + + def to_atom(0x55, :nxm_1) do + nxm_1_to_atom(0x55) + catch + _class, _reason -> 85 + end + + def to_atom(0x56, :nxm_1) do + nxm_1_to_atom(0x56) + catch + _class, _reason -> 86 + end + + def to_atom(0x57, :nxm_1) do + nxm_1_to_atom(0x57) + catch + _class, _reason -> 87 + end + + def to_atom(0x58, :nxm_1) do + nxm_1_to_atom(0x58) + catch + _class, _reason -> 88 + end + + def to_atom(0x59, :nxm_1) do + nxm_1_to_atom(0x59) + catch + _class, _reason -> 89 + end + + def to_atom(0x5A, :nxm_1) do + nxm_1_to_atom(0x5A) + catch + _class, _reason -> 90 + end + + def to_atom(0x5B, :nxm_1) do + nxm_1_to_atom(0x5B) + catch + _class, _reason -> 91 + end + + def to_atom(0x5C, :nxm_1) do + nxm_1_to_atom(0x5C) + catch + _class, _reason -> 92 + end + + def to_atom(0x5D, :nxm_1) do + nxm_1_to_atom(0x5D) + catch + _class, _reason -> 93 + end + + def to_atom(0x5E, :nxm_1) do + nxm_1_to_atom(0x5E) + catch + _class, _reason -> 94 + end + + def to_atom(0x5F, :nxm_1) do + nxm_1_to_atom(0x5F) + catch + _class, _reason -> 95 + end + + def to_atom(0x60, :nxm_1) do + nxm_1_to_atom(0x60) + catch + _class, _reason -> 96 + end + + def to_atom(0x61, :nxm_1) do + nxm_1_to_atom(0x61) + catch + _class, _reason -> 97 + end + + def to_atom(0x62, :nxm_1) do + nxm_1_to_atom(0x62) + catch + _class, _reason -> 98 + end + + def to_atom(0x63, :nxm_1) do + nxm_1_to_atom(0x63) + catch + _class, _reason -> 99 + end + + def to_atom(0x64, :nxm_1) do + nxm_1_to_atom(0x64) + catch + _class, _reason -> 100 + end + + def to_atom(0x65, :nxm_1) do + nxm_1_to_atom(0x65) + catch + _class, _reason -> 101 + end + + def to_atom(0x66, :nxm_1) do + nxm_1_to_atom(0x66) + catch + _class, _reason -> 102 + end + + def to_atom(0x67, :nxm_1) do + nxm_1_to_atom(0x67) + catch + _class, _reason -> 103 + end + + def to_atom(0x68, :nxm_1) do + nxm_1_to_atom(0x68) + catch + _class, _reason -> 104 + end + + def to_atom(0x69, :nxm_1) do + nxm_1_to_atom(0x69) + catch + _class, _reason -> 105 + end + + def to_atom(0x6A, :nxm_1) do + nxm_1_to_atom(0x6A) + catch + _class, _reason -> 106 + end + + def to_atom(0x6B, :nxm_1) do + nxm_1_to_atom(0x6B) + catch + _class, _reason -> 107 + end + + def to_atom(0x6C, :nxm_1) do + nxm_1_to_atom(0x6C) + catch + _class, _reason -> 108 + end + + def to_atom(0x6D, :nxm_1) do + nxm_1_to_atom(0x6D) + catch + _class, _reason -> 109 + end + + def to_atom(0x6E, :nxm_1) do + nxm_1_to_atom(0x6E) + catch + _class, _reason -> 110 + end + + def to_atom(0x6F, :nxm_1) do + nxm_1_to_atom(0x6F) + catch + _class, _reason -> 111 + end + + def to_atom(0x70, :nxm_1) do + nxm_1_to_atom(0x70) + catch + _class, _reason -> 112 + end + + def to_atom(0x71, :nxm_1) do + nxm_1_to_atom(0x71) + catch + _class, _reason -> 113 + end + + def to_atom(0x72, :nxm_1) do + nxm_1_to_atom(0x72) + catch + _class, _reason -> 114 + end + + def to_atom(0x73, :nxm_1) do + nxm_1_to_atom(0x73) + catch + _class, _reason -> 115 + end + + def to_atom(0x74, :nxm_1) do + nxm_1_to_atom(0x74) + catch + _class, _reason -> 116 + end + + def to_atom(0x75, :nxm_1) do + nxm_1_to_atom(0x75) + catch + _class, _reason -> 117 + end + + def to_atom(0x76, :nxm_1) do + nxm_1_to_atom(0x76) + catch + _class, _reason -> 118 + end + + def to_atom(0x77, :nxm_1) do + nxm_1_to_atom(0x77) + catch + _class, _reason -> 119 + end + + def to_atom(0x78, :nxm_1) do + nxm_1_to_atom(0x78) + catch + _class, _reason -> 120 + end + + def to_atom(0x79, :nxm_1) do + nxm_1_to_atom(0x79) + catch + _class, _reason -> 121 + end + + def to_atom(0x7A, :nxm_1) do + nxm_1_to_atom(0x7A) + catch + _class, _reason -> 122 + end + + def to_atom(0x7B, :nxm_1) do + nxm_1_to_atom(0x7B) + catch + _class, _reason -> 123 + end + + def to_atom(0x7C, :nxm_1) do + nxm_1_to_atom(0x7C) + catch + _class, _reason -> 124 + end + + def to_atom(0x7D, :nxm_1) do + nxm_1_to_atom(0x7D) + catch + _class, _reason -> 125 + end + + def to_atom(_, :nxm_1) do + throw(:bad_enum) + end + + def to_atom(0x0, :openflow_basic) do + openflow_basic_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :openflow_basic) do + openflow_basic_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :openflow_basic) do + openflow_basic_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :openflow_basic) do + openflow_basic_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :openflow_basic) do + openflow_basic_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :openflow_basic) do + openflow_basic_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :openflow_basic) do + openflow_basic_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :openflow_basic) do + openflow_basic_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :openflow_basic) do + openflow_basic_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :openflow_basic) do + openflow_basic_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :openflow_basic) do + openflow_basic_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xB, :openflow_basic) do + openflow_basic_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :openflow_basic) do + openflow_basic_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :openflow_basic) do + openflow_basic_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :openflow_basic) do + openflow_basic_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :openflow_basic) do + openflow_basic_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0x10, :openflow_basic) do + openflow_basic_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x11, :openflow_basic) do + openflow_basic_to_atom(0x11) + catch + _class, _reason -> 17 + end + + def to_atom(0x12, :openflow_basic) do + openflow_basic_to_atom(0x12) + catch + _class, _reason -> 18 + end + + def to_atom(0x13, :openflow_basic) do + openflow_basic_to_atom(0x13) + catch + _class, _reason -> 19 + end + + def to_atom(0x14, :openflow_basic) do + openflow_basic_to_atom(0x14) + catch + _class, _reason -> 20 + end + + def to_atom(0x15, :openflow_basic) do + openflow_basic_to_atom(0x15) + catch + _class, _reason -> 21 + end + + def to_atom(0x16, :openflow_basic) do + openflow_basic_to_atom(0x16) + catch + _class, _reason -> 22 + end + + def to_atom(0x17, :openflow_basic) do + openflow_basic_to_atom(0x17) + catch + _class, _reason -> 23 + end + + def to_atom(0x18, :openflow_basic) do + openflow_basic_to_atom(0x18) + catch + _class, _reason -> 24 + end + + def to_atom(0x19, :openflow_basic) do + openflow_basic_to_atom(0x19) + catch + _class, _reason -> 25 + end + + def to_atom(0x1A, :openflow_basic) do + openflow_basic_to_atom(0x1A) + catch + _class, _reason -> 26 + end + + def to_atom(0x1B, :openflow_basic) do + openflow_basic_to_atom(0x1B) + catch + _class, _reason -> 27 + end + + def to_atom(0x1C, :openflow_basic) do + openflow_basic_to_atom(0x1C) + catch + _class, _reason -> 28 + end + + def to_atom(0x1D, :openflow_basic) do + openflow_basic_to_atom(0x1D) + catch + _class, _reason -> 29 + end + + def to_atom(0x1E, :openflow_basic) do + openflow_basic_to_atom(0x1E) + catch + _class, _reason -> 30 + end + + def to_atom(0x1F, :openflow_basic) do + openflow_basic_to_atom(0x1F) + catch + _class, _reason -> 31 + end + + def to_atom(0x20, :openflow_basic) do + openflow_basic_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x21, :openflow_basic) do + openflow_basic_to_atom(0x21) + catch + _class, _reason -> 33 + end + + def to_atom(0x22, :openflow_basic) do + openflow_basic_to_atom(0x22) + catch + _class, _reason -> 34 + end + + def to_atom(0x23, :openflow_basic) do + openflow_basic_to_atom(0x23) + catch + _class, _reason -> 35 + end + + def to_atom(0x24, :openflow_basic) do + openflow_basic_to_atom(0x24) + catch + _class, _reason -> 36 + end + + def to_atom(0x25, :openflow_basic) do + openflow_basic_to_atom(0x25) + catch + _class, _reason -> 37 + end + + def to_atom(0x26, :openflow_basic) do + openflow_basic_to_atom(0x26) + catch + _class, _reason -> 38 + end + + def to_atom(0x27, :openflow_basic) do + openflow_basic_to_atom(0x27) + catch + _class, _reason -> 39 + end + + def to_atom(0x29, :openflow_basic) do + openflow_basic_to_atom(0x29) + catch + _class, _reason -> 41 + end + + def to_atom(0x2A, :openflow_basic) do + openflow_basic_to_atom(0x2A) + catch + _class, _reason -> 42 + end + + def to_atom(0x2B, :openflow_basic) do + openflow_basic_to_atom(0x2B) + catch + _class, _reason -> 43 + end + + def to_atom(0x2C, :openflow_basic) do + openflow_basic_to_atom(0x2C) + catch + _class, _reason -> 44 + end + + def to_atom(0x2D, :openflow_basic) do + openflow_basic_to_atom(0x2D) + catch + _class, _reason -> 45 + end + + def to_atom(0x2E, :openflow_basic) do + openflow_basic_to_atom(0x2E) + catch + _class, _reason -> 46 + end + + def to_atom(0x2F, :openflow_basic) do + openflow_basic_to_atom(0x2F) + catch + _class, _reason -> 47 + end + + def to_atom(0x30, :openflow_basic) do + openflow_basic_to_atom(0x30) + catch + _class, _reason -> 48 + end + + def to_atom(0x31, :openflow_basic) do + openflow_basic_to_atom(0x31) + catch + _class, _reason -> 49 + end + + def to_atom(0x32, :openflow_basic) do + openflow_basic_to_atom(0x32) + catch + _class, _reason -> 50 + end + + def to_atom(0x33, :openflow_basic) do + openflow_basic_to_atom(0x33) + catch + _class, _reason -> 51 + end + + def to_atom(0x34, :openflow_basic) do + openflow_basic_to_atom(0x34) + catch + _class, _reason -> 52 + end + + def to_atom(0x35, :openflow_basic) do + openflow_basic_to_atom(0x35) + catch + _class, _reason -> 53 + end + + def to_atom(0x36, :openflow_basic) do + openflow_basic_to_atom(0x36) + catch + _class, _reason -> 54 + end + + def to_atom(0x37, :openflow_basic) do + openflow_basic_to_atom(0x37) + catch + _class, _reason -> 55 + end + + def to_atom(0x38, :openflow_basic) do + openflow_basic_to_atom(0x38) + catch + _class, _reason -> 56 + end + + def to_atom(0x39, :openflow_basic) do + openflow_basic_to_atom(0x39) + catch + _class, _reason -> 57 + end + + def to_atom(0x3A, :openflow_basic) do + openflow_basic_to_atom(0x3A) + catch + _class, _reason -> 58 + end + + def to_atom(0x3B, :openflow_basic) do + openflow_basic_to_atom(0x3B) + catch + _class, _reason -> 59 + end + + def to_atom(0x3C, :openflow_basic) do + openflow_basic_to_atom(0x3C) + catch + _class, _reason -> 60 + end + + def to_atom(0x3D, :openflow_basic) do + openflow_basic_to_atom(0x3D) + catch + _class, _reason -> 61 + end + + def to_atom(0x3E, :openflow_basic) do + openflow_basic_to_atom(0x3E) + catch + _class, _reason -> 62 + end + + def to_atom(0x3F, :openflow_basic) do + openflow_basic_to_atom(0x3F) + catch + _class, _reason -> 63 + end + + def to_atom(0x40, :openflow_basic) do + openflow_basic_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x41, :openflow_basic) do + openflow_basic_to_atom(0x41) + catch + _class, _reason -> 65 + end + + def to_atom(0x42, :openflow_basic) do + openflow_basic_to_atom(0x42) + catch + _class, _reason -> 66 + end + + def to_atom(0x43, :openflow_basic) do + openflow_basic_to_atom(0x43) + catch + _class, _reason -> 67 + end + + def to_atom(_, :openflow_basic) do + throw(:bad_enum) + end + + def to_atom(0x1000, :vlan_id) do + vlan_id_to_atom(0x1000) + catch + _class, _reason -> 4096 + end + + def to_atom(0x0, :vlan_id) do + vlan_id_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(_, :vlan_id) do + throw(:bad_enum) + end + + def to_atom(0x1, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x20, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x40, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x80, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x80) + catch + _class, _reason -> 128 + end + + def to_atom(0x100, :ipv6exthdr_flags) do + ipv6exthdr_flags_to_atom(0x100) + catch + _class, _reason -> 256 + end + + def to_atom(_, :ipv6exthdr_flags) do + throw(:bad_enum) + end + + def to_atom(0x1, :tcp_flags) do + tcp_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :tcp_flags) do + tcp_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :tcp_flags) do + tcp_flags_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :tcp_flags) do + tcp_flags_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :tcp_flags) do + tcp_flags_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x20, :tcp_flags) do + tcp_flags_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x40, :tcp_flags) do + tcp_flags_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x80, :tcp_flags) do + tcp_flags_to_atom(0x80) + catch + _class, _reason -> 128 + end + + def to_atom(0x100, :tcp_flags) do + tcp_flags_to_atom(0x100) + catch + _class, _reason -> 256 + end + + def to_atom(_, :tcp_flags) do + throw(:bad_enum) + end + + def to_atom(0x1, :ct_state_flags) do + ct_state_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :ct_state_flags) do + ct_state_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :ct_state_flags) do + ct_state_flags_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :ct_state_flags) do + ct_state_flags_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :ct_state_flags) do + ct_state_flags_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x20, :ct_state_flags) do + ct_state_flags_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x40, :ct_state_flags) do + ct_state_flags_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x80, :ct_state_flags) do + ct_state_flags_to_atom(0x80) + catch + _class, _reason -> 128 + end + + def to_atom(_, :ct_state_flags) do + throw(:bad_enum) + end + + def to_atom(0x0, :packet_register) do + packet_register_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :packet_register) do + packet_register_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :packet_register) do + packet_register_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :packet_register) do + packet_register_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :packet_register) do + packet_register_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :packet_register) do + packet_register_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :packet_register) do + packet_register_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :packet_register) do + packet_register_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(_, :packet_register) do + throw(:bad_enum) + end + + def to_atom(0x1, :nicira_ext_match) do + nicira_ext_match_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nicira_ext_match) do + nicira_ext_match_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nicira_ext_match) do + nicira_ext_match_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :nicira_ext_match) do + nicira_ext_match_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :nicira_ext_match) do + nicira_ext_match_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :nicira_ext_match) do + nicira_ext_match_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :nicira_ext_match) do + nicira_ext_match_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :nicira_ext_match) do + nicira_ext_match_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :nicira_ext_match) do + nicira_ext_match_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(_, :nicira_ext_match) do + throw(:bad_enum) + end + + def to_atom(0x0, :hp_ext_match) do + hp_ext_match_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :hp_ext_match) do + hp_ext_match_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :hp_ext_match) do + hp_ext_match_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :hp_ext_match) do + hp_ext_match_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :hp_ext_match) do + hp_ext_match_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :hp_ext_match) do + hp_ext_match_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :hp_ext_match) do + hp_ext_match_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :hp_ext_match) do + hp_ext_match_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :hp_ext_match) do + hp_ext_match_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(_, :hp_ext_match) do + throw(:bad_enum) + end + + def to_atom(0x1, :hp_custom_match_type) do + hp_custom_match_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :hp_custom_match_type) do + hp_custom_match_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :hp_custom_match_type) do + hp_custom_match_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(_, :hp_custom_match_type) do + throw(:bad_enum) + end + + def to_atom(0x2A, :onf_ext_match) do + onf_ext_match_to_atom(0x2A) + catch + _class, _reason -> 42 + end + + def to_atom(0x2B, :onf_ext_match) do + onf_ext_match_to_atom(0x2B) + catch + _class, _reason -> 43 + end + + def to_atom(0xA00, :onf_ext_match) do + onf_ext_match_to_atom(0xA00) + catch + _class, _reason -> 2560 + end + + def to_atom(_, :onf_ext_match) do + throw(:bad_enum) + end + + def to_atom(0xFFFFFFFF, :buffer_id) do + buffer_id_to_atom(0xFFFFFFFF) + catch + _class, _reason -> 4_294_967_295 + end + + def to_atom(_, :buffer_id) do + throw(:bad_enum) + end + + def to_atom(0x1, :port_config) do + port_config_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x4, :port_config) do + port_config_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x20, :port_config) do + port_config_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x40, :port_config) do + port_config_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(_, :port_config) do + throw(:bad_enum) + end + + def to_atom(0x1, :port_state) do + port_state_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :port_state) do + port_state_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :port_state) do + port_state_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(_, :port_state) do + throw(:bad_enum) + end + + def to_atom(0x1, :port_features) do + port_features_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :port_features) do + port_features_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :port_features) do + port_features_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :port_features) do + port_features_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :port_features) do + port_features_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x20, :port_features) do + port_features_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x40, :port_features) do + port_features_to_atom(0x40) + catch + _class, _reason -> 64 + end + + def to_atom(0x80, :port_features) do + port_features_to_atom(0x80) + catch + _class, _reason -> 128 + end + + def to_atom(0x100, :port_features) do + port_features_to_atom(0x100) + catch + _class, _reason -> 256 + end + + def to_atom(0x200, :port_features) do + port_features_to_atom(0x200) + catch + _class, _reason -> 512 + end + + def to_atom(0x400, :port_features) do + port_features_to_atom(0x400) + catch + _class, _reason -> 1024 + end + + def to_atom(0x800, :port_features) do + port_features_to_atom(0x800) + catch + _class, _reason -> 2048 + end + + def to_atom(0x1000, :port_features) do + port_features_to_atom(0x1000) + catch + _class, _reason -> 4096 + end + + def to_atom(0x2000, :port_features) do + port_features_to_atom(0x2000) + catch + _class, _reason -> 8192 + end + + def to_atom(0x4000, :port_features) do + port_features_to_atom(0x4000) + catch + _class, _reason -> 16384 + end + + def to_atom(0x8000, :port_features) do + port_features_to_atom(0x8000) + catch + _class, _reason -> 32768 + end + + def to_atom(_, :port_features) do + throw(:bad_enum) + end + + def to_atom(0xFF00, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFF00) + catch + _class, _reason -> 65280 + end + + def to_atom(0xFFF8, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFF8) + catch + _class, _reason -> 65528 + end + + def to_atom(0xFFF9, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFF9) + catch + _class, _reason -> 65529 + end + + def to_atom(0xFFFA, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFFA) + catch + _class, _reason -> 65530 + end + + def to_atom(0xFFFB, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFFB) + catch + _class, _reason -> 65531 + end + + def to_atom(0xFFFC, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFFC) + catch + _class, _reason -> 65532 + end + + def to_atom(0xFFFD, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFFD) + catch + _class, _reason -> 65533 + end + + def to_atom(0xFFFE, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFFE) + catch + _class, _reason -> 65534 + end + + def to_atom(0xFFFF, :openflow10_port_no) do + openflow10_port_no_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :openflow10_port_no) do + throw(:bad_enum) + end + + def to_atom(0xFFFFFF00, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFF00) + catch + _class, _reason -> 4_294_967_040 + end + + def to_atom(0xFFFFFFF8, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFF8) + catch + _class, _reason -> 4_294_967_288 + end + + def to_atom(0xFFFFFFF9, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFF9) + catch + _class, _reason -> 4_294_967_289 + end + + def to_atom(0xFFFFFFFA, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFFA) + catch + _class, _reason -> 4_294_967_290 + end + + def to_atom(0xFFFFFFFB, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFFB) + catch + _class, _reason -> 4_294_967_291 + end + + def to_atom(0xFFFFFFFC, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFFC) + catch + _class, _reason -> 4_294_967_292 + end + + def to_atom(0xFFFFFFFD, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFFD) + catch + _class, _reason -> 4_294_967_293 + end + + def to_atom(0xFFFFFFFE, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFFE) + catch + _class, _reason -> 4_294_967_294 + end + + def to_atom(0xFFFFFFFF, :openflow13_port_no) do + openflow13_port_no_to_atom(0xFFFFFFFF) + catch + _class, _reason -> 4_294_967_295 + end + + def to_atom(_, :openflow13_port_no) do + throw(:bad_enum) + end + + def to_atom(0x0, :packet_in_reason) do + packet_in_reason_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :packet_in_reason) do + packet_in_reason_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :packet_in_reason) do + packet_in_reason_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :packet_in_reason) do + packet_in_reason_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :packet_in_reason) do + packet_in_reason_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :packet_in_reason) do + packet_in_reason_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(_, :packet_in_reason) do + throw(:bad_enum) + end + + def to_atom(0x0, :flow_mod_command) do + flow_mod_command_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :flow_mod_command) do + flow_mod_command_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :flow_mod_command) do + flow_mod_command_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :flow_mod_command) do + flow_mod_command_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :flow_mod_command) do + flow_mod_command_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(_, :flow_mod_command) do + throw(:bad_enum) + end + + def to_atom(0x1, :flow_mod_flags) do + flow_mod_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :flow_mod_flags) do + flow_mod_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :flow_mod_flags) do + flow_mod_flags_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :flow_mod_flags) do + flow_mod_flags_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :flow_mod_flags) do + flow_mod_flags_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(_, :flow_mod_flags) do + throw(:bad_enum) + end + + def to_atom(0x0, :flow_removed_reason) do + flow_removed_reason_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :flow_removed_reason) do + flow_removed_reason_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :flow_removed_reason) do + flow_removed_reason_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :flow_removed_reason) do + flow_removed_reason_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :flow_removed_reason) do + flow_removed_reason_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :flow_removed_reason) do + flow_removed_reason_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(_, :flow_removed_reason) do + throw(:bad_enum) + end + + def to_atom(0x0, :port_reason) do + port_reason_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :port_reason) do + port_reason_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :port_reason) do + port_reason_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :port_reason) do + throw(:bad_enum) + end + + def to_atom(0x0, :group_mod_command) do + group_mod_command_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :group_mod_command) do + group_mod_command_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :group_mod_command) do + group_mod_command_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :group_mod_command) do + throw(:bad_enum) + end + + def to_atom(0x0, :group_type) do + group_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :group_type) do + group_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :group_type) do + group_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :group_type) do + group_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(_, :group_type) do + throw(:bad_enum) + end + + def to_atom(0xFFFFFF00, :group_id) do + group_id_to_atom(0xFFFFFF00) + catch + _class, _reason -> 4_294_967_040 + end + + def to_atom(0xFFFFFFFC, :group_id) do + group_id_to_atom(0xFFFFFFFC) + catch + _class, _reason -> 4_294_967_292 + end + + def to_atom(0xFFFFFFFF, :group_id) do + group_id_to_atom(0xFFFFFFFF) + catch + _class, _reason -> 4_294_967_295 + end + + def to_atom(_, :group_id) do + throw(:bad_enum) + end + + def to_atom(0x1, :group_capabilities) do + group_capabilities_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :group_capabilities) do + group_capabilities_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :group_capabilities) do + group_capabilities_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :group_capabilities) do + group_capabilities_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(_, :group_capabilities) do + throw(:bad_enum) + end + + def to_atom(0xFE, :table_id) do + table_id_to_atom(0xFE) + catch + _class, _reason -> 254 + end + + def to_atom(0xFF, :table_id) do + table_id_to_atom(0xFF) + catch + _class, _reason -> 255 + end + + def to_atom(_, :table_id) do + throw(:bad_enum) + end + + def to_atom(0xFFFFFFFF, :queue_id) do + queue_id_to_atom(0xFFFFFFFF) + catch + _class, _reason -> 4_294_967_295 + end + + def to_atom(_, :queue_id) do + throw(:bad_enum) + end + + def to_atom(0x0, :meter_mod_command) do + meter_mod_command_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :meter_mod_command) do + meter_mod_command_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :meter_mod_command) do + meter_mod_command_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :meter_mod_command) do + throw(:bad_enum) + end + + def to_atom(0xFFFF0000, :meter_id) do + meter_id_to_atom(0xFFFF0000) + catch + _class, _reason -> 4_294_901_760 + end + + def to_atom(0xFFFFFFFD, :meter_id) do + meter_id_to_atom(0xFFFFFFFD) + catch + _class, _reason -> 4_294_967_293 + end + + def to_atom(0xFFFFFFFE, :meter_id) do + meter_id_to_atom(0xFFFFFFFE) + catch + _class, _reason -> 4_294_967_294 + end + + def to_atom(0xFFFFFFFF, :meter_id) do + meter_id_to_atom(0xFFFFFFFF) + catch + _class, _reason -> 4_294_967_295 + end + + def to_atom(_, :meter_id) do + throw(:bad_enum) + end + + def to_atom(0x1, :meter_flags) do + meter_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :meter_flags) do + meter_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :meter_flags) do + meter_flags_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :meter_flags) do + meter_flags_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(_, :meter_flags) do + throw(:bad_enum) + end + + def to_atom(0x1, :meter_band_type) do + meter_band_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :meter_band_type) do + meter_band_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0xFFFF, :meter_band_type) do + meter_band_type_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :meter_band_type) do + throw(:bad_enum) + end + + def to_atom(0x0, :table_config) do + table_config_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :table_config) do + table_config_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :table_config) do + table_config_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :table_config) do + table_config_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :table_config) do + table_config_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :table_config) do + table_config_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(_, :table_config) do + throw(:bad_enum) + end + + def to_atom(0x0, :action_type) do + action_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0xB, :action_type) do + action_type_to_atom(0xB) + catch + _class, _reason -> 11 + end + + def to_atom(0xC, :action_type) do + action_type_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xF, :action_type) do + action_type_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0x10, :action_type) do + action_type_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x11, :action_type) do + action_type_to_atom(0x11) + catch + _class, _reason -> 17 + end + + def to_atom(0x12, :action_type) do + action_type_to_atom(0x12) + catch + _class, _reason -> 18 + end + + def to_atom(0x13, :action_type) do + action_type_to_atom(0x13) + catch + _class, _reason -> 19 + end + + def to_atom(0x14, :action_type) do + action_type_to_atom(0x14) + catch + _class, _reason -> 20 + end + + def to_atom(0x15, :action_type) do + action_type_to_atom(0x15) + catch + _class, _reason -> 21 + end + + def to_atom(0x16, :action_type) do + action_type_to_atom(0x16) + catch + _class, _reason -> 22 + end + + def to_atom(0x17, :action_type) do + action_type_to_atom(0x17) + catch + _class, _reason -> 23 + end + + def to_atom(0x18, :action_type) do + action_type_to_atom(0x18) + catch + _class, _reason -> 24 + end + + def to_atom(0x19, :action_type) do + action_type_to_atom(0x19) + catch + _class, _reason -> 25 + end + + def to_atom(0x1A, :action_type) do + action_type_to_atom(0x1A) + catch + _class, _reason -> 26 + end + + def to_atom(0x1B, :action_type) do + action_type_to_atom(0x1B) + catch + _class, _reason -> 27 + end + + def to_atom(0x1C, :action_type) do + action_type_to_atom(0x1C) + catch + _class, _reason -> 28 + end + + def to_atom(0x1D, :action_type) do + action_type_to_atom(0x1D) + catch + _class, _reason -> 29 + end + + def to_atom(0x1E, :action_type) do + action_type_to_atom(0x1E) + catch + _class, _reason -> 30 + end + + def to_atom(0x1F, :action_type) do + action_type_to_atom(0x1F) + catch + _class, _reason -> 31 + end + + def to_atom(0xFFFF, :action_type) do + action_type_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :action_type) do + throw(:bad_enum) + end + + def to_atom(0x2320, :action_vendor) do + action_vendor_to_atom(0x2320) + catch + _class, _reason -> 8992 + end + + def to_atom(0x4F4E4600, :action_vendor) do + action_vendor_to_atom(0x4F4E4600) + catch + _class, _reason -> 1_330_529_792 + end + + def to_atom(_, :action_vendor) do + throw(:bad_enum) + end + + def to_atom(0xC80, :onf_ext_action) do + onf_ext_action_to_atom(0xC80) + catch + _class, _reason -> 3200 + end + + def to_atom(_, :onf_ext_action) do + throw(:bad_enum) + end + + def to_atom(0x1, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :nicira_ext_action) do + nicira_ext_action_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :nicira_ext_action) do + nicira_ext_action_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :nicira_ext_action) do + nicira_ext_action_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :nicira_ext_action) do + nicira_ext_action_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :nicira_ext_action) do + nicira_ext_action_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x9, :nicira_ext_action) do + nicira_ext_action_to_atom(0x9) + catch + _class, _reason -> 9 + end + + def to_atom(0xA, :nicira_ext_action) do + nicira_ext_action_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xC, :nicira_ext_action) do + nicira_ext_action_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :nicira_ext_action) do + nicira_ext_action_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :nicira_ext_action) do + nicira_ext_action_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :nicira_ext_action) do + nicira_ext_action_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0x10, :nicira_ext_action) do + nicira_ext_action_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x11, :nicira_ext_action) do + nicira_ext_action_to_atom(0x11) + catch + _class, _reason -> 17 + end + + def to_atom(0x12, :nicira_ext_action) do + nicira_ext_action_to_atom(0x12) + catch + _class, _reason -> 18 + end + + def to_atom(0x13, :nicira_ext_action) do + nicira_ext_action_to_atom(0x13) + catch + _class, _reason -> 19 + end + + def to_atom(0x14, :nicira_ext_action) do + nicira_ext_action_to_atom(0x14) + catch + _class, _reason -> 20 + end + + def to_atom(0x15, :nicira_ext_action) do + nicira_ext_action_to_atom(0x15) + catch + _class, _reason -> 21 + end + + def to_atom(0x16, :nicira_ext_action) do + nicira_ext_action_to_atom(0x16) + catch + _class, _reason -> 22 + end + + def to_atom(0x17, :nicira_ext_action) do + nicira_ext_action_to_atom(0x17) + catch + _class, _reason -> 23 + end + + def to_atom(0x18, :nicira_ext_action) do + nicira_ext_action_to_atom(0x18) + catch + _class, _reason -> 24 + end + + def to_atom(0x19, :nicira_ext_action) do + nicira_ext_action_to_atom(0x19) + catch + _class, _reason -> 25 + end + + def to_atom(0x1A, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1A) + catch + _class, _reason -> 26 + end + + def to_atom(0x1B, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1B) + catch + _class, _reason -> 27 + end + + def to_atom(0x1C, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1C) + catch + _class, _reason -> 28 + end + + def to_atom(0x1D, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1D) + catch + _class, _reason -> 29 + end + + def to_atom(0x1E, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1E) + catch + _class, _reason -> 30 + end + + def to_atom(0x1F, :nicira_ext_action) do + nicira_ext_action_to_atom(0x1F) + catch + _class, _reason -> 31 + end + + def to_atom(0x20, :nicira_ext_action) do + nicira_ext_action_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(0x21, :nicira_ext_action) do + nicira_ext_action_to_atom(0x21) + catch + _class, _reason -> 33 + end + + def to_atom(0x22, :nicira_ext_action) do + nicira_ext_action_to_atom(0x22) + catch + _class, _reason -> 34 + end + + def to_atom(0x23, :nicira_ext_action) do + nicira_ext_action_to_atom(0x23) + catch + _class, _reason -> 35 + end + + def to_atom(0x24, :nicira_ext_action) do + nicira_ext_action_to_atom(0x24) + catch + _class, _reason -> 36 + end + + def to_atom(0x25, :nicira_ext_action) do + nicira_ext_action_to_atom(0x25) + catch + _class, _reason -> 37 + end + + def to_atom(0x26, :nicira_ext_action) do + nicira_ext_action_to_atom(0x26) + catch + _class, _reason -> 38 + end + + def to_atom(0x27, :nicira_ext_action) do + nicira_ext_action_to_atom(0x27) + catch + _class, _reason -> 39 + end + + def to_atom(0x28, :nicira_ext_action) do + nicira_ext_action_to_atom(0x28) + catch + _class, _reason -> 40 + end + + def to_atom(0x29, :nicira_ext_action) do + nicira_ext_action_to_atom(0x29) + catch + _class, _reason -> 41 + end + + def to_atom(0x2A, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2A) + catch + _class, _reason -> 42 + end + + def to_atom(0x2B, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2B) + catch + _class, _reason -> 43 + end + + def to_atom(0x2C, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2C) + catch + _class, _reason -> 44 + end + + def to_atom(0x2D, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2D) + catch + _class, _reason -> 45 + end + + def to_atom(0x2E, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2E) + catch + _class, _reason -> 46 + end + + def to_atom(0x2F, :nicira_ext_action) do + nicira_ext_action_to_atom(0x2F) + catch + _class, _reason -> 47 + end + + def to_atom(0xFF, :nicira_ext_action) do + nicira_ext_action_to_atom(0xFF) + catch + _class, _reason -> 255 + end + + def to_atom(_, :nicira_ext_action) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_mp_algorithm) do + nx_mp_algorithm_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_mp_algorithm) do + nx_mp_algorithm_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_mp_algorithm) do + nx_mp_algorithm_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nx_mp_algorithm) do + nx_mp_algorithm_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(_, :nx_mp_algorithm) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_hash_fields) do + nx_hash_fields_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_hash_fields) do + nx_hash_fields_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_hash_fields) do + nx_hash_fields_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nx_hash_fields) do + nx_hash_fields_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :nx_hash_fields) do + nx_hash_fields_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :nx_hash_fields) do + nx_hash_fields_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(_, :nx_hash_fields) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_bd_algorithm) do + nx_bd_algorithm_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_bd_algorithm) do + nx_bd_algorithm_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :nx_bd_algorithm) do + throw(:bad_enum) + end + + def to_atom(0x1, :nx_learn_flag) do + nx_learn_flag_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_learn_flag) do + nx_learn_flag_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :nx_learn_flag) do + nx_learn_flag_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(_, :nx_learn_flag) do + throw(:bad_enum) + end + + def to_atom(0x1, :nx_conntrack_flags) do + nx_conntrack_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_conntrack_flags) do + nx_conntrack_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :nx_conntrack_flags) do + throw(:bad_enum) + end + + def to_atom(0x1, :nx_nat_flags) do + nx_nat_flags_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_nat_flags) do + nx_nat_flags_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :nx_nat_flags) do + nx_nat_flags_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :nx_nat_flags) do + nx_nat_flags_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :nx_nat_flags) do + nx_nat_flags_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(_, :nx_nat_flags) do + throw(:bad_enum) + end + + def to_atom(0x1, :nx_nat_range) do + nx_nat_range_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_nat_range) do + nx_nat_range_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :nx_nat_range) do + nx_nat_range_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :nx_nat_range) do + nx_nat_range_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :nx_nat_range) do + nx_nat_range_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x20, :nx_nat_range) do + nx_nat_range_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(_, :nx_nat_range) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :nx_action_controller2_prop_type) do + nx_action_controller2_prop_type_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(_, :nx_action_controller2_prop_type) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_action_sample_direction) do + nx_action_sample_direction_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_action_sample_direction) do + nx_action_sample_direction_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_action_sample_direction) do + nx_action_sample_direction_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :nx_action_sample_direction) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_flow_spec_type) do + nx_flow_spec_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_flow_spec_type) do + nx_flow_spec_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_flow_spec_type) do + nx_flow_spec_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :nx_flow_spec_type) do + throw(:bad_enum) + end + + def to_atom(0x1, :instruction_type) do + instruction_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :instruction_type) do + instruction_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :instruction_type) do + instruction_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :instruction_type) do + instruction_type_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :instruction_type) do + instruction_type_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :instruction_type) do + instruction_type_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0xFFFF, :instruction_type) do + instruction_type_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :instruction_type) do + throw(:bad_enum) + end + + def to_atom(0x0, :controller_role) do + controller_role_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :controller_role) do + controller_role_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :controller_role) do + controller_role_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :controller_role) do + controller_role_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(_, :controller_role) do + throw(:bad_enum) + end + + def to_atom(0x0, :nx_role) do + nx_role_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :nx_role) do + nx_role_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :nx_role) do + nx_role_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :nx_role) do + throw(:bad_enum) + end + + def to_atom(0x0, :packet_in_format) do + packet_in_format_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :packet_in_format) do + packet_in_format_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :packet_in_format) do + packet_in_format_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :packet_in_format) do + throw(:bad_enum) + end + + def to_atom(0x0, :flow_format) do + flow_format_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :flow_format) do + flow_format_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(_, :flow_format) do + throw(:bad_enum) + end + + def to_atom(0x0, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :packet_in2_prop_type) do + packet_in2_prop_type_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(_, :packet_in2_prop_type) do + throw(:bad_enum) + end + + def to_atom(0x8000, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8000) + catch + _class, _reason -> 32768 + end + + def to_atom(0x8001, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8001) + catch + _class, _reason -> 32769 + end + + def to_atom(0x8002, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8002) + catch + _class, _reason -> 32770 + end + + def to_atom(0x8003, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8003) + catch + _class, _reason -> 32771 + end + + def to_atom(0x8004, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8004) + catch + _class, _reason -> 32772 + end + + def to_atom(0x8005, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8005) + catch + _class, _reason -> 32773 + end + + def to_atom(0x8006, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8006) + catch + _class, _reason -> 32774 + end + + def to_atom(0x8007, :continuation_prop_type) do + continuation_prop_type_to_atom(0x8007) + catch + _class, _reason -> 32775 + end + + def to_atom(_, :continuation_prop_type) do + throw(:bad_enum) + end + + def to_atom(0x1, :flow_monitor_flag) do + flow_monitor_flag_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :flow_monitor_flag) do + flow_monitor_flag_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x4, :flow_monitor_flag) do + flow_monitor_flag_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x8, :flow_monitor_flag) do + flow_monitor_flag_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0x10, :flow_monitor_flag) do + flow_monitor_flag_to_atom(0x10) + catch + _class, _reason -> 16 + end + + def to_atom(0x20, :flow_monitor_flag) do + flow_monitor_flag_to_atom(0x20) + catch + _class, _reason -> 32 + end + + def to_atom(_, :flow_monitor_flag) do + throw(:bad_enum) + end + + def to_atom(0x0, :flow_update_event) do + flow_update_event_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :flow_update_event) do + flow_update_event_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :flow_update_event) do + flow_update_event_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :flow_update_event) do + flow_update_event_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(_, :flow_update_event) do + throw(:bad_enum) + end + + def to_atom(0x0, :tlv_table_mod_command) do + tlv_table_mod_command_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :tlv_table_mod_command) do + tlv_table_mod_command_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :tlv_table_mod_command) do + tlv_table_mod_command_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(_, :tlv_table_mod_command) do + throw(:bad_enum) + end + + def to_atom(0x0, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x0) + catch + _class, _reason -> 0 + end + + def to_atom(0x1, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x1) + catch + _class, _reason -> 1 + end + + def to_atom(0x2, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x2) + catch + _class, _reason -> 2 + end + + def to_atom(0x3, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x3) + catch + _class, _reason -> 3 + end + + def to_atom(0x4, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x4) + catch + _class, _reason -> 4 + end + + def to_atom(0x5, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x5) + catch + _class, _reason -> 5 + end + + def to_atom(0x6, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x6) + catch + _class, _reason -> 6 + end + + def to_atom(0x7, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x7) + catch + _class, _reason -> 7 + end + + def to_atom(0x8, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0x8) + catch + _class, _reason -> 8 + end + + def to_atom(0xA, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xA) + catch + _class, _reason -> 10 + end + + def to_atom(0xC, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xC) + catch + _class, _reason -> 12 + end + + def to_atom(0xD, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xD) + catch + _class, _reason -> 13 + end + + def to_atom(0xE, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xE) + catch + _class, _reason -> 14 + end + + def to_atom(0xF, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xF) + catch + _class, _reason -> 15 + end + + def to_atom(0xFFFE, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xFFFE) + catch + _class, _reason -> 65534 + end + + def to_atom(0xFFFF, :table_feature_prop_type) do + table_feature_prop_type_to_atom(0xFFFF) + catch + _class, _reason -> 65535 + end + + def to_atom(_, :table_feature_prop_type) do + throw(:bad_enum) + end + + def openflow_codec_to_int(Openflow.Hello), do: 0x0 + def openflow_codec_to_int(Openflow.ErrorMsg), do: 0x1 + def openflow_codec_to_int(Openflow.Echo.Request), do: 0x2 + def openflow_codec_to_int(Openflow.Echo.Reply), do: 0x3 + def openflow_codec_to_int(Openflow.Experimenter), do: 0x4 + def openflow_codec_to_int(Openflow.Features.Request), do: 0x5 + def openflow_codec_to_int(Openflow.Features.Reply), do: 0x6 + def openflow_codec_to_int(Openflow.GetConfig.Request), do: 0x7 + def openflow_codec_to_int(Openflow.GetConfig.Reply), do: 0x8 + def openflow_codec_to_int(Openflow.SetConfig), do: 0x9 + def openflow_codec_to_int(Openflow.PacketIn), do: 0xA + def openflow_codec_to_int(Openflow.FlowRemoved), do: 0xB + def openflow_codec_to_int(Openflow.PortStatus), do: 0xC + def openflow_codec_to_int(Openflow.PacketOut), do: 0xD + def openflow_codec_to_int(Openflow.FlowMod), do: 0xE + def openflow_codec_to_int(Openflow.GroupMod), do: 0xF + def openflow_codec_to_int(Openflow.PortMod), do: 0x10 + def openflow_codec_to_int(Openflow.TableMod), do: 0x11 + def openflow_codec_to_int(Openflow.Multipart.Request), do: 0x12 + def openflow_codec_to_int(Openflow.Multipart.Reply), do: 0x13 + def openflow_codec_to_int(Openflow.Barrier.Request), do: 0x14 + def openflow_codec_to_int(Openflow.Barrier.Reply), do: 0x15 + def openflow_codec_to_int(Openflow.Role.Request), do: 0x18 + def openflow_codec_to_int(Openflow.Role.Reply), do: 0x19 + def openflow_codec_to_int(Openflow.GetAsync.Request), do: 0x1A + def openflow_codec_to_int(Openflow.GetAsync.Reply), do: 0x1B + def openflow_codec_to_int(Openflow.SetAsync), do: 0x1C + def openflow_codec_to_int(Openflow.MeterMod), do: 0x1D + def openflow_codec_to_int(_), do: throw(:bad_enum) + def openflow_codec_to_atom(0x0), do: Openflow.Hello + def openflow_codec_to_atom(0x1), do: Openflow.ErrorMsg + def openflow_codec_to_atom(0x2), do: Openflow.Echo.Request + def openflow_codec_to_atom(0x3), do: Openflow.Echo.Reply + def openflow_codec_to_atom(0x4), do: Openflow.Experimenter + def openflow_codec_to_atom(0x5), do: Openflow.Features.Request + def openflow_codec_to_atom(0x6), do: Openflow.Features.Reply + def openflow_codec_to_atom(0x7), do: Openflow.GetConfig.Request + def openflow_codec_to_atom(0x8), do: Openflow.GetConfig.Reply + def openflow_codec_to_atom(0x9), do: Openflow.SetConfig + def openflow_codec_to_atom(0xA), do: Openflow.PacketIn + def openflow_codec_to_atom(0xB), do: Openflow.FlowRemoved + def openflow_codec_to_atom(0xC), do: Openflow.PortStatus + def openflow_codec_to_atom(0xD), do: Openflow.PacketOut + def openflow_codec_to_atom(0xE), do: Openflow.FlowMod + def openflow_codec_to_atom(0xF), do: Openflow.GroupMod + def openflow_codec_to_atom(0x10), do: Openflow.PortMod + def openflow_codec_to_atom(0x11), do: Openflow.TableMod + def openflow_codec_to_atom(0x12), do: Openflow.Multipart.Request + def openflow_codec_to_atom(0x13), do: Openflow.Multipart.Reply + def openflow_codec_to_atom(0x14), do: Openflow.Barrier.Request + def openflow_codec_to_atom(0x15), do: Openflow.Barrier.Reply + def openflow_codec_to_atom(0x18), do: Openflow.Role.Request + def openflow_codec_to_atom(0x19), do: Openflow.Role.Reply + def openflow_codec_to_atom(0x1A), do: Openflow.GetAsync.Request + def openflow_codec_to_atom(0x1B), do: Openflow.GetAsync.Reply + def openflow_codec_to_atom(0x1C), do: Openflow.SetAsync + def openflow_codec_to_atom(0x1D), do: Openflow.MeterMod + def openflow_codec_to_atom(_), do: throw(:bad_enum) + def experimenter_id_to_int(:nicira_ext_message), do: 0x2320 + def experimenter_id_to_int(:onf_ext_message), do: 0x4F4E4600 + def experimenter_id_to_int(_), do: throw(:bad_enum) + def experimenter_id_to_atom(0x2320), do: :nicira_ext_message + def experimenter_id_to_atom(0x4F4E4600), do: :onf_ext_message + def experimenter_id_to_atom(_), do: throw(:bad_enum) + def nicira_ext_message_to_int(Openflow.NxSetPacketInFormat), do: 0x10 + def nicira_ext_message_to_int(Openflow.NxSetControllerId), do: 0x14 + def nicira_ext_message_to_int(Openflow.NxFlowMonitor.Cancel), do: 0x15 + def nicira_ext_message_to_int(Openflow.NxFlowMonitor.Paused), do: 0x16 + def nicira_ext_message_to_int(Openflow.NxFlowMonitor.Resumed), do: 0x17 + def nicira_ext_message_to_int(Openflow.NxTLVTableMod), do: 0x18 + def nicira_ext_message_to_int(Openflow.NxTLVTable.Request), do: 0x19 + def nicira_ext_message_to_int(Openflow.NxTLVTable.Reply), do: 0x1A + def nicira_ext_message_to_int(Openflow.NxSetAsyncConfig2), do: 0x1B + def nicira_ext_message_to_int(Openflow.NxResume), do: 0x1C + def nicira_ext_message_to_int(Openflow.NxCtFlushZone), do: 0x1D + def nicira_ext_message_to_int(Openflow.NxPacketIn2), do: 0x1E + def nicira_ext_message_to_int(_), do: throw(:bad_enum) + def nicira_ext_message_to_atom(0x10), do: Openflow.NxSetPacketInFormat + def nicira_ext_message_to_atom(0x14), do: Openflow.NxSetControllerId + def nicira_ext_message_to_atom(0x15), do: Openflow.NxFlowMonitor.Cancel + def nicira_ext_message_to_atom(0x16), do: Openflow.NxFlowMonitor.Paused + def nicira_ext_message_to_atom(0x17), do: Openflow.NxFlowMonitor.Resumed + def nicira_ext_message_to_atom(0x18), do: Openflow.NxTLVTableMod + def nicira_ext_message_to_atom(0x19), do: Openflow.NxTLVTable.Request + def nicira_ext_message_to_atom(0x1A), do: Openflow.NxTLVTable.Reply + def nicira_ext_message_to_atom(0x1B), do: Openflow.NxSetAsyncConfig2 + def nicira_ext_message_to_atom(0x1C), do: Openflow.NxResume + def nicira_ext_message_to_atom(0x1D), do: Openflow.NxCtFlushZone + def nicira_ext_message_to_atom(0x1E), do: Openflow.NxPacketIn2 + def nicira_ext_message_to_atom(_), do: throw(:bad_enum) + def onf_ext_message_to_int(Openflow.OnfBundleControl), do: 0x8FC + def onf_ext_message_to_int(Openflow.OnfBundleAddMessage), do: 0x8FD + def onf_ext_message_to_int(_), do: throw(:bad_enum) + def onf_ext_message_to_atom(0x8FC), do: Openflow.OnfBundleControl + def onf_ext_message_to_atom(0x8FD), do: Openflow.OnfBundleAddMessage + def onf_ext_message_to_atom(_), do: throw(:bad_enum) + def multipart_request_flags_to_int(:more), do: 0x1 + def multipart_request_flags_to_int(_), do: throw(:bad_enum) + def multipart_request_flags_to_atom(0x1), do: :more + def multipart_request_flags_to_atom(_), do: throw(:bad_enum) + def multipart_reply_flags_to_int(:more), do: 0x1 + def multipart_reply_flags_to_int(_), do: throw(:bad_enum) + def multipart_reply_flags_to_atom(0x1), do: :more + def multipart_reply_flags_to_atom(_), do: throw(:bad_enum) + def multipart_request_codec_to_int(Openflow.Multipart.Desc.Request), do: 0x0 + def multipart_request_codec_to_int(Openflow.Multipart.Flow.Request), do: 0x1 + def multipart_request_codec_to_int(Openflow.Multipart.Aggregate.Request), do: 0x2 + def multipart_request_codec_to_int(Openflow.Multipart.Table.Request), do: 0x3 + def multipart_request_codec_to_int(Openflow.Multipart.PortStats.Request), do: 0x4 + def multipart_request_codec_to_int(Openflow.Multipart.Queue.Request), do: 0x5 + def multipart_request_codec_to_int(Openflow.Multipart.Group.Request), do: 0x6 + def multipart_request_codec_to_int(Openflow.Multipart.GroupDesc.Request), do: 0x7 + def multipart_request_codec_to_int(Openflow.Multipart.GroupFeatures.Request), do: 0x8 + def multipart_request_codec_to_int(Openflow.Multipart.Meter.Request), do: 0x9 + def multipart_request_codec_to_int(Openflow.Multipart.MeterConfig.Request), do: 0xA + def multipart_request_codec_to_int(Openflow.Multipart.MeterFeatures.Request), do: 0xB + def multipart_request_codec_to_int(Openflow.Multipart.TableFeatures.Request), do: 0xC + def multipart_request_codec_to_int(Openflow.Multipart.PortDesc.Request), do: 0xD + def multipart_request_codec_to_int(Openflow.Multipart.Experimenter.Request), do: 0xFFFF + def multipart_request_codec_to_int(_), do: throw(:bad_enum) + def multipart_request_codec_to_atom(0x0), do: Openflow.Multipart.Desc.Request + def multipart_request_codec_to_atom(0x1), do: Openflow.Multipart.Flow.Request + def multipart_request_codec_to_atom(0x2), do: Openflow.Multipart.Aggregate.Request + def multipart_request_codec_to_atom(0x3), do: Openflow.Multipart.Table.Request + def multipart_request_codec_to_atom(0x4), do: Openflow.Multipart.PortStats.Request + def multipart_request_codec_to_atom(0x5), do: Openflow.Multipart.Queue.Request + def multipart_request_codec_to_atom(0x6), do: Openflow.Multipart.Group.Request + def multipart_request_codec_to_atom(0x7), do: Openflow.Multipart.GroupDesc.Request + def multipart_request_codec_to_atom(0x8), do: Openflow.Multipart.GroupFeatures.Request + def multipart_request_codec_to_atom(0x9), do: Openflow.Multipart.Meter.Request + def multipart_request_codec_to_atom(0xA), do: Openflow.Multipart.MeterConfig.Request + def multipart_request_codec_to_atom(0xB), do: Openflow.Multipart.MeterFeatures.Request + def multipart_request_codec_to_atom(0xC), do: Openflow.Multipart.TableFeatures.Request + def multipart_request_codec_to_atom(0xD), do: Openflow.Multipart.PortDesc.Request + def multipart_request_codec_to_atom(0xFFFF), do: Openflow.Multipart.Experimenter.Request + def multipart_request_codec_to_atom(_), do: throw(:bad_enum) + def multipart_reply_codec_to_int(Openflow.Multipart.Desc.Reply), do: 0x0 + def multipart_reply_codec_to_int(Openflow.Multipart.Flow.Reply), do: 0x1 + def multipart_reply_codec_to_int(Openflow.Multipart.Aggregate.Reply), do: 0x2 + def multipart_reply_codec_to_int(Openflow.Multipart.Table.Reply), do: 0x3 + def multipart_reply_codec_to_int(Openflow.Multipart.PortStats.Reply), do: 0x4 + def multipart_reply_codec_to_int(Openflow.Multipart.Queue.Reply), do: 0x5 + def multipart_reply_codec_to_int(Openflow.Multipart.Group.Reply), do: 0x6 + def multipart_reply_codec_to_int(Openflow.Multipart.GroupDesc.Reply), do: 0x7 + def multipart_reply_codec_to_int(Openflow.Multipart.GroupFeatures.Reply), do: 0x8 + def multipart_reply_codec_to_int(Openflow.Multipart.Meter.Reply), do: 0x9 + def multipart_reply_codec_to_int(Openflow.Multipart.MeterConfig.Reply), do: 0xA + def multipart_reply_codec_to_int(Openflow.Multipart.MeterFeatures.Reply), do: 0xB + def multipart_reply_codec_to_int(Openflow.Multipart.TableFeatures.Reply), do: 0xC + def multipart_reply_codec_to_int(Openflow.Multipart.PortDesc.Reply), do: 0xD + def multipart_reply_codec_to_int(Openflow.Multipart.Experimenter.Reply), do: 0xFFFF + def multipart_reply_codec_to_int(_), do: throw(:bad_enum) + def multipart_reply_codec_to_atom(0x0), do: Openflow.Multipart.Desc.Reply + def multipart_reply_codec_to_atom(0x1), do: Openflow.Multipart.Flow.Reply + def multipart_reply_codec_to_atom(0x2), do: Openflow.Multipart.Aggregate.Reply + def multipart_reply_codec_to_atom(0x3), do: Openflow.Multipart.Table.Reply + def multipart_reply_codec_to_atom(0x4), do: Openflow.Multipart.PortStats.Reply + def multipart_reply_codec_to_atom(0x5), do: Openflow.Multipart.Queue.Reply + def multipart_reply_codec_to_atom(0x6), do: Openflow.Multipart.Group.Reply + def multipart_reply_codec_to_atom(0x7), do: Openflow.Multipart.GroupDesc.Reply + def multipart_reply_codec_to_atom(0x8), do: Openflow.Multipart.GroupFeatures.Reply + def multipart_reply_codec_to_atom(0x9), do: Openflow.Multipart.Meter.Reply + def multipart_reply_codec_to_atom(0xA), do: Openflow.Multipart.MeterConfig.Reply + def multipart_reply_codec_to_atom(0xB), do: Openflow.Multipart.MeterFeatures.Reply + def multipart_reply_codec_to_atom(0xC), do: Openflow.Multipart.TableFeatures.Reply + def multipart_reply_codec_to_atom(0xD), do: Openflow.Multipart.PortDesc.Reply + def multipart_reply_codec_to_atom(0xFFFF), do: Openflow.Multipart.Experimenter.Reply + def multipart_reply_codec_to_atom(_), do: throw(:bad_enum) + def nicira_ext_stats_to_int(Openflow.Multipart.NxFlow), do: 0x0 + def nicira_ext_stats_to_int(Openflow.Multipart.NxAggregate), do: 0x1 + def nicira_ext_stats_to_int(Openflow.Multipart.NxFlowMonitor), do: 0x2 + def nicira_ext_stats_to_int(Openflow.Multipart.NxIPFIXBridge), do: 0x3 + def nicira_ext_stats_to_int(Openflow.Multipart.NxIPFIXFlow), do: 0x4 + def nicira_ext_stats_to_int(_), do: throw(:bad_enum) + def nicira_ext_stats_to_atom(0x0), do: Openflow.Multipart.NxFlow + def nicira_ext_stats_to_atom(0x1), do: Openflow.Multipart.NxAggregate + def nicira_ext_stats_to_atom(0x2), do: Openflow.Multipart.NxFlowMonitor + def nicira_ext_stats_to_atom(0x3), do: Openflow.Multipart.NxIPFIXBridge + def nicira_ext_stats_to_atom(0x4), do: Openflow.Multipart.NxIPFIXFlow + def nicira_ext_stats_to_atom(_), do: throw(:bad_enum) + def hello_elem_to_int(:versionbitmap), do: 0x1 + def hello_elem_to_int(_), do: throw(:bad_enum) + def hello_elem_to_atom(0x1), do: :versionbitmap + def hello_elem_to_atom(_), do: throw(:bad_enum) + def error_type_to_int(:hello_failed), do: 0x0 + def error_type_to_int(:bad_request), do: 0x1 + def error_type_to_int(:bad_action), do: 0x2 + def error_type_to_int(:bad_instruction), do: 0x3 + def error_type_to_int(:bad_match), do: 0x4 + def error_type_to_int(:flow_mod_failed), do: 0x5 + def error_type_to_int(:group_mod_failed), do: 0x6 + def error_type_to_int(:port_mod_failed), do: 0x7 + def error_type_to_int(:table_mod_failed), do: 0x8 + def error_type_to_int(:queue_op_failed), do: 0x9 + def error_type_to_int(:switch_config_failed), do: 0xA + def error_type_to_int(:role_request_failed), do: 0xB + def error_type_to_int(:meter_mod_failed), do: 0xC + def error_type_to_int(:table_features_failed), do: 0xD + def error_type_to_int(:experimenter), do: 0xFFFF + def error_type_to_int(_), do: throw(:bad_enum) + def error_type_to_atom(0x0), do: :hello_failed + def error_type_to_atom(0x1), do: :bad_request + def error_type_to_atom(0x2), do: :bad_action + def error_type_to_atom(0x3), do: :bad_instruction + def error_type_to_atom(0x4), do: :bad_match + def error_type_to_atom(0x5), do: :flow_mod_failed + def error_type_to_atom(0x6), do: :group_mod_failed + def error_type_to_atom(0x7), do: :port_mod_failed + def error_type_to_atom(0x8), do: :table_mod_failed + def error_type_to_atom(0x9), do: :queue_op_failed + def error_type_to_atom(0xA), do: :switch_config_failed + def error_type_to_atom(0xB), do: :role_request_failed + def error_type_to_atom(0xC), do: :meter_mod_failed + def error_type_to_atom(0xD), do: :table_features_failed + def error_type_to_atom(0xFFFF), do: :experimenter + def error_type_to_atom(_), do: throw(:bad_enum) + def hello_failed_to_int(:inconpatible), do: 0x0 + def hello_failed_to_int(:eperm), do: 0x1 + def hello_failed_to_int(_), do: throw(:bad_enum) + def hello_failed_to_atom(0x0), do: :inconpatible + def hello_failed_to_atom(0x1), do: :eperm + def hello_failed_to_atom(_), do: throw(:bad_enum) + def bad_request_to_int(:bad_version), do: 0x0 + def bad_request_to_int(:bad_type), do: 0x1 + def bad_request_to_int(:bad_multipart), do: 0x2 + def bad_request_to_int(:bad_experimeter), do: 0x3 + def bad_request_to_int(:bad_exp_type), do: 0x4 + def bad_request_to_int(:eperm), do: 0x5 + def bad_request_to_int(:bad_len), do: 0x6 + def bad_request_to_int(:buffer_empty), do: 0x7 + def bad_request_to_int(:buffer_unknown), do: 0x8 + def bad_request_to_int(:bad_table_id), do: 0x9 + def bad_request_to_int(:is_slave), do: 0xA + def bad_request_to_int(:bad_port), do: 0xB + def bad_request_to_int(:bad_packet), do: 0xC + def bad_request_to_int(:multipart_buffer_overflow), do: 0xD + def bad_request_to_int(_), do: throw(:bad_enum) + def bad_request_to_atom(0x0), do: :bad_version + def bad_request_to_atom(0x1), do: :bad_type + def bad_request_to_atom(0x2), do: :bad_multipart + def bad_request_to_atom(0x3), do: :bad_experimeter + def bad_request_to_atom(0x4), do: :bad_exp_type + def bad_request_to_atom(0x5), do: :eperm + def bad_request_to_atom(0x6), do: :bad_len + def bad_request_to_atom(0x7), do: :buffer_empty + def bad_request_to_atom(0x8), do: :buffer_unknown + def bad_request_to_atom(0x9), do: :bad_table_id + def bad_request_to_atom(0xA), do: :is_slave + def bad_request_to_atom(0xB), do: :bad_port + def bad_request_to_atom(0xC), do: :bad_packet + def bad_request_to_atom(0xD), do: :multipart_buffer_overflow + def bad_request_to_atom(_), do: throw(:bad_enum) + def bad_action_to_int(:bad_type), do: 0x0 + def bad_action_to_int(:bad_len), do: 0x1 + def bad_action_to_int(:bad_experimeter), do: 0x2 + def bad_action_to_int(:bad_exp_type), do: 0x3 + def bad_action_to_int(:bad_out_port), do: 0x4 + def bad_action_to_int(:bad_argument), do: 0x5 + def bad_action_to_int(:eperm), do: 0x6 + def bad_action_to_int(:too_many), do: 0x7 + def bad_action_to_int(:bad_queue), do: 0x8 + def bad_action_to_int(:bad_out_group), do: 0x9 + def bad_action_to_int(:match_inconsistent), do: 0xA + def bad_action_to_int(:unsupported_order), do: 0xB + def bad_action_to_int(:bad_tag), do: 0xC + def bad_action_to_int(:bad_set_type), do: 0xD + def bad_action_to_int(:bad_set_len), do: 0xE + def bad_action_to_int(:bad_set_argument), do: 0xF + def bad_action_to_int(_), do: throw(:bad_enum) + def bad_action_to_atom(0x0), do: :bad_type + def bad_action_to_atom(0x1), do: :bad_len + def bad_action_to_atom(0x2), do: :bad_experimeter + def bad_action_to_atom(0x3), do: :bad_exp_type + def bad_action_to_atom(0x4), do: :bad_out_port + def bad_action_to_atom(0x5), do: :bad_argument + def bad_action_to_atom(0x6), do: :eperm + def bad_action_to_atom(0x7), do: :too_many + def bad_action_to_atom(0x8), do: :bad_queue + def bad_action_to_atom(0x9), do: :bad_out_group + def bad_action_to_atom(0xA), do: :match_inconsistent + def bad_action_to_atom(0xB), do: :unsupported_order + def bad_action_to_atom(0xC), do: :bad_tag + def bad_action_to_atom(0xD), do: :bad_set_type + def bad_action_to_atom(0xE), do: :bad_set_len + def bad_action_to_atom(0xF), do: :bad_set_argument + def bad_action_to_atom(_), do: throw(:bad_enum) + def bad_instruction_to_int(:unknown_instruction), do: 0x0 + def bad_instruction_to_int(:unsupported_instruction), do: 0x1 + def bad_instruction_to_int(:bad_table_id), do: 0x2 + def bad_instruction_to_int(:unsupported_metadata), do: 0x3 + def bad_instruction_to_int(:unsupported_metadata_mask), do: 0x4 + def bad_instruction_to_int(:bad_experimeter), do: 0x5 + def bad_instruction_to_int(:bad_exp_type), do: 0x6 + def bad_instruction_to_int(:bad_len), do: 0x7 + def bad_instruction_to_int(:eperm), do: 0x8 + def bad_instruction_to_int(_), do: throw(:bad_enum) + def bad_instruction_to_atom(0x0), do: :unknown_instruction + def bad_instruction_to_atom(0x1), do: :unsupported_instruction + def bad_instruction_to_atom(0x2), do: :bad_table_id + def bad_instruction_to_atom(0x3), do: :unsupported_metadata + def bad_instruction_to_atom(0x4), do: :unsupported_metadata_mask + def bad_instruction_to_atom(0x5), do: :bad_experimeter + def bad_instruction_to_atom(0x6), do: :bad_exp_type + def bad_instruction_to_atom(0x7), do: :bad_len + def bad_instruction_to_atom(0x8), do: :eperm + def bad_instruction_to_atom(_), do: throw(:bad_enum) + def bad_match_to_int(:bad_type), do: 0x0 + def bad_match_to_int(:bad_len), do: 0x1 + def bad_match_to_int(:bad_tag), do: 0x2 + def bad_match_to_int(:bad_dl_addr_mask), do: 0x3 + def bad_match_to_int(:bad_nw_addr_mask), do: 0x4 + def bad_match_to_int(:bad_wildcards), do: 0x5 + def bad_match_to_int(:bad_field), do: 0x6 + def bad_match_to_int(:bad_value), do: 0x7 + def bad_match_to_int(:bad_mask), do: 0x8 + def bad_match_to_int(:bad_prereq), do: 0x9 + def bad_match_to_int(:dup_field), do: 0xA + def bad_match_to_int(:eperm), do: 0xB + def bad_match_to_int(_), do: throw(:bad_enum) + def bad_match_to_atom(0x0), do: :bad_type + def bad_match_to_atom(0x1), do: :bad_len + def bad_match_to_atom(0x2), do: :bad_tag + def bad_match_to_atom(0x3), do: :bad_dl_addr_mask + def bad_match_to_atom(0x4), do: :bad_nw_addr_mask + def bad_match_to_atom(0x5), do: :bad_wildcards + def bad_match_to_atom(0x6), do: :bad_field + def bad_match_to_atom(0x7), do: :bad_value + def bad_match_to_atom(0x8), do: :bad_mask + def bad_match_to_atom(0x9), do: :bad_prereq + def bad_match_to_atom(0xA), do: :dup_field + def bad_match_to_atom(0xB), do: :eperm + def bad_match_to_atom(_), do: throw(:bad_enum) + def flow_mod_failed_to_int(:unknown), do: 0x0 + def flow_mod_failed_to_int(:table_full), do: 0x1 + def flow_mod_failed_to_int(:bad_table_id), do: 0x2 + def flow_mod_failed_to_int(:overlap), do: 0x3 + def flow_mod_failed_to_int(:eperm), do: 0x4 + def flow_mod_failed_to_int(:bad_timeout), do: 0x5 + def flow_mod_failed_to_int(:bad_command), do: 0x6 + def flow_mod_failed_to_int(:bad_flags), do: 0x7 + def flow_mod_failed_to_int(_), do: throw(:bad_enum) + def flow_mod_failed_to_atom(0x0), do: :unknown + def flow_mod_failed_to_atom(0x1), do: :table_full + def flow_mod_failed_to_atom(0x2), do: :bad_table_id + def flow_mod_failed_to_atom(0x3), do: :overlap + def flow_mod_failed_to_atom(0x4), do: :eperm + def flow_mod_failed_to_atom(0x5), do: :bad_timeout + def flow_mod_failed_to_atom(0x6), do: :bad_command + def flow_mod_failed_to_atom(0x7), do: :bad_flags + def flow_mod_failed_to_atom(_), do: throw(:bad_enum) + def group_mod_failed_to_int(:group_exists), do: 0x0 + def group_mod_failed_to_int(:invalid_group), do: 0x1 + def group_mod_failed_to_int(:weight_unsupported), do: 0x2 + def group_mod_failed_to_int(:out_of_groups), do: 0x3 + def group_mod_failed_to_int(:ouf_of_buckets), do: 0x4 + def group_mod_failed_to_int(:chaining_unsupported), do: 0x5 + def group_mod_failed_to_int(:watch_unsupported), do: 0x6 + def group_mod_failed_to_int(:loop), do: 0x7 + def group_mod_failed_to_int(:unknown_group), do: 0x8 + def group_mod_failed_to_int(:chained_group), do: 0x9 + def group_mod_failed_to_int(:bad_type), do: 0xA + def group_mod_failed_to_int(:bad_command), do: 0xB + def group_mod_failed_to_int(:bad_bucket), do: 0xC + def group_mod_failed_to_int(:bad_watch), do: 0xD + def group_mod_failed_to_int(:eperm), do: 0xE + def group_mod_failed_to_int(_), do: throw(:bad_enum) + def group_mod_failed_to_atom(0x0), do: :group_exists + def group_mod_failed_to_atom(0x1), do: :invalid_group + def group_mod_failed_to_atom(0x2), do: :weight_unsupported + def group_mod_failed_to_atom(0x3), do: :out_of_groups + def group_mod_failed_to_atom(0x4), do: :ouf_of_buckets + def group_mod_failed_to_atom(0x5), do: :chaining_unsupported + def group_mod_failed_to_atom(0x6), do: :watch_unsupported + def group_mod_failed_to_atom(0x7), do: :loop + def group_mod_failed_to_atom(0x8), do: :unknown_group + def group_mod_failed_to_atom(0x9), do: :chained_group + def group_mod_failed_to_atom(0xA), do: :bad_type + def group_mod_failed_to_atom(0xB), do: :bad_command + def group_mod_failed_to_atom(0xC), do: :bad_bucket + def group_mod_failed_to_atom(0xD), do: :bad_watch + def group_mod_failed_to_atom(0xE), do: :eperm + def group_mod_failed_to_atom(_), do: throw(:bad_enum) + def port_mod_failed_to_int(:bad_port), do: 0x0 + def port_mod_failed_to_int(:bad_hw_addr), do: 0x1 + def port_mod_failed_to_int(:bad_config), do: 0x2 + def port_mod_failed_to_int(:bad_advertise), do: 0x3 + def port_mod_failed_to_int(:eperm), do: 0x4 + def port_mod_failed_to_int(_), do: throw(:bad_enum) + def port_mod_failed_to_atom(0x0), do: :bad_port + def port_mod_failed_to_atom(0x1), do: :bad_hw_addr + def port_mod_failed_to_atom(0x2), do: :bad_config + def port_mod_failed_to_atom(0x3), do: :bad_advertise + def port_mod_failed_to_atom(0x4), do: :eperm + def port_mod_failed_to_atom(_), do: throw(:bad_enum) + def table_mod_failed_to_int(:bad_table), do: 0x0 + def table_mod_failed_to_int(:bad_config), do: 0x1 + def table_mod_failed_to_int(:eperm), do: 0x2 + def table_mod_failed_to_int(_), do: throw(:bad_enum) + def table_mod_failed_to_atom(0x0), do: :bad_table + def table_mod_failed_to_atom(0x1), do: :bad_config + def table_mod_failed_to_atom(0x2), do: :eperm + def table_mod_failed_to_atom(_), do: throw(:bad_enum) + def queue_op_failed_to_int(:bad_port), do: 0x0 + def queue_op_failed_to_int(:bad_queue), do: 0x1 + def queue_op_failed_to_int(:eperm), do: 0x2 + def queue_op_failed_to_int(_), do: throw(:bad_enum) + def queue_op_failed_to_atom(0x0), do: :bad_port + def queue_op_failed_to_atom(0x1), do: :bad_queue + def queue_op_failed_to_atom(0x2), do: :eperm + def queue_op_failed_to_atom(_), do: throw(:bad_enum) + def switch_config_failed_to_int(:bad_flags), do: 0x0 + def switch_config_failed_to_int(:bad_len), do: 0x1 + def switch_config_failed_to_int(:eperm), do: 0x2 + def switch_config_failed_to_int(_), do: throw(:bad_enum) + def switch_config_failed_to_atom(0x0), do: :bad_flags + def switch_config_failed_to_atom(0x1), do: :bad_len + def switch_config_failed_to_atom(0x2), do: :eperm + def switch_config_failed_to_atom(_), do: throw(:bad_enum) + def role_request_failed_to_int(:stale), do: 0x0 + def role_request_failed_to_int(:unsup), do: 0x1 + def role_request_failed_to_int(:bad_role), do: 0x2 + def role_request_failed_to_int(_), do: throw(:bad_enum) + def role_request_failed_to_atom(0x0), do: :stale + def role_request_failed_to_atom(0x1), do: :unsup + def role_request_failed_to_atom(0x2), do: :bad_role + def role_request_failed_to_atom(_), do: throw(:bad_enum) + def meter_mod_failed_to_int(:unknown), do: 0x0 + def meter_mod_failed_to_int(:meter_exists), do: 0x1 + def meter_mod_failed_to_int(:invalid_meter), do: 0x2 + def meter_mod_failed_to_int(:unknown_meter), do: 0x3 + def meter_mod_failed_to_int(:bad_command), do: 0x4 + def meter_mod_failed_to_int(:bad_flags), do: 0x5 + def meter_mod_failed_to_int(:bad_rate), do: 0x6 + def meter_mod_failed_to_int(:bad_burst), do: 0x7 + def meter_mod_failed_to_int(:bad_band), do: 0x8 + def meter_mod_failed_to_int(:bad_band_value), do: 0x9 + def meter_mod_failed_to_int(:out_of_meters), do: 0xA + def meter_mod_failed_to_int(:out_of_bands), do: 0xB + def meter_mod_failed_to_int(_), do: throw(:bad_enum) + def meter_mod_failed_to_atom(0x0), do: :unknown + def meter_mod_failed_to_atom(0x1), do: :meter_exists + def meter_mod_failed_to_atom(0x2), do: :invalid_meter + def meter_mod_failed_to_atom(0x3), do: :unknown_meter + def meter_mod_failed_to_atom(0x4), do: :bad_command + def meter_mod_failed_to_atom(0x5), do: :bad_flags + def meter_mod_failed_to_atom(0x6), do: :bad_rate + def meter_mod_failed_to_atom(0x7), do: :bad_burst + def meter_mod_failed_to_atom(0x8), do: :bad_band + def meter_mod_failed_to_atom(0x9), do: :bad_band_value + def meter_mod_failed_to_atom(0xA), do: :out_of_meters + def meter_mod_failed_to_atom(0xB), do: :out_of_bands + def meter_mod_failed_to_atom(_), do: throw(:bad_enum) + def table_features_failed_to_int(:bad_table), do: 0x0 + def table_features_failed_to_int(:bad_metadata), do: 0x1 + def table_features_failed_to_int(:bad_type), do: 0x2 + def table_features_failed_to_int(:bad_len), do: 0x3 + def table_features_failed_to_int(:bad_argument), do: 0x4 + def table_features_failed_to_int(:eperm), do: 0x5 + def table_features_failed_to_int(_), do: throw(:bad_enum) + def table_features_failed_to_atom(0x0), do: :bad_table + def table_features_failed_to_atom(0x1), do: :bad_metadata + def table_features_failed_to_atom(0x2), do: :bad_type + def table_features_failed_to_atom(0x3), do: :bad_len + def table_features_failed_to_atom(0x4), do: :bad_argument + def table_features_failed_to_atom(0x5), do: :eperm + def table_features_failed_to_atom(_), do: throw(:bad_enum) + def switch_capabilities_to_int(:flow_stats), do: 0x1 + def switch_capabilities_to_int(:table_stats), do: 0x2 + def switch_capabilities_to_int(:port_stats), do: 0x4 + def switch_capabilities_to_int(:group_stats), do: 0x8 + def switch_capabilities_to_int(:ip_reasm), do: 0x20 + def switch_capabilities_to_int(:queue_stats), do: 0x40 + def switch_capabilities_to_int(:arp_match_ip), do: 0x80 + def switch_capabilities_to_int(:port_blocked), do: 0x100 + def switch_capabilities_to_int(_), do: throw(:bad_enum) + def switch_capabilities_to_atom(0x1), do: :flow_stats + def switch_capabilities_to_atom(0x2), do: :table_stats + def switch_capabilities_to_atom(0x4), do: :port_stats + def switch_capabilities_to_atom(0x8), do: :group_stats + def switch_capabilities_to_atom(0x20), do: :ip_reasm + def switch_capabilities_to_atom(0x40), do: :queue_stats + def switch_capabilities_to_atom(0x80), do: :arp_match_ip + def switch_capabilities_to_atom(0x100), do: :port_blocked + def switch_capabilities_to_atom(_), do: throw(:bad_enum) + def config_flags_to_int(:drop), do: 0x1 + def config_flags_to_int(:reasm), do: 0x2 + def config_flags_to_int(_), do: throw(:bad_enum) + def config_flags_to_atom(0x1), do: :drop + def config_flags_to_atom(0x2), do: :reasm + def config_flags_to_atom(_), do: throw(:bad_enum) + def controller_max_len_to_int(:max), do: 0xFFE5 + def controller_max_len_to_int(:no_buffer), do: 0xFFFF + def controller_max_len_to_int(_), do: throw(:bad_enum) + def controller_max_len_to_atom(0xFFE5), do: :max + def controller_max_len_to_atom(0xFFFF), do: :no_buffer + def controller_max_len_to_atom(_), do: throw(:bad_enum) + def experimenter_oxm_vendors_to_int(:nicira_ext_match), do: 0x2320 + def experimenter_oxm_vendors_to_int(:hp_ext_match), do: 0x2428 + def experimenter_oxm_vendors_to_int(:onf_ext_match), do: 0x4F4E4600 + def experimenter_oxm_vendors_to_int(_), do: throw(:bad_enum) + def experimenter_oxm_vendors_to_atom(0x2320), do: :nicira_ext_match + def experimenter_oxm_vendors_to_atom(0x2428), do: :hp_ext_match + def experimenter_oxm_vendors_to_atom(0x4F4E4600), do: :onf_ext_match + def experimenter_oxm_vendors_to_atom(_), do: throw(:bad_enum) + def match_type_to_int(:standard), do: 0x0 + def match_type_to_int(:oxm), do: 0x1 + def match_type_to_int(_), do: throw(:bad_enum) + def match_type_to_atom(0x0), do: :standard + def match_type_to_atom(0x1), do: :oxm + def match_type_to_atom(_), do: throw(:bad_enum) + def oxm_class_to_int(:nxm_0), do: 0x0 + def oxm_class_to_int(:nxm_1), do: 0x1 + def oxm_class_to_int(:openflow_basic), do: 0x8000 + def oxm_class_to_int(:packet_register), do: 0x8001 + def oxm_class_to_int(:experimenter), do: 0xFFFF + def oxm_class_to_int(_), do: throw(:bad_enum) + def oxm_class_to_atom(0x0), do: :nxm_0 + def oxm_class_to_atom(0x1), do: :nxm_1 + def oxm_class_to_atom(0x8000), do: :openflow_basic + def oxm_class_to_atom(0x8001), do: :packet_register + def oxm_class_to_atom(0xFFFF), do: :experimenter + def oxm_class_to_atom(_), do: throw(:bad_enum) + def nxm_0_to_int(:nx_in_port), do: 0x0 + def nxm_0_to_int(:nx_eth_dst), do: 0x1 + def nxm_0_to_int(:nx_eth_src), do: 0x2 + def nxm_0_to_int(:nx_eth_type), do: 0x3 + def nxm_0_to_int(:nx_vlan_tci), do: 0x4 + def nxm_0_to_int(:nx_ip_tos), do: 0x5 + def nxm_0_to_int(:nx_ip_proto), do: 0x6 + def nxm_0_to_int(:nx_ipv4_src), do: 0x7 + def nxm_0_to_int(:nx_ipv4_dst), do: 0x8 + def nxm_0_to_int(:nx_tcp_src), do: 0x9 + def nxm_0_to_int(:nx_tcp_dst), do: 0xA + def nxm_0_to_int(:nx_udp_src), do: 0xB + def nxm_0_to_int(:nx_udp_dst), do: 0xC + def nxm_0_to_int(:nx_icmpv4_type), do: 0xD + def nxm_0_to_int(:nx_icmpv4_code), do: 0xE + def nxm_0_to_int(:nx_arp_op), do: 0xF + def nxm_0_to_int(:nx_arp_spa), do: 0x10 + def nxm_0_to_int(:nx_arp_tpa), do: 0x11 + def nxm_0_to_int(:nx_tcp_flags), do: 0x22 + def nxm_0_to_int(_), do: throw(:bad_enum) + def nxm_0_to_atom(0x0), do: :nx_in_port + def nxm_0_to_atom(0x1), do: :nx_eth_dst + def nxm_0_to_atom(0x2), do: :nx_eth_src + def nxm_0_to_atom(0x3), do: :nx_eth_type + def nxm_0_to_atom(0x4), do: :nx_vlan_tci + def nxm_0_to_atom(0x5), do: :nx_ip_tos + def nxm_0_to_atom(0x6), do: :nx_ip_proto + def nxm_0_to_atom(0x7), do: :nx_ipv4_src + def nxm_0_to_atom(0x8), do: :nx_ipv4_dst + def nxm_0_to_atom(0x9), do: :nx_tcp_src + def nxm_0_to_atom(0xA), do: :nx_tcp_dst + def nxm_0_to_atom(0xB), do: :nx_udp_src + def nxm_0_to_atom(0xC), do: :nx_udp_dst + def nxm_0_to_atom(0xD), do: :nx_icmpv4_type + def nxm_0_to_atom(0xE), do: :nx_icmpv4_code + def nxm_0_to_atom(0xF), do: :nx_arp_op + def nxm_0_to_atom(0x10), do: :nx_arp_spa + def nxm_0_to_atom(0x11), do: :nx_arp_tpa + def nxm_0_to_atom(0x22), do: :nx_tcp_flags + def nxm_0_to_atom(_), do: throw(:bad_enum) + def nxm_1_to_int(:reg0), do: 0x0 + def nxm_1_to_int(:reg1), do: 0x1 + def nxm_1_to_int(:reg2), do: 0x2 + def nxm_1_to_int(:reg3), do: 0x3 + def nxm_1_to_int(:reg4), do: 0x4 + def nxm_1_to_int(:reg5), do: 0x5 + def nxm_1_to_int(:reg6), do: 0x6 + def nxm_1_to_int(:reg7), do: 0x7 + def nxm_1_to_int(:reg8), do: 0x8 + def nxm_1_to_int(:reg9), do: 0x9 + def nxm_1_to_int(:reg10), do: 0xA + def nxm_1_to_int(:reg11), do: 0xB + def nxm_1_to_int(:reg12), do: 0xC + def nxm_1_to_int(:reg13), do: 0xD + def nxm_1_to_int(:reg14), do: 0xE + def nxm_1_to_int(:reg15), do: 0xF + def nxm_1_to_int(:tun_id), do: 0x10 + def nxm_1_to_int(:nx_arp_sha), do: 0x11 + def nxm_1_to_int(:nx_arp_tha), do: 0x12 + def nxm_1_to_int(:nx_ipv6_src), do: 0x13 + def nxm_1_to_int(:nx_ipv6_dst), do: 0x14 + def nxm_1_to_int(:nx_icmpv6_type), do: 0x15 + def nxm_1_to_int(:nx_icmpv6_code), do: 0x16 + def nxm_1_to_int(:nx_ipv6_nd_target), do: 0x17 + def nxm_1_to_int(:nx_ipv6_nd_sll), do: 0x18 + def nxm_1_to_int(:nx_ipv6_nd_tll), do: 0x19 + def nxm_1_to_int(:nx_ip_frag), do: 0x1A + def nxm_1_to_int(:nx_ipv6_label), do: 0x1B + def nxm_1_to_int(:nx_ip_ecn), do: 0x1C + def nxm_1_to_int(:nx_ip_ttl), do: 0x1D + def nxm_1_to_int(:nx_mpls_ttl), do: 0x1E + def nxm_1_to_int(:tun_src), do: 0x1F + def nxm_1_to_int(:tun_dst), do: 0x20 + def nxm_1_to_int(:pkt_mark), do: 0x21 + def nxm_1_to_int(:dp_hash), do: 0x23 + def nxm_1_to_int(:recirc_id), do: 0x24 + def nxm_1_to_int(:conj_id), do: 0x25 + def nxm_1_to_int(:tun_gbp_id), do: 0x26 + def nxm_1_to_int(:tun_gbp_flags), do: 0x27 + def nxm_1_to_int(:tun_metadata0), do: 0x28 + def nxm_1_to_int(:tun_metadata1), do: 0x29 + def nxm_1_to_int(:tun_metadata2), do: 0x2A + def nxm_1_to_int(:tun_metadata3), do: 0x2B + def nxm_1_to_int(:tun_metadata4), do: 0x2C + def nxm_1_to_int(:tun_metadata5), do: 0x2D + def nxm_1_to_int(:tun_metadata6), do: 0x2E + def nxm_1_to_int(:tun_metadata7), do: 0x2F + def nxm_1_to_int(:tun_metadata8), do: 0x30 + def nxm_1_to_int(:tun_metadata9), do: 0x31 + def nxm_1_to_int(:tun_metadata10), do: 0x32 + def nxm_1_to_int(:tun_metadata11), do: 0x33 + def nxm_1_to_int(:tun_metadata12), do: 0x34 + def nxm_1_to_int(:tun_metadata13), do: 0x35 + def nxm_1_to_int(:tun_metadata14), do: 0x36 + def nxm_1_to_int(:tun_metadata15), do: 0x37 + def nxm_1_to_int(:tun_metadata16), do: 0x38 + def nxm_1_to_int(:tun_metadata17), do: 0x39 + def nxm_1_to_int(:tun_metadata18), do: 0x3A + def nxm_1_to_int(:tun_metadata19), do: 0x3B + def nxm_1_to_int(:tun_metadata20), do: 0x3C + def nxm_1_to_int(:tun_metadata21), do: 0x3D + def nxm_1_to_int(:tun_metadata22), do: 0x3E + def nxm_1_to_int(:tun_metadata23), do: 0x3F + def nxm_1_to_int(:tun_metadata24), do: 0x40 + def nxm_1_to_int(:tun_metadata25), do: 0x41 + def nxm_1_to_int(:tun_metadata26), do: 0x42 + def nxm_1_to_int(:tun_metadata27), do: 0x43 + def nxm_1_to_int(:tun_metadata28), do: 0x44 + def nxm_1_to_int(:tun_metadata29), do: 0x45 + def nxm_1_to_int(:tun_metadata30), do: 0x46 + def nxm_1_to_int(:tun_metadata31), do: 0x47 + def nxm_1_to_int(:tun_metadata32), do: 0x48 + def nxm_1_to_int(:tun_metadata33), do: 0x49 + def nxm_1_to_int(:tun_metadata34), do: 0x4A + def nxm_1_to_int(:tun_metadata35), do: 0x4B + def nxm_1_to_int(:tun_metadata36), do: 0x4C + def nxm_1_to_int(:tun_metadata37), do: 0x4D + def nxm_1_to_int(:tun_metadata38), do: 0x4E + def nxm_1_to_int(:tun_metadata39), do: 0x4F + def nxm_1_to_int(:tun_metadata40), do: 0x50 + def nxm_1_to_int(:tun_metadata41), do: 0x51 + def nxm_1_to_int(:tun_metadata42), do: 0x52 + def nxm_1_to_int(:tun_metadata43), do: 0x53 + def nxm_1_to_int(:tun_metadata44), do: 0x54 + def nxm_1_to_int(:tun_metadata45), do: 0x55 + def nxm_1_to_int(:tun_metadata46), do: 0x56 + def nxm_1_to_int(:tun_metadata47), do: 0x57 + def nxm_1_to_int(:tun_metadata48), do: 0x58 + def nxm_1_to_int(:tun_metadata49), do: 0x59 + def nxm_1_to_int(:tun_metadata50), do: 0x5A + def nxm_1_to_int(:tun_metadata51), do: 0x5B + def nxm_1_to_int(:tun_metadata52), do: 0x5C + def nxm_1_to_int(:tun_metadata53), do: 0x5D + def nxm_1_to_int(:tun_metadata54), do: 0x5E + def nxm_1_to_int(:tun_metadata55), do: 0x5F + def nxm_1_to_int(:tun_metadata56), do: 0x60 + def nxm_1_to_int(:tun_metadata57), do: 0x61 + def nxm_1_to_int(:tun_metadata58), do: 0x62 + def nxm_1_to_int(:tun_metadata59), do: 0x63 + def nxm_1_to_int(:tun_metadata60), do: 0x64 + def nxm_1_to_int(:tun_metadata61), do: 0x65 + def nxm_1_to_int(:tun_metadata62), do: 0x66 + def nxm_1_to_int(:tun_metadata63), do: 0x67 + def nxm_1_to_int(:tun_flags), do: 0x68 + def nxm_1_to_int(:ct_state), do: 0x69 + def nxm_1_to_int(:ct_zone), do: 0x6A + def nxm_1_to_int(:ct_mark), do: 0x6B + def nxm_1_to_int(:ct_label), do: 0x6C + def nxm_1_to_int(:tun_ipv6_src), do: 0x6D + def nxm_1_to_int(:tun_ipv6_dst), do: 0x6E + def nxm_1_to_int(:xxreg0), do: 0x6F + def nxm_1_to_int(:xxreg1), do: 0x70 + def nxm_1_to_int(:xxreg2), do: 0x71 + def nxm_1_to_int(:xxreg3), do: 0x72 + def nxm_1_to_int(:xxreg4), do: 0x73 + def nxm_1_to_int(:xxreg5), do: 0x74 + def nxm_1_to_int(:xxreg6), do: 0x75 + def nxm_1_to_int(:xxreg7), do: 0x76 + def nxm_1_to_int(:ct_nw_proto), do: 0x77 + def nxm_1_to_int(:ct_nw_src), do: 0x78 + def nxm_1_to_int(:ct_nw_dst), do: 0x79 + def nxm_1_to_int(:ct_ipv6_src), do: 0x7A + def nxm_1_to_int(:ct_ipv6_dst), do: 0x7B + def nxm_1_to_int(:ct_tp_src), do: 0x7C + def nxm_1_to_int(:ct_tp_dst), do: 0x7D + def nxm_1_to_int(_), do: throw(:bad_enum) + def nxm_1_to_atom(0x0), do: :reg0 + def nxm_1_to_atom(0x1), do: :reg1 + def nxm_1_to_atom(0x2), do: :reg2 + def nxm_1_to_atom(0x3), do: :reg3 + def nxm_1_to_atom(0x4), do: :reg4 + def nxm_1_to_atom(0x5), do: :reg5 + def nxm_1_to_atom(0x6), do: :reg6 + def nxm_1_to_atom(0x7), do: :reg7 + def nxm_1_to_atom(0x8), do: :reg8 + def nxm_1_to_atom(0x9), do: :reg9 + def nxm_1_to_atom(0xA), do: :reg10 + def nxm_1_to_atom(0xB), do: :reg11 + def nxm_1_to_atom(0xC), do: :reg12 + def nxm_1_to_atom(0xD), do: :reg13 + def nxm_1_to_atom(0xE), do: :reg14 + def nxm_1_to_atom(0xF), do: :reg15 + def nxm_1_to_atom(0x10), do: :tun_id + def nxm_1_to_atom(0x11), do: :nx_arp_sha + def nxm_1_to_atom(0x12), do: :nx_arp_tha + def nxm_1_to_atom(0x13), do: :nx_ipv6_src + def nxm_1_to_atom(0x14), do: :nx_ipv6_dst + def nxm_1_to_atom(0x15), do: :nx_icmpv6_type + def nxm_1_to_atom(0x16), do: :nx_icmpv6_code + def nxm_1_to_atom(0x17), do: :nx_ipv6_nd_target + def nxm_1_to_atom(0x18), do: :nx_ipv6_nd_sll + def nxm_1_to_atom(0x19), do: :nx_ipv6_nd_tll + def nxm_1_to_atom(0x1A), do: :nx_ip_frag + def nxm_1_to_atom(0x1B), do: :nx_ipv6_label + def nxm_1_to_atom(0x1C), do: :nx_ip_ecn + def nxm_1_to_atom(0x1D), do: :nx_ip_ttl + def nxm_1_to_atom(0x1E), do: :nx_mpls_ttl + def nxm_1_to_atom(0x1F), do: :tun_src + def nxm_1_to_atom(0x20), do: :tun_dst + def nxm_1_to_atom(0x21), do: :pkt_mark + def nxm_1_to_atom(0x23), do: :dp_hash + def nxm_1_to_atom(0x24), do: :recirc_id + def nxm_1_to_atom(0x25), do: :conj_id + def nxm_1_to_atom(0x26), do: :tun_gbp_id + def nxm_1_to_atom(0x27), do: :tun_gbp_flags + def nxm_1_to_atom(0x28), do: :tun_metadata0 + def nxm_1_to_atom(0x29), do: :tun_metadata1 + def nxm_1_to_atom(0x2A), do: :tun_metadata2 + def nxm_1_to_atom(0x2B), do: :tun_metadata3 + def nxm_1_to_atom(0x2C), do: :tun_metadata4 + def nxm_1_to_atom(0x2D), do: :tun_metadata5 + def nxm_1_to_atom(0x2E), do: :tun_metadata6 + def nxm_1_to_atom(0x2F), do: :tun_metadata7 + def nxm_1_to_atom(0x30), do: :tun_metadata8 + def nxm_1_to_atom(0x31), do: :tun_metadata9 + def nxm_1_to_atom(0x32), do: :tun_metadata10 + def nxm_1_to_atom(0x33), do: :tun_metadata11 + def nxm_1_to_atom(0x34), do: :tun_metadata12 + def nxm_1_to_atom(0x35), do: :tun_metadata13 + def nxm_1_to_atom(0x36), do: :tun_metadata14 + def nxm_1_to_atom(0x37), do: :tun_metadata15 + def nxm_1_to_atom(0x38), do: :tun_metadata16 + def nxm_1_to_atom(0x39), do: :tun_metadata17 + def nxm_1_to_atom(0x3A), do: :tun_metadata18 + def nxm_1_to_atom(0x3B), do: :tun_metadata19 + def nxm_1_to_atom(0x3C), do: :tun_metadata20 + def nxm_1_to_atom(0x3D), do: :tun_metadata21 + def nxm_1_to_atom(0x3E), do: :tun_metadata22 + def nxm_1_to_atom(0x3F), do: :tun_metadata23 + def nxm_1_to_atom(0x40), do: :tun_metadata24 + def nxm_1_to_atom(0x41), do: :tun_metadata25 + def nxm_1_to_atom(0x42), do: :tun_metadata26 + def nxm_1_to_atom(0x43), do: :tun_metadata27 + def nxm_1_to_atom(0x44), do: :tun_metadata28 + def nxm_1_to_atom(0x45), do: :tun_metadata29 + def nxm_1_to_atom(0x46), do: :tun_metadata30 + def nxm_1_to_atom(0x47), do: :tun_metadata31 + def nxm_1_to_atom(0x48), do: :tun_metadata32 + def nxm_1_to_atom(0x49), do: :tun_metadata33 + def nxm_1_to_atom(0x4A), do: :tun_metadata34 + def nxm_1_to_atom(0x4B), do: :tun_metadata35 + def nxm_1_to_atom(0x4C), do: :tun_metadata36 + def nxm_1_to_atom(0x4D), do: :tun_metadata37 + def nxm_1_to_atom(0x4E), do: :tun_metadata38 + def nxm_1_to_atom(0x4F), do: :tun_metadata39 + def nxm_1_to_atom(0x50), do: :tun_metadata40 + def nxm_1_to_atom(0x51), do: :tun_metadata41 + def nxm_1_to_atom(0x52), do: :tun_metadata42 + def nxm_1_to_atom(0x53), do: :tun_metadata43 + def nxm_1_to_atom(0x54), do: :tun_metadata44 + def nxm_1_to_atom(0x55), do: :tun_metadata45 + def nxm_1_to_atom(0x56), do: :tun_metadata46 + def nxm_1_to_atom(0x57), do: :tun_metadata47 + def nxm_1_to_atom(0x58), do: :tun_metadata48 + def nxm_1_to_atom(0x59), do: :tun_metadata49 + def nxm_1_to_atom(0x5A), do: :tun_metadata50 + def nxm_1_to_atom(0x5B), do: :tun_metadata51 + def nxm_1_to_atom(0x5C), do: :tun_metadata52 + def nxm_1_to_atom(0x5D), do: :tun_metadata53 + def nxm_1_to_atom(0x5E), do: :tun_metadata54 + def nxm_1_to_atom(0x5F), do: :tun_metadata55 + def nxm_1_to_atom(0x60), do: :tun_metadata56 + def nxm_1_to_atom(0x61), do: :tun_metadata57 + def nxm_1_to_atom(0x62), do: :tun_metadata58 + def nxm_1_to_atom(0x63), do: :tun_metadata59 + def nxm_1_to_atom(0x64), do: :tun_metadata60 + def nxm_1_to_atom(0x65), do: :tun_metadata61 + def nxm_1_to_atom(0x66), do: :tun_metadata62 + def nxm_1_to_atom(0x67), do: :tun_metadata63 + def nxm_1_to_atom(0x68), do: :tun_flags + def nxm_1_to_atom(0x69), do: :ct_state + def nxm_1_to_atom(0x6A), do: :ct_zone + def nxm_1_to_atom(0x6B), do: :ct_mark + def nxm_1_to_atom(0x6C), do: :ct_label + def nxm_1_to_atom(0x6D), do: :tun_ipv6_src + def nxm_1_to_atom(0x6E), do: :tun_ipv6_dst + def nxm_1_to_atom(0x6F), do: :xxreg0 + def nxm_1_to_atom(0x70), do: :xxreg1 + def nxm_1_to_atom(0x71), do: :xxreg2 + def nxm_1_to_atom(0x72), do: :xxreg3 + def nxm_1_to_atom(0x73), do: :xxreg4 + def nxm_1_to_atom(0x74), do: :xxreg5 + def nxm_1_to_atom(0x75), do: :xxreg6 + def nxm_1_to_atom(0x76), do: :xxreg7 + def nxm_1_to_atom(0x77), do: :ct_nw_proto + def nxm_1_to_atom(0x78), do: :ct_nw_src + def nxm_1_to_atom(0x79), do: :ct_nw_dst + def nxm_1_to_atom(0x7A), do: :ct_ipv6_src + def nxm_1_to_atom(0x7B), do: :ct_ipv6_dst + def nxm_1_to_atom(0x7C), do: :ct_tp_src + def nxm_1_to_atom(0x7D), do: :ct_tp_dst + def nxm_1_to_atom(_), do: throw(:bad_enum) + def openflow_basic_to_int(:in_port), do: 0x0 + def openflow_basic_to_int(:in_phy_port), do: 0x1 + def openflow_basic_to_int(:metadata), do: 0x2 + def openflow_basic_to_int(:eth_dst), do: 0x3 + def openflow_basic_to_int(:eth_src), do: 0x4 + def openflow_basic_to_int(:eth_type), do: 0x5 + def openflow_basic_to_int(:vlan_vid), do: 0x6 + def openflow_basic_to_int(:vlan_pcp), do: 0x7 + def openflow_basic_to_int(:ip_dscp), do: 0x8 + def openflow_basic_to_int(:ip_ecn), do: 0x9 + def openflow_basic_to_int(:ip_proto), do: 0xA + def openflow_basic_to_int(:ipv4_src), do: 0xB + def openflow_basic_to_int(:ipv4_dst), do: 0xC + def openflow_basic_to_int(:tcp_src), do: 0xD + def openflow_basic_to_int(:tcp_dst), do: 0xE + def openflow_basic_to_int(:udp_src), do: 0xF + def openflow_basic_to_int(:udp_dst), do: 0x10 + def openflow_basic_to_int(:sctp_src), do: 0x11 + def openflow_basic_to_int(:sctp_dst), do: 0x12 + def openflow_basic_to_int(:icmpv4_type), do: 0x13 + def openflow_basic_to_int(:icmpv4_code), do: 0x14 + def openflow_basic_to_int(:arp_op), do: 0x15 + def openflow_basic_to_int(:arp_spa), do: 0x16 + def openflow_basic_to_int(:arp_tpa), do: 0x17 + def openflow_basic_to_int(:arp_sha), do: 0x18 + def openflow_basic_to_int(:arp_tha), do: 0x19 + def openflow_basic_to_int(:ipv6_src), do: 0x1A + def openflow_basic_to_int(:ipv6_dst), do: 0x1B + def openflow_basic_to_int(:ipv6_flabel), do: 0x1C + def openflow_basic_to_int(:icmpv6_type), do: 0x1D + def openflow_basic_to_int(:icmpv6_code), do: 0x1E + def openflow_basic_to_int(:ipv6_nd_target), do: 0x1F + def openflow_basic_to_int(:ipv6_nd_sll), do: 0x20 + def openflow_basic_to_int(:ipv6_nd_tll), do: 0x21 + def openflow_basic_to_int(:mpls_label), do: 0x22 + def openflow_basic_to_int(:mpls_tc), do: 0x23 + def openflow_basic_to_int(:mpls_bos), do: 0x24 + def openflow_basic_to_int(:pbb_isid), do: 0x25 + def openflow_basic_to_int(:tunnel_id), do: 0x26 + def openflow_basic_to_int(:ipv6_exthdr), do: 0x27 + def openflow_basic_to_int(:pbb_uca), do: 0x29 + def openflow_basic_to_int(:packet_type), do: 0x2A + def openflow_basic_to_int(:gre_flags), do: 0x2B + def openflow_basic_to_int(:gre_ver), do: 0x2C + def openflow_basic_to_int(:gre_protocol), do: 0x2D + def openflow_basic_to_int(:gre_key), do: 0x2E + def openflow_basic_to_int(:gre_seqnum), do: 0x2F + def openflow_basic_to_int(:lisp_flags), do: 0x30 + def openflow_basic_to_int(:lisp_nonce), do: 0x31 + def openflow_basic_to_int(:lisp_id), do: 0x32 + def openflow_basic_to_int(:vxlan_flags), do: 0x33 + def openflow_basic_to_int(:vxlan_vni), do: 0x34 + def openflow_basic_to_int(:mpls_data_first_nibble), do: 0x35 + def openflow_basic_to_int(:mpls_ach_version), do: 0x36 + def openflow_basic_to_int(:mpls_ach_channel), do: 0x37 + def openflow_basic_to_int(:mpls_pw_metadata), do: 0x38 + def openflow_basic_to_int(:mpls_cw_flags), do: 0x39 + def openflow_basic_to_int(:mpls_cw_fragment), do: 0x3A + def openflow_basic_to_int(:mpls_cw_len), do: 0x3B + def openflow_basic_to_int(:mpls_cw_seq_num), do: 0x3C + def openflow_basic_to_int(:gtpu_flags), do: 0x3D + def openflow_basic_to_int(:gtpu_ver), do: 0x3E + def openflow_basic_to_int(:gtpu_msg_type), do: 0x3F + def openflow_basic_to_int(:gtpu_teid), do: 0x40 + def openflow_basic_to_int(:gtpu_extn_hdr), do: 0x41 + def openflow_basic_to_int(:gtpu_extn_udp_port), do: 0x42 + def openflow_basic_to_int(:gtpu_extn_sci), do: 0x43 + def openflow_basic_to_int(_), do: throw(:bad_enum) + def openflow_basic_to_atom(0x0), do: :in_port + def openflow_basic_to_atom(0x1), do: :in_phy_port + def openflow_basic_to_atom(0x2), do: :metadata + def openflow_basic_to_atom(0x3), do: :eth_dst + def openflow_basic_to_atom(0x4), do: :eth_src + def openflow_basic_to_atom(0x5), do: :eth_type + def openflow_basic_to_atom(0x6), do: :vlan_vid + def openflow_basic_to_atom(0x7), do: :vlan_pcp + def openflow_basic_to_atom(0x8), do: :ip_dscp + def openflow_basic_to_atom(0x9), do: :ip_ecn + def openflow_basic_to_atom(0xA), do: :ip_proto + def openflow_basic_to_atom(0xB), do: :ipv4_src + def openflow_basic_to_atom(0xC), do: :ipv4_dst + def openflow_basic_to_atom(0xD), do: :tcp_src + def openflow_basic_to_atom(0xE), do: :tcp_dst + def openflow_basic_to_atom(0xF), do: :udp_src + def openflow_basic_to_atom(0x10), do: :udp_dst + def openflow_basic_to_atom(0x11), do: :sctp_src + def openflow_basic_to_atom(0x12), do: :sctp_dst + def openflow_basic_to_atom(0x13), do: :icmpv4_type + def openflow_basic_to_atom(0x14), do: :icmpv4_code + def openflow_basic_to_atom(0x15), do: :arp_op + def openflow_basic_to_atom(0x16), do: :arp_spa + def openflow_basic_to_atom(0x17), do: :arp_tpa + def openflow_basic_to_atom(0x18), do: :arp_sha + def openflow_basic_to_atom(0x19), do: :arp_tha + def openflow_basic_to_atom(0x1A), do: :ipv6_src + def openflow_basic_to_atom(0x1B), do: :ipv6_dst + def openflow_basic_to_atom(0x1C), do: :ipv6_flabel + def openflow_basic_to_atom(0x1D), do: :icmpv6_type + def openflow_basic_to_atom(0x1E), do: :icmpv6_code + def openflow_basic_to_atom(0x1F), do: :ipv6_nd_target + def openflow_basic_to_atom(0x20), do: :ipv6_nd_sll + def openflow_basic_to_atom(0x21), do: :ipv6_nd_tll + def openflow_basic_to_atom(0x22), do: :mpls_label + def openflow_basic_to_atom(0x23), do: :mpls_tc + def openflow_basic_to_atom(0x24), do: :mpls_bos + def openflow_basic_to_atom(0x25), do: :pbb_isid + def openflow_basic_to_atom(0x26), do: :tunnel_id + def openflow_basic_to_atom(0x27), do: :ipv6_exthdr + def openflow_basic_to_atom(0x29), do: :pbb_uca + def openflow_basic_to_atom(0x2A), do: :packet_type + def openflow_basic_to_atom(0x2B), do: :gre_flags + def openflow_basic_to_atom(0x2C), do: :gre_ver + def openflow_basic_to_atom(0x2D), do: :gre_protocol + def openflow_basic_to_atom(0x2E), do: :gre_key + def openflow_basic_to_atom(0x2F), do: :gre_seqnum + def openflow_basic_to_atom(0x30), do: :lisp_flags + def openflow_basic_to_atom(0x31), do: :lisp_nonce + def openflow_basic_to_atom(0x32), do: :lisp_id + def openflow_basic_to_atom(0x33), do: :vxlan_flags + def openflow_basic_to_atom(0x34), do: :vxlan_vni + def openflow_basic_to_atom(0x35), do: :mpls_data_first_nibble + def openflow_basic_to_atom(0x36), do: :mpls_ach_version + def openflow_basic_to_atom(0x37), do: :mpls_ach_channel + def openflow_basic_to_atom(0x38), do: :mpls_pw_metadata + def openflow_basic_to_atom(0x39), do: :mpls_cw_flags + def openflow_basic_to_atom(0x3A), do: :mpls_cw_fragment + def openflow_basic_to_atom(0x3B), do: :mpls_cw_len + def openflow_basic_to_atom(0x3C), do: :mpls_cw_seq_num + def openflow_basic_to_atom(0x3D), do: :gtpu_flags + def openflow_basic_to_atom(0x3E), do: :gtpu_ver + def openflow_basic_to_atom(0x3F), do: :gtpu_msg_type + def openflow_basic_to_atom(0x40), do: :gtpu_teid + def openflow_basic_to_atom(0x41), do: :gtpu_extn_hdr + def openflow_basic_to_atom(0x42), do: :gtpu_extn_udp_port + def openflow_basic_to_atom(0x43), do: :gtpu_extn_sci + def openflow_basic_to_atom(_), do: throw(:bad_enum) + def vlan_id_to_int(:present), do: 0x1000 + def vlan_id_to_int(:none), do: 0x0 + def vlan_id_to_int(_), do: throw(:bad_enum) + def vlan_id_to_atom(0x1000), do: :present + def vlan_id_to_atom(0x0), do: :none + def vlan_id_to_atom(_), do: throw(:bad_enum) + def ipv6exthdr_flags_to_int(:nonext), do: 0x1 + def ipv6exthdr_flags_to_int(:esp), do: 0x2 + def ipv6exthdr_flags_to_int(:auth), do: 0x4 + def ipv6exthdr_flags_to_int(:dest), do: 0x8 + def ipv6exthdr_flags_to_int(:frag), do: 0x10 + def ipv6exthdr_flags_to_int(:router), do: 0x20 + def ipv6exthdr_flags_to_int(:hop), do: 0x40 + def ipv6exthdr_flags_to_int(:unrep), do: 0x80 + def ipv6exthdr_flags_to_int(:unseq), do: 0x100 + def ipv6exthdr_flags_to_int(_), do: throw(:bad_enum) + def ipv6exthdr_flags_to_atom(0x1), do: :nonext + def ipv6exthdr_flags_to_atom(0x2), do: :esp + def ipv6exthdr_flags_to_atom(0x4), do: :auth + def ipv6exthdr_flags_to_atom(0x8), do: :dest + def ipv6exthdr_flags_to_atom(0x10), do: :frag + def ipv6exthdr_flags_to_atom(0x20), do: :router + def ipv6exthdr_flags_to_atom(0x40), do: :hop + def ipv6exthdr_flags_to_atom(0x80), do: :unrep + def ipv6exthdr_flags_to_atom(0x100), do: :unseq + def ipv6exthdr_flags_to_atom(_), do: throw(:bad_enum) + def tcp_flags_to_int(:fin), do: 0x1 + def tcp_flags_to_int(:syn), do: 0x2 + def tcp_flags_to_int(:rst), do: 0x4 + def tcp_flags_to_int(:psh), do: 0x8 + def tcp_flags_to_int(:ack), do: 0x10 + def tcp_flags_to_int(:urg), do: 0x20 + def tcp_flags_to_int(:ece), do: 0x40 + def tcp_flags_to_int(:cwr), do: 0x80 + def tcp_flags_to_int(:ns), do: 0x100 + def tcp_flags_to_int(_), do: throw(:bad_enum) + def tcp_flags_to_atom(0x1), do: :fin + def tcp_flags_to_atom(0x2), do: :syn + def tcp_flags_to_atom(0x4), do: :rst + def tcp_flags_to_atom(0x8), do: :psh + def tcp_flags_to_atom(0x10), do: :ack + def tcp_flags_to_atom(0x20), do: :urg + def tcp_flags_to_atom(0x40), do: :ece + def tcp_flags_to_atom(0x80), do: :cwr + def tcp_flags_to_atom(0x100), do: :ns + def tcp_flags_to_atom(_), do: throw(:bad_enum) + def ct_state_flags_to_int(:new), do: 0x1 + def ct_state_flags_to_int(:est), do: 0x2 + def ct_state_flags_to_int(:rel), do: 0x4 + def ct_state_flags_to_int(:rep), do: 0x8 + def ct_state_flags_to_int(:inv), do: 0x10 + def ct_state_flags_to_int(:trk), do: 0x20 + def ct_state_flags_to_int(:snat), do: 0x40 + def ct_state_flags_to_int(:dnat), do: 0x80 + def ct_state_flags_to_int(_), do: throw(:bad_enum) + def ct_state_flags_to_atom(0x1), do: :new + def ct_state_flags_to_atom(0x2), do: :est + def ct_state_flags_to_atom(0x4), do: :rel + def ct_state_flags_to_atom(0x8), do: :rep + def ct_state_flags_to_atom(0x10), do: :inv + def ct_state_flags_to_atom(0x20), do: :trk + def ct_state_flags_to_atom(0x40), do: :snat + def ct_state_flags_to_atom(0x80), do: :dnat + def ct_state_flags_to_atom(_), do: throw(:bad_enum) + def packet_register_to_int(:xreg0), do: 0x0 + def packet_register_to_int(:xreg1), do: 0x1 + def packet_register_to_int(:xreg2), do: 0x2 + def packet_register_to_int(:xreg3), do: 0x3 + def packet_register_to_int(:xreg4), do: 0x4 + def packet_register_to_int(:xreg5), do: 0x5 + def packet_register_to_int(:xreg6), do: 0x6 + def packet_register_to_int(:xreg7), do: 0x7 + def packet_register_to_int(_), do: throw(:bad_enum) + def packet_register_to_atom(0x0), do: :xreg0 + def packet_register_to_atom(0x1), do: :xreg1 + def packet_register_to_atom(0x2), do: :xreg2 + def packet_register_to_atom(0x3), do: :xreg3 + def packet_register_to_atom(0x4), do: :xreg4 + def packet_register_to_atom(0x5), do: :xreg5 + def packet_register_to_atom(0x6), do: :xreg6 + def packet_register_to_atom(0x7), do: :xreg7 + def packet_register_to_atom(_), do: throw(:bad_enum) + def nicira_ext_match_to_int(:nsh_flags), do: 0x1 + def nicira_ext_match_to_int(:nsh_mdtype), do: 0x2 + def nicira_ext_match_to_int(:nsh_np), do: 0x3 + def nicira_ext_match_to_int(:nsh_spi), do: 0x4 + def nicira_ext_match_to_int(:nsh_si), do: 0x5 + def nicira_ext_match_to_int(:nsh_c1), do: 0x6 + def nicira_ext_match_to_int(:nsh_c2), do: 0x7 + def nicira_ext_match_to_int(:nsh_c3), do: 0x8 + def nicira_ext_match_to_int(:nsh_c4), do: 0x9 + def nicira_ext_match_to_int(_), do: throw(:bad_enum) + def nicira_ext_match_to_atom(0x1), do: :nsh_flags + def nicira_ext_match_to_atom(0x2), do: :nsh_mdtype + def nicira_ext_match_to_atom(0x3), do: :nsh_np + def nicira_ext_match_to_atom(0x4), do: :nsh_spi + def nicira_ext_match_to_atom(0x5), do: :nsh_si + def nicira_ext_match_to_atom(0x6), do: :nsh_c1 + def nicira_ext_match_to_atom(0x7), do: :nsh_c2 + def nicira_ext_match_to_atom(0x8), do: :nsh_c3 + def nicira_ext_match_to_atom(0x9), do: :nsh_c4 + def nicira_ext_match_to_atom(_), do: throw(:bad_enum) + def hp_ext_match_to_int(:hp_udp_src_port_range), do: 0x0 + def hp_ext_match_to_int(:hp_udp_dst_port_range), do: 0x1 + def hp_ext_match_to_int(:hp_tcp_src_port_range), do: 0x2 + def hp_ext_match_to_int(:hp_tcp_dst_port_range), do: 0x3 + def hp_ext_match_to_int(:hp_tcp_flags), do: 0x4 + def hp_ext_match_to_int(:hp_custom_1), do: 0x5 + def hp_ext_match_to_int(:hp_custom_2), do: 0x6 + def hp_ext_match_to_int(:hp_custom_3), do: 0x7 + def hp_ext_match_to_int(:hp_custom_4), do: 0x8 + def hp_ext_match_to_int(_), do: throw(:bad_enum) + def hp_ext_match_to_atom(0x0), do: :hp_udp_src_port_range + def hp_ext_match_to_atom(0x1), do: :hp_udp_dst_port_range + def hp_ext_match_to_atom(0x2), do: :hp_tcp_src_port_range + def hp_ext_match_to_atom(0x3), do: :hp_tcp_dst_port_range + def hp_ext_match_to_atom(0x4), do: :hp_tcp_flags + def hp_ext_match_to_atom(0x5), do: :hp_custom_1 + def hp_ext_match_to_atom(0x6), do: :hp_custom_2 + def hp_ext_match_to_atom(0x7), do: :hp_custom_3 + def hp_ext_match_to_atom(0x8), do: :hp_custom_4 + def hp_ext_match_to_atom(_), do: throw(:bad_enum) + def hp_custom_match_type_to_int(:l2_start), do: 0x1 + def hp_custom_match_type_to_int(:l3_start), do: 0x2 + def hp_custom_match_type_to_int(:l4_start), do: 0x3 + def hp_custom_match_type_to_int(_), do: throw(:bad_enum) + def hp_custom_match_type_to_atom(0x1), do: :l2_start + def hp_custom_match_type_to_atom(0x2), do: :l3_start + def hp_custom_match_type_to_atom(0x3), do: :l4_start + def hp_custom_match_type_to_atom(_), do: throw(:bad_enum) + def onf_ext_match_to_int(:onf_tcp_flags), do: 0x2A + def onf_ext_match_to_int(:onf_actset_output), do: 0x2B + def onf_ext_match_to_int(:onf_pbb_uca), do: 0xA00 + def onf_ext_match_to_int(_), do: throw(:bad_enum) + def onf_ext_match_to_atom(0x2A), do: :onf_tcp_flags + def onf_ext_match_to_atom(0x2B), do: :onf_actset_output + def onf_ext_match_to_atom(0xA00), do: :onf_pbb_uca + def onf_ext_match_to_atom(_), do: throw(:bad_enum) + def buffer_id_to_int(:no_buffer), do: 0xFFFFFFFF + def buffer_id_to_int(_), do: throw(:bad_enum) + def buffer_id_to_atom(0xFFFFFFFF), do: :no_buffer + def buffer_id_to_atom(_), do: throw(:bad_enum) + def port_config_to_int(:port_down), do: 0x1 + def port_config_to_int(:no_receive), do: 0x4 + def port_config_to_int(:no_forward), do: 0x20 + def port_config_to_int(:no_packet_in), do: 0x40 + def port_config_to_int(_), do: throw(:bad_enum) + def port_config_to_atom(0x1), do: :port_down + def port_config_to_atom(0x4), do: :no_receive + def port_config_to_atom(0x20), do: :no_forward + def port_config_to_atom(0x40), do: :no_packet_in + def port_config_to_atom(_), do: throw(:bad_enum) + def port_state_to_int(:link_down), do: 0x1 + def port_state_to_int(:blocked), do: 0x2 + def port_state_to_int(:live), do: 0x4 + def port_state_to_int(_), do: throw(:bad_enum) + def port_state_to_atom(0x1), do: :link_down + def port_state_to_atom(0x2), do: :blocked + def port_state_to_atom(0x4), do: :live + def port_state_to_atom(_), do: throw(:bad_enum) + def port_features_to_int(:"10mb_hd"), do: 0x1 + def port_features_to_int(:"10mb_fd"), do: 0x2 + def port_features_to_int(:"100mb_hd"), do: 0x4 + def port_features_to_int(:"100mb_fd"), do: 0x8 + def port_features_to_int(:"1gb_hd"), do: 0x10 + def port_features_to_int(:"1gb_fd"), do: 0x20 + def port_features_to_int(:"10gb_fd"), do: 0x40 + def port_features_to_int(:"40gb_fd"), do: 0x80 + def port_features_to_int(:"100gb_fd"), do: 0x100 + def port_features_to_int(:"1tb_fd"), do: 0x200 + def port_features_to_int(:other), do: 0x400 + def port_features_to_int(:copper), do: 0x800 + def port_features_to_int(:fiber), do: 0x1000 + def port_features_to_int(:autoneg), do: 0x2000 + def port_features_to_int(:pause), do: 0x4000 + def port_features_to_int(:pause_asym), do: 0x8000 + def port_features_to_int(_), do: throw(:bad_enum) + def port_features_to_atom(0x1), do: :"10mb_hd" + def port_features_to_atom(0x2), do: :"10mb_fd" + def port_features_to_atom(0x4), do: :"100mb_hd" + def port_features_to_atom(0x8), do: :"100mb_fd" + def port_features_to_atom(0x10), do: :"1gb_hd" + def port_features_to_atom(0x20), do: :"1gb_fd" + def port_features_to_atom(0x40), do: :"10gb_fd" + def port_features_to_atom(0x80), do: :"40gb_fd" + def port_features_to_atom(0x100), do: :"100gb_fd" + def port_features_to_atom(0x200), do: :"1tb_fd" + def port_features_to_atom(0x400), do: :other + def port_features_to_atom(0x800), do: :copper + def port_features_to_atom(0x1000), do: :fiber + def port_features_to_atom(0x2000), do: :autoneg + def port_features_to_atom(0x4000), do: :pause + def port_features_to_atom(0x8000), do: :pause_asym + def port_features_to_atom(_), do: throw(:bad_enum) + def openflow10_port_no_to_int(:max), do: 0xFF00 + def openflow10_port_no_to_int(:in_port), do: 0xFFF8 + def openflow10_port_no_to_int(:table), do: 0xFFF9 + def openflow10_port_no_to_int(:normal), do: 0xFFFA + def openflow10_port_no_to_int(:flood), do: 0xFFFB + def openflow10_port_no_to_int(:all), do: 0xFFFC + def openflow10_port_no_to_int(:controller), do: 0xFFFD + def openflow10_port_no_to_int(:local), do: 0xFFFE + def openflow10_port_no_to_int(:none), do: 0xFFFF + def openflow10_port_no_to_int(_), do: throw(:bad_enum) + def openflow10_port_no_to_atom(0xFF00), do: :max + def openflow10_port_no_to_atom(0xFFF8), do: :in_port + def openflow10_port_no_to_atom(0xFFF9), do: :table + def openflow10_port_no_to_atom(0xFFFA), do: :normal + def openflow10_port_no_to_atom(0xFFFB), do: :flood + def openflow10_port_no_to_atom(0xFFFC), do: :all + def openflow10_port_no_to_atom(0xFFFD), do: :controller + def openflow10_port_no_to_atom(0xFFFE), do: :local + def openflow10_port_no_to_atom(0xFFFF), do: :none + def openflow10_port_no_to_atom(_), do: throw(:bad_enum) + def openflow13_port_no_to_int(:max), do: 0xFFFFFF00 + def openflow13_port_no_to_int(:in_port), do: 0xFFFFFFF8 + def openflow13_port_no_to_int(:table), do: 0xFFFFFFF9 + def openflow13_port_no_to_int(:normal), do: 0xFFFFFFFA + def openflow13_port_no_to_int(:flood), do: 0xFFFFFFFB + def openflow13_port_no_to_int(:all), do: 0xFFFFFFFC + def openflow13_port_no_to_int(:controller), do: 0xFFFFFFFD + def openflow13_port_no_to_int(:local), do: 0xFFFFFFFE + def openflow13_port_no_to_int(:any), do: 0xFFFFFFFF + def openflow13_port_no_to_int(_), do: throw(:bad_enum) + def openflow13_port_no_to_atom(0xFFFFFF00), do: :max + def openflow13_port_no_to_atom(0xFFFFFFF8), do: :in_port + def openflow13_port_no_to_atom(0xFFFFFFF9), do: :table + def openflow13_port_no_to_atom(0xFFFFFFFA), do: :normal + def openflow13_port_no_to_atom(0xFFFFFFFB), do: :flood + def openflow13_port_no_to_atom(0xFFFFFFFC), do: :all + def openflow13_port_no_to_atom(0xFFFFFFFD), do: :controller + def openflow13_port_no_to_atom(0xFFFFFFFE), do: :local + def openflow13_port_no_to_atom(0xFFFFFFFF), do: :any + def openflow13_port_no_to_atom(_), do: throw(:bad_enum) + def packet_in_reason_to_int(:no_match), do: 0x0 + def packet_in_reason_to_int(:action), do: 0x1 + def packet_in_reason_to_int(:invalid_ttl), do: 0x2 + def packet_in_reason_to_int(:action_set), do: 0x3 + def packet_in_reason_to_int(:group), do: 0x4 + def packet_in_reason_to_int(:packet_out), do: 0x5 + def packet_in_reason_to_int(_), do: throw(:bad_enum) + def packet_in_reason_to_atom(0x0), do: :no_match + def packet_in_reason_to_atom(0x1), do: :action + def packet_in_reason_to_atom(0x2), do: :invalid_ttl + def packet_in_reason_to_atom(0x3), do: :action_set + def packet_in_reason_to_atom(0x4), do: :group + def packet_in_reason_to_atom(0x5), do: :packet_out + def packet_in_reason_to_atom(_), do: throw(:bad_enum) + def flow_mod_command_to_int(:add), do: 0x0 + def flow_mod_command_to_int(:modify), do: 0x1 + def flow_mod_command_to_int(:modify_strict), do: 0x2 + def flow_mod_command_to_int(:delete), do: 0x3 + def flow_mod_command_to_int(:delete_strict), do: 0x4 + def flow_mod_command_to_int(_), do: throw(:bad_enum) + def flow_mod_command_to_atom(0x0), do: :add + def flow_mod_command_to_atom(0x1), do: :modify + def flow_mod_command_to_atom(0x2), do: :modify_strict + def flow_mod_command_to_atom(0x3), do: :delete + def flow_mod_command_to_atom(0x4), do: :delete_strict + def flow_mod_command_to_atom(_), do: throw(:bad_enum) + def flow_mod_flags_to_int(:send_flow_rem), do: 0x1 + def flow_mod_flags_to_int(:check_overlap), do: 0x2 + def flow_mod_flags_to_int(:reset_counts), do: 0x4 + def flow_mod_flags_to_int(:no_packet_counts), do: 0x8 + def flow_mod_flags_to_int(:no_byte_counts), do: 0x10 + def flow_mod_flags_to_int(_), do: throw(:bad_enum) + def flow_mod_flags_to_atom(0x1), do: :send_flow_rem + def flow_mod_flags_to_atom(0x2), do: :check_overlap + def flow_mod_flags_to_atom(0x4), do: :reset_counts + def flow_mod_flags_to_atom(0x8), do: :no_packet_counts + def flow_mod_flags_to_atom(0x10), do: :no_byte_counts + def flow_mod_flags_to_atom(_), do: throw(:bad_enum) + def flow_removed_reason_to_int(:idle_timeout), do: 0x0 + def flow_removed_reason_to_int(:hard_timeout), do: 0x1 + def flow_removed_reason_to_int(:delete), do: 0x2 + def flow_removed_reason_to_int(:group_delete), do: 0x3 + def flow_removed_reason_to_int(:meter_delete), do: 0x4 + def flow_removed_reason_to_int(:eviction), do: 0x5 + def flow_removed_reason_to_int(_), do: throw(:bad_enum) + def flow_removed_reason_to_atom(0x0), do: :idle_timeout + def flow_removed_reason_to_atom(0x1), do: :hard_timeout + def flow_removed_reason_to_atom(0x2), do: :delete + def flow_removed_reason_to_atom(0x3), do: :group_delete + def flow_removed_reason_to_atom(0x4), do: :meter_delete + def flow_removed_reason_to_atom(0x5), do: :eviction + def flow_removed_reason_to_atom(_), do: throw(:bad_enum) + def port_reason_to_int(:add), do: 0x0 + def port_reason_to_int(:delete), do: 0x1 + def port_reason_to_int(:modify), do: 0x2 + def port_reason_to_int(_), do: throw(:bad_enum) + def port_reason_to_atom(0x0), do: :add + def port_reason_to_atom(0x1), do: :delete + def port_reason_to_atom(0x2), do: :modify + def port_reason_to_atom(_), do: throw(:bad_enum) + def group_mod_command_to_int(:add), do: 0x0 + def group_mod_command_to_int(:modify), do: 0x1 + def group_mod_command_to_int(:delete), do: 0x2 + def group_mod_command_to_int(_), do: throw(:bad_enum) + def group_mod_command_to_atom(0x0), do: :add + def group_mod_command_to_atom(0x1), do: :modify + def group_mod_command_to_atom(0x2), do: :delete + def group_mod_command_to_atom(_), do: throw(:bad_enum) + def group_type_to_int(:all), do: 0x0 + def group_type_to_int(:select), do: 0x1 + def group_type_to_int(:indirect), do: 0x2 + def group_type_to_int(:fast_failover), do: 0x3 + def group_type_to_int(_), do: throw(:bad_enum) + def group_type_to_atom(0x0), do: :all + def group_type_to_atom(0x1), do: :select + def group_type_to_atom(0x2), do: :indirect + def group_type_to_atom(0x3), do: :fast_failover + def group_type_to_atom(_), do: throw(:bad_enum) + def group_id_to_int(:max), do: 0xFFFFFF00 + def group_id_to_int(:all), do: 0xFFFFFFFC + def group_id_to_int(:any), do: 0xFFFFFFFF + def group_id_to_int(_), do: throw(:bad_enum) + def group_id_to_atom(0xFFFFFF00), do: :max + def group_id_to_atom(0xFFFFFFFC), do: :all + def group_id_to_atom(0xFFFFFFFF), do: :any + def group_id_to_atom(_), do: throw(:bad_enum) + def group_capabilities_to_int(:select_weight), do: 0x1 + def group_capabilities_to_int(:select_liveness), do: 0x2 + def group_capabilities_to_int(:chaining), do: 0x4 + def group_capabilities_to_int(:chaining_checks), do: 0x8 + def group_capabilities_to_int(_), do: throw(:bad_enum) + def group_capabilities_to_atom(0x1), do: :select_weight + def group_capabilities_to_atom(0x2), do: :select_liveness + def group_capabilities_to_atom(0x4), do: :chaining + def group_capabilities_to_atom(0x8), do: :chaining_checks + def group_capabilities_to_atom(_), do: throw(:bad_enum) + def table_id_to_int(:max), do: 0xFE + def table_id_to_int(:all), do: 0xFF + def table_id_to_int(_), do: throw(:bad_enum) + def table_id_to_atom(0xFE), do: :max + def table_id_to_atom(0xFF), do: :all + def table_id_to_atom(_), do: throw(:bad_enum) + def queue_id_to_int(:all), do: 0xFFFFFFFF + def queue_id_to_int(_), do: throw(:bad_enum) + def queue_id_to_atom(0xFFFFFFFF), do: :all + def queue_id_to_atom(_), do: throw(:bad_enum) + def meter_mod_command_to_int(:add), do: 0x0 + def meter_mod_command_to_int(:modify), do: 0x1 + def meter_mod_command_to_int(:delete), do: 0x2 + def meter_mod_command_to_int(_), do: throw(:bad_enum) + def meter_mod_command_to_atom(0x0), do: :add + def meter_mod_command_to_atom(0x1), do: :modify + def meter_mod_command_to_atom(0x2), do: :delete + def meter_mod_command_to_atom(_), do: throw(:bad_enum) + def meter_id_to_int(:max), do: 0xFFFF0000 + def meter_id_to_int(:slowpath), do: 0xFFFFFFFD + def meter_id_to_int(:controller), do: 0xFFFFFFFE + def meter_id_to_int(:all), do: 0xFFFFFFFF + def meter_id_to_int(_), do: throw(:bad_enum) + def meter_id_to_atom(0xFFFF0000), do: :max + def meter_id_to_atom(0xFFFFFFFD), do: :slowpath + def meter_id_to_atom(0xFFFFFFFE), do: :controller + def meter_id_to_atom(0xFFFFFFFF), do: :all + def meter_id_to_atom(_), do: throw(:bad_enum) + def meter_flags_to_int(:kbps), do: 0x1 + def meter_flags_to_int(:pktps), do: 0x2 + def meter_flags_to_int(:burst), do: 0x4 + def meter_flags_to_int(:stats), do: 0x8 + def meter_flags_to_int(_), do: throw(:bad_enum) + def meter_flags_to_atom(0x1), do: :kbps + def meter_flags_to_atom(0x2), do: :pktps + def meter_flags_to_atom(0x4), do: :burst + def meter_flags_to_atom(0x8), do: :stats + def meter_flags_to_atom(_), do: throw(:bad_enum) + def meter_band_type_to_int(Openflow.MeterBand.Drop), do: 0x1 + def meter_band_type_to_int(Openflow.MeterBand.Remark), do: 0x2 + def meter_band_type_to_int(Openflow.MeterBand.Experimenter), do: 0xFFFF + def meter_band_type_to_int(_), do: throw(:bad_enum) + def meter_band_type_to_atom(0x1), do: Openflow.MeterBand.Drop + def meter_band_type_to_atom(0x2), do: Openflow.MeterBand.Remark + def meter_band_type_to_atom(0xFFFF), do: Openflow.MeterBand.Experimenter + def meter_band_type_to_atom(_), do: throw(:bad_enum) + def table_config_to_int(:table_miss_controller), do: 0x0 + def table_config_to_int(:table_miss_continue), do: 0x1 + def table_config_to_int(:table_miss_drop), do: 0x2 + def table_config_to_int(:table_miss_mask), do: 0x3 + def table_config_to_int(:eviction), do: 0x4 + def table_config_to_int(:vacancy_events), do: 0x8 + def table_config_to_int(_), do: throw(:bad_enum) + def table_config_to_atom(0x0), do: :table_miss_controller + def table_config_to_atom(0x1), do: :table_miss_continue + def table_config_to_atom(0x2), do: :table_miss_drop + def table_config_to_atom(0x3), do: :table_miss_mask + def table_config_to_atom(0x4), do: :eviction + def table_config_to_atom(0x8), do: :vacancy_events + def table_config_to_atom(_), do: throw(:bad_enum) + def action_type_to_int(Openflow.Action.Output), do: 0x0 + def action_type_to_int(Openflow.Action.CopyTtlOut), do: 0xB + def action_type_to_int(Openflow.Action.CopyTtlIn), do: 0xC + def action_type_to_int(Openflow.Action.SetMplsTtl), do: 0xF + def action_type_to_int(Openflow.Action.DecMplsTtl), do: 0x10 + def action_type_to_int(Openflow.Action.PushVlan), do: 0x11 + def action_type_to_int(Openflow.Action.PopVlan), do: 0x12 + def action_type_to_int(Openflow.Action.PushMpls), do: 0x13 + def action_type_to_int(Openflow.Action.PopMpls), do: 0x14 + def action_type_to_int(Openflow.Action.SetQueue), do: 0x15 + def action_type_to_int(Openflow.Action.Group), do: 0x16 + def action_type_to_int(Openflow.Action.SetNwTtl), do: 0x17 + def action_type_to_int(Openflow.Action.DecNwTtl), do: 0x18 + def action_type_to_int(Openflow.Action.SetField), do: 0x19 + def action_type_to_int(Openflow.Action.PushPbb), do: 0x1A + def action_type_to_int(Openflow.Action.PopPbb), do: 0x1B + def action_type_to_int(Openflow.Action.Encap), do: 0x1C + def action_type_to_int(Openflow.Action.Decap), do: 0x1D + def action_type_to_int(Openflow.Action.SetSequence), do: 0x1E + def action_type_to_int(Openflow.Action.ValidateSequence), do: 0x1F + def action_type_to_int(Openflow.Action.Experimenter), do: 0xFFFF + def action_type_to_int(_), do: throw(:bad_enum) + def action_type_to_atom(0x0), do: Openflow.Action.Output + def action_type_to_atom(0xB), do: Openflow.Action.CopyTtlOut + def action_type_to_atom(0xC), do: Openflow.Action.CopyTtlIn + def action_type_to_atom(0xF), do: Openflow.Action.SetMplsTtl + def action_type_to_atom(0x10), do: Openflow.Action.DecMplsTtl + def action_type_to_atom(0x11), do: Openflow.Action.PushVlan + def action_type_to_atom(0x12), do: Openflow.Action.PopVlan + def action_type_to_atom(0x13), do: Openflow.Action.PushMpls + def action_type_to_atom(0x14), do: Openflow.Action.PopMpls + def action_type_to_atom(0x15), do: Openflow.Action.SetQueue + def action_type_to_atom(0x16), do: Openflow.Action.Group + def action_type_to_atom(0x17), do: Openflow.Action.SetNwTtl + def action_type_to_atom(0x18), do: Openflow.Action.DecNwTtl + def action_type_to_atom(0x19), do: Openflow.Action.SetField + def action_type_to_atom(0x1A), do: Openflow.Action.PushPbb + def action_type_to_atom(0x1B), do: Openflow.Action.PopPbb + def action_type_to_atom(0x1C), do: Openflow.Action.Encap + def action_type_to_atom(0x1D), do: Openflow.Action.Decap + def action_type_to_atom(0x1E), do: Openflow.Action.SetSequence + def action_type_to_atom(0x1F), do: Openflow.Action.ValidateSequence + def action_type_to_atom(0xFFFF), do: Openflow.Action.Experimenter + def action_type_to_atom(_), do: throw(:bad_enum) + def action_vendor_to_int(:nicira_ext_action), do: 0x2320 + def action_vendor_to_int(:onf_ext_action), do: 0x4F4E4600 + def action_vendor_to_int(_), do: throw(:bad_enum) + def action_vendor_to_atom(0x2320), do: :nicira_ext_action + def action_vendor_to_atom(0x4F4E4600), do: :onf_ext_action + def action_vendor_to_atom(_), do: throw(:bad_enum) + def onf_ext_action_to_int(Openflow.Action.OnfCopyField), do: 0xC80 + def onf_ext_action_to_int(_), do: throw(:bad_enum) + def onf_ext_action_to_atom(0xC80), do: Openflow.Action.OnfCopyField + def onf_ext_action_to_atom(_), do: throw(:bad_enum) + def nicira_ext_action_to_int(Openflow.Action.NxResubmit), do: 0x1 + def nicira_ext_action_to_int(Openflow.Action.NxSetTunnel), do: 0x2 + def nicira_ext_action_to_int(Openflow.Action.NxSetQueue), do: 0x4 + def nicira_ext_action_to_int(Openflow.Action.NxPopQueue), do: 0x5 + def nicira_ext_action_to_int(Openflow.Action.NxRegMove), do: 0x6 + def nicira_ext_action_to_int(Openflow.Action.NxRegLoad), do: 0x7 + def nicira_ext_action_to_int(Openflow.Action.NxNote), do: 0x8 + def nicira_ext_action_to_int(Openflow.Action.NxSetTunnel64), do: 0x9 + def nicira_ext_action_to_int(Openflow.Action.NxMultipath), do: 0xA + def nicira_ext_action_to_int(Openflow.Action.NxBundle), do: 0xC + def nicira_ext_action_to_int(Openflow.Action.NxBundleLoad), do: 0xD + def nicira_ext_action_to_int(Openflow.Action.NxResubmitTable), do: 0xE + def nicira_ext_action_to_int(Openflow.Action.NxOutputReg), do: 0xF + def nicira_ext_action_to_int(Openflow.Action.NxLearn), do: 0x10 + def nicira_ext_action_to_int(Openflow.Action.NxExit), do: 0x11 + def nicira_ext_action_to_int(Openflow.Action.NxDecTtl), do: 0x12 + def nicira_ext_action_to_int(Openflow.Action.NxFinTimeout), do: 0x13 + def nicira_ext_action_to_int(Openflow.Action.NxController), do: 0x14 + def nicira_ext_action_to_int(Openflow.Action.NxDecTtlCntIds), do: 0x15 + def nicira_ext_action_to_int(Openflow.Action.NxWriteMetadata), do: 0x16 + def nicira_ext_action_to_int(Openflow.Action.NxPushMpls), do: 0x17 + def nicira_ext_action_to_int(Openflow.Action.NxPopMpls), do: 0x18 + def nicira_ext_action_to_int(Openflow.Action.NxSetMplsTtl), do: 0x19 + def nicira_ext_action_to_int(Openflow.Action.NxDecMplsTtl), do: 0x1A + def nicira_ext_action_to_int(Openflow.Action.NxStackPush), do: 0x1B + def nicira_ext_action_to_int(Openflow.Action.NxStackPop), do: 0x1C + def nicira_ext_action_to_int(Openflow.Action.NxSample), do: 0x1D + def nicira_ext_action_to_int(Openflow.Action.NxSetMplsLabel), do: 0x1E + def nicira_ext_action_to_int(Openflow.Action.NxSetMplsTc), do: 0x1F + def nicira_ext_action_to_int(Openflow.Action.NxOutputReg2), do: 0x20 + def nicira_ext_action_to_int(Openflow.Action.NxRegLoad2), do: 0x21 + def nicira_ext_action_to_int(Openflow.Action.NxConjunction), do: 0x22 + def nicira_ext_action_to_int(Openflow.Action.NxConntrack), do: 0x23 + def nicira_ext_action_to_int(Openflow.Action.NxNat), do: 0x24 + def nicira_ext_action_to_int(Openflow.Action.NxController2), do: 0x25 + def nicira_ext_action_to_int(Openflow.Action.NxSample2), do: 0x26 + def nicira_ext_action_to_int(Openflow.Action.NxOutputTrunc), do: 0x27 + def nicira_ext_action_to_int(Openflow.Action.NxGroup), do: 0x28 + def nicira_ext_action_to_int(Openflow.Action.NxSample3), do: 0x29 + def nicira_ext_action_to_int(Openflow.Action.NxClone), do: 0x2A + def nicira_ext_action_to_int(Openflow.Action.NxCtClear), do: 0x2B + def nicira_ext_action_to_int(Openflow.Action.NxResubmitTableCt), do: 0x2C + def nicira_ext_action_to_int(Openflow.Action.NxLearn2), do: 0x2D + def nicira_ext_action_to_int(Openflow.Action.NxEncap), do: 0x2E + def nicira_ext_action_to_int(Openflow.Action.NxDecap), do: 0x2F + def nicira_ext_action_to_int(Openflow.Action.NxDebugRecirc), do: 0xFF + def nicira_ext_action_to_int(_), do: throw(:bad_enum) + def nicira_ext_action_to_atom(0x1), do: Openflow.Action.NxResubmit + def nicira_ext_action_to_atom(0x2), do: Openflow.Action.NxSetTunnel + def nicira_ext_action_to_atom(0x4), do: Openflow.Action.NxSetQueue + def nicira_ext_action_to_atom(0x5), do: Openflow.Action.NxPopQueue + def nicira_ext_action_to_atom(0x6), do: Openflow.Action.NxRegMove + def nicira_ext_action_to_atom(0x7), do: Openflow.Action.NxRegLoad + def nicira_ext_action_to_atom(0x8), do: Openflow.Action.NxNote + def nicira_ext_action_to_atom(0x9), do: Openflow.Action.NxSetTunnel64 + def nicira_ext_action_to_atom(0xA), do: Openflow.Action.NxMultipath + def nicira_ext_action_to_atom(0xC), do: Openflow.Action.NxBundle + def nicira_ext_action_to_atom(0xD), do: Openflow.Action.NxBundleLoad + def nicira_ext_action_to_atom(0xE), do: Openflow.Action.NxResubmitTable + def nicira_ext_action_to_atom(0xF), do: Openflow.Action.NxOutputReg + def nicira_ext_action_to_atom(0x10), do: Openflow.Action.NxLearn + def nicira_ext_action_to_atom(0x11), do: Openflow.Action.NxExit + def nicira_ext_action_to_atom(0x12), do: Openflow.Action.NxDecTtl + def nicira_ext_action_to_atom(0x13), do: Openflow.Action.NxFinTimeout + def nicira_ext_action_to_atom(0x14), do: Openflow.Action.NxController + def nicira_ext_action_to_atom(0x15), do: Openflow.Action.NxDecTtlCntIds + def nicira_ext_action_to_atom(0x16), do: Openflow.Action.NxWriteMetadata + def nicira_ext_action_to_atom(0x17), do: Openflow.Action.NxPushMpls + def nicira_ext_action_to_atom(0x18), do: Openflow.Action.NxPopMpls + def nicira_ext_action_to_atom(0x19), do: Openflow.Action.NxSetMplsTtl + def nicira_ext_action_to_atom(0x1A), do: Openflow.Action.NxDecMplsTtl + def nicira_ext_action_to_atom(0x1B), do: Openflow.Action.NxStackPush + def nicira_ext_action_to_atom(0x1C), do: Openflow.Action.NxStackPop + def nicira_ext_action_to_atom(0x1D), do: Openflow.Action.NxSample + def nicira_ext_action_to_atom(0x1E), do: Openflow.Action.NxSetMplsLabel + def nicira_ext_action_to_atom(0x1F), do: Openflow.Action.NxSetMplsTc + def nicira_ext_action_to_atom(0x20), do: Openflow.Action.NxOutputReg2 + def nicira_ext_action_to_atom(0x21), do: Openflow.Action.NxRegLoad2 + def nicira_ext_action_to_atom(0x22), do: Openflow.Action.NxConjunction + def nicira_ext_action_to_atom(0x23), do: Openflow.Action.NxConntrack + def nicira_ext_action_to_atom(0x24), do: Openflow.Action.NxNat + def nicira_ext_action_to_atom(0x25), do: Openflow.Action.NxController2 + def nicira_ext_action_to_atom(0x26), do: Openflow.Action.NxSample2 + def nicira_ext_action_to_atom(0x27), do: Openflow.Action.NxOutputTrunc + def nicira_ext_action_to_atom(0x28), do: Openflow.Action.NxGroup + def nicira_ext_action_to_atom(0x29), do: Openflow.Action.NxSample3 + def nicira_ext_action_to_atom(0x2A), do: Openflow.Action.NxClone + def nicira_ext_action_to_atom(0x2B), do: Openflow.Action.NxCtClear + def nicira_ext_action_to_atom(0x2C), do: Openflow.Action.NxResubmitTableCt + def nicira_ext_action_to_atom(0x2D), do: Openflow.Action.NxLearn2 + def nicira_ext_action_to_atom(0x2E), do: Openflow.Action.NxEncap + def nicira_ext_action_to_atom(0x2F), do: Openflow.Action.NxDecap + def nicira_ext_action_to_atom(0xFF), do: Openflow.Action.NxDebugRecirc + def nicira_ext_action_to_atom(_), do: throw(:bad_enum) + def nx_mp_algorithm_to_int(:modulo_n), do: 0x0 + def nx_mp_algorithm_to_int(:hash_threshold), do: 0x1 + def nx_mp_algorithm_to_int(:highest_random_weight), do: 0x2 + def nx_mp_algorithm_to_int(:iterative_hash), do: 0x3 + def nx_mp_algorithm_to_int(_), do: throw(:bad_enum) + def nx_mp_algorithm_to_atom(0x0), do: :modulo_n + def nx_mp_algorithm_to_atom(0x1), do: :hash_threshold + def nx_mp_algorithm_to_atom(0x2), do: :highest_random_weight + def nx_mp_algorithm_to_atom(0x3), do: :iterative_hash + def nx_mp_algorithm_to_atom(_), do: throw(:bad_enum) + def nx_hash_fields_to_int(:eth_src), do: 0x0 + def nx_hash_fields_to_int(:symmetric_l4), do: 0x1 + def nx_hash_fields_to_int(:symmetric_l3l4), do: 0x2 + def nx_hash_fields_to_int(:symmetric_l3l4_udp), do: 0x3 + def nx_hash_fields_to_int(:nw_src), do: 0x4 + def nx_hash_fields_to_int(:nw_dst), do: 0x5 + def nx_hash_fields_to_int(_), do: throw(:bad_enum) + def nx_hash_fields_to_atom(0x0), do: :eth_src + def nx_hash_fields_to_atom(0x1), do: :symmetric_l4 + def nx_hash_fields_to_atom(0x2), do: :symmetric_l3l4 + def nx_hash_fields_to_atom(0x3), do: :symmetric_l3l4_udp + def nx_hash_fields_to_atom(0x4), do: :nw_src + def nx_hash_fields_to_atom(0x5), do: :nw_dst + def nx_hash_fields_to_atom(_), do: throw(:bad_enum) + def nx_bd_algorithm_to_int(:active_backup), do: 0x0 + def nx_bd_algorithm_to_int(:highest_random_weight), do: 0x1 + def nx_bd_algorithm_to_int(_), do: throw(:bad_enum) + def nx_bd_algorithm_to_atom(0x0), do: :active_backup + def nx_bd_algorithm_to_atom(0x1), do: :highest_random_weight + def nx_bd_algorithm_to_atom(_), do: throw(:bad_enum) + def nx_learn_flag_to_int(:send_flow_rem), do: 0x1 + def nx_learn_flag_to_int(:delete_learned), do: 0x2 + def nx_learn_flag_to_int(:write_result), do: 0x4 + def nx_learn_flag_to_int(_), do: throw(:bad_enum) + def nx_learn_flag_to_atom(0x1), do: :send_flow_rem + def nx_learn_flag_to_atom(0x2), do: :delete_learned + def nx_learn_flag_to_atom(0x4), do: :write_result + def nx_learn_flag_to_atom(_), do: throw(:bad_enum) + def nx_conntrack_flags_to_int(:commit), do: 0x1 + def nx_conntrack_flags_to_int(:force), do: 0x2 + def nx_conntrack_flags_to_int(_), do: throw(:bad_enum) + def nx_conntrack_flags_to_atom(0x1), do: :commit + def nx_conntrack_flags_to_atom(0x2), do: :force + def nx_conntrack_flags_to_atom(_), do: throw(:bad_enum) + def nx_nat_flags_to_int(:src), do: 0x1 + def nx_nat_flags_to_int(:dst), do: 0x2 + def nx_nat_flags_to_int(:persistent), do: 0x4 + def nx_nat_flags_to_int(:protocol_hash), do: 0x8 + def nx_nat_flags_to_int(:protocol_random), do: 0x10 + def nx_nat_flags_to_int(_), do: throw(:bad_enum) + def nx_nat_flags_to_atom(0x1), do: :src + def nx_nat_flags_to_atom(0x2), do: :dst + def nx_nat_flags_to_atom(0x4), do: :persistent + def nx_nat_flags_to_atom(0x8), do: :protocol_hash + def nx_nat_flags_to_atom(0x10), do: :protocol_random + def nx_nat_flags_to_atom(_), do: throw(:bad_enum) + def nx_nat_range_to_int(:ipv4_min), do: 0x1 + def nx_nat_range_to_int(:ipv4_max), do: 0x2 + def nx_nat_range_to_int(:ipv6_min), do: 0x4 + def nx_nat_range_to_int(:ipv6_max), do: 0x8 + def nx_nat_range_to_int(:proto_min), do: 0x10 + def nx_nat_range_to_int(:proto_max), do: 0x20 + def nx_nat_range_to_int(_), do: throw(:bad_enum) + def nx_nat_range_to_atom(0x1), do: :ipv4_min + def nx_nat_range_to_atom(0x2), do: :ipv4_max + def nx_nat_range_to_atom(0x4), do: :ipv6_min + def nx_nat_range_to_atom(0x8), do: :ipv6_max + def nx_nat_range_to_atom(0x10), do: :proto_min + def nx_nat_range_to_atom(0x20), do: :proto_max + def nx_nat_range_to_atom(_), do: throw(:bad_enum) + def nx_action_controller2_prop_type_to_int(:max_len), do: 0x0 + def nx_action_controller2_prop_type_to_int(:controller_id), do: 0x1 + def nx_action_controller2_prop_type_to_int(:reason), do: 0x2 + def nx_action_controller2_prop_type_to_int(:userdata), do: 0x3 + def nx_action_controller2_prop_type_to_int(:pause), do: 0x4 + def nx_action_controller2_prop_type_to_int(_), do: throw(:bad_enum) + def nx_action_controller2_prop_type_to_atom(0x0), do: :max_len + def nx_action_controller2_prop_type_to_atom(0x1), do: :controller_id + def nx_action_controller2_prop_type_to_atom(0x2), do: :reason + def nx_action_controller2_prop_type_to_atom(0x3), do: :userdata + def nx_action_controller2_prop_type_to_atom(0x4), do: :pause + def nx_action_controller2_prop_type_to_atom(_), do: throw(:bad_enum) + def nx_action_sample_direction_to_int(:default), do: 0x0 + def nx_action_sample_direction_to_int(:ingress), do: 0x1 + def nx_action_sample_direction_to_int(:egress), do: 0x2 + def nx_action_sample_direction_to_int(_), do: throw(:bad_enum) + def nx_action_sample_direction_to_atom(0x0), do: :default + def nx_action_sample_direction_to_atom(0x1), do: :ingress + def nx_action_sample_direction_to_atom(0x2), do: :egress + def nx_action_sample_direction_to_atom(_), do: throw(:bad_enum) + def nx_flow_spec_type_to_int(Openflow.Action.NxFlowSpecMatch), do: 0x0 + def nx_flow_spec_type_to_int(Openflow.Action.NxFlowSpecLoad), do: 0x1 + def nx_flow_spec_type_to_int(Openflow.Action.NxFlowSpecOutput), do: 0x2 + def nx_flow_spec_type_to_int(_), do: throw(:bad_enum) + def nx_flow_spec_type_to_atom(0x0), do: Openflow.Action.NxFlowSpecMatch + def nx_flow_spec_type_to_atom(0x1), do: Openflow.Action.NxFlowSpecLoad + def nx_flow_spec_type_to_atom(0x2), do: Openflow.Action.NxFlowSpecOutput + def nx_flow_spec_type_to_atom(_), do: throw(:bad_enum) + def instruction_type_to_int(Openflow.Instruction.GotoTable), do: 0x1 + def instruction_type_to_int(Openflow.Instruction.WriteMetadata), do: 0x2 + def instruction_type_to_int(Openflow.Instruction.WriteActions), do: 0x3 + def instruction_type_to_int(Openflow.Instruction.ApplyActions), do: 0x4 + def instruction_type_to_int(Openflow.Instruction.ClearActions), do: 0x5 + def instruction_type_to_int(Openflow.Instruction.Meter), do: 0x6 + def instruction_type_to_int(Openflow.Instruction.Experimenter), do: 0xFFFF + def instruction_type_to_int(_), do: throw(:bad_enum) + def instruction_type_to_atom(0x1), do: Openflow.Instruction.GotoTable + def instruction_type_to_atom(0x2), do: Openflow.Instruction.WriteMetadata + def instruction_type_to_atom(0x3), do: Openflow.Instruction.WriteActions + def instruction_type_to_atom(0x4), do: Openflow.Instruction.ApplyActions + def instruction_type_to_atom(0x5), do: Openflow.Instruction.ClearActions + def instruction_type_to_atom(0x6), do: Openflow.Instruction.Meter + def instruction_type_to_atom(0xFFFF), do: Openflow.Instruction.Experimenter + def instruction_type_to_atom(_), do: throw(:bad_enum) + def controller_role_to_int(:nochange), do: 0x0 + def controller_role_to_int(:equal), do: 0x1 + def controller_role_to_int(:master), do: 0x2 + def controller_role_to_int(:slave), do: 0x3 + def controller_role_to_int(_), do: throw(:bad_enum) + def controller_role_to_atom(0x0), do: :nochange + def controller_role_to_atom(0x1), do: :equal + def controller_role_to_atom(0x2), do: :master + def controller_role_to_atom(0x3), do: :slave + def controller_role_to_atom(_), do: throw(:bad_enum) + def nx_role_to_int(:other), do: 0x0 + def nx_role_to_int(:master), do: 0x1 + def nx_role_to_int(:slave), do: 0x2 + def nx_role_to_int(_), do: throw(:bad_enum) + def nx_role_to_atom(0x0), do: :other + def nx_role_to_atom(0x1), do: :master + def nx_role_to_atom(0x2), do: :slave + def nx_role_to_atom(_), do: throw(:bad_enum) + def packet_in_format_to_int(:standard), do: 0x0 + def packet_in_format_to_int(:nxt_packet_in), do: 0x1 + def packet_in_format_to_int(:nxt_packet_in2), do: 0x2 + def packet_in_format_to_int(_), do: throw(:bad_enum) + def packet_in_format_to_atom(0x0), do: :standard + def packet_in_format_to_atom(0x1), do: :nxt_packet_in + def packet_in_format_to_atom(0x2), do: :nxt_packet_in2 + def packet_in_format_to_atom(_), do: throw(:bad_enum) + def flow_format_to_int(:openflow10), do: 0x0 + def flow_format_to_int(:nxm), do: 0x1 + def flow_format_to_int(_), do: throw(:bad_enum) + def flow_format_to_atom(0x0), do: :openflow10 + def flow_format_to_atom(0x1), do: :nxm + def flow_format_to_atom(_), do: throw(:bad_enum) + def packet_in2_prop_type_to_int(:packet), do: 0x0 + def packet_in2_prop_type_to_int(:full_len), do: 0x1 + def packet_in2_prop_type_to_int(:buffer_id), do: 0x2 + def packet_in2_prop_type_to_int(:table_id), do: 0x3 + def packet_in2_prop_type_to_int(:cookie), do: 0x4 + def packet_in2_prop_type_to_int(:reason), do: 0x5 + def packet_in2_prop_type_to_int(:metadata), do: 0x6 + def packet_in2_prop_type_to_int(:userdata), do: 0x7 + def packet_in2_prop_type_to_int(:continuation), do: 0x8 + def packet_in2_prop_type_to_int(_), do: throw(:bad_enum) + def packet_in2_prop_type_to_atom(0x0), do: :packet + def packet_in2_prop_type_to_atom(0x1), do: :full_len + def packet_in2_prop_type_to_atom(0x2), do: :buffer_id + def packet_in2_prop_type_to_atom(0x3), do: :table_id + def packet_in2_prop_type_to_atom(0x4), do: :cookie + def packet_in2_prop_type_to_atom(0x5), do: :reason + def packet_in2_prop_type_to_atom(0x6), do: :metadata + def packet_in2_prop_type_to_atom(0x7), do: :userdata + def packet_in2_prop_type_to_atom(0x8), do: :continuation + def packet_in2_prop_type_to_atom(_), do: throw(:bad_enum) + def continuation_prop_type_to_int(:bridge), do: 0x8000 + def continuation_prop_type_to_int(:stack), do: 0x8001 + def continuation_prop_type_to_int(:mirrors), do: 0x8002 + def continuation_prop_type_to_int(:conntracked), do: 0x8003 + def continuation_prop_type_to_int(:table_id), do: 0x8004 + def continuation_prop_type_to_int(:cookie), do: 0x8005 + def continuation_prop_type_to_int(:actions), do: 0x8006 + def continuation_prop_type_to_int(:action_set), do: 0x8007 + def continuation_prop_type_to_int(_), do: throw(:bad_enum) + def continuation_prop_type_to_atom(0x8000), do: :bridge + def continuation_prop_type_to_atom(0x8001), do: :stack + def continuation_prop_type_to_atom(0x8002), do: :mirrors + def continuation_prop_type_to_atom(0x8003), do: :conntracked + def continuation_prop_type_to_atom(0x8004), do: :table_id + def continuation_prop_type_to_atom(0x8005), do: :cookie + def continuation_prop_type_to_atom(0x8006), do: :actions + def continuation_prop_type_to_atom(0x8007), do: :action_set + def continuation_prop_type_to_atom(_), do: throw(:bad_enum) + def flow_monitor_flag_to_int(:initial), do: 0x1 + def flow_monitor_flag_to_int(:add), do: 0x2 + def flow_monitor_flag_to_int(:delete), do: 0x4 + def flow_monitor_flag_to_int(:modify), do: 0x8 + def flow_monitor_flag_to_int(:actions), do: 0x10 + def flow_monitor_flag_to_int(:own), do: 0x20 + def flow_monitor_flag_to_int(_), do: throw(:bad_enum) + def flow_monitor_flag_to_atom(0x1), do: :initial + def flow_monitor_flag_to_atom(0x2), do: :add + def flow_monitor_flag_to_atom(0x4), do: :delete + def flow_monitor_flag_to_atom(0x8), do: :modify + def flow_monitor_flag_to_atom(0x10), do: :actions + def flow_monitor_flag_to_atom(0x20), do: :own + def flow_monitor_flag_to_atom(_), do: throw(:bad_enum) + def flow_update_event_to_int(:added), do: 0x0 + def flow_update_event_to_int(:deleted), do: 0x1 + def flow_update_event_to_int(:modified), do: 0x2 + def flow_update_event_to_int(:abbrev), do: 0x3 + def flow_update_event_to_int(_), do: throw(:bad_enum) + def flow_update_event_to_atom(0x0), do: :added + def flow_update_event_to_atom(0x1), do: :deleted + def flow_update_event_to_atom(0x2), do: :modified + def flow_update_event_to_atom(0x3), do: :abbrev + def flow_update_event_to_atom(_), do: throw(:bad_enum) + def tlv_table_mod_command_to_int(:add), do: 0x0 + def tlv_table_mod_command_to_int(:delete), do: 0x1 + def tlv_table_mod_command_to_int(:clear), do: 0x2 + def tlv_table_mod_command_to_int(_), do: throw(:bad_enum) + def tlv_table_mod_command_to_atom(0x0), do: :add + def tlv_table_mod_command_to_atom(0x1), do: :delete + def tlv_table_mod_command_to_atom(0x2), do: :clear + def tlv_table_mod_command_to_atom(_), do: throw(:bad_enum) + def table_feature_prop_type_to_int(:instructions), do: 0x0 + def table_feature_prop_type_to_int(:instructions_miss), do: 0x1 + def table_feature_prop_type_to_int(:next_tables), do: 0x2 + def table_feature_prop_type_to_int(:next_tables_miss), do: 0x3 + def table_feature_prop_type_to_int(:write_actions), do: 0x4 + def table_feature_prop_type_to_int(:write_actions_miss), do: 0x5 + def table_feature_prop_type_to_int(:apply_actions), do: 0x6 + def table_feature_prop_type_to_int(:apply_actions_miss), do: 0x7 + def table_feature_prop_type_to_int(:match), do: 0x8 + def table_feature_prop_type_to_int(:wildcards), do: 0xA + def table_feature_prop_type_to_int(:write_setfield), do: 0xC + def table_feature_prop_type_to_int(:write_setfield_miss), do: 0xD + def table_feature_prop_type_to_int(:apply_setfield), do: 0xE + def table_feature_prop_type_to_int(:apply_setfield_miss), do: 0xF + def table_feature_prop_type_to_int(:experimenter), do: 0xFFFE + def table_feature_prop_type_to_int(:experimenter_miss), do: 0xFFFF + def table_feature_prop_type_to_int(_), do: throw(:bad_enum) + def table_feature_prop_type_to_atom(0x0), do: :instructions + def table_feature_prop_type_to_atom(0x1), do: :instructions_miss + def table_feature_prop_type_to_atom(0x2), do: :next_tables + def table_feature_prop_type_to_atom(0x3), do: :next_tables_miss + def table_feature_prop_type_to_atom(0x4), do: :write_actions + def table_feature_prop_type_to_atom(0x5), do: :write_actions_miss + def table_feature_prop_type_to_atom(0x6), do: :apply_actions + def table_feature_prop_type_to_atom(0x7), do: :apply_actions_miss + def table_feature_prop_type_to_atom(0x8), do: :match + def table_feature_prop_type_to_atom(0xA), do: :wildcards + def table_feature_prop_type_to_atom(0xC), do: :write_setfield + def table_feature_prop_type_to_atom(0xD), do: :write_setfield_miss + def table_feature_prop_type_to_atom(0xE), do: :apply_setfield + def table_feature_prop_type_to_atom(0xF), do: :apply_setfield_miss + def table_feature_prop_type_to_atom(0xFFFE), do: :experimenter + def table_feature_prop_type_to_atom(0xFFFF), do: :experimenter_miss + def table_feature_prop_type_to_atom(_), do: throw(:bad_enum) + + def int_to_flags(int, :openflow_codec) do + Openflow.Utils.int_to_flags([], int, enum_of(:openflow_codec)) + end + + def int_to_flags(int, :experimenter_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:experimenter_id)) + end + + def int_to_flags(int, :nicira_ext_message) do + Openflow.Utils.int_to_flags([], int, enum_of(:nicira_ext_message)) + end + + def int_to_flags(int, :onf_ext_message) do + Openflow.Utils.int_to_flags([], int, enum_of(:onf_ext_message)) + end + + def int_to_flags(int, :multipart_request_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:multipart_request_flags)) + end + + def int_to_flags(int, :multipart_reply_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:multipart_reply_flags)) + end + + def int_to_flags(int, :multipart_request_codec) do + Openflow.Utils.int_to_flags([], int, enum_of(:multipart_request_codec)) + end + + def int_to_flags(int, :multipart_reply_codec) do + Openflow.Utils.int_to_flags([], int, enum_of(:multipart_reply_codec)) + end + + def int_to_flags(int, :nicira_ext_stats) do + Openflow.Utils.int_to_flags([], int, enum_of(:nicira_ext_stats)) + end + + def int_to_flags(int, :hello_elem) do + Openflow.Utils.int_to_flags([], int, enum_of(:hello_elem)) + end + + def int_to_flags(int, :error_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:error_type)) + end + + def int_to_flags(int, :hello_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:hello_failed)) + end + + def int_to_flags(int, :bad_request) do + Openflow.Utils.int_to_flags([], int, enum_of(:bad_request)) + end + + def int_to_flags(int, :bad_action) do + Openflow.Utils.int_to_flags([], int, enum_of(:bad_action)) + end + + def int_to_flags(int, :bad_instruction) do + Openflow.Utils.int_to_flags([], int, enum_of(:bad_instruction)) + end + + def int_to_flags(int, :bad_match) do + Openflow.Utils.int_to_flags([], int, enum_of(:bad_match)) + end + + def int_to_flags(int, :flow_mod_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_mod_failed)) + end + + def int_to_flags(int, :group_mod_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:group_mod_failed)) + end + + def int_to_flags(int, :port_mod_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:port_mod_failed)) + end + + def int_to_flags(int, :table_mod_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:table_mod_failed)) + end + + def int_to_flags(int, :queue_op_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:queue_op_failed)) + end + + def int_to_flags(int, :switch_config_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:switch_config_failed)) + end + + def int_to_flags(int, :role_request_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:role_request_failed)) + end + + def int_to_flags(int, :meter_mod_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:meter_mod_failed)) + end + + def int_to_flags(int, :table_features_failed) do + Openflow.Utils.int_to_flags([], int, enum_of(:table_features_failed)) + end + + def int_to_flags(int, :switch_capabilities) do + Openflow.Utils.int_to_flags([], int, enum_of(:switch_capabilities)) + end + + def int_to_flags(int, :config_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:config_flags)) + end + + def int_to_flags(int, :controller_max_len) do + Openflow.Utils.int_to_flags([], int, enum_of(:controller_max_len)) + end + + def int_to_flags(int, :experimenter_oxm_vendors) do + Openflow.Utils.int_to_flags([], int, enum_of(:experimenter_oxm_vendors)) + end + + def int_to_flags(int, :match_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:match_type)) + end + + def int_to_flags(int, :oxm_class) do + Openflow.Utils.int_to_flags([], int, enum_of(:oxm_class)) + end + + def int_to_flags(int, :nxm_0) do + Openflow.Utils.int_to_flags([], int, enum_of(:nxm_0)) + end + + def int_to_flags(int, :nxm_1) do + Openflow.Utils.int_to_flags([], int, enum_of(:nxm_1)) + end + + def int_to_flags(int, :openflow_basic) do + Openflow.Utils.int_to_flags([], int, enum_of(:openflow_basic)) + end + + def int_to_flags(int, :vlan_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:vlan_id)) + end + + def int_to_flags(int, :ipv6exthdr_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:ipv6exthdr_flags)) + end + + def int_to_flags(int, :tcp_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:tcp_flags)) + end + + def int_to_flags(int, :ct_state_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:ct_state_flags)) + end + + def int_to_flags(int, :packet_register) do + Openflow.Utils.int_to_flags([], int, enum_of(:packet_register)) + end + + def int_to_flags(int, :nicira_ext_match) do + Openflow.Utils.int_to_flags([], int, enum_of(:nicira_ext_match)) + end + + def int_to_flags(int, :hp_ext_match) do + Openflow.Utils.int_to_flags([], int, enum_of(:hp_ext_match)) + end + + def int_to_flags(int, :hp_custom_match_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:hp_custom_match_type)) + end + + def int_to_flags(int, :onf_ext_match) do + Openflow.Utils.int_to_flags([], int, enum_of(:onf_ext_match)) + end + + def int_to_flags(int, :buffer_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:buffer_id)) + end + + def int_to_flags(int, :port_config) do + Openflow.Utils.int_to_flags([], int, enum_of(:port_config)) + end + + def int_to_flags(int, :port_state) do + Openflow.Utils.int_to_flags([], int, enum_of(:port_state)) + end + + def int_to_flags(int, :port_features) do + Openflow.Utils.int_to_flags([], int, enum_of(:port_features)) + end + + def int_to_flags(int, :openflow10_port_no) do + Openflow.Utils.int_to_flags([], int, enum_of(:openflow10_port_no)) + end + + def int_to_flags(int, :openflow13_port_no) do + Openflow.Utils.int_to_flags([], int, enum_of(:openflow13_port_no)) + end + + def int_to_flags(int, :packet_in_reason) do + Openflow.Utils.int_to_flags([], int, enum_of(:packet_in_reason)) + end + + def int_to_flags(int, :flow_mod_command) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_mod_command)) + end + + def int_to_flags(int, :flow_mod_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_mod_flags)) + end + + def int_to_flags(int, :flow_removed_reason) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_removed_reason)) + end + + def int_to_flags(int, :port_reason) do + Openflow.Utils.int_to_flags([], int, enum_of(:port_reason)) + end + + def int_to_flags(int, :group_mod_command) do + Openflow.Utils.int_to_flags([], int, enum_of(:group_mod_command)) + end + + def int_to_flags(int, :group_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:group_type)) + end + + def int_to_flags(int, :group_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:group_id)) + end + + def int_to_flags(int, :group_capabilities) do + Openflow.Utils.int_to_flags([], int, enum_of(:group_capabilities)) + end + + def int_to_flags(int, :table_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:table_id)) + end + + def int_to_flags(int, :queue_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:queue_id)) + end + + def int_to_flags(int, :meter_mod_command) do + Openflow.Utils.int_to_flags([], int, enum_of(:meter_mod_command)) + end + + def int_to_flags(int, :meter_id) do + Openflow.Utils.int_to_flags([], int, enum_of(:meter_id)) + end + + def int_to_flags(int, :meter_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:meter_flags)) + end + + def int_to_flags(int, :meter_band_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:meter_band_type)) + end + + def int_to_flags(int, :table_config) do + Openflow.Utils.int_to_flags([], int, enum_of(:table_config)) + end + + def int_to_flags(int, :action_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:action_type)) + end + + def int_to_flags(int, :action_vendor) do + Openflow.Utils.int_to_flags([], int, enum_of(:action_vendor)) + end + + def int_to_flags(int, :onf_ext_action) do + Openflow.Utils.int_to_flags([], int, enum_of(:onf_ext_action)) + end + + def int_to_flags(int, :nicira_ext_action) do + Openflow.Utils.int_to_flags([], int, enum_of(:nicira_ext_action)) + end + + def int_to_flags(int, :nx_mp_algorithm) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_mp_algorithm)) + end + + def int_to_flags(int, :nx_hash_fields) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_hash_fields)) + end + + def int_to_flags(int, :nx_bd_algorithm) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_bd_algorithm)) + end + + def int_to_flags(int, :nx_learn_flag) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_learn_flag)) + end + + def int_to_flags(int, :nx_conntrack_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_conntrack_flags)) + end + + def int_to_flags(int, :nx_nat_flags) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_nat_flags)) + end + + def int_to_flags(int, :nx_nat_range) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_nat_range)) + end + + def int_to_flags(int, :nx_action_controller2_prop_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_action_controller2_prop_type)) + end + + def int_to_flags(int, :nx_action_sample_direction) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_action_sample_direction)) + end + + def int_to_flags(int, :nx_flow_spec_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_flow_spec_type)) + end + + def int_to_flags(int, :instruction_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:instruction_type)) + end + + def int_to_flags(int, :controller_role) do + Openflow.Utils.int_to_flags([], int, enum_of(:controller_role)) + end + + def int_to_flags(int, :nx_role) do + Openflow.Utils.int_to_flags([], int, enum_of(:nx_role)) + end + + def int_to_flags(int, :packet_in_format) do + Openflow.Utils.int_to_flags([], int, enum_of(:packet_in_format)) + end + + def int_to_flags(int, :flow_format) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_format)) + end + + def int_to_flags(int, :packet_in2_prop_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:packet_in2_prop_type)) + end + + def int_to_flags(int, :continuation_prop_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:continuation_prop_type)) + end + + def int_to_flags(int, :flow_monitor_flag) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_monitor_flag)) + end + + def int_to_flags(int, :flow_update_event) do + Openflow.Utils.int_to_flags([], int, enum_of(:flow_update_event)) + end + + def int_to_flags(int, :tlv_table_mod_command) do + Openflow.Utils.int_to_flags([], int, enum_of(:tlv_table_mod_command)) + end + + def int_to_flags(int, :table_feature_prop_type) do + Openflow.Utils.int_to_flags([], int, enum_of(:table_feature_prop_type)) + end + + def flags_to_int(flags, :openflow_codec) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:openflow_codec)) + end + + def flags_to_int(flags, :experimenter_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:experimenter_id)) + end + + def flags_to_int(flags, :nicira_ext_message) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nicira_ext_message)) + end + + def flags_to_int(flags, :onf_ext_message) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:onf_ext_message)) + end + + def flags_to_int(flags, :multipart_request_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:multipart_request_flags)) + end + + def flags_to_int(flags, :multipart_reply_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:multipart_reply_flags)) + end + + def flags_to_int(flags, :multipart_request_codec) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:multipart_request_codec)) + end + + def flags_to_int(flags, :multipart_reply_codec) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:multipart_reply_codec)) + end + + def flags_to_int(flags, :nicira_ext_stats) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nicira_ext_stats)) + end + + def flags_to_int(flags, :hello_elem) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:hello_elem)) + end + + def flags_to_int(flags, :error_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:error_type)) + end + + def flags_to_int(flags, :hello_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:hello_failed)) + end + + def flags_to_int(flags, :bad_request) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:bad_request)) + end + + def flags_to_int(flags, :bad_action) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:bad_action)) + end + + def flags_to_int(flags, :bad_instruction) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:bad_instruction)) + end + + def flags_to_int(flags, :bad_match) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:bad_match)) + end + + def flags_to_int(flags, :flow_mod_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_mod_failed)) + end + + def flags_to_int(flags, :group_mod_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:group_mod_failed)) + end + + def flags_to_int(flags, :port_mod_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:port_mod_failed)) + end + + def flags_to_int(flags, :table_mod_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:table_mod_failed)) + end + + def flags_to_int(flags, :queue_op_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:queue_op_failed)) + end + + def flags_to_int(flags, :switch_config_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:switch_config_failed)) + end + + def flags_to_int(flags, :role_request_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:role_request_failed)) + end + + def flags_to_int(flags, :meter_mod_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:meter_mod_failed)) + end + + def flags_to_int(flags, :table_features_failed) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:table_features_failed)) + end + + def flags_to_int(flags, :switch_capabilities) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:switch_capabilities)) + end + + def flags_to_int(flags, :config_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:config_flags)) + end + + def flags_to_int(flags, :controller_max_len) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:controller_max_len)) + end + + def flags_to_int(flags, :experimenter_oxm_vendors) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:experimenter_oxm_vendors)) + end + + def flags_to_int(flags, :match_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:match_type)) + end + + def flags_to_int(flags, :oxm_class) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:oxm_class)) + end + + def flags_to_int(flags, :nxm_0) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nxm_0)) + end + + def flags_to_int(flags, :nxm_1) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nxm_1)) + end + + def flags_to_int(flags, :openflow_basic) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:openflow_basic)) + end + + def flags_to_int(flags, :vlan_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:vlan_id)) + end + + def flags_to_int(flags, :ipv6exthdr_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:ipv6exthdr_flags)) + end + + def flags_to_int(flags, :tcp_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:tcp_flags)) + end + + def flags_to_int(flags, :ct_state_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:ct_state_flags)) + end + + def flags_to_int(flags, :packet_register) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:packet_register)) + end + + def flags_to_int(flags, :nicira_ext_match) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nicira_ext_match)) + end + + def flags_to_int(flags, :hp_ext_match) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:hp_ext_match)) + end + + def flags_to_int(flags, :hp_custom_match_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:hp_custom_match_type)) + end + + def flags_to_int(flags, :onf_ext_match) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:onf_ext_match)) + end + + def flags_to_int(flags, :buffer_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:buffer_id)) + end + + def flags_to_int(flags, :port_config) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:port_config)) + end + + def flags_to_int(flags, :port_state) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:port_state)) + end + + def flags_to_int(flags, :port_features) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:port_features)) + end + + def flags_to_int(flags, :openflow10_port_no) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:openflow10_port_no)) + end + + def flags_to_int(flags, :openflow13_port_no) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:openflow13_port_no)) + end + + def flags_to_int(flags, :packet_in_reason) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:packet_in_reason)) + end + + def flags_to_int(flags, :flow_mod_command) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_mod_command)) + end + + def flags_to_int(flags, :flow_mod_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_mod_flags)) + end + + def flags_to_int(flags, :flow_removed_reason) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_removed_reason)) + end + + def flags_to_int(flags, :port_reason) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:port_reason)) + end + + def flags_to_int(flags, :group_mod_command) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:group_mod_command)) + end + + def flags_to_int(flags, :group_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:group_type)) + end + + def flags_to_int(flags, :group_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:group_id)) + end + + def flags_to_int(flags, :group_capabilities) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:group_capabilities)) + end + + def flags_to_int(flags, :table_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:table_id)) + end + + def flags_to_int(flags, :queue_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:queue_id)) + end + + def flags_to_int(flags, :meter_mod_command) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:meter_mod_command)) + end + + def flags_to_int(flags, :meter_id) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:meter_id)) + end + + def flags_to_int(flags, :meter_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:meter_flags)) + end + + def flags_to_int(flags, :meter_band_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:meter_band_type)) + end + + def flags_to_int(flags, :table_config) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:table_config)) + end + + def flags_to_int(flags, :action_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:action_type)) + end + + def flags_to_int(flags, :action_vendor) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:action_vendor)) + end + + def flags_to_int(flags, :onf_ext_action) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:onf_ext_action)) + end + + def flags_to_int(flags, :nicira_ext_action) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nicira_ext_action)) + end + + def flags_to_int(flags, :nx_mp_algorithm) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_mp_algorithm)) + end + + def flags_to_int(flags, :nx_hash_fields) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_hash_fields)) + end + + def flags_to_int(flags, :nx_bd_algorithm) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_bd_algorithm)) + end + + def flags_to_int(flags, :nx_learn_flag) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_learn_flag)) + end + + def flags_to_int(flags, :nx_conntrack_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_conntrack_flags)) + end + + def flags_to_int(flags, :nx_nat_flags) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_nat_flags)) + end + + def flags_to_int(flags, :nx_nat_range) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_nat_range)) + end + + def flags_to_int(flags, :nx_action_controller2_prop_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_action_controller2_prop_type)) + end + + def flags_to_int(flags, :nx_action_sample_direction) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_action_sample_direction)) + end + + def flags_to_int(flags, :nx_flow_spec_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_flow_spec_type)) + end + + def flags_to_int(flags, :instruction_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:instruction_type)) + end + + def flags_to_int(flags, :controller_role) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:controller_role)) + end + + def flags_to_int(flags, :nx_role) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:nx_role)) + end + + def flags_to_int(flags, :packet_in_format) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:packet_in_format)) + end + + def flags_to_int(flags, :flow_format) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_format)) + end + + def flags_to_int(flags, :packet_in2_prop_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:packet_in2_prop_type)) + end + + def flags_to_int(flags, :continuation_prop_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:continuation_prop_type)) + end + + def flags_to_int(flags, :flow_monitor_flag) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_monitor_flag)) + end + + def flags_to_int(flags, :flow_update_event) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:flow_update_event)) + end + + def flags_to_int(flags, :tlv_table_mod_command) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:tlv_table_mod_command)) + end + + def flags_to_int(flags, :table_feature_prop_type) do + Openflow.Utils.flags_to_int(0, flags, enum_of(:table_feature_prop_type)) + end + + defp enum_of(:openflow_codec), + do: [ + {Openflow.Hello, 0}, + {Openflow.ErrorMsg, 1}, + {Openflow.Echo.Request, 2}, + {Openflow.Echo.Reply, 3}, + {Openflow.Experimenter, 4}, + {Openflow.Features.Request, 5}, + {Openflow.Features.Reply, 6}, + {Openflow.GetConfig.Request, 7}, + {Openflow.GetConfig.Reply, 8}, + {Openflow.SetConfig, 9}, + {Openflow.PacketIn, 10}, + {Openflow.FlowRemoved, 11}, + {Openflow.PortStatus, 12}, + {Openflow.PacketOut, 13}, + {Openflow.FlowMod, 14}, + {Openflow.GroupMod, 15}, + {Openflow.PortMod, 16}, + {Openflow.TableMod, 17}, + {Openflow.Multipart.Request, 18}, + {Openflow.Multipart.Reply, 19}, + {Openflow.Barrier.Request, 20}, + {Openflow.Barrier.Reply, 21}, + {Openflow.Role.Request, 24}, + {Openflow.Role.Reply, 25}, + {Openflow.GetAsync.Request, 26}, + {Openflow.GetAsync.Reply, 27}, + {Openflow.SetAsync, 28}, + {Openflow.MeterMod, 29} + ] + + defp enum_of(:experimenter_id), do: [nicira_ext_message: 8992, onf_ext_message: 1_330_529_792] + + defp enum_of(:nicira_ext_message), + do: [ + {Openflow.NxSetPacketInFormat, 16}, + {Openflow.NxSetControllerId, 20}, + {Openflow.NxFlowMonitor.Cancel, 21}, + {Openflow.NxFlowMonitor.Paused, 22}, + {Openflow.NxFlowMonitor.Resumed, 23}, + {Openflow.NxTLVTableMod, 24}, + {Openflow.NxTLVTable.Request, 25}, + {Openflow.NxTLVTable.Reply, 26}, + {Openflow.NxSetAsyncConfig2, 27}, + {Openflow.NxResume, 28}, + {Openflow.NxCtFlushZone, 29}, + {Openflow.NxPacketIn2, 30} + ] + + defp enum_of(:onf_ext_message), + do: [{Openflow.OnfBundleControl, 2300}, {Openflow.OnfBundleAddMessage, 2301}] + + defp enum_of(:multipart_request_flags), do: [more: 1] + defp enum_of(:multipart_reply_flags), do: [more: 1] + + defp enum_of(:multipart_request_codec), + do: [ + {Openflow.Multipart.Desc.Request, 0}, + {Openflow.Multipart.Flow.Request, 1}, + {Openflow.Multipart.Aggregate.Request, 2}, + {Openflow.Multipart.Table.Request, 3}, + {Openflow.Multipart.PortStats.Request, 4}, + {Openflow.Multipart.Queue.Request, 5}, + {Openflow.Multipart.Group.Request, 6}, + {Openflow.Multipart.GroupDesc.Request, 7}, + {Openflow.Multipart.GroupFeatures.Request, 8}, + {Openflow.Multipart.Meter.Request, 9}, + {Openflow.Multipart.MeterConfig.Request, 10}, + {Openflow.Multipart.MeterFeatures.Request, 11}, + {Openflow.Multipart.TableFeatures.Request, 12}, + {Openflow.Multipart.PortDesc.Request, 13}, + {Openflow.Multipart.Experimenter.Request, 65535} + ] + + defp enum_of(:multipart_reply_codec), + do: [ + {Openflow.Multipart.Desc.Reply, 0}, + {Openflow.Multipart.Flow.Reply, 1}, + {Openflow.Multipart.Aggregate.Reply, 2}, + {Openflow.Multipart.Table.Reply, 3}, + {Openflow.Multipart.PortStats.Reply, 4}, + {Openflow.Multipart.Queue.Reply, 5}, + {Openflow.Multipart.Group.Reply, 6}, + {Openflow.Multipart.GroupDesc.Reply, 7}, + {Openflow.Multipart.GroupFeatures.Reply, 8}, + {Openflow.Multipart.Meter.Reply, 9}, + {Openflow.Multipart.MeterConfig.Reply, 10}, + {Openflow.Multipart.MeterFeatures.Reply, 11}, + {Openflow.Multipart.TableFeatures.Reply, 12}, + {Openflow.Multipart.PortDesc.Reply, 13}, + {Openflow.Multipart.Experimenter.Reply, 65535} + ] + + defp enum_of(:nicira_ext_stats), + do: [ + {Openflow.Multipart.NxFlow, 0}, + {Openflow.Multipart.NxAggregate, 1}, + {Openflow.Multipart.NxFlowMonitor, 2}, + {Openflow.Multipart.NxIPFIXBridge, 3}, + {Openflow.Multipart.NxIPFIXFlow, 4} + ] + + defp enum_of(:hello_elem), do: [versionbitmap: 1] + + defp enum_of(:error_type), + do: [ + hello_failed: 0, + bad_request: 1, + bad_action: 2, + bad_instruction: 3, + bad_match: 4, + flow_mod_failed: 5, + group_mod_failed: 6, + port_mod_failed: 7, + table_mod_failed: 8, + queue_op_failed: 9, + switch_config_failed: 10, + role_request_failed: 11, + meter_mod_failed: 12, + table_features_failed: 13, + experimenter: 65535 + ] + + defp enum_of(:hello_failed), do: [inconpatible: 0, eperm: 1] + + defp enum_of(:bad_request), + do: [ + bad_version: 0, + bad_type: 1, + bad_multipart: 2, + bad_experimeter: 3, + bad_exp_type: 4, + eperm: 5, + bad_len: 6, + buffer_empty: 7, + buffer_unknown: 8, + bad_table_id: 9, + is_slave: 10, + bad_port: 11, + bad_packet: 12, + multipart_buffer_overflow: 13 + ] + + defp enum_of(:bad_action), + do: [ + bad_type: 0, + bad_len: 1, + bad_experimeter: 2, + bad_exp_type: 3, + bad_out_port: 4, + bad_argument: 5, + eperm: 6, + too_many: 7, + bad_queue: 8, + bad_out_group: 9, + match_inconsistent: 10, + unsupported_order: 11, + bad_tag: 12, + bad_set_type: 13, + bad_set_len: 14, + bad_set_argument: 15 + ] + + defp enum_of(:bad_instruction), + do: [ + unknown_instruction: 0, + unsupported_instruction: 1, + bad_table_id: 2, + unsupported_metadata: 3, + unsupported_metadata_mask: 4, + bad_experimeter: 5, + bad_exp_type: 6, + bad_len: 7, + eperm: 8 + ] + + defp enum_of(:bad_match), + do: [ + bad_type: 0, + bad_len: 1, + bad_tag: 2, + bad_dl_addr_mask: 3, + bad_nw_addr_mask: 4, + bad_wildcards: 5, + bad_field: 6, + bad_value: 7, + bad_mask: 8, + bad_prereq: 9, + dup_field: 10, + eperm: 11 + ] + + defp enum_of(:flow_mod_failed), + do: [ + unknown: 0, + table_full: 1, + bad_table_id: 2, + overlap: 3, + eperm: 4, + bad_timeout: 5, + bad_command: 6, + bad_flags: 7 + ] + + defp enum_of(:group_mod_failed), + do: [ + group_exists: 0, + invalid_group: 1, + weight_unsupported: 2, + out_of_groups: 3, + ouf_of_buckets: 4, + chaining_unsupported: 5, + watch_unsupported: 6, + loop: 7, + unknown_group: 8, + chained_group: 9, + bad_type: 10, + bad_command: 11, + bad_bucket: 12, + bad_watch: 13, + eperm: 14 + ] + + defp enum_of(:port_mod_failed), + do: [bad_port: 0, bad_hw_addr: 1, bad_config: 2, bad_advertise: 3, eperm: 4] + + defp enum_of(:table_mod_failed), do: [bad_table: 0, bad_config: 1, eperm: 2] + defp enum_of(:queue_op_failed), do: [bad_port: 0, bad_queue: 1, eperm: 2] + defp enum_of(:switch_config_failed), do: [bad_flags: 0, bad_len: 1, eperm: 2] + defp enum_of(:role_request_failed), do: [stale: 0, unsup: 1, bad_role: 2] + + defp enum_of(:meter_mod_failed), + do: [ + unknown: 0, + meter_exists: 1, + invalid_meter: 2, + unknown_meter: 3, + bad_command: 4, + bad_flags: 5, + bad_rate: 6, + bad_burst: 7, + bad_band: 8, + bad_band_value: 9, + out_of_meters: 10, + out_of_bands: 11 + ] + + defp enum_of(:table_features_failed), + do: [ + bad_table: 0, + bad_metadata: 1, + bad_type: 2, + bad_len: 3, + bad_argument: 4, + eperm: 5 + ] + + defp enum_of(:switch_capabilities), + do: [ + flow_stats: 1, + table_stats: 2, + port_stats: 4, + group_stats: 8, + ip_reasm: 32, + queue_stats: 64, + arp_match_ip: 128, + port_blocked: 256 + ] + + defp enum_of(:config_flags), do: [drop: 1, reasm: 2] + defp enum_of(:controller_max_len), do: [max: 65509, no_buffer: 65535] + + defp enum_of(:experimenter_oxm_vendors), + do: [nicira_ext_match: 8992, hp_ext_match: 9256, onf_ext_match: 1_330_529_792] + + defp enum_of(:match_type), do: [standard: 0, oxm: 1] + + defp enum_of(:oxm_class), + do: [ + nxm_0: 0, + nxm_1: 1, + openflow_basic: 32768, + packet_register: 32769, + experimenter: 65535 + ] + + defp enum_of(:nxm_0), + do: [ + nx_in_port: 0, + nx_eth_dst: 1, + nx_eth_src: 2, + nx_eth_type: 3, + nx_vlan_tci: 4, + nx_ip_tos: 5, + nx_ip_proto: 6, + nx_ipv4_src: 7, + nx_ipv4_dst: 8, + nx_tcp_src: 9, + nx_tcp_dst: 10, + nx_udp_src: 11, + nx_udp_dst: 12, + nx_icmpv4_type: 13, + nx_icmpv4_code: 14, + nx_arp_op: 15, + nx_arp_spa: 16, + nx_arp_tpa: 17, + nx_tcp_flags: 34 + ] + + defp enum_of(:nxm_1), + do: [ + reg0: 0, + reg1: 1, + reg2: 2, + reg3: 3, + reg4: 4, + reg5: 5, + reg6: 6, + reg7: 7, + reg8: 8, + reg9: 9, + reg10: 10, + reg11: 11, + reg12: 12, + reg13: 13, + reg14: 14, + reg15: 15, + tun_id: 16, + nx_arp_sha: 17, + nx_arp_tha: 18, + nx_ipv6_src: 19, + nx_ipv6_dst: 20, + nx_icmpv6_type: 21, + nx_icmpv6_code: 22, + nx_ipv6_nd_target: 23, + nx_ipv6_nd_sll: 24, + nx_ipv6_nd_tll: 25, + nx_ip_frag: 26, + nx_ipv6_label: 27, + nx_ip_ecn: 28, + nx_ip_ttl: 29, + nx_mpls_ttl: 30, + tun_src: 31, + tun_dst: 32, + pkt_mark: 33, + dp_hash: 35, + recirc_id: 36, + conj_id: 37, + tun_gbp_id: 38, + tun_gbp_flags: 39, + tun_metadata0: 40, + tun_metadata1: 41, + tun_metadata2: 42, + tun_metadata3: 43, + tun_metadata4: 44, + tun_metadata5: 45, + tun_metadata6: 46, + tun_metadata7: 47, + tun_metadata8: 48, + tun_metadata9: 49, + tun_metadata10: 50, + tun_metadata11: 51, + tun_metadata12: 52, + tun_metadata13: 53, + tun_metadata14: 54, + tun_metadata15: 55, + tun_metadata16: 56, + tun_metadata17: 57, + tun_metadata18: 58, + tun_metadata19: 59, + tun_metadata20: 60, + tun_metadata21: 61, + tun_metadata22: 62, + tun_metadata23: 63, + tun_metadata24: 64, + tun_metadata25: 65, + tun_metadata26: 66, + tun_metadata27: 67, + tun_metadata28: 68, + tun_metadata29: 69, + tun_metadata30: 70, + tun_metadata31: 71, + tun_metadata32: 72, + tun_metadata33: 73, + tun_metadata34: 74, + tun_metadata35: 75, + tun_metadata36: 76, + tun_metadata37: 77, + tun_metadata38: 78, + tun_metadata39: 79, + tun_metadata40: 80, + tun_metadata41: 81, + tun_metadata42: 82, + tun_metadata43: 83, + tun_metadata44: 84, + tun_metadata45: 85, + tun_metadata46: 86, + tun_metadata47: 87, + tun_metadata48: 88, + tun_metadata49: 89, + tun_metadata50: 90, + tun_metadata51: 91, + tun_metadata52: 92, + tun_metadata53: 93, + tun_metadata54: 94, + tun_metadata55: 95, + tun_metadata56: 96, + tun_metadata57: 97, + tun_metadata58: 98, + tun_metadata59: 99, + tun_metadata60: 100, + tun_metadata61: 101, + tun_metadata62: 102, + tun_metadata63: 103, + tun_flags: 104, + ct_state: 105, + ct_zone: 106, + ct_mark: 107, + ct_label: 108, + tun_ipv6_src: 109, + tun_ipv6_dst: 110, + xxreg0: 111, + xxreg1: 112, + xxreg2: 113, + xxreg3: 114, + xxreg4: 115, + xxreg5: 116, + xxreg6: 117, + xxreg7: 118, + ct_nw_proto: 119, + ct_nw_src: 120, + ct_nw_dst: 121, + ct_ipv6_src: 122, + ct_ipv6_dst: 123, + ct_tp_src: 124, + ct_tp_dst: 125 + ] + + defp enum_of(:openflow_basic), + do: [ + in_port: 0, + in_phy_port: 1, + metadata: 2, + eth_dst: 3, + eth_src: 4, + eth_type: 5, + vlan_vid: 6, + vlan_pcp: 7, + ip_dscp: 8, + ip_ecn: 9, + ip_proto: 10, + ipv4_src: 11, + ipv4_dst: 12, + tcp_src: 13, + tcp_dst: 14, + udp_src: 15, + udp_dst: 16, + sctp_src: 17, + sctp_dst: 18, + icmpv4_type: 19, + icmpv4_code: 20, + arp_op: 21, + arp_spa: 22, + arp_tpa: 23, + arp_sha: 24, + arp_tha: 25, + ipv6_src: 26, + ipv6_dst: 27, + ipv6_flabel: 28, + icmpv6_type: 29, + icmpv6_code: 30, + ipv6_nd_target: 31, + ipv6_nd_sll: 32, + ipv6_nd_tll: 33, + mpls_label: 34, + mpls_tc: 35, + mpls_bos: 36, + pbb_isid: 37, + tunnel_id: 38, + ipv6_exthdr: 39, + pbb_uca: 41, + packet_type: 42, + gre_flags: 43, + gre_ver: 44, + gre_protocol: 45, + gre_key: 46, + gre_seqnum: 47, + lisp_flags: 48, + lisp_nonce: 49, + lisp_id: 50, + vxlan_flags: 51, + vxlan_vni: 52, + mpls_data_first_nibble: 53, + mpls_ach_version: 54, + mpls_ach_channel: 55, + mpls_pw_metadata: 56, + mpls_cw_flags: 57, + mpls_cw_fragment: 58, + mpls_cw_len: 59, + mpls_cw_seq_num: 60, + gtpu_flags: 61, + gtpu_ver: 62, + gtpu_msg_type: 63, + gtpu_teid: 64, + gtpu_extn_hdr: 65, + gtpu_extn_udp_port: 66, + gtpu_extn_sci: 67 + ] + + defp enum_of(:vlan_id), do: [present: 4096, none: 0] + + defp enum_of(:ipv6exthdr_flags), + do: [ + nonext: 1, + esp: 2, + auth: 4, + dest: 8, + frag: 16, + router: 32, + hop: 64, + unrep: 128, + unseq: 256 + ] + + defp enum_of(:tcp_flags), + do: [fin: 1, syn: 2, rst: 4, psh: 8, ack: 16, urg: 32, ece: 64, cwr: 128, ns: 256] + + defp enum_of(:ct_state_flags), + do: [new: 1, est: 2, rel: 4, rep: 8, inv: 16, trk: 32, snat: 64, dnat: 128] + + defp enum_of(:packet_register), + do: [xreg0: 0, xreg1: 1, xreg2: 2, xreg3: 3, xreg4: 4, xreg5: 5, xreg6: 6, xreg7: 7] + + defp enum_of(:nicira_ext_match), + do: [ + nsh_flags: 1, + nsh_mdtype: 2, + nsh_np: 3, + nsh_spi: 4, + nsh_si: 5, + nsh_c1: 6, + nsh_c2: 7, + nsh_c3: 8, + nsh_c4: 9 + ] + + defp enum_of(:hp_ext_match), + do: [ + 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 + ] + + defp enum_of(:hp_custom_match_type), do: [l2_start: 1, l3_start: 2, l4_start: 3] + defp enum_of(:onf_ext_match), do: [onf_tcp_flags: 42, onf_actset_output: 43, onf_pbb_uca: 2560] + defp enum_of(:buffer_id), do: [no_buffer: 4_294_967_295] + defp enum_of(:port_config), do: [port_down: 1, no_receive: 4, no_forward: 32, no_packet_in: 64] + defp enum_of(:port_state), do: [link_down: 1, blocked: 2, live: 4] + + defp enum_of(:port_features), + do: [ + "10mb_hd": 1, + "10mb_fd": 2, + "100mb_hd": 4, + "100mb_fd": 8, + "1gb_hd": 16, + "1gb_fd": 32, + "10gb_fd": 64, + "40gb_fd": 128, + "100gb_fd": 256, + "1tb_fd": 512, + other: 1024, + copper: 2048, + fiber: 4096, + autoneg: 8192, + pause: 16384, + pause_asym: 32768 + ] + + defp enum_of(:openflow10_port_no), + do: [ + max: 65280, + in_port: 65528, + table: 65529, + normal: 65530, + flood: 65531, + all: 65532, + controller: 65533, + local: 65534, + none: 65535 + ] + + defp enum_of(:openflow13_port_no), + do: [ + max: 4_294_967_040, + in_port: 4_294_967_288, + table: 4_294_967_289, + normal: 4_294_967_290, + flood: 4_294_967_291, + all: 4_294_967_292, + controller: 4_294_967_293, + local: 4_294_967_294, + any: 4_294_967_295 + ] + + defp enum_of(:packet_in_reason), + do: [no_match: 0, action: 1, invalid_ttl: 2, action_set: 3, group: 4, packet_out: 5] + + defp enum_of(:flow_mod_command), + do: [add: 0, modify: 1, modify_strict: 2, delete: 3, delete_strict: 4] + + defp enum_of(:flow_mod_flags), + do: [ + send_flow_rem: 1, + check_overlap: 2, + reset_counts: 4, + no_packet_counts: 8, + no_byte_counts: 16 + ] + + defp enum_of(:flow_removed_reason), + do: [ + idle_timeout: 0, + hard_timeout: 1, + delete: 2, + group_delete: 3, + meter_delete: 4, + eviction: 5 + ] + + defp enum_of(:port_reason), do: [add: 0, delete: 1, modify: 2] + defp enum_of(:group_mod_command), do: [add: 0, modify: 1, delete: 2] + defp enum_of(:group_type), do: [all: 0, select: 1, indirect: 2, fast_failover: 3] + defp enum_of(:group_id), do: [max: 4_294_967_040, all: 4_294_967_292, any: 4_294_967_295] + + defp enum_of(:group_capabilities), + do: [select_weight: 1, select_liveness: 2, chaining: 4, chaining_checks: 8] + + defp enum_of(:table_id), do: [max: 254, all: 255] + defp enum_of(:queue_id), do: [all: 4_294_967_295] + defp enum_of(:meter_mod_command), do: [add: 0, modify: 1, delete: 2] + + defp enum_of(:meter_id), + do: [ + max: 4_294_901_760, + slowpath: 4_294_967_293, + controller: 4_294_967_294, + all: 4_294_967_295 + ] + + defp enum_of(:meter_flags), do: [kbps: 1, pktps: 2, burst: 4, stats: 8] + + defp enum_of(:meter_band_type), + do: [ + {Openflow.MeterBand.Drop, 1}, + {Openflow.MeterBand.Remark, 2}, + {Openflow.MeterBand.Experimenter, 65535} + ] + + defp enum_of(:table_config), + do: [ + table_miss_controller: 0, + table_miss_continue: 1, + table_miss_drop: 2, + table_miss_mask: 3, + eviction: 4, + vacancy_events: 8 + ] + + defp enum_of(:action_type), + do: [ + {Openflow.Action.Output, 0}, + {Openflow.Action.CopyTtlOut, 11}, + {Openflow.Action.CopyTtlIn, 12}, + {Openflow.Action.SetMplsTtl, 15}, + {Openflow.Action.DecMplsTtl, 16}, + {Openflow.Action.PushVlan, 17}, + {Openflow.Action.PopVlan, 18}, + {Openflow.Action.PushMpls, 19}, + {Openflow.Action.PopMpls, 20}, + {Openflow.Action.SetQueue, 21}, + {Openflow.Action.Group, 22}, + {Openflow.Action.SetNwTtl, 23}, + {Openflow.Action.DecNwTtl, 24}, + {Openflow.Action.SetField, 25}, + {Openflow.Action.PushPbb, 26}, + {Openflow.Action.PopPbb, 27}, + {Openflow.Action.Encap, 28}, + {Openflow.Action.Decap, 29}, + {Openflow.Action.SetSequence, 30}, + {Openflow.Action.ValidateSequence, 31}, + {Openflow.Action.Experimenter, 65535} + ] + + defp enum_of(:action_vendor), do: [nicira_ext_action: 8992, onf_ext_action: 1_330_529_792] + defp enum_of(:onf_ext_action), do: [{Openflow.Action.OnfCopyField, 3200}] + + defp enum_of(:nicira_ext_action), + do: [ + {Openflow.Action.NxResubmit, 1}, + {Openflow.Action.NxSetTunnel, 2}, + {Openflow.Action.NxSetQueue, 4}, + {Openflow.Action.NxPopQueue, 5}, + {Openflow.Action.NxRegMove, 6}, + {Openflow.Action.NxRegLoad, 7}, + {Openflow.Action.NxNote, 8}, + {Openflow.Action.NxSetTunnel64, 9}, + {Openflow.Action.NxMultipath, 10}, + {Openflow.Action.NxBundle, 12}, + {Openflow.Action.NxBundleLoad, 13}, + {Openflow.Action.NxResubmitTable, 14}, + {Openflow.Action.NxOutputReg, 15}, + {Openflow.Action.NxLearn, 16}, + {Openflow.Action.NxExit, 17}, + {Openflow.Action.NxDecTtl, 18}, + {Openflow.Action.NxFinTimeout, 19}, + {Openflow.Action.NxController, 20}, + {Openflow.Action.NxDecTtlCntIds, 21}, + {Openflow.Action.NxWriteMetadata, 22}, + {Openflow.Action.NxPushMpls, 23}, + {Openflow.Action.NxPopMpls, 24}, + {Openflow.Action.NxSetMplsTtl, 25}, + {Openflow.Action.NxDecMplsTtl, 26}, + {Openflow.Action.NxStackPush, 27}, + {Openflow.Action.NxStackPop, 28}, + {Openflow.Action.NxSample, 29}, + {Openflow.Action.NxSetMplsLabel, 30}, + {Openflow.Action.NxSetMplsTc, 31}, + {Openflow.Action.NxOutputReg2, 32}, + {Openflow.Action.NxRegLoad2, 33}, + {Openflow.Action.NxConjunction, 34}, + {Openflow.Action.NxConntrack, 35}, + {Openflow.Action.NxNat, 36}, + {Openflow.Action.NxController2, 37}, + {Openflow.Action.NxSample2, 38}, + {Openflow.Action.NxOutputTrunc, 39}, + {Openflow.Action.NxGroup, 40}, + {Openflow.Action.NxSample3, 41}, + {Openflow.Action.NxClone, 42}, + {Openflow.Action.NxCtClear, 43}, + {Openflow.Action.NxResubmitTableCt, 44}, + {Openflow.Action.NxLearn2, 45}, + {Openflow.Action.NxEncap, 46}, + {Openflow.Action.NxDecap, 47}, + {Openflow.Action.NxDebugRecirc, 255} + ] + + defp enum_of(:nx_mp_algorithm), + do: [modulo_n: 0, hash_threshold: 1, highest_random_weight: 2, iterative_hash: 3] + + defp enum_of(:nx_hash_fields), + do: [ + eth_src: 0, + symmetric_l4: 1, + symmetric_l3l4: 2, + symmetric_l3l4_udp: 3, + nw_src: 4, + nw_dst: 5 + ] + + defp enum_of(:nx_bd_algorithm), do: [active_backup: 0, highest_random_weight: 1] + defp enum_of(:nx_learn_flag), do: [send_flow_rem: 1, delete_learned: 2, write_result: 4] + defp enum_of(:nx_conntrack_flags), do: [commit: 1, force: 2] + + defp enum_of(:nx_nat_flags), + do: [src: 1, dst: 2, persistent: 4, protocol_hash: 8, protocol_random: 16] + + defp enum_of(:nx_nat_range), + do: [ + ipv4_min: 1, + ipv4_max: 2, + ipv6_min: 4, + ipv6_max: 8, + proto_min: 16, + proto_max: 32 + ] + + defp enum_of(:nx_action_controller2_prop_type), + do: [max_len: 0, controller_id: 1, reason: 2, userdata: 3, pause: 4] + + defp enum_of(:nx_action_sample_direction), do: [default: 0, ingress: 1, egress: 2] + + defp enum_of(:nx_flow_spec_type), + do: [ + {Openflow.Action.NxFlowSpecMatch, 0}, + {Openflow.Action.NxFlowSpecLoad, 1}, + {Openflow.Action.NxFlowSpecOutput, 2} + ] + + defp enum_of(:instruction_type), + do: [ + {Openflow.Instruction.GotoTable, 1}, + {Openflow.Instruction.WriteMetadata, 2}, + {Openflow.Instruction.WriteActions, 3}, + {Openflow.Instruction.ApplyActions, 4}, + {Openflow.Instruction.ClearActions, 5}, + {Openflow.Instruction.Meter, 6}, + {Openflow.Instruction.Experimenter, 65535} + ] + + defp enum_of(:controller_role), do: [nochange: 0, equal: 1, master: 2, slave: 3] + defp enum_of(:nx_role), do: [other: 0, master: 1, slave: 2] + defp enum_of(:packet_in_format), do: [standard: 0, nxt_packet_in: 1, nxt_packet_in2: 2] + defp enum_of(:flow_format), do: [openflow10: 0, nxm: 1] + + defp enum_of(:packet_in2_prop_type), + do: [ + packet: 0, + full_len: 1, + buffer_id: 2, + table_id: 3, + cookie: 4, + reason: 5, + metadata: 6, + userdata: 7, + continuation: 8 + ] + + defp enum_of(:continuation_prop_type), + do: [ + bridge: 32768, + stack: 32769, + mirrors: 32770, + conntracked: 32771, + table_id: 32772, + cookie: 32773, + actions: 32774, + action_set: 32775 + ] + + defp enum_of(:flow_monitor_flag), + do: [initial: 1, add: 2, delete: 4, modify: 8, actions: 16, own: 32] + + defp enum_of(:flow_update_event), do: [added: 0, deleted: 1, modified: 2, abbrev: 3] + defp enum_of(:tlv_table_mod_command), do: [add: 0, delete: 1, clear: 2] + + defp enum_of(:table_feature_prop_type), + do: [ + instructions: 0, + instructions_miss: 1, + next_tables: 2, + next_tables_miss: 3, + write_actions: 4, + write_actions_miss: 5, + apply_actions: 6, + apply_actions_miss: 7, + match: 8, + wildcards: 10, + write_setfield: 12, + write_setfield_miss: 13, + apply_setfield: 14, + apply_setfield_miss: 15, + experimenter: 65534, + experimenter_miss: 65535 + ] +end diff --git a/lib/openflow/error_msg.ex b/lib/openflow/error_msg.ex new file mode 100644 index 0000000..2279230 --- /dev/null +++ b/lib/openflow/error_msg.ex @@ -0,0 +1,59 @@ +defmodule Openflow.ErrorMsg do + @moduledoc "OpenFlow Error codec module" + + defstruct( + version: 4, + xid: 0, + type: nil, + code: nil, + data: "", + exp_type: nil, + experimenter: nil, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 1 + + def read(<<0xFFFF::16, exp_type::16, experimenter::32, data::bytes>>) do + error_type = Openflow.Enums.to_atom(0xFFFF, :error_type) + + %ErrorMsg{ + type: error_type, + exp_type: exp_type, + experimenter: experimenter, + data: data + } + end + + def read(<>) do + error_type = Openflow.Enums.to_atom(type, :error_type) + error_code = Openflow.Enums.to_atom(code, error_type) + + %ErrorMsg{ + type: error_type, + code: error_code, + data: data + } + end + + def to_binary(%ErrorMsg{ + type: :experimenter, + exp_type: exp_type, + experimenter: experimenter, + data: data + }) do + error_type = Openflow.Enums.to_int(:experimenter, :error_type) + <> + end + + def to_binary(%ErrorMsg{type: type, code: code, data: data}) do + error_type = Openflow.Enums.to_int(type, :error_type) + error_code = Openflow.Enums.to_int(code, type) + <> + end +end diff --git a/lib/openflow/experimenter.ex b/lib/openflow/experimenter.ex new file mode 100644 index 0000000..52f1505 --- /dev/null +++ b/lib/openflow/experimenter.ex @@ -0,0 +1,44 @@ +defmodule Openflow.Experimenter do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + exp_id: 0, + exp_type: 0, + data: "" + ) + + alias __MODULE__ + + def ofp_type, do: 4 + + def new(options) do + %Experimenter{ + xid: options[:xid] || 0, + exp_id: Keyword.get(options, :exp_id, 0), + exp_type: Keyword.get(options, :exp_type, 0), + data: Keyword.get(options, :data, "") + } + end + + def to_binary(%Experimenter{exp_id: exp_id, exp_type: exp_type, data: data}) do + <> + end + + def read(<>) do + case Openflow.Utils.get_enum(exp_id, :experimenter_id) do + ^exp_id -> + %Experimenter{exp_id: exp_id, exp_type: exp_type, data: data} + + experimenter when is_atom(experimenter) -> + case Openflow.Utils.get_enum(exp_type, experimenter) do + ^exp_type -> + %Experimenter{exp_id: exp_id, exp_type: exp_type, data: data} + + codec when is_atom(codec) -> + codec.read(<>) + end + end + end +end diff --git a/lib/openflow/features.ex b/lib/openflow/features.ex new file mode 100644 index 0000000..43b26b8 --- /dev/null +++ b/lib/openflow/features.ex @@ -0,0 +1,2 @@ +defmodule Openflow.Features do +end diff --git a/lib/openflow/features/reply.ex b/lib/openflow/features/reply.ex new file mode 100644 index 0000000..e104ba8 --- /dev/null +++ b/lib/openflow/features/reply.ex @@ -0,0 +1,42 @@ +defmodule Openflow.Features.Reply do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + n_buffers: 0, + n_tables: 0, + aux_id: 0, + capabilities: [] + ) + + alias __MODULE__ + + def ofp_type, do: 6 + + def read( + <> + ) do + dpid = Openflow.Utils.to_hex_string(datapath_id) + flags = Openflow.Enums.int_to_flags(caps_int, :switch_capabilities) + + %Reply{ + datapath_id: dpid, + n_buffers: n_buf, + n_tables: n_tab, + aux_id: aux_id, + capabilities: flags + } + end + + def to_binary(%Reply{ + datapath_id: datapath_id, + n_buffers: n_buf, + n_tables: n_tab, + aux_id: aux_id, + capabilities: flags + }) do + dpid_int = String.to_integer(datapath_id, 16) + flags_int = Openflow.Enums.flags_to_int(flags, :switch_capabilities) + <> + end +end diff --git a/lib/openflow/features/request.ex b/lib/openflow/features/request.ex new file mode 100644 index 0000000..8fb5f4e --- /dev/null +++ b/lib/openflow/features/request.ex @@ -0,0 +1,26 @@ +defmodule Openflow.Features.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 5 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read(_) do + %Request{} + end + + def to_binary(%Request{}) do + <<>> + end +end diff --git a/lib/openflow/flow_mod.ex b/lib/openflow/flow_mod.ex new file mode 100644 index 0000000..4b3b541 --- /dev/null +++ b/lib/openflow/flow_mod.ex @@ -0,0 +1,122 @@ +defmodule Openflow.FlowMod do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + cookie: 0, + cookie_mask: 0, + table_id: 0, + command: :add, + idle_timeout: 0, + hard_timeout: 0, + priority: 0, + buffer_id: :no_buffer, + out_port: :any, + out_group: :any, + flags: [], + match: [], + instructions: [] + ) + + alias __MODULE__ + + def ofp_type, do: 14 + + def new(options \\ []) do + xid = Keyword.get(options, :xid, 0) + cookie = Keyword.get(options, :cookie, 0) + cookie_mask = Keyword.get(options, :cookie_mask, 0) + table_id = Keyword.get(options, :table_id, 0) + command = Keyword.get(options, :command, :add) + idle = Keyword.get(options, :idle_timeout, 0) + hard = Keyword.get(options, :hard_timeout, 0) + priority = Keyword.get(options, :priority, 0) + buffer_id = Keyword.get(options, :buffer_id, :no_buffer) + out_port = Keyword.get(options, :out_port, :any) + out_group = Keyword.get(options, :out_group, :any) + flags = Keyword.get(options, :flags, []) + match = Keyword.get(options, :match, Openflow.Match.new()) + instructions = Keyword.get(options, :instructions, []) + + %FlowMod{ + xid: xid, + cookie: cookie, + cookie_mask: cookie_mask, + priority: priority, + table_id: table_id, + command: command, + idle_timeout: idle, + hard_timeout: hard, + buffer_id: buffer_id, + out_port: out_port, + out_group: out_group, + flags: flags, + match: match, + instructions: instructions + } + end + + def read( + <> + ) do + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + command = Openflow.Utils.get_enum(command_int, :flow_mod_command) + buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id) + out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) + out_group = Openflow.Utils.get_enum(out_group_int, :group_id) + flags = Openflow.Enums.int_to_flags(flags_int, :flow_mod_flags) + {match_fields, instructions_bin} = Openflow.Match.read(rest) + match = Openflow.Match.new(match_fields) + instructions = Openflow.Instruction.read(instructions_bin) + + %FlowMod{ + cookie: cookie, + cookie_mask: cookie_mask, + priority: prio, + table_id: table_id, + command: command, + idle_timeout: idle, + hard_timeout: hard, + buffer_id: buffer_id, + out_port: out_port, + out_group: out_group, + flags: flags, + match: match, + instructions: instructions + } + end + + def to_binary(flow_mod) do + %FlowMod{ + cookie: cookie, + cookie_mask: cookie_mask, + priority: prio, + table_id: table_id, + command: command, + idle_timeout: idle, + hard_timeout: hard, + buffer_id: buffer_id, + out_port: out_port, + out_group: out_group, + flags: flags, + match: match_fields, + instructions: instructions + } = flow_mod + + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + command_int = Openflow.Utils.get_enum(command, :flow_mod_command) + buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id) + out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) + out_group_int = Openflow.Utils.get_enum(out_group, :group_id) + flags_int = Openflow.Enums.flags_to_int(flags, :flow_mod_flags) + match_fields_bin = Openflow.Match.to_binary(match_fields) + instructions_bin = Openflow.Instruction.to_binary(instructions) + + <> + end +end diff --git a/lib/openflow/flow_removed.ex b/lib/openflow/flow_removed.ex new file mode 100644 index 0000000..eea87d3 --- /dev/null +++ b/lib/openflow/flow_removed.ex @@ -0,0 +1,46 @@ +defmodule Openflow.FlowRemoved do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + cookie: 0, + priority: 0, + reason: :idle_timeout, + table_id: 0, + duration_sec: 0, + duration_nsec: 0, + idle_timeout: 0, + hard_timeout: 0, + packet_count: 0, + byte_count: 0, + match: [] + ) + + alias __MODULE__ + + def ofp_type, do: 11 + + def read( + <> + ) do + reason = Openflow.Enums.to_atom(reason_int, :flow_removed_reason) + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + {match_fields, _rest} = Openflow.Match.read(rest) + + %FlowRemoved{ + cookie: cookie, + priority: priority, + reason: reason, + table_id: table_id, + duration_sec: dsec, + duration_nsec: dnsec, + idle_timeout: idle, + hard_timeout: hard, + packet_count: pkt, + byte_count: byt, + match: match_fields + } + end +end diff --git a/lib/openflow/get_async/reply.ex b/lib/openflow/get_async/reply.ex new file mode 100644 index 0000000..2f2e1a7 --- /dev/null +++ b/lib/openflow/get_async/reply.ex @@ -0,0 +1,46 @@ +defmodule Openflow.GetAsync.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, + packet_in_mask_master: 0, + packet_in_mask_slave: 0, + port_status_mask_master: 0, + port_status_mask_slave: 0, + flow_removed_mask_master: 0, + flow_removed_mask_slave: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 27 + + def read( + <> + ) do + %Reply{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + port_status_mask_slave: port_status_mask_slave, + flow_removed_mask_master: flow_removed_mask_master, + flow_removed_mask_slave: flow_removed_mask_slave + } + end + + def to_binary(%Reply{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + port_status_mask_slave: port_status_mask_slave, + flow_removed_mask_master: flow_removed_mask_master, + flow_removed_mask_slave: flow_removed_mask_slave + }) do + <> + end +end diff --git a/lib/openflow/get_async/request.ex b/lib/openflow/get_async/request.ex new file mode 100644 index 0000000..0306095 --- /dev/null +++ b/lib/openflow/get_async/request.ex @@ -0,0 +1,26 @@ +defmodule Openflow.GetAsync.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 26 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read(_) do + %Request{} + end + + def to_binary(%Request{}) do + <<>> + end +end diff --git a/lib/openflow/get_config.ex b/lib/openflow/get_config.ex new file mode 100644 index 0000000..ceb38e2 --- /dev/null +++ b/lib/openflow/get_config.ex @@ -0,0 +1,2 @@ +defmodule Openflow.GetConfig do +end diff --git a/lib/openflow/get_config/reply.ex b/lib/openflow/get_config/reply.ex new file mode 100644 index 0000000..55f08ff --- /dev/null +++ b/lib/openflow/get_config/reply.ex @@ -0,0 +1,27 @@ +defmodule Openflow.GetConfig.Reply do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # default = "normal" is no special handling + flags: [], + miss_send_len: 128 + ) + + alias __MODULE__ + + def ofp_type, do: 8 + + def read(<>) do + flags = Openflow.Enums.int_to_flags(flags_int, :config_flags) + miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len) + %Reply{flags: flags, miss_send_len: miss_send_len} + end + + def to_binary(%Reply{flags: flags, miss_send_len: miss_send_len0}) do + flags_int = Openflow.Enums.flags_to_int(flags, :config_flags) + miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len) + <> + end +end diff --git a/lib/openflow/get_config/request.ex b/lib/openflow/get_config/request.ex new file mode 100644 index 0000000..f5ec984 --- /dev/null +++ b/lib/openflow/get_config/request.ex @@ -0,0 +1,26 @@ +defmodule Openflow.GetConfig.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 7 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read(_) do + %Request{} + end + + def to_binary(%Request{}) do + <<>> + end +end diff --git a/lib/openflow/group_mod.ex b/lib/openflow/group_mod.ex new file mode 100644 index 0000000..6f76684 --- /dev/null +++ b/lib/openflow/group_mod.ex @@ -0,0 +1,41 @@ +defmodule Openflow.GroupMod do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + command: :add, + type: :all, + group_id: 0, + buckets: [] + ) + + alias __MODULE__ + + def ofp_type, do: 15 + + def new(options \\ []) do + xid = Keyword.get(options, :xid, 0) + command = Keyword.get(options, :command, :add) + type = Keyword.get(options, :type, :all) + group_id = Keyword.get(options, :group_id, 0) + buckets = Keyword.get(options, :buckets, []) + %GroupMod{xid: xid, command: command, type: type, group_id: group_id, buckets: buckets} + end + + def read(<>) do + command = Openflow.Utils.get_enum(command_int, :group_mod_command) + type = Openflow.Utils.get_enum(type_int, :group_type) + group_id = Openflow.Utils.get_enum(group_id_int, :group_id) + buckets = Openflow.Bucket.read(buckets_bin) + %GroupMod{command: command, type: type, group_id: group_id, buckets: buckets} + end + + def to_binary(%GroupMod{command: command, type: type, group_id: group_id, buckets: buckets}) do + command_int = Openflow.Utils.get_enum(command, :group_mod_command) + type_int = Openflow.Utils.get_enum(type, :group_type) + group_id_int = Openflow.Utils.get_enum(group_id, :group_id) + buckets_bin = Openflow.Bucket.to_binary(buckets) + <> + end +end diff --git a/lib/openflow/hello.ex b/lib/openflow/hello.ex new file mode 100644 index 0000000..463e32e --- /dev/null +++ b/lib/openflow/hello.ex @@ -0,0 +1,106 @@ +defmodule Openflow.Hello do + @moduledoc "OpenFlow Hello codec module" + + import Bitwise + + @ofp_hello_size 4 + + defstruct(version: 4, xid: 0, elements: []) + + alias __MODULE__ + + def ofp_type, do: 0 + + def new(version) when is_integer(version) do + %Hello{elements: [versionbitmap: [version]]} + end + + def new(versions) when is_list(versions) do + %Hello{elements: [versionbitmap: versions]} + end + + def supported_version?(%Hello{version: 4, elements: []}), do: true + def supported_version?(%Hello{elements: []}), do: false + + def supported_version?(%Hello{elements: elements}) do + versionbitmaps = for {:versionbitmap, versions} <- elements, do: versions + Enum.any?(versionbitmaps, fn versions -> 4 in versions end) + end + + def read(binary), do: %Hello{elements: decode([], binary)} + + def to_binary(%Hello{elements: elements}), do: encode([], elements) + + # private functions + + defp decode(acc, <<>>), do: acc + + defp decode(acc, <>) do + data_len = length - @ofp_hello_size + <> = rest + + try do + typeint + |> Openflow.Enums.to_atom(:hello_elem) + |> decode_hello_elem(acc, data) + |> decode(rest2) + catch + :bad_enum -> + decode(acc, rest2) + end + end + + defp encode(acc, []), do: to_string(acc) + defp encode(acc, [h | rest]), do: encode([encode_hello_elem(h) | acc], rest) + + defp decode_hello_elem(:versionbitmap, acc, binary), + do: [{:versionbitmap, decode_bitmap([], binary, 0)} | acc] + + defp decode_hello_elem(_, acc, _binary), do: acc + + defp encode_hello_elem({:versionbitmap, versions}) do + bitmap_bin = encode_bitmap(versions) + type_int = Openflow.Enums.to_int(:versionbitmap, :hello_elem) + size_int = @ofp_hello_size + byte_size(bitmap_bin) + <> + end + + defp encode_hello_elem(_) do + <<>> + end + + defp decode_bitmap(acc, "", _), do: acc + + defp decode_bitmap(acc, <>, base) do + acc + |> decode_bitmap(int, 0, base) + |> decode_bitmap(rest, base + 32) + end + + defp encode_bitmap(list) do + size = + list + |> Enum.max() + |> div(32) + + encode_bitmap(0, list, size) + end + + defp decode_bitmap(acc, _, index, _) when index >= 32, do: acc + + defp decode_bitmap(acc, int, index, base) when (int &&& 1 <<< index) == 0, + do: decode_bitmap(acc, int, index + 1, base) + + defp decode_bitmap(acc, int, index, base), + do: decode_bitmap([base + index | acc], int, index + 1, base) + + defp encode_bitmap(acc, [], size) do + bytes = (size + 1) * 32 + <> + end + + defp encode_bitmap(acc, [h | rest], size) do + index = size - div(h, 32) * 32 + rem(h, 32) + encode_bitmap(acc ||| 1 <<< index, rest, size) + end +end diff --git a/lib/openflow/instruction.ex b/lib/openflow/instruction.ex new file mode 100644 index 0000000..b64b1c7 --- /dev/null +++ b/lib/openflow/instruction.ex @@ -0,0 +1,30 @@ +defmodule Openflow.Instruction do + def read(instruction_bin) do + do_read([], instruction_bin) + end + + def to_binary(instructions) when is_list(instructions) do + to_binary(<<>>, instructions) + end + + def to_binary(instruction) do + to_binary([instruction]) + end + + # private functions + + defp do_read(acc, <<>>), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + codec = Openflow.Enums.to_atom(type, :instruction_type) + do_read([codec.read(instruction_bin) | acc], rest) + end + + defp to_binary(acc, []), do: acc + + defp to_binary(acc, [instruction | rest]) do + codec = instruction.__struct__ + to_binary(<>, rest) + end +end diff --git a/lib/openflow/instructions/apply_actions.ex b/lib/openflow/instructions/apply_actions.ex new file mode 100644 index 0000000..b331419 --- /dev/null +++ b/lib/openflow/instructions/apply_actions.ex @@ -0,0 +1,20 @@ +defmodule Openflow.Instruction.ApplyActions do + defstruct(actions: []) + + alias __MODULE__ + + def new(actions) do + %ApplyActions{actions: actions} + end + + def to_binary(%ApplyActions{actions: actions}) do + actions_bin = Openflow.Action.to_binary(actions) + length = 8 + byte_size(actions_bin) + <<4::16, length::16, 0::size(4)-unit(8), actions_bin::bytes>> + end + + def read(<<4::16, _length::16, _::size(4)-unit(8), actions_bin::bytes>>) do + actions = Openflow.Action.read(actions_bin) + %ApplyActions{actions: actions} + end +end diff --git a/lib/openflow/instructions/clear_actions.ex b/lib/openflow/instructions/clear_actions.ex new file mode 100644 index 0000000..6d52c08 --- /dev/null +++ b/lib/openflow/instructions/clear_actions.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Instruction.ClearActions do + defstruct([]) + + alias __MODULE__ + + def new do + %ClearActions{} + end + + def to_binary(%ClearActions{}) do + actions_bin = "" + length = 8 + byte_size(actions_bin) + <<5::16, length::16, 0::size(4)-unit(8), actions_bin::bytes>> + end + + def read(<<5::16, _length::16, _::size(4)-unit(8), _::bytes>>) do + %ClearActions{} + end +end diff --git a/lib/openflow/instructions/experimenter.ex b/lib/openflow/instructions/experimenter.ex new file mode 100644 index 0000000..f4cc3f2 --- /dev/null +++ b/lib/openflow/instructions/experimenter.ex @@ -0,0 +1,18 @@ +defmodule Openflow.Instruction.Experimenter do + defstruct(exp_id: 0, data: "") + + alias __MODULE__ + + def new(exp_id, data \\ "") do + %Experimenter{exp_id: exp_id, data: data} + end + + def to_binary(%Experimenter{exp_id: exp_id, data: data}) do + length = 8 + byte_size(data) + <<0xFFFF::16, length::16, exp_id::32, data::bytes>> + end + + def read(<<0xFFFF::16, _::16, exp_id::32, data::bytes>>) do + %Experimenter{exp_id: exp_id, data: data} + end +end diff --git a/lib/openflow/instructions/goto_table.ex b/lib/openflow/instructions/goto_table.ex new file mode 100644 index 0000000..f78c2c9 --- /dev/null +++ b/lib/openflow/instructions/goto_table.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Instruction.GotoTable do + defstruct(table_id: 0) + + alias __MODULE__ + + def new(table_id) do + %GotoTable{table_id: table_id} + end + + def to_binary(%GotoTable{table_id: table_id}) do + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + <<1::16, 8::16, table_id_int::8, 0::size(3)-unit(8)>> + end + + def read(<<1::16, 8::16, table_id_int::8, _::size(3)-unit(8)>>) do + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + %GotoTable{table_id: table_id} + end +end diff --git a/lib/openflow/instructions/meter.ex b/lib/openflow/instructions/meter.ex new file mode 100644 index 0000000..f038fc9 --- /dev/null +++ b/lib/openflow/instructions/meter.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Instruction.Meter do + defstruct(meter_id: 0) + + alias __MODULE__ + + def new(meter_id) do + %Meter{meter_id: meter_id} + end + + def to_binary(%Meter{meter_id: meter_id}) do + meter_id_int = Openflow.Utils.get_enum(meter_id, :meter_id) + <<6::16, 8::16, meter_id_int::32>> + end + + def read(<<6::16, _::16, meter_id_int::32>>) do + meter_id = Openflow.Utils.get_enum(meter_id_int, :meter_id) + %Meter{meter_id: meter_id} + end +end diff --git a/lib/openflow/instructions/write_actions.ex b/lib/openflow/instructions/write_actions.ex new file mode 100644 index 0000000..fb9eeea --- /dev/null +++ b/lib/openflow/instructions/write_actions.ex @@ -0,0 +1,20 @@ +defmodule Openflow.Instruction.WriteActions do + defstruct(actions: []) + + alias __MODULE__ + + def new(actions) do + %WriteActions{actions: actions} + end + + def to_binary(%WriteActions{actions: actions}) do + actions_bin = Openflow.Action.to_binary(actions) + length = 8 + byte_size(actions_bin) + <<3::16, length::16, 0::size(4)-unit(8), actions_bin::bytes>> + end + + def read(<<3::16, _length::16, _::size(4)-unit(8), actions_bin::bytes>>) do + actions = Openflow.Action.read(actions_bin) + %WriteActions{actions: actions} + end +end diff --git a/lib/openflow/instructions/write_metadata.ex b/lib/openflow/instructions/write_metadata.ex new file mode 100644 index 0000000..5b0df98 --- /dev/null +++ b/lib/openflow/instructions/write_metadata.ex @@ -0,0 +1,19 @@ +defmodule Openflow.Instruction.WriteMetadata do + defstruct(metadata: 0, metadata_mask: 0xFFFFFFFFFFFFFFFF) + + alias __MODULE__ + + def new(options) do + metadata = Keyword.get(options, :metadata, 0) + metadata_mask = Keyword.get(options, :metadata_mask, 0xFFFFFFFFFFFFFFFF) + %WriteMetadata{metadata: metadata, metadata_mask: metadata_mask} + end + + def to_binary(%WriteMetadata{metadata: metadata, metadata_mask: metadata_mask}) do + <<2::16, 24::16, 0::size(4)-unit(8), metadata::64, metadata_mask::64>> + end + + def read(<<2::16, 24::16, _::size(4)-unit(8), metadata::64, metadata_mask::64>>) do + %WriteMetadata{metadata: metadata, metadata_mask: metadata_mask} + end +end diff --git a/lib/openflow/match.ex b/lib/openflow/match.ex new file mode 100644 index 0000000..3cbf258 --- /dev/null +++ b/lib/openflow/match.ex @@ -0,0 +1,238 @@ +defmodule Openflow.Match do + @match_size 8 + @header_size 4 + + defstruct( + type: :oxm, + fields: [] + ) + + alias __MODULE__ + + def new(fields \\ []) do + oxm_fields = + fields + |> keyword_to_oxm_fields([]) + + %Match{type: :oxm, fields: oxm_fields} + end + + def read(binary) do + <<1::16, no_pad_len::16, binary1::binary>> = binary + padding_length = Openflow.Utils.pad_length(no_pad_len, 8) + match_field_len = no_pad_len - @header_size + + <> = binary1 + + {decode_fields(match_fields, []), rest} + end + + def to_binary(%Match{fields: fields}) do + fields_bin = encode_fields(fields, <<>>) + length = byte_size(fields_bin) + @match_size - @header_size + type_int = Openflow.Enums.to_int(:oxm, :match_type) + padding = Openflow.Utils.padding(length, 8) + <> + end + + def codec_header(oxm_field0) when is_atom(oxm_field0) do + oxm_field = + case has_mask(oxm_field0) do + 1 -> + string = to_string(oxm_field0) + "masked_" <> field = string + String.to_atom(field) + + 0 -> + oxm_field0 + end + + case Openflow.Match.Field.vendor_of(oxm_field) do + oxm_class when oxm_class in [:nxm_0, :nxm_1, :openflow_basic, :packet_register] -> + oxm_class_int = Openflow.Enums.to_int(oxm_class, :oxm_class) + oxm_field_int = Openflow.Enums.to_int(oxm_field, oxm_class) + oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field), 8) + has_mask = has_mask(oxm_field0) + <> + + experimenter when experimenter in [:nicira_ext_match, :onf_ext_match, :hp_ext_match] -> + oxm_class_int = 0xFFFF + experimenter_int = Openflow.Enums.to_int(experimenter, :experimenter_oxm_vendors) + oxm_field_int = Openflow.Enums.to_int(oxm_field, experimenter) + oxm_length = div(Openflow.Match.Field.n_bits_of(oxm_field) + 4, 8) + has_mask = has_mask(oxm_field0) + <> + end + end + + def codec_header(<>) do + oxm_class = Openflow.Enums.to_atom(oxm_class_int, :oxm_class) + + case oxm_has_mask do + 0 -> + Openflow.Enums.to_atom(oxm_field_int, oxm_class) + + 1 -> + field_str = + oxm_field_int + |> Openflow.Enums.to_atom(oxm_class) + |> to_string + + String.to_atom("masked_" <> field_str) + end + end + + def codec_header( + <<0xFFFF::16, oxm_field_int::7, oxm_has_mask::1, _oxm_length::8, experimenter_int::32>> + ) do + experimenter = Openflow.Enums.to_atom(experimenter_int, :experimenter_oxm_vendors) + Openflow.Enums.to_atom(oxm_field_int, experimenter) + + case oxm_has_mask do + 0 -> + Openflow.Enums.to_atom(oxm_field_int, experimenter) + + 1 -> + field_str = + oxm_field_int + |> Openflow.Enums.to_atom(experimenter) + |> to_string + + String.to_atom("masked_" <> field_str) + end + end + + def header_size( + <<_oxm_class_int::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _::bytes>> + ), + do: 4 + + def header_size( + <<0xFFFF::16, _oxm_field_int::7, _oxm_has_mask::1, _oxm_length::8, _exp_int::32, + _::bytes>> + ), + do: 8 + + # private functions + + defp decode_fields(<<>>, acc), do: Enum.reverse(acc) + + defp decode_fields( + <<0xFFFF::16, _::7, 1::1, length::8, vendor_int::32, field_int::16, binary::bytes>>, + acc + ) do + length = length - 6 + field_len = div(length, 2) + <> = binary + experimenter = Openflow.Enums.to_atom(vendor_int, :experimenter_oxm_vendors) + field_name = Openflow.Enums.to_atom(field_int, experimenter) + value = Openflow.Match.Field.codec(value_bin, field_name) + mask = Openflow.Match.Field.codec(mask_bin, field_name) + decode_fields(rest, [{field_name, {value, mask}} | acc]) + end + + defp decode_fields( + <<0xFFFF::16, _::7, 0::1, length::8, vendor_int::32, field_int::16, binary::bytes>>, + acc + ) do + length = length - 6 + <> = binary + experimenter = Openflow.Enums.to_atom(vendor_int, :experimenter_oxm_vendors) + field_name = Openflow.Enums.to_atom(field_int, experimenter) + value = Openflow.Match.Field.codec(value_bin, field_name) + decode_fields(rest, [{field_name, value} | acc]) + end + + defp decode_fields(<>, acc) do + field_len = div(length, 2) + <> = binary + class = Openflow.Enums.to_atom(class_int, :oxm_class) + field_name = Openflow.Enums.to_atom(field_int, class) + value = Openflow.Match.Field.codec(value_bin, field_name) + mask = Openflow.Match.Field.codec(mask_bin, field_name) + decode_fields(rest, [{field_name, {value, mask}} | acc]) + end + + defp decode_fields(<>, acc) do + <> = binary + class = Openflow.Enums.to_atom(class_int, :oxm_class) + field_name = Openflow.Enums.to_atom(field_int, class) + value = Openflow.Match.Field.codec(value_bin, field_name) + decode_fields(rest, [{field_name, value} | acc]) + end + + defp encode_fields([], acc), do: acc + + defp encode_fields([field | fields], acc) do + encode_fields(fields, <>) + end + + defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask}) + when class == :nicira_ext_match or class == :onf_ext_match do + vendor_int = Openflow.Enums.to_int(class, :experimenter_oxm_vendors) + field_int = Openflow.Enums.to_int(field, class) + has_mask_int = 1 + length = byte_size(value) * 2 + 6 + + <<0xFFFF::16, 0::7, has_mask_int::1, length::8, vendor_int::32, field_int::16, value::bytes, + mask::bytes>> + end + + defp encode_field(%{class: class, field: field, has_mask: false, value: value}) + when class == :nicira_ext_match or class == :onf_ext_match do + vendor_int = Openflow.Enums.to_int(class, :experimenter_oxm_vendors) + field_int = Openflow.Enums.to_int(field, class) + has_mask_int = 0 + length = byte_size(value) + 6 + <<0xFFFF::16, 0::7, has_mask_int::1, length::8, vendor_int::32, field_int::16, value::bytes>> + end + + defp encode_field(%{class: class, field: field, has_mask: true, value: value, mask: mask}) do + class_int = Openflow.Enums.to_int(class, :oxm_class) + field_int = Openflow.Enums.to_int(field, class) + has_mask_int = 1 + length = byte_size(value) * 2 + <> + end + + defp encode_field(%{class: class, field: field, has_mask: false, value: value}) do + class_int = Openflow.Enums.to_int(class, :oxm_class) + field_int = Openflow.Enums.to_int(field, class) + has_mask_int = 0 + length = byte_size(value) + <> + end + + defp keyword_to_oxm_fields([], acc), do: Enum.reverse(acc) + + defp keyword_to_oxm_fields([{field_name, field_value} | fields], acc) do + keyword_to_oxm_fields(fields, [oxm_field(field_name, field_value) | acc]) + end + + defp oxm_field(field_name, {value, mask}) do + value_bin = Openflow.Match.Field.codec(value, field_name) + mask_bin = Openflow.Match.Field.codec(mask, field_name) + match_class = Openflow.Match.Field.vendor_of(field_name) + %{class: match_class, field: field_name, has_mask: true, value: value_bin, mask: mask_bin} + end + + defp oxm_field(field_name, value) do + value_bin = Openflow.Match.Field.codec(value, field_name) + match_class = Openflow.Match.Field.vendor_of(field_name) + %{class: match_class, field: field_name, has_mask: false, value: value_bin} + end + + def has_mask(oxm_field) when is_atom(oxm_field) do + has_mask? = + oxm_field + |> to_string + |> String.match?(~r/^masked_/) + + if has_mask? do + 1 + else + 0 + end + end +end diff --git a/lib/openflow/match/field.ex b/lib/openflow/match/field.ex new file mode 100644 index 0000000..3cabbd4 --- /dev/null +++ b/lib/openflow/match/field.ex @@ -0,0 +1,673 @@ +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(<>, :u8, :decimal), do: value + def formatting(value, :u8, :decimal) when is_integer(value), do: <> + def formatting(<>, :be16, :decimal), do: value + def formatting(value, :be16, :decimal) when is_integer(value), do: <> + def formatting(<>, :u24, :decimal), do: value + def formatting(value, :u24, :decimal) when is_integer(value), do: <> + def formatting(<>, :be32, :decimal), do: value + def formatting(value, :be32, :decimal) when is_integer(value), do: <> + def formatting(<>, :be64, :decimal), do: value + def formatting(value, :be64, :decimal) when is_integer(value), do: <> + def formatting(<>, :be128, :decimal), do: value + def formatting(value, :be128, :decimal) when is_integer(value), do: <> + + # Formatting = hexadecimal + def formatting(<>, :be16, :hexadecimal), do: value + def formatting(value, :be16, :hexadecimal) when is_integer(value), do: <> + + def formatting(<>, :u24, :hexadecimal), do: value + def formatting(value, :u24, :hexadecimal) when is_integer(value), do: <> + + def formatting(<>, :be32, :hexadecimal), do: value + def formatting(value, :be32, :hexadecimal) when is_integer(value), do: <> + + def formatting(<>, :be64, :hexadecimal), do: value + def formatting(value, :be64, :hexadecimal) when is_integer(value), do: <> + + def formatting(<>, :be128, :hexadecimal), do: value + def formatting(value, :be128, :hexadecimal) when is_integer(value), do: <> + + # Formatting = ethernet + def formatting(<>, :mac, :ethernet), do: Openflow.Utils.to_hex_string(value) + def formatting(value, :mac, :ethernet), do: <> + + # Formatting = IPv4 + def formatting(<>, :be32, :ipv4), do: {a1, a2, a3, a4} + def formatting({a1, a2, a3, a4}, :be32, :ipv4), do: <> + + # Formatting = IPv6 + def formatting( + <>, + :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 + <> + end + + # Formatting = OpenFlow 1.0 port + def formatting(<>, :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 + + <> + end + + # Formatting = OpenFlow 1.3 port + def formatting(<>, :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 + + <> + end + + # TCP flags + def formatting(<>, :be16, :tcp_flags) do + Openflow.Enums.int_to_flags(value, :tcp_flags) + end + + def formatting(value, :be16, :tcp_flags) do + <> + end + + # CT State + def formatting(<>, :be32, :ct_state) do + Openflow.Enums.int_to_flags(value, :ct_state_flags) + end + + def formatting(value, :be32, :ct_state) do + <> + end + + # CT State + def formatting(<>, :be16, :ipv6exthdr_flags) do + Openflow.Enums.int_to_flags(value, :ipv6exthdr_flags) + end + + def formatting(value, :be16, :ipv6exthdr_flags) do + <> + end + + # Other + def formatting(value, _, _) do + value + end +end diff --git a/lib/openflow/meter_band.ex b/lib/openflow/meter_band.ex new file mode 100644 index 0000000..ab8a8b8 --- /dev/null +++ b/lib/openflow/meter_band.ex @@ -0,0 +1,30 @@ +defmodule Openflow.MeterBand do + def read(meter_band_bin) do + do_read([], meter_band_bin) + end + + def to_binary(meter_bands) when is_list(meter_bands) do + to_binary(<<>>, meter_bands) + end + + def to_binary(meter_band) do + to_binary([meter_band]) + end + + # private functions + + defp do_read(acc, <<>>), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + codec = Openflow.Enums.to_atom(type, :meter_band_type) + do_read([codec.read(meter_band_bin) | acc], rest) + end + + defp to_binary(acc, []), do: acc + + defp to_binary(acc, [meter_band | rest]) do + codec = meter_band.__struct__ + to_binary(<>, rest) + end +end diff --git a/lib/openflow/meter_band/drop.ex b/lib/openflow/meter_band/drop.ex new file mode 100644 index 0000000..bacd01d --- /dev/null +++ b/lib/openflow/meter_band/drop.ex @@ -0,0 +1,22 @@ +defmodule Openflow.MeterBand.Drop do + defstruct( + rate: 0, + burst_size: 0 + ) + + alias __MODULE__ + + def new(options) do + rate = Keyword.get(options, :rate, 0) + burst_size = Keyword.get(options, :burst_size, 0) + %Drop{rate: rate, burst_size: burst_size} + end + + def read(<<1::16, 16::16, rate::32, burst_size::32, _::size(4)-unit(8)>>) do + %Drop{rate: rate, burst_size: burst_size} + end + + def to_binary(%Drop{rate: rate, burst_size: burst_size}) do + <<1::16, 16::16, rate::32, burst_size::32, 0::size(4)-unit(8)>> + end +end diff --git a/lib/openflow/meter_band/experimenter.ex b/lib/openflow/meter_band/experimenter.ex new file mode 100644 index 0000000..1fab8e6 --- /dev/null +++ b/lib/openflow/meter_band/experimenter.ex @@ -0,0 +1,24 @@ +defmodule Openflow.MeterBand.Experimenter do + defstruct( + rate: 0, + burst_size: 0, + experimenter: 0 + ) + + alias __MODULE__ + + def new(options) do + rate = Keyword.get(options, :rate, 0) + burst_size = Keyword.get(options, :burst_size, 0) + experimenter = Keyword.get(options, :experimenter, 0) + %Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter} + end + + def read(<<0xFFFF::16, _::16, rate::32, burst_size::32, experimenter::32>>) do + %Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter} + end + + def to_binary(%Experimenter{rate: rate, burst_size: burst_size, experimenter: experimenter}) do + <<0xFFFF::16, 16::16, rate::32, burst_size::32, experimenter::32>> + end +end diff --git a/lib/openflow/meter_band/remark.ex b/lib/openflow/meter_band/remark.ex new file mode 100644 index 0000000..1bb3f93 --- /dev/null +++ b/lib/openflow/meter_band/remark.ex @@ -0,0 +1,24 @@ +defmodule Openflow.MeterBand.Remark do + defstruct( + rate: 0, + burst_size: 0, + prec_level: 0 + ) + + alias __MODULE__ + + def new(options) do + rate = Keyword.get(options, :rate, 0) + burst_size = Keyword.get(options, :burst_size, 0) + prec_level = Keyword.get(options, :prec_level, 0) + %Remark{rate: rate, burst_size: burst_size, prec_level: prec_level} + end + + def read(<<2::16, 16::16, rate::32, burst_size::32, prec_level::8, _::size(3)-unit(8)>>) do + %Remark{rate: rate, burst_size: burst_size, prec_level: prec_level} + end + + def to_binary(%Remark{rate: rate, burst_size: burst_size, prec_level: prec_level}) do + <<2::16, 16::16, rate::32, burst_size::32, prec_level::8, 0::size(3)-unit(8)>> + end +end diff --git a/lib/openflow/meter_mod.ex b/lib/openflow/meter_mod.ex new file mode 100644 index 0000000..05e47b3 --- /dev/null +++ b/lib/openflow/meter_mod.ex @@ -0,0 +1,32 @@ +defmodule Openflow.MeterMod do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + command: :add, + flags: [], + meter_id: 0, + bands: [] + ) + + alias __MODULE__ + + def ofp_type, do: 29 + + def read(<>) do + command = Openflow.Enums.to_atom(command_int, :meter_mod_command) + flags = Openflow.Enums.int_to_flags(flags_int, :meter_flags) + meter_id = Openflow.Utils.get_enum(meter_id_int, :meter_id) + bands = Openflow.MeterBand.read(bands_bin) + %MeterMod{command: command, flags: flags, meter_id: meter_id, bands: bands} + end + + def to_binary(%MeterMod{command: command, flags: flags, meter_id: meter_id, bands: bands}) do + command_int = Openflow.Enums.to_int(command, :meter_mod_command) + flags_int = Openflow.Enums.flags_to_int(flags, :meter_flags) + meter_id_int = Openflow.Utils.get_enum(meter_id, :meter_id) + bands_bin = Openflow.MeterBand.to_binary(bands) + <> + end +end diff --git a/lib/openflow/multipart/aggregate/reply.ex b/lib/openflow/multipart/aggregate/reply.ex new file mode 100644 index 0000000..7b710c2 --- /dev/null +++ b/lib/openflow/multipart/aggregate/reply.ex @@ -0,0 +1,21 @@ +defmodule Openflow.Multipart.Aggregate.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + packet_count: 0, + byte_count: 0, + flow_count: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def read(<>) do + %Reply{packet_count: packet_count, byte_count: byte_count, flow_count: flow_count} + end +end diff --git a/lib/openflow/multipart/aggregate/request.ex b/lib/openflow/multipart/aggregate/request.ex new file mode 100644 index 0000000..0335cb9 --- /dev/null +++ b/lib/openflow/multipart/aggregate/request.ex @@ -0,0 +1,81 @@ +defmodule Openflow.Multipart.Aggregate.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + table_id: :all, + out_port: :any, + out_group: :any, + cookie: 0, + cookie_mask: 0, + match: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(options) do + xid = Keyword.get(options, :xid, 0) + table_id = Keyword.get(options, :table_id, :all) + out_port = Keyword.get(options, :out_port, :any) + out_group = Keyword.get(options, :out_group, :any) + cookie = Keyword.get(options, :cookie, 0) + cookie_mask = Keyword.get(options, :cookie, 0) + match = Keyword.get(options, :match, []) + + %Request{ + xid: xid, + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } + end + + def read( + <> + ) do + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) + out_group = Openflow.Utils.get_enum(out_group_int, :group_id) + {match, _rest} = Openflow.Match.read(match_bin) + + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } + end + + def to_binary( + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } = msg + ) do + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) + out_group_int = Openflow.Utils.get_enum(out_group, :group_id) + match_bin = Openflow.Match.to_binary(match) + + body_bin = + <> + + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/desc/reply.ex b/lib/openflow/multipart/desc/reply.ex new file mode 100644 index 0000000..a995cf2 --- /dev/null +++ b/lib/openflow/multipart/desc/reply.ex @@ -0,0 +1,36 @@ +defmodule Openflow.Multipart.Desc.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + mfr_desc: "", + hw_desc: "", + sw_desc: "", + serial_num: "", + dp_desc: "" + ) + + alias __MODULE__ + + @desc_str_len 256 + @serial_num_len 32 + + def ofp_type, do: 19 + + def read( + <> + ) do + %Reply{ + mfr_desc: Openflow.Utils.decode_string(mfr_desc), + hw_desc: Openflow.Utils.decode_string(hw_desc), + sw_desc: Openflow.Utils.decode_string(sw_desc), + serial_num: Openflow.Utils.decode_string(serial_num), + dp_desc: Openflow.Utils.decode_string(dp_desc) + } + end +end diff --git a/lib/openflow/multipart/desc/request.ex b/lib/openflow/multipart/desc/request.ex new file mode 100644 index 0000000..f0b17c5 --- /dev/null +++ b/lib/openflow/multipart/desc/request.ex @@ -0,0 +1,25 @@ +defmodule Openflow.Multipart.Desc.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read("") do + %Request{} + end + + def to_binary(%Request{} = msg) do + Openflow.Multipart.Request.header(msg) + end +end diff --git a/lib/openflow/multipart/flow/reply.ex b/lib/openflow/multipart/flow/reply.ex new file mode 100644 index 0000000..135a222 --- /dev/null +++ b/lib/openflow/multipart/flow/reply.ex @@ -0,0 +1,95 @@ +defmodule Openflow.Multipart.Flow.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + flows: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(flows \\ []) do + %Reply{flows: flows} + end + + def read(<>) do + flows = Openflow.Multipart.FlowStats.read(flows_bin) + %Reply{flows: flows} + end + + def append_body(%Reply{flows: flows} = message, %Reply{flags: [:more], flows: continue}) do + %{message | flows: [continue | flows]} + end + + def append_body(%Reply{flows: flows} = message, %Reply{flags: [], flows: continue}) do + new_flows = + [continue | flows] + |> Enum.reverse() + |> List.flatten() + + %{message | flows: new_flows} + end +end + +defmodule Openflow.Multipart.FlowStats do + defstruct( + table_id: 0, + duration_sec: 0, + duration_nsec: 0, + priority: 0, + idle_timeout: 0, + hard_timeout: 0, + flags: 0, + cookie: 0, + packet_count: 0, + byte_count: 0, + match: [], + instructions: [] + ) + + alias __MODULE__ + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + do_read([codec(flow_stats_bin) | acc], rest) + end + + defp codec( + <<_length::16, table_id_int::8, 0::8, duration_sec::32, duration_nsec::32, priority::16, + idle::16, hard::16, flags_int::16, _::size(4)-unit(8), cookie::64, packet_count::64, + byte_count::64, tail::bytes>> + ) do + {match, instructions_bin} = Openflow.Match.read(tail) + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + flags = Openflow.Enums.int_to_flags(flags_int, :flow_mod_flags) + instructions = Openflow.Instruction.read(instructions_bin) + + %FlowStats{ + table_id: table_id, + duration_sec: duration_sec, + duration_nsec: duration_nsec, + priority: priority, + idle_timeout: idle, + hard_timeout: hard, + flags: flags, + cookie: cookie, + packet_count: packet_count, + byte_count: byte_count, + match: match, + instructions: instructions + } + end +end diff --git a/lib/openflow/multipart/flow/request.ex b/lib/openflow/multipart/flow/request.ex new file mode 100644 index 0000000..c3b37b6 --- /dev/null +++ b/lib/openflow/multipart/flow/request.ex @@ -0,0 +1,81 @@ +defmodule Openflow.Multipart.Flow.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + table_id: :all, + out_port: :any, + out_group: :any, + cookie: 0, + cookie_mask: 0, + match: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(options \\ []) do + xid = Keyword.get(options, :xid, 0) + table_id = Keyword.get(options, :table_id, :all) + out_port = Keyword.get(options, :out_port, :any) + out_group = Keyword.get(options, :out_group, :any) + cookie = Keyword.get(options, :cookie, 0) + cookie_mask = Keyword.get(options, :cookie, 0) + match = Keyword.get(options, :match, Openflow.Match.new()) + + %Request{ + xid: xid, + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } + end + + def read( + <> + ) do + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + out_port = Openflow.Utils.get_enum(out_port_int, :openflow13_port_no) + out_group = Openflow.Utils.get_enum(out_group_int, :group_id) + {match, _rest} = Openflow.Match.read(match_bin) + + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } + end + + def to_binary( + %Request{ + table_id: table_id, + out_port: out_port, + out_group: out_group, + cookie: cookie, + cookie_mask: cookie_mask, + match: match + } = msg + ) do + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + out_port_int = Openflow.Utils.get_enum(out_port, :openflow13_port_no) + out_group_int = Openflow.Utils.get_enum(out_group, :group_id) + match_bin = Openflow.Match.to_binary(match) + + body_bin = + <> + + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/group/reply.ex b/lib/openflow/multipart/group/reply.ex new file mode 100644 index 0000000..5e4b86f --- /dev/null +++ b/lib/openflow/multipart/group/reply.ex @@ -0,0 +1,89 @@ +defmodule Openflow.Multipart.Group.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + groups: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(groups \\ []) do + %Reply{groups: groups} + end + + def read(<>) do + groups = Openflow.Multipart.Group.read(groups_bin) + %Reply{groups: groups} + end + + def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do + %{message | groups: [continue | groups]} + end + + def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do + new_groups = + [continue | groups] + |> Enum.reverse() + |> List.flatten() + + %{message | groups: new_groups} + end +end + +defmodule Openflow.Multipart.Group do + defstruct( + group_id: 0, + ref_count: 0, + packet_count: 0, + byte_count: 0, + duration_sec: 0, + duration_nsec: 0, + bucket_stats: [] + ) + + @ofp_group_stats_size 40 + + alias __MODULE__ + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + do_read([codec(group_bin) | acc], rest) + end + + defp codec( + <> + ) do + bucket_stats_size = length - @ofp_group_stats_size + <> = tail + + bucket_stats = + for <> do + %{packet_count: packet_count, byte_count: byte_count} + end + + %Group{ + group_id: group_id, + ref_count: ref_count, + packet_count: packet_count, + byte_count: byte_count, + duration_sec: duration_sec, + duration_nsec: duration_nsec, + bucket_stats: bucket_stats + } + end +end diff --git a/lib/openflow/multipart/group/request.ex b/lib/openflow/multipart/group/request.ex new file mode 100644 index 0000000..30103d8 --- /dev/null +++ b/lib/openflow/multipart/group/request.ex @@ -0,0 +1,37 @@ +defmodule Openflow.Multipart.Group.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + group_id: :all + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(options) when is_list(options) do + %Request{ + xid: options[:xid] || 0, + group_id: options[:group_id] || :all + } + end + + def new(group_id) when is_integer(group_id) or is_atom(group_id) do + %Request{group_id: group_id} + end + + def read(<>) do + group_id = Openflow.Utils.get_enum(group_id_int, :group_id) + %Request{group_id: group_id} + end + + def to_binary(%Request{group_id: group_id} = msg) do + group_id_int = Openflow.Utils.get_enum(group_id, :group_id) + body_bin = <> + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/group_desc/reply.ex b/lib/openflow/multipart/group_desc/reply.ex new file mode 100644 index 0000000..8e8d424 --- /dev/null +++ b/lib/openflow/multipart/group_desc/reply.ex @@ -0,0 +1,69 @@ +defmodule Openflow.Multipart.GroupDesc.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + groups: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(groups \\ []) do + %Reply{groups: groups} + end + + def read(<>) do + groups = Openflow.Multipart.GroupDescStats.read(groups_bin) + %Reply{groups: groups} + end + + def append_body(%Reply{groups: groups} = message, %Reply{flags: [:more], groups: continue}) do + %{message | groups: [continue | groups]} + end + + def append_body(%Reply{groups: groups} = message, %Reply{flags: [], groups: continue}) do + new_groups = + [continue | groups] + |> Enum.reverse() + |> List.flatten() + + %{message | groups: new_groups} + end +end + +defmodule Openflow.Multipart.GroupDescStats do + defstruct( + type: :all, + group_id: 0, + buckets: [] + ) + + alias __MODULE__ + + @ofp_group_desc_size 8 + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + do_read([codec(group_stats_bin) | acc], rest) + end + + defp codec(<>) do + buckets_bin_len = length - @ofp_group_desc_size + <> = tail + type = Openflow.Enums.to_atom(type_int, :group_type) + buckets = Openflow.Bucket.read(buckets_bin) + %GroupDescStats{type: type, group_id: group_id, buckets: buckets} + end +end diff --git a/lib/openflow/multipart/group_desc/request.ex b/lib/openflow/multipart/group_desc/request.ex new file mode 100644 index 0000000..c8c3dae --- /dev/null +++ b/lib/openflow/multipart/group_desc/request.ex @@ -0,0 +1,25 @@ +defmodule Openflow.Multipart.GroupDesc.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read("") do + %Request{} + end + + def to_binary(%Request{} = msg) do + Openflow.Multipart.Request.header(msg) + end +end diff --git a/lib/openflow/multipart/group_features/reply.ex b/lib/openflow/multipart/group_features/reply.ex new file mode 100644 index 0000000..a43667b --- /dev/null +++ b/lib/openflow/multipart/group_features/reply.ex @@ -0,0 +1,47 @@ +defmodule Openflow.Multipart.GroupFeatures.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + types: 0, + capabilities: [], + max_groups_for_all: 0, + max_groups_for_select: 0, + max_groups_for_indirect: 0, + max_groups_for_fast_failover: 0, + actions_for_all: 0, + actions_for_select: 0, + actions_for_indirect: 0, + actions_for_fast_failover: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def read( + <> + ) do + capabilities = Openflow.Enums.int_to_flags(capabilities_int, :group_capabilities) + + %Reply{ + types: types_int, + capabilities: capabilities, + max_groups_for_all: max_groups_for_all_int, + max_groups_for_select: max_groups_for_select_int, + max_groups_for_indirect: max_groups_for_indirect_int, + max_groups_for_fast_failover: max_groups_for_fast_failover_int, + actions_for_all: actions_for_all_int, + actions_for_select: actions_for_select_int, + actions_for_indirect: actions_for_indirect_int, + actions_for_fast_failover: actions_for_fast_failover_int + } + end +end diff --git a/lib/openflow/multipart/group_features/request.ex b/lib/openflow/multipart/group_features/request.ex new file mode 100644 index 0000000..e473878 --- /dev/null +++ b/lib/openflow/multipart/group_features/request.ex @@ -0,0 +1,25 @@ +defmodule Openflow.Multipart.GroupFeatures.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read("") do + %Request{} + end + + def to_binary(%Request{} = msg) do + Openflow.Multipart.Request.header(msg) + end +end diff --git a/lib/openflow/multipart/meter/reply.ex b/lib/openflow/multipart/meter/reply.ex new file mode 100644 index 0000000..7fe9656 --- /dev/null +++ b/lib/openflow/multipart/meter/reply.ex @@ -0,0 +1,85 @@ +defmodule Openflow.Multipart.Meter.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + meters: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def read(<>) do + meters = Openflow.Multipart.Meter.read(meters_bin) + %Reply{meters: meters} + end + + def append_body(%Reply{meters: meters} = message, %Reply{flags: [:more], meters: continue}) do + %{message | meters: [continue | meters]} + end + + def append_body(%Reply{meters: meters} = message, %Reply{flags: [], meters: continue}) do + new_meters = + [continue | meters] + |> Enum.reverse() + |> List.flatten() + + %{message | meters: new_meters} + end +end + +defmodule Openflow.Multipart.Meter do + defstruct( + meter_id: 0, + flow_count: 0, + packet_in_count: 0, + byte_in_count: 0, + duration_sec: 0, + duration_nsec: 0, + band_stats: [] + ) + + @ofp_meter_stats_size 40 + + alias __MODULE__ + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <<_::32, length::16, _binary::bytes>> = binary) do + <> = binary + do_read([codec(meter_bin) | acc], rest) + end + + defp codec( + <> + ) do + band_stats_size = length - @ofp_meter_stats_size + <> = tail + + band_stats = + for <> do + %{packet_band_count: packet_band_count, byte_band_count: byte_band_count} + end + + %Meter{ + meter_id: meter_id, + flow_count: flow_count, + packet_in_count: packet_in_count, + byte_in_count: byte_in_count, + duration_sec: duration_sec, + duration_nsec: duration_nsec, + band_stats: band_stats + } + end +end diff --git a/lib/openflow/multipart/meter/request.ex b/lib/openflow/multipart/meter/request.ex new file mode 100644 index 0000000..ea7bbdf --- /dev/null +++ b/lib/openflow/multipart/meter/request.ex @@ -0,0 +1,37 @@ +defmodule Openflow.Multipart.Meter.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + meter_id: :all + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(meter_id) when is_integer(meter_id) or is_atom(meter_id) do + %Request{meter_id: meter_id} + end + + def new(options) when is_list(options) do + %Request{ + xid: options[:xid] || 0, + meter_id: options[:meter_id] || :all + } + end + + def read(<>) do + meter_id = Openflow.Utils.get_enum(meter_id_int, :meter_id) + %Request{meter_id: meter_id} + end + + def to_binary(%Request{meter_id: meter_id} = msg) do + meter_id_int = Openflow.Utils.get_enum(meter_id, :meter_id) + body_bin = <> + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/meter_config/request.ex b/lib/openflow/multipart/meter_config/request.ex new file mode 100644 index 0000000..bd4c7a2 --- /dev/null +++ b/lib/openflow/multipart/meter_config/request.ex @@ -0,0 +1,37 @@ +defmodule Openflow.Multipart.MeterConfig.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + meter_id: :all + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(meter_id) when is_integer(meter_id) or is_atom(meter_id) do + %Request{meter_id: meter_id} + end + + def new(options) when is_list(options) do + %Request{ + xid: options[:xid] || 0, + meter_id: options[:meter_id] || :all + } + end + + def read(<>) do + meter_id = Openflow.Utils.get_enum(meter_id_int, :meter_id) + %Request{meter_id: meter_id} + end + + def to_binary(%Request{meter_id: meter_id} = msg) do + meter_id_int = Openflow.Utils.get_enum(meter_id, :meter_id) + body_bin = <> + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/port_desc/reply.ex b/lib/openflow/multipart/port_desc/reply.ex new file mode 100644 index 0000000..6025dab --- /dev/null +++ b/lib/openflow/multipart/port_desc/reply.ex @@ -0,0 +1,37 @@ +defmodule Openflow.Multipart.PortDesc.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + ports: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(ports \\ []) do + %Reply{ports: ports} + end + + def read(<>) do + ports = for <>, do: Openflow.Port.read(port_bin) + %Reply{ports: Enum.reverse(ports)} + end + + def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do + %{message | ports: [continue | ports]} + end + + def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do + new_ports = + [continue | ports] + |> Enum.reverse() + |> List.flatten() + + %{message | ports: new_ports} + end +end diff --git a/lib/openflow/multipart/port_desc/request.ex b/lib/openflow/multipart/port_desc/request.ex new file mode 100644 index 0000000..2a029f3 --- /dev/null +++ b/lib/openflow/multipart/port_desc/request.ex @@ -0,0 +1,25 @@ +defmodule Openflow.Multipart.PortDesc.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read("") do + %Request{} + end + + def to_binary(%Request{} = msg) do + Openflow.Multipart.Request.header(msg) + end +end diff --git a/lib/openflow/multipart/port_stats/reply.ex b/lib/openflow/multipart/port_stats/reply.ex new file mode 100644 index 0000000..880c639 --- /dev/null +++ b/lib/openflow/multipart/port_stats/reply.ex @@ -0,0 +1,96 @@ +defmodule Openflow.Multipart.PortStats.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + ports: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(ports \\ []) do + %Reply{ports: ports} + end + + def read(<>) do + ports = Openflow.Multipart.PortStats.read(ports_bin) + %Reply{ports: ports} + end + + def append_body(%Reply{ports: ports} = message, %Reply{flags: [:more], ports: continue}) do + %{message | ports: [continue | ports]} + end + + def append_body(%Reply{ports: ports} = message, %Reply{flags: [], ports: continue}) do + new_ports = + [continue | ports] + |> Enum.reverse() + |> List.flatten() + + %{message | ports: new_ports} + end +end + +defmodule Openflow.Multipart.PortStats do + defstruct( + port_number: 0, + rx_packets: 0, + tx_packets: 0, + rx_bytes: 0, + tx_bytes: 0, + rx_dropped: 0, + tx_dropped: 0, + rx_errors: 0, + tx_errors: 0, + rx_frame_err: 0, + rx_over_err: 0, + rx_crc_err: 0, + collisions: 0, + duration_sec: 0, + duration_nsec: 0 + ) + + alias __MODULE__ + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <>) do + do_read([codec(port_stats_bin) | acc], rest) + end + + defp codec( + <> + ) do + %PortStats{ + port_number: port_no, + rx_packets: rx_packets, + tx_packets: tx_packets, + rx_bytes: rx_bytes, + tx_bytes: tx_bytes, + rx_dropped: rx_dropped, + tx_dropped: tx_dropped, + rx_errors: rx_errors, + tx_errors: tx_errors, + rx_frame_err: rx_frame_err, + rx_over_err: rx_over_err, + rx_crc_err: rx_crc_err, + collisions: collisions, + duration_sec: duration_sec, + duration_nsec: duration_nsec + } + end +end diff --git a/lib/openflow/multipart/port_stats/request.ex b/lib/openflow/multipart/port_stats/request.ex new file mode 100644 index 0000000..ba85c04 --- /dev/null +++ b/lib/openflow/multipart/port_stats/request.ex @@ -0,0 +1,37 @@ +defmodule Openflow.Multipart.PortStats.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + port_number: :any + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(port_no) when is_integer(port_no) or is_atom(port_no) do + %Request{port_number: port_no} + end + + def new(options) when is_list(options) do + %Request{ + xid: options[:xid] || 0, + port_number: options[:port_no] || :any + } + end + + def read(<>) do + port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) + %Request{port_number: port_no} + end + + def to_binary(%Request{port_number: port_no} = msg) do + port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no) + body_bin = <> + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/queue/reply.ex b/lib/openflow/multipart/queue/reply.ex new file mode 100644 index 0000000..a420ba1 --- /dev/null +++ b/lib/openflow/multipart/queue/reply.ex @@ -0,0 +1,78 @@ +defmodule Openflow.Multipart.Queue.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + queues: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(queues \\ []) do + %Reply{queues: queues} + end + + def read(<>) do + queues = Openflow.Multipart.Queue.read(queues_bin) + %Reply{queues: queues} + end + + def append_body(%Reply{queues: queues} = message, %Reply{flags: [:more], queues: continue}) do + %{message | queues: [continue | queues]} + end + + def append_body(%Reply{queues: queues} = message, %Reply{flags: [], queues: continue}) do + new_queues = + [continue | queues] + |> Enum.reverse() + |> List.flatten() + + %{message | queues: new_queues} + end +end + +defmodule Openflow.Multipart.Queue do + defstruct( + port_number: 0, + queue_id: 0, + tx_bytes: 0, + tx_packets: 0, + tx_errors: 0, + duration_sec: 0, + duration_nsec: 0 + ) + + alias __MODULE__ + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <>) do + do_read([codec(queue_bin) | acc], rest) + end + + defp codec( + <> + ) do + %Queue{ + port_number: port_no, + queue_id: queue_id, + tx_bytes: tx_bytes, + tx_packets: tx_packets, + tx_errors: tx_errors, + duration_sec: duration_sec, + duration_nsec: duration_nsec + } + end +end diff --git a/lib/openflow/multipart/queue/request.ex b/lib/openflow/multipart/queue/request.ex new file mode 100644 index 0000000..4240ede --- /dev/null +++ b/lib/openflow/multipart/queue/request.ex @@ -0,0 +1,36 @@ +defmodule Openflow.Multipart.Queue.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [], + port_number: :any, + queue_id: :all + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(options) do + xid = Keyword.get(options, :xid, 0) + port_no = Keyword.get(options, :port_number, :any) + queue_id = Keyword.get(options, :queue_id, :all) + %Request{xid: xid, port_number: port_no, queue_id: queue_id} + end + + def read(<>) do + port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) + queue_id = Openflow.Utils.get_enum(queue_id_int, :queue_id) + %Request{port_number: port_no, queue_id: queue_id} + end + + def to_binary(%Request{port_number: port_no, queue_id: queue_id} = msg) do + port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no) + queue_id_int = Openflow.Utils.get_enum(queue_id, :queue_id) + body_bin = <> + header_bin = Openflow.Multipart.Request.header(msg) + <> + end +end diff --git a/lib/openflow/multipart/reply.ex b/lib/openflow/multipart/reply.ex new file mode 100644 index 0000000..18893b0 --- /dev/null +++ b/lib/openflow/multipart/reply.ex @@ -0,0 +1,29 @@ +defmodule Openflow.Multipart.Reply do + def ofp_type, do: 19 + + def read(<>) do + codec = Openflow.Enums.to_atom(type_int, :multipart_reply_codec) + flags = Openflow.Enums.int_to_flags(flags_int, :multipart_reply_flags) + reply = codec.read(reply_bin) + %{reply | flags: flags} + end + + def to_binary(%{__struct__: codec, flags: flags} = msg) do + flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags) + type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec) + + case codec.to_binary(msg) do + reply_bin when is_binary(reply_bin) -> + <> + + {:error, reason} -> + {:error, reason} + end + end + + def header(%{__struct__: codec, flags: flags}) do + flags_int = Openflow.Enums.flags_to_int(flags, :multipart_reply_flags) + type_int = Openflow.Enums.to_int(codec, :multipart_reply_codec) + <> + end +end diff --git a/lib/openflow/multipart/request.ex b/lib/openflow/multipart/request.ex new file mode 100644 index 0000000..43d6e78 --- /dev/null +++ b/lib/openflow/multipart/request.ex @@ -0,0 +1,29 @@ +defmodule Openflow.Multipart.Request do + def ofp_type, do: 18 + + def read(<>) do + codec = Openflow.Enums.to_atom(type_int, :multipart_request_codec) + flags = Openflow.Enums.int_to_flags(flags_int, :multipart_request_flags) + request = codec.read(request_bin) + %{request | flags: flags} + end + + def to_binary(%{__struct__: codec, flags: flags} = msg) do + flags_int = Openflow.Enums.flags_to_int(flags, :multipart_request_flags) + type_int = Openflow.Enums.to_int(codec, :multipart_request_codec) + + case codec.to_binary(msg) do + request_bin when is_binary(request_bin) -> + <> + + {:error, reason} -> + {:error, reason} + end + end + + def header(%{__struct__: codec, flags: flags}) do + flags_int = Openflow.Enums.flags_to_int(flags, :multipart_request_flags) + type_int = Openflow.Enums.to_int(codec, :multipart_request_codec) + <> + end +end diff --git a/lib/openflow/multipart/table/reply.ex b/lib/openflow/multipart/table/reply.ex new file mode 100644 index 0000000..f83406f --- /dev/null +++ b/lib/openflow/multipart/table/reply.ex @@ -0,0 +1,68 @@ +defmodule Openflow.Multipart.Table.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + tables: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def read(<>) do + tables = Openflow.Multipart.TableStats.read(tables_bin) + %Reply{tables: tables} + end + + def append_body(%Reply{tables: tables} = message, %Reply{flags: [:more], tables: continue}) do + %{message | tables: [continue | tables]} + end + + def append_body(%Reply{tables: tables} = message, %Reply{flags: [], tables: continue}) do + new_tables = + [continue | tables] + |> Enum.reverse() + |> List.flatten() + + %{message | tables: new_tables} + end +end + +defmodule Openflow.Multipart.TableStats do + defstruct( + table_id: 0, + active_count: 0, + lookup_count: 0, + matched_count: 0 + ) + + alias __MODULE__ + + def read(binary) do + do_read([], binary) + end + + # private functions + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <>) do + do_read([codec(table_stats_bin) | acc], rest) + end + + defp codec( + <> + ) do + %TableStats{ + table_id: table_id, + active_count: active_count, + lookup_count: lookup_count, + matched_count: matched_count + } + end +end diff --git a/lib/openflow/multipart/table/request.ex b/lib/openflow/multipart/table/request.ex new file mode 100644 index 0000000..1e0390d --- /dev/null +++ b/lib/openflow/multipart/table/request.ex @@ -0,0 +1,25 @@ +defmodule Openflow.Multipart.Table.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + flags: [] + ) + + alias __MODULE__ + + def ofp_type, do: 18 + + def new(xid \\ 0) do + %Request{xid: xid} + end + + def read("") do + %Request{} + end + + def to_binary(%Request{} = msg) do + Openflow.Multipart.Request.header(msg) + end +end diff --git a/lib/openflow/multipart/table_features/body.ex b/lib/openflow/multipart/table_features/body.ex new file mode 100644 index 0000000..3399a06 --- /dev/null +++ b/lib/openflow/multipart/table_features/body.ex @@ -0,0 +1,322 @@ +defmodule Openflow.Multipart.TableFeatures.Body do + defstruct table_id: 0, + name: "", + metadata_match: 0, + metadata_write: 0, + config: [], + max_entries: 0, + instructions: nil, + instructions_miss: nil, + next_tables: nil, + next_tables_miss: nil, + write_actions: nil, + write_actions_miss: nil, + apply_actions: nil, + apply_actions_miss: nil, + match: nil, + wildcards: nil, + write_setfield: nil, + write_setfield_miss: nil, + apply_setfield: nil, + apply_setfield_miss: nil + + alias __MODULE__ + + @max_table_name_len 32 + @prop_header_length 4 + @table_features_length 64 + + @instructions 0 + @instructions_miss 1 + @next_tables 2 + @next_tables_miss 3 + @write_actions 4 + @write_actions_miss 5 + @apply_actions 6 + @apply_actions_miss 7 + @match 8 + @wildcards 10 + @write_setfield 12 + @write_setfield_miss 13 + @apply_setfield 14 + @apply_setfield_miss 15 + + @prop_keys [ + :instructions, + :instructions_miss, + :next_tables, + :next_tables_miss, + :write_actions, + :write_actions_miss, + :apply_actions, + :apply_actions_miss, + :match, + :wildcards, + :write_setfield, + :write_setfield_miss, + :apply_setfield, + :apply_setfield_miss + ] + + def new(options) do + %Body{ + table_id: options[:table_id] || 0, + name: options[:name] || "", + metadata_match: options[:metadata_match] || 0, + metadata_write: options[:metadata_write] || 0, + config: options[:config] || [], + max_entries: options[:max_entries] || 0, + instructions: options[:instructions], + instructions_miss: options[:instructions_miss], + next_tables: options[:next_tables], + next_tables_miss: options[:next_tables_miss], + write_actions: options[:write_actions], + write_actions_miss: options[:write_actions_miss], + apply_actions: options[:apply_actions], + apply_actions_miss: options[:apply_actions_miss], + match: options[:match], + wildcards: options[:wildcards], + write_setfield: options[:write_setfield], + write_setfield_miss: options[:write_setfield_miss], + apply_setfield: options[:apply_setfield], + apply_setfield_miss: options[:apply_setfield_miss] + } + end + + def read(binary) do + do_read([], binary) + end + + def to_binary(features) do + do_to_binary("", features) + end + + # private functions + + defp do_to_binary(acc, []), do: acc + + defp do_to_binary(acc, [table | rest]) do + do_to_binary(<>, rest) + end + + defp do_read(acc, ""), do: Enum.reverse(acc) + + defp do_read(acc, <> = binary) do + <> = binary + do_read([decode(features_bin) | acc], rest) + end + + defp decode( + <<_length::16, table_id::8, _::size(5)-unit(8), + name_bin::size(@max_table_name_len)-bytes, metadata_match::64, metadata_write::64, + config_int::32, max_entries::32, props_bin::bytes>> + ) do + name = Openflow.Utils.decode_string(name_bin) + config = Openflow.Enums.int_to_flags(config_int, :table_config) + + body = %Body{ + table_id: table_id, + name: name, + metadata_match: metadata_match, + metadata_write: metadata_write, + config: config, + max_entries: max_entries + } + + decode_props(body, props_bin) + end + + defp encode(table) do + filter_fn = fn key -> not is_nil(Map.get(table, key)) end + keys = Enum.filter(@prop_keys, filter_fn) + props_bin = encode_props("", table, keys) + length = @table_features_length + byte_size(props_bin) + + %Body{ + table_id: table_id, + name: name, + metadata_match: metadata_match, + metadata_write: metadata_write, + config: config, + max_entries: max_entries + } = table + + config_int = Openflow.Enums.flags_to_int(config, :table_config) + name_bin = Openflow.Utils.encode_string(name, @max_table_name_len) + + <> + end + + defp decode_props(body, ""), do: body + + defp decode_props(body, <>) + when type_int == @instructions or type_int == @instructions_miss do + pad_length = Openflow.Utils.pad_length(length, 8) + value_length = length - @prop_header_length + + <> = + tail + + instructions = decode_instructions([], instructions_bin) + type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + + body + |> struct(%{type => instructions}) + |> decode_props(rest) + end + + defp decode_props(body, <>) + when type_int == @next_tables or type_int == @next_tables_miss do + pad_length = Openflow.Utils.pad_length(length, 8) + value_length = length - @prop_header_length + <> = tail + next_tables = for <>, do: table_id + type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + + body + |> struct(%{type => next_tables}) + |> decode_props(rest) + end + + defp decode_props(body, <>) + when type_int == @write_actions or type_int == @write_actions_miss or + type_int == @apply_actions or type_int == @apply_actions_miss do + pad_length = Openflow.Utils.pad_length(length, 8) + value_length = length - @prop_header_length + <> = tail + actions = decode_actions([], actions_bin) + type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + + body + |> struct(%{type => actions}) + |> decode_props(rest) + end + + defp decode_props(body, <>) + when type_int == @match or type_int == @wildcards or type_int == @write_setfield or + type_int == @write_setfield_miss or type_int == @apply_setfield or + type_int == @apply_setfield_miss do + pad_length = Openflow.Utils.pad_length(length, 8) + value_length = length - @prop_header_length + <> = tail + matches = decode_matches([], matches_bin) + type = Openflow.Enums.to_atom(type_int, :table_feature_prop_type) + + body + |> struct(%{type => matches}) + |> decode_props(rest) + end + + defp decode_props(body, <<_type_int::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + value_length = length - @prop_header_length + <<_::size(value_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail + decode_props(body, rest) + end + + defp encode_props(acc, _table, []), do: acc + + defp encode_props(acc, table, [type | rest]) + when type == :instructions or type == :instructions_miss do + type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) + instructions_bin = encode_instructions("", Map.get(table, type)) + length = @prop_header_length + byte_size(instructions_bin) + pad_length = Openflow.Utils.pad_length(length, 8) + body = <> + encode_props(<>, table, rest) + end + + defp encode_props(acc, table, [type | rest]) + when type == :next_tables or type == :next_tables_miss do + type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) + next_tables_bin = to_string(Map.get(table, type)) + length = @prop_header_length + byte_size(next_tables_bin) + pad_length = Openflow.Utils.pad_length(length, 8) + body = <> + encode_props(<>, table, rest) + end + + defp encode_props(acc, table, [type | rest]) + when type == :write_actions or type == :write_actions_miss or type == :apply_actions or + type == :apply_actions_miss do + type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) + actions_bin = encode_actions("", Map.get(table, type)) + length = @prop_header_length + byte_size(actions_bin) + pad_length = Openflow.Utils.pad_length(length, 8) + body = <> + encode_props(<>, table, rest) + end + + defp encode_props(acc, table, [type | rest]) + when type == :match or type == :wildcards or type == :write_setfield or + type == :write_setfield_miss or type == :apply_setfield or + type == :apply_setfield_miss do + type_int = Openflow.Enums.to_int(type, :table_feature_prop_type) + matches_bin = encode_matches("", Map.get(table, type)) + length = @prop_header_length + byte_size(matches_bin) + pad_length = Openflow.Utils.pad_length(length, 8) + body = <> + encode_props(<>, table, rest) + end + + defp decode_instructions(acc, ""), do: Enum.reverse(acc) + + defp decode_instructions(acc, <<0xFFFF::16, _::16, exp_id::32, rest::bytes>>) do + decode_instructions([Openflow.Instruction.Experimenter.new(exp_id) | acc], rest) + end + + defp decode_instructions(acc, <>) do + instruction = Openflow.Enums.to_atom(type_int, :instruction_type) + decode_instructions([instruction | acc], rest) + end + + defp encode_instructions(acc, []), do: acc + + defp encode_instructions(acc, [%Openflow.Instruction.Experimenter{exp_id: exp_id} | rest]) do + encode_instructions(<>, rest) + end + + defp encode_instructions(acc, [type | rest]) do + type_int = Openflow.Enums.to_int(type, :instruction_type) + encode_instructions(<>, rest) + end + + defp decode_actions(acc, ""), do: Enum.reverse(acc) + + defp decode_actions(acc, <<0xFFFF::16, _::16, exp_id::32, rest::bytes>>) do + decode_actions([Openflow.Action.Experimenter.new(exp_id) | acc], rest) + end + + defp decode_actions(acc, <>) do + action = Openflow.Enums.to_atom(type_int, :action_type) + decode_actions([action | acc], rest) + end + + defp encode_actions(acc, []), do: acc + + defp encode_actions(acc, [%Openflow.Action.Experimenter{exp_id: exp_id} | rest]) do + encode_actions(<>, rest) + end + + defp encode_actions(acc, [type | rest]) do + type_int = Openflow.Enums.to_int(type, :action_type) + encode_actions(<>, rest) + end + + defp decode_matches(acc, ""), do: Enum.reverse(acc) + + defp decode_matches(acc, binary) do + length = Openflow.Match.header_size(binary) + <> = binary + field = Openflow.Match.codec_header(header_bin) + decode_matches([field | acc], rest) + end + + defp encode_matches(acc, []), do: acc + + defp encode_matches(acc, [field | rest]) do + header_bin = Openflow.Match.codec_header(field) + encode_matches(<>, rest) + end +end diff --git a/lib/openflow/multipart/table_features/reply.ex b/lib/openflow/multipart/table_features/reply.ex new file mode 100644 index 0000000..f44f4fa --- /dev/null +++ b/lib/openflow/multipart/table_features/reply.ex @@ -0,0 +1,45 @@ +defmodule Openflow.Multipart.TableFeatures.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + tables: [] + ) + + alias __MODULE__ + alias Openflow.Multipart.TableFeatures.Body + + def ofp_type, do: 18 + + def new(tables \\ []) do + %Reply{tables: tables} + end + + def read(<>) do + tables = Body.read(tables_bin) + %Reply{tables: tables} + end + + def to_binary(msg) do + header_bin = Openflow.Multipart.Reply.header(msg) + %Reply{tables: tables} = msg + tables_bin = Openflow.Multipart.TableFeatures.Body.to_binary(tables) + <> + end + + def append_body(%Reply{tables: tables} = message, %Reply{flags: [:more], tables: continue}) do + %{message | tables: [continue | tables]} + end + + def append_body(%Reply{tables: tables} = message, %Reply{flags: [], tables: continue}) do + new_tables = + [continue | tables] + |> Enum.reverse() + |> List.flatten() + + %{message | tables: new_tables} + end +end diff --git a/lib/openflow/multipart/table_features/request.ex b/lib/openflow/multipart/table_features/request.ex new file mode 100644 index 0000000..451977d --- /dev/null +++ b/lib/openflow/multipart/table_features/request.ex @@ -0,0 +1,48 @@ +defmodule Openflow.Multipart.TableFeatures.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + aux_id: nil, + flags: [], + tables: [] + ) + + alias __MODULE__ + alias Openflow.Multipart.TableFeatures.Body + + def ofp_type, do: 18 + + def new(options \\ []) do + %Request{ + xid: options[:xid] || 0, + tables: options[:tables] || [] + } + end + + def read(<>) do + tables = Body.read(tables_bin) + %Request{tables: tables} + end + + def to_binary(msg) do + header_bin = Openflow.Multipart.Request.header(msg) + %Request{tables: tables} = msg + tables_bin = Openflow.Multipart.TableFeatures.Body.to_binary(tables) + <> + end + + def append_body(%Request{tables: tables} = message, %Request{flags: [:more], tables: continue}) do + %{message | tables: [continue | tables]} + end + + def append_body(%Request{tables: tables} = message, %Request{flags: [], tables: continue}) do + new_tables = + [continue | tables] + |> Enum.reverse() + |> List.flatten() + + %{message | tables: new_tables} + end +end diff --git a/lib/openflow/nx_packet_in2.ex b/lib/openflow/nx_packet_in2.ex new file mode 100644 index 0000000..77955be --- /dev/null +++ b/lib/openflow/nx_packet_in2.ex @@ -0,0 +1,191 @@ +defmodule Openflow.NxPacketIn2 do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # packet_in properties: + packet: nil, + full_len: nil, + buffer_id: nil, + table_id: nil, + cookie: nil, + reason: nil, + metadata: nil, + userdata: nil, + # continuation properties: + continuation_bridge: "", + continuation_stack: [], + continuation_conntracked: false, + continuation_table_id: nil, + continuation_cookie: nil, + continuation_actions: [], + continuation_action_set: nil + ) + + alias __MODULE__ + + @experimenter 0x00002320 + @nx_type 30 + + @packet 0 + @full_len 1 + @buffer_id 2 + @table_id 3 + @cookie 4 + @reason 5 + @metadata 6 + @userdata 7 + @continuation 8 + + @nxcpt_bridge 0x8000 + @nxcpt_stack 0x8001 + @nxcpt_mirrors 0x8002 + @nxcpt_conntracked 0x8003 + @nxcpt_table_id 0x8004 + @nxcpt_cookie 0x8005 + @nxcpt_actions 0x8006 + @nxcpt_action_set 0x8007 + + @prop_header_length 4 + + def ofp_type, do: 4 + + def read(<<@experimenter::32, @nx_type::32, props_bin::bytes>>) do + %NxPacketIn2{} + |> decode_props(props_bin) + end + + ## private functions + + defp decode_props(pktin, ""), do: pktin + + defp decode_props(pktin, <<@packet::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + packet_length = length - @prop_header_length + <> = tail + decode_props(%{pktin | packet: packet}, rest) + end + + defp decode_props(pktin, <<@full_len::16, _length::16, full_len::32, rest::bytes>>) do + decode_props(%{pktin | full_len: full_len}, rest) + end + + defp decode_props(pktin, <<@buffer_id::16, _length::16, buffer_id::32, rest::bytes>>) do + decode_props(%{pktin | buffer_id: buffer_id}, rest) + end + + defp decode_props(pktin, <<@table_id::16, _length::16, table_id::8, _::24, rest::bytes>>) do + decode_props(%{pktin | table_id: table_id}, rest) + end + + defp decode_props(pktin, <<@cookie::16, _length::16, _::32, cookie::64, rest::bytes>>) do + decode_props(%{pktin | cookie: cookie}, rest) + end + + defp decode_props(pktin, <<@reason::16, _length::16, reason_int::8, _::24, rest::bytes>>) do + reason = Openflow.Enums.to_atom(reason_int, :packet_in_reason) + decode_props(%{pktin | reason: reason}, rest) + end + + defp decode_props(pktin, <<@metadata::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + match_field_length = length - @prop_header_length + + <> = + tail + + match_len = 4 + byte_size(match_fields_bin) + padding = Openflow.Utils.pad_length(match_len, 8) + match_bin = <<1::16, match_len::16, match_fields_bin::bytes, 0::size(padding)-unit(8)>> + {fields, _rest} = Openflow.Match.read(match_bin) + decode_props(%{pktin | metadata: fields}, rest) + end + + defp decode_props(pktin, <<@userdata::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + userdata_length = length - @prop_header_length + <> = tail + decode_props(%{pktin | userdata: userdata}, rest) + end + + defp decode_props(pktin, <<@continuation::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length - 4 + <<_pad::32, data::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail + + pktin + |> decode_continuations(data) + |> decode_props(rest) + end + + defp decode_props(pktin, <<_::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length + <<_data::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail + decode_props(pktin, rest) + end + + defp decode_continuations(pktin, ""), do: pktin + + defp decode_continuations(pktin, <<@nxcpt_bridge::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length + <> = tail + decode_continuations(%{pktin | continuation_bridge: bridge}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_stack::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = (length - @prop_header_length) * 8 + <> = tail + decode_continuations(%{pktin | continuation_stack: pktin.continuation_stack ++ [stack]}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_mirrors::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length + <> = tail + decode_continuations(%{pktin | continuation_mirrors: mirrors}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_conntracked::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length + <<_::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = tail + decode_continuations(%{pktin | continuation_conntracked: true}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_table_id::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + <> = tail + decode_continuations(%{pktin | continuation_table_id: table_id}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_cookie::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + <> = tail + decode_continuations(%{pktin | continuation_cookie: cookie}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_actions::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length - 4 + + <<_pad::32, actions::size(data_length)-bytes, _::size(pad_length)-unit(8), rest::bytes>> = + tail + + decode_continuations(%{pktin | continuation_actions: Openflow.Action.read(actions)}, rest) + end + + defp decode_continuations(pktin, <<@nxcpt_action_set::16, length::16, tail::bytes>>) do + pad_length = Openflow.Utils.pad_length(length, 8) + data_length = length - @prop_header_length + <> = tail + decode_continuations(%{pktin | continuation_action_set: action_set}, rest) + end + + defp decode_continuations(pktin, _) do + decode_continuations(pktin, "") + end +end diff --git a/lib/openflow/nx_packet_in_format.ex b/lib/openflow/nx_packet_in_format.ex new file mode 100644 index 0000000..e42b570 --- /dev/null +++ b/lib/openflow/nx_packet_in_format.ex @@ -0,0 +1,30 @@ +defmodule Openflow.NxSetPacketInFormat do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + format: :standard + ) + + @experimenter 0x00002320 + @nx_type 16 + + alias __MODULE__ + + def ofp_type, do: 4 + + def new(format \\ :standard) do + %NxSetPacketInFormat{format: format} + end + + def read(<<@experimenter::32, @nx_type::32, format_int::32>>) do + format = Openflow.Enums.to_atom(format_int, :packet_in_format) + %NxSetPacketInFormat{format: format} + end + + def to_binary(%NxSetPacketInFormat{format: format}) do + format_int = Openflow.Enums.to_int(format, :packet_in_format) + <<@experimenter::32, @nx_type::32, format_int::32>> + end +end diff --git a/lib/openflow/nx_set_controller_id.ex b/lib/openflow/nx_set_controller_id.ex new file mode 100644 index 0000000..f249960 --- /dev/null +++ b/lib/openflow/nx_set_controller_id.ex @@ -0,0 +1,26 @@ +defmodule Openflow.NxSetControllerId do + defstruct( + version: 4, + xid: 0, + id: 0 + ) + + @experimenter 0x00002320 + @nx_type 20 + + alias __MODULE__ + + def ofp_type, do: 4 + + def new(controller_id) do + %NxSetControllerId{id: controller_id} + end + + def read(<<@experimenter::32, @nx_type::32, _::size(6)-unit(8), controller_id::16>>) do + %NxSetControllerId{id: controller_id} + end + + def to_binary(%NxSetControllerId{id: controller_id}) do + <<@experimenter::32, @nx_type::32, 0::size(6)-unit(8), controller_id::16>> + end +end diff --git a/lib/openflow/packet_in.ex b/lib/openflow/packet_in.ex new file mode 100644 index 0000000..2d436e8 --- /dev/null +++ b/lib/openflow/packet_in.ex @@ -0,0 +1,69 @@ +defmodule Openflow.PacketIn do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + buffer_id: :no_buffer, + total_len: 0, + reason: :no_match, + table_id: 0, + cookie: 0, + in_port: :controller, + match: [], + data: "" + ) + + alias __MODULE__ + + def ofp_type, do: 10 + + def read( + <> + ) do + buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id) + reason = Openflow.Utils.get_enum(reason_int, :packet_in_reason) + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + {match_fields0, rest1} = Openflow.Match.read(rest0) + <<_pad::size(2)-unit(8), data::bytes>> = rest1 + in_port = Keyword.get(match_fields0, :in_port, :any) + match_fields = Keyword.delete(match_fields0, :in_port) + + %PacketIn{ + buffer_id: buffer_id, + total_len: total_len, + reason: reason, + table_id: table_id, + cookie: cookie, + in_port: in_port, + match: match_fields, + data: data + } + end + + def to_binary(%PacketIn{} = packet_in) do + %PacketIn{ + buffer_id: buffer_id, + total_len: total_len, + reason: reason, + table_id: table_id, + cookie: cookie, + in_port: in_port, + match: match_fields, + data: data + } = packet_in + + buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id) + reason_int = Openflow.Utils.get_enum(reason, :packet_in_reason) + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + + match_fields_bin = + [{:in_port, in_port} | match_fields] + |> Openflow.Match.new() + |> Openflow.Match.to_binary() + + <> + end +end diff --git a/lib/openflow/packet_out.ex b/lib/openflow/packet_out.ex new file mode 100644 index 0000000..42ca76b --- /dev/null +++ b/lib/openflow/packet_out.ex @@ -0,0 +1,45 @@ +defmodule Openflow.PacketOut do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + buffer_id: :no_buffer, + in_port: :controller, + actions: [], + data: "" + ) + + alias __MODULE__ + + def ofp_type, do: 13 + + def new(options) do + buffer_id = Keyword.get(options, :buffer_id, :no_buffer) + in_port = Keyword.get(options, :in_port, :controller) + actions = Keyword.get(options, :actions, []) + data = Keyword.get(options, :data, "") + %PacketOut{buffer_id: buffer_id, in_port: in_port, actions: actions, data: data} + end + + def read( + <> + ) do + buffer_id = Openflow.Utils.get_enum(buffer_id_int, :buffer_id) + in_port = Openflow.Utils.get_enum(in_port_int, :openflow13_port_no) + actions = Openflow.Action.read(actions_bin) + %PacketOut{buffer_id: buffer_id, in_port: in_port, actions: actions, data: data} + end + + def to_binary(%PacketOut{} = packet_out) do + %PacketOut{buffer_id: buffer_id, in_port: in_port, actions: actions, data: data} = packet_out + buffer_id_int = Openflow.Utils.get_enum(buffer_id, :buffer_id) + in_port_int = Openflow.Utils.get_enum(in_port, :openflow13_port_no) + actions_bin = Openflow.Action.to_binary(actions) + actions_len = byte_size(actions_bin) + + <> + end +end diff --git a/lib/openflow/port.ex b/lib/openflow/port.ex new file mode 100644 index 0000000..099b0bc --- /dev/null +++ b/lib/openflow/port.ex @@ -0,0 +1,50 @@ +defmodule Openflow.Port do + defstruct( + number: 0, + hw_addr: "000000000000", + name: "", + config: [], + state: [], + current_features: [], + advertised_features: [], + supported_features: [], + peer_features: [], + current_speed: :"10mb_hd", + max_speed: :"10mb_hd" + ) + + @ofp_max_port_name_len 16 + + alias __MODULE__ + + def read( + <> + ) do + port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) + hw_addr = Openflow.Utils.to_hex_string(hw_addr_bin) + name = Openflow.Utils.decode_string(name_bin) + config = Openflow.Enums.int_to_flags(config_int, :port_config) + state = Openflow.Enums.int_to_flags(state_int, :port_state) + curr = Openflow.Enums.int_to_flags(curr_int, :port_features) + adv = Openflow.Enums.int_to_flags(advertised_int, :port_features) + supp = Openflow.Enums.int_to_flags(supp_int, :port_features) + peer = Openflow.Enums.int_to_flags(peer_int, :port_features) + + %Port{ + number: port_no, + hw_addr: hw_addr, + name: name, + config: config, + state: state, + current_features: curr, + advertised_features: adv, + supported_features: supp, + peer_features: peer, + current_speed: curr_speed, + max_speed: max_speed + } + end +end diff --git a/lib/openflow/port_mod.ex b/lib/openflow/port_mod.ex new file mode 100644 index 0000000..2a8ff57 --- /dev/null +++ b/lib/openflow/port_mod.ex @@ -0,0 +1,55 @@ +defmodule Openflow.PortMod do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + number: 0, + hw_addr: "000000000000", + config: [], + mask: [], + advertise: [] + ) + + alias __MODULE__ + + def ofp_type, do: 16 + + def new(options \\ []) do + port_no = Keyword.get(options, :number, :all) + hw_addr = Keyword.get(options, :hw_adddr, "000000000000") + config = Keyword.get(options, :config, []) + mask = Keyword.get(options, :mask, []) + advertise = Keyword.get(options, :advertise, []) + %PortMod{number: port_no, hw_addr: hw_addr, config: config, mask: mask, advertise: advertise} + end + + def read( + <> + ) do + port_no = Openflow.Utils.get_enum(port_no_int, :openflow13_port_no) + hw_addr = Openflow.Utils.to_hex_string(hw_addr_bin) + config = Openflow.Enums.int_to_flags(config_int, :port_config) + mask = Openflow.Enums.int_to_flags(mask_int, :port_config) + adv = Openflow.Enums.int_to_flags(advertised_int, :port_features) + %PortMod{number: port_no, hw_addr: hw_addr, config: config, mask: mask, advertise: adv} + end + + def to_binary(%PortMod{ + number: port_no, + hw_addr: hw_addr, + config: config, + mask: mask, + advertise: adv + }) do + port_no_int = Openflow.Utils.get_enum(port_no, :openflow13_port_no) + hw_addr_bin = <> + config_int = Openflow.Enums.flags_to_int(config, :port_config) + mask_int = Openflow.Enums.flags_to_int(mask, :port_config) + advertised_int = Openflow.Enums.flags_to_int(adv, :port_features) + + <> + end +end diff --git a/lib/openflow/port_status.ex b/lib/openflow/port_status.ex new file mode 100644 index 0000000..9b92554 --- /dev/null +++ b/lib/openflow/port_status.ex @@ -0,0 +1,20 @@ +defmodule Openflow.PortStatus do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + reason: :add, + port: nil + ) + + alias __MODULE__ + + def ofp_type, do: 12 + + def read(<>) do + reason = Openflow.Enums.to_atom(reason_int, :port_reason) + port = Openflow.Port.read(port_bin) + %PortStatus{reason: reason, port: port} + end +end diff --git a/lib/openflow/role/reply.ex b/lib/openflow/role/reply.ex new file mode 100644 index 0000000..0480a0f --- /dev/null +++ b/lib/openflow/role/reply.ex @@ -0,0 +1,32 @@ +defmodule Openflow.Role.Reply do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, + role: :nochange, + generation_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 25 + + def new(options \\ []) do + role = Keyword.get(options, :role, :nochange) + generation_id = Keyword.get(options, :generation_id, 0) + %Reply{role: role, generation_id: generation_id} + end + + def read(<>) do + role = Openflow.Enums.to_atom(role_int, :controller_role) + %Reply{role: role, generation_id: generation_id} + end + + def to_binary(%Reply{role: role, generation_id: generation_id}) do + role_int = Openflow.Enums.to_int(role, :controller_role) + <> + end +end diff --git a/lib/openflow/role/request.ex b/lib/openflow/role/request.ex new file mode 100644 index 0000000..3bacde8 --- /dev/null +++ b/lib/openflow/role/request.ex @@ -0,0 +1,33 @@ +defmodule Openflow.Role.Request do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, + role: :nochange, + generation_id: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 24 + + def new(options \\ []) do + xid = Keyword.get(options, :xid, 0) + role = Keyword.get(options, :role, :nochange) + generation_id = Keyword.get(options, :generation_id, 0) + %Request{xid: xid, role: role, generation_id: generation_id} + end + + def read(<>) do + role = Openflow.Enums.to_atom(role_int, :controller_role) + %Request{role: role, generation_id: generation_id} + end + + def to_binary(%Request{role: role, generation_id: generation_id}) do + role_int = Openflow.Enums.to_int(role, :controller_role) + <> + end +end diff --git a/lib/openflow/set_async.ex b/lib/openflow/set_async.ex new file mode 100644 index 0000000..f42095b --- /dev/null +++ b/lib/openflow/set_async.ex @@ -0,0 +1,58 @@ +defmodule Openflow.SetAsync do + defstruct( + version: 4, + xid: 0, + # virtual field + datapath_id: nil, + # virtual field + aux_id: 0, + packet_in_mask_master: 0, + packet_in_mask_slave: 0, + port_status_mask_master: 0, + port_status_mask_slave: 0, + flow_removed_mask_master: 0, + flow_removed_mask_slave: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 28 + + def new(options \\ []) do + %SetAsync{ + xid: options[:xid] || 0, + packet_in_mask_master: options[:packet_in_mask_master], + packet_in_mask_slave: options[:packet_in_mask_slave], + port_status_mask_master: options[:port_status_mask_master], + port_status_mask_slave: options[:port_status_mask_slave], + flow_removed_mask_master: options[:flow_removed_mask_master], + flow_removed_mask_slave: options[:flow_removed_mask_slave] + } + end + + def read( + <> + ) do + %SetAsync{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + port_status_mask_slave: port_status_mask_slave, + flow_removed_mask_master: flow_removed_mask_master, + flow_removed_mask_slave: flow_removed_mask_slave + } + end + + def to_binary(%SetAsync{ + packet_in_mask_master: packet_in_mask_master, + packet_in_mask_slave: packet_in_mask_slave, + port_status_mask_master: port_status_mask_master, + port_status_mask_slave: port_status_mask_slave, + flow_removed_mask_master: flow_removed_mask_master, + flow_removed_mask_slave: flow_removed_mask_slave + }) do + <> + end +end diff --git a/lib/openflow/set_config.ex b/lib/openflow/set_config.ex new file mode 100644 index 0000000..95929a8 --- /dev/null +++ b/lib/openflow/set_config.ex @@ -0,0 +1,34 @@ +defmodule Openflow.SetConfig do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + # default = "normal" is no special handling + flags: [], + miss_send_len: 128 + ) + + alias __MODULE__ + + def ofp_type, do: 9 + + def new(options \\ []) do + xid = Keyword.get(options, :xid, 0) + flags = Keyword.get(options, :flags, []) + miss_send_len = Keyword.get(options, :miss_send_len, :no_buffer) + %SetConfig{xid: xid, flags: flags, miss_send_len: miss_send_len} + end + + def read(<>) do + flags = Openflow.Enums.int_to_flags(flags_int, :config_flags) + miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len) + %SetConfig{flags: flags, miss_send_len: miss_send_len} + end + + def to_binary(%SetConfig{flags: flags, miss_send_len: miss_send_len0}) do + flags_int = Openflow.Enums.flags_to_int(flags, :config_flags) + miss_send_len = Openflow.Utils.get_enum(miss_send_len0, :controller_max_len) + <> + end +end diff --git a/lib/openflow/table_mod.ex b/lib/openflow/table_mod.ex new file mode 100644 index 0000000..f0e148e --- /dev/null +++ b/lib/openflow/table_mod.ex @@ -0,0 +1,35 @@ +defmodule Openflow.TableMod do + defstruct( + version: 4, + xid: 0, + datapath_id: "", + aux_id: 0, + table_id: 0, + config: 0 + ) + + alias __MODULE__ + + def ofp_type, do: 17 + + def new(options) when is_list(options) do + %TableMod{ + xid: options[:xid] || 0, + table_id: options[:table_id] || 0 + } + end + + def new(table_id) when is_integer(table_id) or is_atom(table_id) do + %TableMod{table_id: table_id} + end + + def read(<>) do + table_id = Openflow.Utils.get_enum(table_id_int, :table_id) + %TableMod{table_id: table_id, config: config} + end + + def to_binary(%TableMod{table_id: table_id, config: config}) do + table_id_int = Openflow.Utils.get_enum(table_id, :table_id) + <> + end +end diff --git a/lib/openflow/utils.ex b/lib/openflow/utils.ex new file mode 100644 index 0000000..79456f0 --- /dev/null +++ b/lib/openflow/utils.ex @@ -0,0 +1,77 @@ +defmodule Openflow.Utils do + import Bitwise + + def int_to_flags(acc, int, [{type, flagint} | rest]) when (int &&& flagint) == flagint do + int_to_flags([type | acc], int, rest) + end + + def int_to_flags(acc, int, [_h | rest]) do + int_to_flags(acc, int, rest) + end + + def int_to_flags(acc, _int, []), do: Enum.reverse(acc) + + def flags_to_int(acc, [], _enum), do: acc + + def flags_to_int(acc0, [flag | rest], enum) do + acc = acc0 ||| Keyword.get(enum, flag, 0) + flags_to_int(acc, rest, enum) + end + + def to_hex_string(binary), do: datapath_id(binary) + + def padding(length, padding) do + case padding - rem(length, padding) do + ^padding -> 0 + pad_len -> pad_len + end + end + + def pad_length(length, width) do + rem(width - rem(length, width), width) + end + + def decode_string(binary) do + String.trim_trailing(binary, <<0>>) + end + + def encode_string(binary, length) do + String.pad_trailing(binary, length, <<0>>) + end + + def get_enum(int, type) when is_integer(int) do + try do + Openflow.Enums.to_atom(int, type) + catch + :bad_enum -> int + end + end + + def get_enum(int, type) do + try do + Openflow.Enums.to_int(int, type) + catch + :bad_enum -> int + end + end + + # private functions + + defp datapath_id(binary) do + binary + |> split_to_hex_string + |> Enum.join("") + |> String.downcase() + end + + defp split_to_hex_string(binary) do + for <>, do: integer_to_hex(int) + end + + defp integer_to_hex(int) do + case Integer.to_string(int, 16) do + <> -> <<48, d>> + dd -> dd + end + end +end diff --git a/lib/ovsdb.ex b/lib/ovsdb.ex new file mode 100644 index 0000000..7a4c9d0 --- /dev/null +++ b/lib/ovsdb.ex @@ -0,0 +1,22 @@ +defmodule OVSDB do + @moduledoc false + + @behaviour :supervisor + + def start_link do + :supervisor.start_link({:local, __MODULE__}, __MODULE__, []) + end + + def init([]) do + child = OVSDB.OpenvSwitch + strategy = :simple_one_for_one + max_r = 1000 + intensity = 3600 + sup_flags = {strategy, max_r, intensity} + {:ok, {sup_flags, [{child, {child, :start_link, []}, :temporary, 1000, :worker, [child]}]}} + end + + def start_child(server) do + :supervisor.start_child(__MODULE__, [server]) + end +end diff --git a/lib/ovsdb/open_vswitch.ex b/lib/ovsdb/open_vswitch.ex new file mode 100644 index 0000000..43b15ca --- /dev/null +++ b/lib/ovsdb/open_vswitch.ex @@ -0,0 +1,174 @@ +defmodule OVSDB.OpenvSwitch do + use GenServer + + defmodule State do + defstruct server: nil, + client_pid: nil, + monitor_pid: nil, + ovs_uuid: nil + end + + @database "Open_vSwitch" + + @open_vswitch "Open_vSwitch" + @interface "Interface" + @port "Port" + @controller "Controller" + @bridge "Bridge" + + def start_link(server) do + GenServer.start_link(__MODULE__, [server]) + end + + def find_by_name(pid, table, name) do + GenServer.call(pid, {:find_by_name, table, name}) + end + + def add_br(pid, bridge, options \\ []) do + br_uuids = GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"}) + + add_br_options = [ + bridge: bridge, + controller: options[:controller] || "tcp:127.0.0.1:6653", + protocol: options[:protocol] || "OpenFlow13", + fail_mode: options[:fail_mode] || "standalone", + br_uuids: br_uuids + ] + + GenServer.call(pid, {:add_br, add_br_options}) + end + + def del_br(pid, bridge) do + case find_by_name(pid, @bridge, bridge) do + %{"_uuid" => uuid} -> + new_bridges = + case GenServer.call(pid, {:sync_get, @open_vswitch, "bridges"}) do + ["set", bridges] -> %{"bridges" => ["set", bridges -- [uuid]]} + ^uuid -> %{"bridges" => ["set", []]} + curr_bridges -> %{"bridges" => curr_bridges} + end + + GenServer.call(pid, {:del_br, new_bridges}) + + :not_found -> + {:error, :not_found} + end + end + + def init([server]) do + state = + server + |> String.to_charlist() + |> init_client + + {:ok, state} + end + + def handle_call({:sync_get, table, col_name}, _from, state) do + [%{"rows" => [%{^col_name => values} | _]}] = + [col_name] + |> :eovsdb_op.select(table, []) + |> xact(state.client_pid) + + {:reply, values, state} + end + + def handle_call({:add_br, options}, _from, state) do + %State{client_pid: pid, ovs_uuid: ovs} = state + br_iface = %{name: options[:bridge], type: :internal} + br_port = %{name: options[:bridge], interfaces: ["named-uuid", "brinterface"]} + controller = %{target: options[:controller]} + + new_bridge = %{ + name: options[:bridge], + ports: ["named-uuid", "brport"], + controller: ["named-uuid", "brcontroller"], + fail_mode: options[:fail_mode], + protocols: options[:protocol] + } + + named_uuid = ["named-uuid", "bridge"] + + new_bridges = + case options[:br_uuids] do + ["set", []] -> %{bridges: named_uuid} + ["set", bridges] -> %{bridges: ["set", bridges ++ [named_uuid]]} + ["uuid", _] = bridge -> %{bridges: ["set", [bridge] ++ [named_uuid]]} + end + + next_config = [{"next_cfg", "+=", 1}] + eq_ovs_uuid = [{"_uuid", "==", ovs}] + + replies = + xact( + [ + :eovsdb_op.insert(@interface, br_iface, "brinterface"), + :eovsdb_op.insert(@port, br_port, "brport"), + :eovsdb_op.insert(@controller, controller, "brcontroller"), + :eovsdb_op.insert(@bridge, new_bridge, "bridge"), + :eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges), + :eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config) + ], + pid + ) + + {:reply, replies, state} + end + + def handle_call({:del_br, new_bridges}, _from, state) do + %State{client_pid: pid, ovs_uuid: ovs} = state + eq_ovs_uuid = [{"_uuid", "==", ovs}] + next_config = [{"next_cfg", "+=", 1}] + + replies = + xact( + [ + :eovsdb_op.update(@open_vswitch, eq_ovs_uuid, new_bridges), + :eovsdb_op.mutate(@open_vswitch, eq_ovs_uuid, next_config) + ], + pid + ) + + {:reply, replies, state} + end + + def handle_call({:find_by_name, table, name}, _from, state) do + %State{client_pid: pid} = state + query = :eovsdb_op.select('*', table, [{"name", "==", name}]) + + reply = + case xact(query, pid) do + [%{"rows" => []}] -> :not_found + [%{"rows" => [row]}] -> row + end + + {:reply, reply, state} + end + + def handle_cast({:async_get, "_uuid"}, state) do + [%{"rows" => [%{"_uuid" => values} | _]}] = + ["_uuid"] + |> :eovsdb_op.select(@open_vswitch, []) + |> xact(state.client_pid) + + {:noreply, %{state | ovs_uuid: values}} + end + + # private functions + + defp init_client(server) do + {:ok, pid} = :eovsdb_client.connect(server, database: @database) + :eovsdb_client.regist_schema(pid) + :ok = GenServer.cast(self(), {:async_get, "_uuid"}) + %State{server: server, client_pid: pid} + end + + defp xact(query, pid) when is_list(query) do + {:ok, res} = :eovsdb_client.transaction(pid, query) + res + end + + defp xact(query, pid) when is_map(query) do + xact([query], pid) + end +end diff --git a/lib/tres.ex b/lib/tres.ex new file mode 100644 index 0000000..36ddade --- /dev/null +++ b/lib/tres.ex @@ -0,0 +1,2 @@ +defmodule Tres do +end diff --git a/lib/tres/application.ex b/lib/tres/application.ex new file mode 100644 index 0000000..f5ecd20 --- /dev/null +++ b/lib/tres/application.ex @@ -0,0 +1,23 @@ +defmodule Tres.Application do + @moduledoc false + + use Application + + alias Tres.SwitchRegistry + + def start(_type, _args) do + import Supervisor.Spec + + {cb_mod, _cb_args} = Tres.Utils.get_callback_module() + + children = [ + worker(Registry, [[keys: :unique, name: SwitchRegistry]], id: SwitchRegistry), + supervisor(Tres.MessageHandlerSup, [cb_mod], id: MessageHandlerSup), + supervisor(OVSDB, [], id: OVSDB) + ] + + opts = [strategy: :one_for_one, name: Tres.Supervisor] + {:ok, _connection_pid} = Tres.Utils.start_openflow_listener() + Supervisor.start_link(children, opts) + end +end diff --git a/lib/tres/controller.ex b/lib/tres/controller.ex new file mode 100644 index 0000000..92d962e --- /dev/null +++ b/lib/tres/controller.ex @@ -0,0 +1,18 @@ +defmodule Tres.Controller do + def controller_helpers do + quote do + import Tres.SwitchRegistry, + only: [ + send_message: 2, + get_current_xid: 1 + ] + + use Tres.Messages + use Tres.MessageHelper + end + end + + defmacro __using__(_) do + controller_helpers() + end +end diff --git a/lib/tres/example_handler.ex b/lib/tres/example_handler.ex new file mode 100644 index 0000000..5e9a7b7 --- /dev/null +++ b/lib/tres/example_handler.ex @@ -0,0 +1,89 @@ +defmodule Tres.ExampleHandler do + use GenServer + use Tres.Controller + + import Logger + + defmodule State do + defstruct datapath_id: nil, + aux_id: nil, + conn_ref: nil + end + + def start_link(datapath, args) do + GenServer.start_link(__MODULE__, [datapath, args]) + end + + def init([{datapath_id, aux_id}, _args]) do + info( + "[#{__MODULE__}] Switch Ready: " <> + "datapath_id: #{datapath_id} " <> "aux_id: #{aux_id} " <> "on #{inspect(self())}" + ) + + _ = send_desc_stats_request(datapath_id) + _ = send_port_desc_stats_request(datapath_id) + state = %State{datapath_id: datapath_id, aux_id: aux_id} + {:ok, state} + end + + def handle_info(%PortDesc.Reply{datapath_id: datapath_id} = desc, state) do + handle_port_desc_stats_reply(desc, datapath_id) + {:noreply, state} + end + + def handle_info(%Desc.Reply{datapath_id: datapath_id} = desc, state) do + handle_desc_stats_reply(desc, datapath_id) + {:noreply, state} + end + + def handle_info({:switch_disconnected, reason}, state) do + :ok = + warn("[#{__MODULE__}] Switch Disconnected: datapath_id: #{state.datapath_id} by #{reason}") + + {:stop, :normal, state} + end + + def handle_info({:switch_hang, _datapath_id}, state) do + :ok = warn("[#{__MODULE__}] Switch possible hang: datapath_id: #{state.datapath_id}") + {:noreply, state} + end + + # `Catch all` function is required. + def handle_info(info, state) do + :ok = warn("[#{__MODULE__}] unhandled message #{inspect(info)}: #{state.datapath_id}") + {:noreply, state} + end + + # private functions + + defp send_desc_stats_request(datapath_id) do + Desc.Request.new() + |> send_message(datapath_id) + end + + defp send_port_desc_stats_request(datapath_id) do + PortDesc.Request.new() + |> send_message(datapath_id) + end + + defp handle_desc_stats_reply(desc, datapath_id) do + info( + "[#{__MODULE__}] Switch Desc: " <> + "mfr = #{desc.mfr_desc} " <> + "hw = #{desc.hw_desc} " <> "sw = #{desc.sw_desc} " <> "for #{datapath_id}" + ) + end + + defp handle_port_desc_stats_reply(port_desc, datapath_id) do + for port <- port_desc.ports do + info( + "[#{__MODULE__}] Switch has port: " <> + "number = #{port.number} " <> + "hw_addr = #{port.hw_addr} " <> + "name = #{port.name} " <> + "config = #{inspect(port.config)} " <> + "current_speed = #{port.current_speed} " <> "on #{datapath_id}" + ) + end + end +end diff --git a/lib/tres/message_handler_sup.ex b/lib/tres/message_handler_sup.ex new file mode 100644 index 0000000..b847bff --- /dev/null +++ b/lib/tres/message_handler_sup.ex @@ -0,0 +1,17 @@ +defmodule Tres.MessageHandlerSup do + use Supervisor + + def start_link(cb_mod) do + Supervisor.start_link(__MODULE__, [cb_mod], name: __MODULE__) + end + + def init([cb_mod]) do + children = [worker(cb_mod, [], restart: :temporary, shutdown: 5000)] + supervise(children, strategy: :simple_one_for_one) + end + + def start_child({dpid, aux_id}) do + {_cb_mod, cb_args} = Tres.Utils.get_callback_module() + Supervisor.start_child(__MODULE__, [{dpid, aux_id}, cb_args]) + end +end diff --git a/lib/tres/message_helper.ex b/lib/tres/message_helper.ex new file mode 100644 index 0000000..b9b1655 --- /dev/null +++ b/lib/tres/message_helper.ex @@ -0,0 +1,120 @@ +defmodule Tres.MessageHelper do + defmacro __using__(_) do + quote location: :keep do + defp send_flow_mod_add(datapath_id, options \\ []) do + flow_mod = %Openflow.FlowMod{ + cookie: options[:cookie] || 0, + priority: options[:priority] || 0, + table_id: options[:table_id] || 0, + command: :add, + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0, + buffer_id: :no_buffer, + out_port: :any, + out_group: :any, + flags: options[:flags] || [], + match: options[:match] || Openflow.Match.new(), + instructions: options[:instructions] || [] + } + + send_message(flow_mod, datapath_id) + end + + defp send_flow_mod_modify(datapath_id, options \\ []) do + command = Tres.Utils.flow_command(:modify, options) + + flow_mod = %Openflow.FlowMod{ + xid: options[:xid] || 0, + cookie: options[:cookie] || 0, + table_id: options[:table_id] || 0, + command: command, + idle_timeout: options[:idle_timeout] || 0, + hard_timeout: options[:hard_timeout] || 0, + out_port: :any, + out_group: :any, + match: options[:match] || Openflow.Match.new(), + instructions: options[:instructions] || [] + } + + send_message(flow_mod, datapath_id) + end + + defp send_flow_mod_delete(datapath_id, options \\ []) do + command = Tres.Utils.flow_command(:delete, options) + + flow_mod = %Openflow.FlowMod{ + xid: options[:xid] || 0, + cookie: options[:cookie] || 0, + cookie_mask: options[:cookie_mask] || 0, + table_id: options[:table_id] || :all, + command: command, + out_port: options[:out_port] || :any, + out_group: options[:out_group] || :any, + match: options[:match] || Openflow.Match.new() + } + + send_message(flow_mod, datapath_id) + end + + defp send_packet_out(datapath_id, options \\ []) do + packet_out = %Openflow.PacketOut{ + xid: options[:xid] || 0, + buffer_id: options[:buffer_id] || :no_buffer, + in_port: options[:in_port] || :controller, + actions: options[:actions] || [], + data: options[:data] || "" + } + + send_message(packet_out, datapath_id) + end + + defp send_group_mod_add(datapath_id, options \\ []) do + group_mod = + Openflow.GroupMod.new( + xid: options[:xid] || 0, + command: :add, + type: options[:type] || :all, + group_id: options[:group_id] || 0, + buckets: options[:buckets] || [] + ) + + send_message(group_mod, datapath_id) + end + + defp send_group_mod_delete(datapath_id, options \\ []) do + group_mod = + Openflow.GroupMod.new( + xid: options[:xid] || 0, + command: :delete, + group_id: options[:group_id] || :all + ) + + send_message(group_mod, datapath_id) + end + + defp send_group_mod_modify(datapath_id, options \\ []) do + group_mod = + Openflow.GroupMod.new( + xid: options[:xid] || 0, + command: :modify, + type: options[:type] || :all, + group_id: options[:group_id] || 0, + buckets: options[:buckets] || [] + ) + + send_message(group_mod, datapath_id) + end + + defp send_role_request(datapath_id, options) do + role_request = + Openflow.Role.Request.new( + xid: options[:xid] || 0, + role: options[:role] || :nochange, + generation_id: options[:generation_id] || 0 + ) + + send_message(role_request, datapath_id) + end + end + end +end diff --git a/lib/tres/messages.ex b/lib/tres/messages.ex new file mode 100644 index 0000000..04810a2 --- /dev/null +++ b/lib/tres/messages.ex @@ -0,0 +1,128 @@ +defmodule Tres.Messages do + defmacro __using__(_) do + quote do + alias Openflow.ErrorMsg + alias Openflow.Echo + alias Openflow.Features + alias Openflow.GetConfig + alias Openflow.SetConfig + alias Openflow.PacketIn + alias Openflow.FlowRemoved + alias Openflow.PortStatus + alias Openflow.PacketOut + alias Openflow.FlowMod + alias Openflow.GroupMod + alias Openflow.PortMod + alias Openflow.TableMod + alias Openflow.Multipart + alias Openflow.Barrier + alias Openflow.Role + alias Openflow.GetAsync + alias Openflow.SetAsync + alias Openflow.MeterMod + + alias Openflow.Match + alias Openflow.Port + + alias Openflow.NxSetPacketInFormat + alias Openflow.NxSetControllerId + alias Openflow.NxPacketIn2 + + alias Openflow.Multipart.Desc + alias Openflow.Multipart.Flow + alias Openflow.Multipart.Aggregate + alias Openflow.Multipart.Table + alias Openflow.Multipart.PortStats + alias Openflow.Multipart.Queue + alias Openflow.Multipart.Group + alias Openflow.Multipart.GroupDesc + alias Openflow.Multipart.GroupFeatures + alias Openflow.Multipart.Meter + alias Openflow.Multipart.MeterConfig + alias Openflow.Multipart.MeterFeatures + alias Openflow.Multipart.TableFeatures + alias Openflow.Multipart.PortDesc + + alias Openflow.Instruction.GotoTable + alias Openflow.Instruction.WriteMetadata + alias Openflow.Instruction.WriteActions + alias Openflow.Instruction.ApplyActions + alias Openflow.Instruction.ClearActions + alias Openflow.Instruction.Meter + + alias Openflow.Action.Output + alias Openflow.Action.CopyTtlOut + alias Openflow.Action.CopyTtlIn + alias Openflow.Action.SetMplsTtl + alias Openflow.Action.DecMplsTtl + alias Openflow.Action.PushVlan + alias Openflow.Action.PopVlan + alias Openflow.Action.PushMpls + alias Openflow.Action.PopMpls + alias Openflow.Action.SetQueue + alias Openflow.Action.Group + alias Openflow.Action.SetNwTtl + alias Openflow.Action.DecNwTtl + alias Openflow.Action.SetField + alias Openflow.Action.PushPbb + alias Openflow.Action.PopPbb + alias Openflow.Action.Encap + alias Openflow.Action.Decap + alias Openflow.Action.SetSequence + alias Openflow.Action.ValidateSequence + + alias Openflow.Action.NxResubmit + alias Openflow.Action.NxSetTunnel + alias Openflow.Action.NxSetQueue + alias Openflow.Action.NxPopQueue + alias Openflow.Action.NxRegMove + alias Openflow.Action.NxRegLoad + alias Openflow.Action.NxNote + alias Openflow.Action.NxSetTunnel64 + alias Openflow.Action.NxMultipath + alias Openflow.Action.NxBundle + alias Openflow.Action.NxBundleLoad + alias Openflow.Action.NxResubmitTable + alias Openflow.Action.NxOutputReg + alias Openflow.Action.NxLearn + alias Openflow.Action.NxExit + alias Openflow.Action.NxDecTtl + alias Openflow.Action.NxFinTimeout + alias Openflow.Action.NxController + alias Openflow.Action.NxDecTtlCntIds + alias Openflow.Action.NxWriteMetadata + alias Openflow.Action.NxPushMpls + alias Openflow.Action.NxPopMpls + alias Openflow.Action.NxSetMplsTtl + alias Openflow.Action.NxDecMplsTtl + alias Openflow.Action.NxStackPush + alias Openflow.Action.NxStackPop + alias Openflow.Action.NxSample + alias Openflow.Action.NxSetMplsLabel + alias Openflow.Action.NxSetMplsTc + alias Openflow.Action.NxOutputReg2 + alias Openflow.Action.NxRegLoad2 + alias Openflow.Action.NxConjunction + alias Openflow.Action.NxConntrack + alias Openflow.Action.NxNat + alias Openflow.Action.NxController2 + alias Openflow.Action.NxSample2 + alias Openflow.Action.NxOutputTrunc + alias Openflow.Action.NxGroup + alias Openflow.Action.NxSample3 + alias Openflow.Action.NxClone + alias Openflow.Action.NxCtClear + alias Openflow.Action.NxResubmitTableCt + alias Openflow.Action.NxLearn2 + alias Openflow.Action.NxEncap + alias Openflow.Action.NxDecap + alias Openflow.Action.NxDebugRecirc + + alias Openflow.Action.NxFlowSpecMatch + alias Openflow.Action.NxFlowSpecLoad + alias Openflow.Action.NxFlowSpecOutput + + alias Tres.SwitchRegistry + end + end +end diff --git a/lib/tres/secure_channel.ex b/lib/tres/secure_channel.ex new file mode 100644 index 0000000..033809b --- /dev/null +++ b/lib/tres/secure_channel.ex @@ -0,0 +1,614 @@ +defmodule Tres.SecureChannel do + @behaviour :gen_statem + + import Logger + + alias :tres_xact_kv, as: XACT_KV + alias :queue, as: Queue + alias Tres.SecureChannelState, as: State + alias Tres.SwitchRegistry + alias Tres.MessageHandlerSup + + @process_flags [ + trap_exit: true, + message_queue_data: :off_heap + ] + + @supported_version 4 + + @hello_handshake_timeout 1000 + @features_handshake_timeout 1000 + @ping_timeout 5000 + # @transaction_timeout 5000 + + @ping_interval 5000 + @ping_fail_max_count 10 + + def callback_mode do + [:handle_event_function, :state_enter] + end + + def start_link(ref, socket, transport, opts \\ []) do + init_args = [[ref, socket, transport, opts]] + :proc_lib.start_link(__MODULE__, :init, init_args) + end + + def init([ref, socket, transport, _opts]) do + state_data = init_secure_channel(ref, socket, transport) + + debug( + "[#{__MODULE__}] TCP connected to Switch on" <> + " #{state_data.ip_addr}:#{state_data.port}" <> " on #{inspect(self())}" + ) + + :gen_statem.enter_loop(__MODULE__, [], :INIT, state_data, []) + end + + # TCP handler + def handle_event( + :info, + {:tcp, socket, packet}, + state, + %State{socket: socket, transport: transport} = state_data + ) do + transport.setopts(socket, active: :once) + handle_packet(packet, state_data, state, []) + end + + def handle_event(:info, {:tcp_closed, socket}, _state, %State{socket: socket} = state_data) do + close_connection(:tcp_closed, state_data) + end + + def handle_event( + :info, + {:tcp_error, socket, reason}, + _state, + %State{socket: socket} = state_data + ) do + close_connection({:tcp_error, reason}, state_data) + end + + def handle_event( + :info, + {:DOWN, _ref, :process, _main_pid, _reason} = signal, + _state, + state_data + ) do + handle_signal(signal, state_data) + end + + def handle_event(:info, {:EXIT, _pid, _reason} = signal, _state, state_data) do + handle_signal(signal, state_data) + end + + def handle_event(type, message, :INIT, state_data) do + handle_INIT(type, message, state_data) + end + + def handle_event(type, message, :CONNECTING, state_data) do + handle_CONNECTING(type, message, state_data) + end + + def handle_event(type, message, :CONNECTED, state_data) do + handle_CONNECTED(type, message, state_data) + end + + def handle_event(type, message, :WAITING, state_data) do + handle_WATING(type, message, state_data) + end + + def terminate(reason, state, %State{ + datapath_id: datapath_id, + aux_id: aux_id, + xact_kv_ref: kv_ref + }) do + warn("[#{__MODULE__}] termiate: #{inspect(reason)} state = #{inspect(state)}") + true = XACT_KV.drop(kv_ref) + :ok = SwitchRegistry.unregister({datapath_id, aux_id}) + end + + # private functions + + defp init_secure_channel(ref, socket, transport) do + init_process(ref) + :ok = transport.setopts(socket, active: :once) + kv_ref = XACT_KV.create() + State.new(ref: ref, socket: socket, transport: transport, xact_kv_ref: kv_ref) + end + + defp init_process(ref) do + :ok = :proc_lib.init_ack({:ok, self()}) + :ok = :ranch.accept_ack(ref) + for {flag, value} <- @process_flags, do: Process.flag(flag, value) + end + + defp init_handler(state_data) do + %State{datapath_id: dpid, aux_id: aux_id} = state_data + + case MessageHandlerSup.start_child({dpid, aux_id}) do + {:ok, pid} -> + ref = Process.monitor(pid) + %{state_data | handler_pid: pid, handler_ref: ref} + + {:error, reason} -> + {:stop, reason} + end + end + + # INIT state + defp handle_INIT(:enter, _old_state, state_data) do + debug( + "[#{__MODULE__}] Initiate HELLO handshake: " <> "#{state_data.ip_addr}:#{state_data.port}" + ) + + initiate_hello_handshake(state_data) + end + + defp handle_INIT(:info, :hello_timeout, state_data) do + close_connection(:hello_handshake_timeout, state_data) + end + + defp handle_INIT(:internal, {:openflow, %Openflow.Hello{} = hello}, state_data) do + handle_hello_handshake_1(hello, state_data) + end + + defp handle_INIT(:internal, message, _state_data) do + debug( + "[#{__MODULE__}] Hello handshake in progress, " <> "dropping message: #{inspect(message)}" + ) + + :keep_state_and_data + end + + # CONNECTING state + defp handle_CONNECTING(:enter, :INIT, state_data) do + debug( + "[#{__MODULE__}] Initiate FEATURES handshake:" <> + " #{state_data.ip_addr}:#{state_data.port}" + ) + + initiate_features_handshake(state_data) + end + + defp handle_CONNECTING(:enter, :WAITING, state_data) do + debug("[#{__MODULE__}] Re-entered features handshake") + initiate_features_handshake(state_data) + end + + defp handle_CONNECTING(:info, :features_timeout, state_data) do + close_connection(:features_handshake_timeout, state_data) + end + + defp handle_CONNECTING( + :internal, + {:openflow, %Openflow.Features.Reply{} = features}, + state_data + ) do + debug( + "[#{__MODULE__}] Switch connected " <> + "datapath_id: #{features.datapath_id}" <> " auxiliary_id: #{features.aux_id}" + ) + + _ = maybe_cancel_timer(state_data.timer_ref) + handle_features_handshake(features, state_data) + end + + defp handle_CONNECTING(:internal, {:openflow, message}, _state_data) do + debug( + "[#{__MODULE__}] Features handshake in progress," <> + " dropping message: #{inspect(message.__struct__)}" + ) + + :keep_state_and_data + end + + defp handle_CONNECTING(type, _message, state_data) when type == :cast or type == :call do + {:keep_state, state_data, [{:postpone, true}]} + end + + # CONNECTED state + defp handle_CONNECTED(:enter, :CONNECTING, state_data) do + case init_handler(state_data) do + %State{} = new_state_data -> + start_periodic_idle_check() + {:keep_state, new_state_data} + + {:stop, reason} -> + close_connection({:handler_down, reason}, state_data) + end + end + + defp handle_CONNECTED(:info, :idle_check, state_data) do + start_periodic_idle_check() + new_state_data = maybe_ping(state_data) + {:keep_state, new_state_data} + end + + defp handle_CONNECTED(:info, :ping_timeout, state_data) do + handle_ping_timeout(state_data, :CONNECTED) + end + + defp handle_CONNECTED( + :internal, + {:openflow, %Openflow.Echo.Reply{xid: xid}}, + %State{ping_xid: xid} = state_data + ) do + handle_ping_reply(state_data) + end + + defp handle_CONNECTED(:internal, {:openflow, %Openflow.Echo.Request{} = echo}, state_data) do + send_echo_reply(echo.xid, echo.data, state_data) + :keep_state_and_data + end + + defp handle_CONNECTED(:internal, {:openflow, %Openflow.Barrier.Reply{} = barrier}, state_data) do + {new_state_data, next_actions} = process_xact(barrier, state_data) + {:keep_state, new_state_data, next_actions} + end + + defp handle_CONNECTED(:internal, {:openflow, message}, state_data) do + %State{datapath_id: dpid, aux_id: aux_id} = state_data + new_message = %{message | datapath_id: dpid, aux_id: aux_id} + + state_data.xact_kv_ref + |> XACT_KV.is_exists(message.xid) + |> handle_message(new_message, state_data) + + :keep_state_and_data + end + + defp handle_CONNECTED(:internal, {:send_message, message}, state_data) do + xactional_send_message(message, state_data) + :keep_state_and_data + end + + defp handle_CONNECTED({:call, from}, :get_xid, state_data) do + xid = State.get_transaction_id(state_data.xid) + {:keep_state_and_data, [{:reply, from, {:ok, xid}}]} + end + + defp handle_CONNECTED(:cast, {:send_message, message} = action, state_data) do + new_action_queue = + if XACT_KV.is_empty(state_data.xact_kv_ref) do + xactional_send_message(message, state_data) + state_data.action_queue + else + Queue.in(action, state_data.action_queue) + end + + {:keep_state, %{state_data | action_queue: new_action_queue}} + end + + # WATING state + defp handle_WATING(:enter, _state, state_data) do + warn("[#{__MODULE__}] Possible HANG Detected on datapath_id: #{state_data.datapath_id} !") + %State{handler_pid: handler_pid, datapath_id: dpid, aux_id: aux_id} = state_data + send(handler_pid, {:switch_hang, {dpid, aux_id}}) + start_periodic_idle_check() + :keep_state_and_data + end + + defp handle_WATING(:info, :idle_check, state_data) do + start_periodic_idle_check() + new_state_data = maybe_ping(state_data) + {:keep_state, new_state_data} + end + + defp handle_WATING(:info, :ping_timeout, state_data) do + handle_ping_timeout(state_data, :WAITING) + end + + defp handle_WATING(:internal, {:openflow, message}, state_data) do + %State{handler_pid: handler_pid, datapath_id: dpid, aux_id: aux_id} = state_data + send(handler_pid, %{message | datapath_id: dpid, aux_id: aux_id}) + {:next_state, :CONNECTING, state_data} + end + + defp handle_WATING(type, message, state_data) + when type == :cast or type == :call do + debug("[#{__MODULE__}] Postponed: #{inspect(message)}, now WATING") + {:keep_state, state_data, [{:postpone, true}]} + end + + defp handle_packet("", state_data, _state, actions) do + {:keep_state, %{state_data | ping_fail_count: 0}, Enum.reverse(actions)} + end + + defp handle_packet(packet, %State{buffer: buffer} = state_data, state, actions) do + binary = <> + + case Openflow.read(binary) do + {:ok, message, leftovers} -> + debug( + "[#{__MODULE__}] Received: #{inspect(message.__struct__)}" <> + "(xid: #{message.xid}) in #{state}" + ) + + action = {:next_event, :internal, {:openflow, message}} + new_state_data = %{state_data | buffer: "", last_received: :os.timestamp()} + handle_packet(leftovers, new_state_data, state, [action | actions]) + + {:error, :binary_too_small} -> + handle_packet("", %{state_data | buffer: binary}, state, actions) + + {:error, _reason} -> + handle_packet("", state_data, state, actions) + end + end + + defp handle_message(_in_xact = true, message, state_data) do + case XACT_KV.get(state_data.xact_kv_ref, message.xid) do + [{:xact_entry, _xid, prev_message, _orig} | _] -> + new_message = Openflow.append_body(prev_message, message) + XACT_KV.update(state_data.xact_kv_ref, message.xid, new_message) + + _ -> + XACT_KV.delete(state_data.xact_kv_ref, message.xid) + end + end + + defp handle_message(_in_xact = false, message, state_data), + do: send(state_data.handler_pid, message) + + defp process_xact(%Openflow.Barrier.Reply{xid: xid}, state_data) do + :ok = + state_data.xact_kv_ref + |> XACT_KV.get(xid) + |> Enum.each(&process_xact_entry(&1, state_data)) + + pop_action_queue(state_data) + end + + defp process_xact_entry({:xact_entry, xid, message, _orig}, state_data) do + unless is_nil(message), do: send(state_data.handler_pid, message) + XACT_KV.delete(state_data.xact_kv_ref, xid) + end + + defp pop_action_queue(%State{action_queue: queue} = state_data) do + {next_actions, new_queue} = + case Queue.out(queue) do + {:empty, action_queue} -> + {[], action_queue} + + {{:value, next_action}, action_queue} -> + {[{:next_event, :internal, next_action}], action_queue} + end + + {%{state_data | action_queue: new_queue}, next_actions} + end + + defp initiate_hello_handshake(state_data) do + send_hello(state_data) + ref = Process.send_after(self(), :hello_timeout, @hello_handshake_timeout) + {:keep_state, %{state_data | timer_ref: ref}} + end + + defp handle_hello_handshake_1(hello, state_data) do + maybe_cancel_timer(state_data.timer_ref) + State.set_transaction_id(state_data.xid, hello.xid) + + if Openflow.Hello.supported_version?(hello) do + {:next_state, :CONNECTING, %{state_data | timer_ref: nil}} + else + close_connection(:failed_version_negotiation, state_data) + end + end + + defp initiate_features_handshake(state_data) do + new_xid = State.increment_transaction_id(state_data.xid) + send_features(new_xid, state_data) + ref = Process.send_after(self(), :features_timeout, @features_handshake_timeout) + {:keep_state, %{state_data | timer_ref: ref}} + end + + defp handle_features_handshake( + %Openflow.Features.Reply{datapath_id: datapath_id, aux_id: aux_id}, + state_data + ) do + {:ok, _} = SwitchRegistry.register({datapath_id, aux_id}) + + new_state_data = %{ + state_data + | datapath_id: datapath_id, + aux_id: aux_id, + timer_ref: nil, + main_monitor_ref: monitor_connection(datapath_id, aux_id) + } + + {:next_state, :CONNECTED, new_state_data} + end + + defp monitor_connection(datapath_id, aux_id) when aux_id > 0, + do: SwitchRegistry.monitor(datapath_id) + + defp monitor_connection(_datapath_id, _aux_id), do: nil + + defp send_hello(state_data) do + @supported_version + |> Openflow.Hello.new() + |> send_message(state_data) + end + + defp send_features(xid, state_data) do + %{Openflow.Features.Request.new() | xid: xid} + |> send_message(state_data) + end + + defp send_echo_reply(xid, data, state_data) do + %{Openflow.Echo.Reply.new(data) | xid: xid} + |> send_message(state_data) + end + + defp send_echo_request(xid, data, state_data) do + %{Openflow.Echo.Request.new(data) | xid: xid} + |> send_message(state_data) + end + + defp start_periodic_idle_check do + Process.send_after(self(), :idle_check, @ping_interval) + end + + defp maybe_ping(state_data) do + case should_be_ping?(state_data) do + true -> send_ping(state_data) + false -> state_data + end + end + + defp should_be_ping?(%State{last_received: last_received, aux_id: 0}) do + :timer.now_diff(:os.timestamp(), last_received) > 1000 * @ping_interval + end + + defp should_be_ping?(_) do + false + end + + defp send_ping(%State{xid: table_ref} = state_data) do + xid = State.increment_transaction_id(table_ref) + send_echo_request(xid, "", state_data) + ping_ref = Process.send_after(self(), :ping_timeout, @ping_timeout) + %{state_data | ping_timer_ref: ping_ref, ping_xid: xid} + end + + defp handle_ping_timeout(%State{ping_fail_count: fail_count} = state_data, :CONNECTED) + when fail_count > @ping_fail_max_count do + {:next_state, :WAITING, %{state_data | ping_fail_count: fail_count + 1}} + end + + defp handle_ping_timeout(%State{ping_fail_count: fail_count} = state_data, :WAITING) + when fail_count > @ping_fail_max_count do + close_connection(:ping_failed, state_data) + end + + defp handle_ping_timeout(state_data, _) do + {:keep_state, %{state_data | ping_fail_count: state_data.ping_fail_count + 1}} + end + + defp handle_ping_reply(state_data) do + :ok = maybe_cancel_timer(state_data.ping_timer_ref) + {:keep_state, %{state_data | ping_timer_ref: nil, ping_xid: nil}} + end + + defp xactional_send_message(%{xid: 0} = message, state_data) do + xid = State.increment_transaction_id(state_data.xid) + + messages = [ + %{message | xid: xid}, + %{Openflow.Barrier.Request.new() | xid: xid} + ] + + XACT_KV.insert(state_data.xact_kv_ref, xid, message) + send_message(messages, state_data) + end + + defp xactional_send_message(%{xid: xid} = message, state_data) do + _ = State.set_transaction_id(state_data.xid, xid) + + messages = [ + %{message | xid: xid}, + %{Openflow.Barrier.Request.new() | xid: xid} + ] + + XACT_KV.insert(state_data.xact_kv_ref, xid, message) + send_message(messages, state_data) + end + + defp send_message(message, %State{socket: socket, transport: transport}) do + if is_list(message) do + for message <- message, + do: + debug("[#{__MODULE__}] Sending: #{inspect(message.__struct__)}(xid: #{message.xid})") + else + debug("[#{__MODULE__}] Sending: #{inspect(message.__struct__)}(xid: #{message.xid})") + end + + Tres.Utils.send_message(message, socket, transport) + end + + defp maybe_cancel_timer(ref) when not is_reference(ref), do: :ok + + defp maybe_cancel_timer(ref) do + Process.cancel_timer(ref) + :ok + end + + defp handle_signal( + {:DOWN, mon_ref, :process, _main_pid, reason}, + %State{main_monitor_ref: mon_ref} = state_data + ) do + close_connection({:main_closed, reason}, state_data) + end + + defp handle_signal( + {:DOWN, handler_ref, :process, _main_pid, reason}, + %State{handler_ref: handler_ref} = state_data + ) do + close_connection({:handler_down, reason}, state_data) + end + + defp handle_signal({:EXIT, _pid, reason}, state_data) do + close_connection({:trap_detected, reason}, state_data) + end + + defp close_connection(:failed_version_negotiation, state_data) do + warn("[#{__MODULE__}] connection terminated: Version negotiation failed") + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection(:hello_handshake_timeout, state_data) do + warn("[#{__MODULE__}] connection terminated: Hello handshake timed out") + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection(:features_timeout, state_data) do + warn("[#{__MODULE__}] connection terminated: Features handshake timed out") + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection(:handler_error = disconnected_reason, state_data) do + warn("[#{__MODULE__}] connection terminated: Got handler error") + %State{handler_pid: handler_pid} = state_data + send(handler_pid, {:switch_disconnected, disconnected_reason}) + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection(:ping_failed = disconnected_reason, state_data) do + warn("[#{__MODULE__}] connection terminated: Exceeded to max_ping_fail_count") + %State{handler_pid: handler_pid} = state_data + send(handler_pid, {:switch_disconnected, disconnected_reason}) + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection({:main_closed = disconnected_reason, reason}, state_data) do + warn("[#{__MODULE__}] connection terminated: Main connection down by #{reason}") + %State{handler_pid: handler_pid} = state_data + send(handler_pid, {:switch_disconnected, disconnected_reason}) + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection({:handler_down = _disconnected_reason, reason}, state_data) do + warn("[#{__MODULE__}] connection terminated: Handler process down by #{reason}") + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection({:trap_detected = disconnected_reason, reason}, state_data) do + warn("[#{__MODULE__}] connection terminated: Trapped by #{reason}") + %State{handler_pid: handler_pid} = state_data + send(handler_pid, {:switch_disconnected, disconnected_reason}) + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection(:tcp_closed = disconnected_reason, state_data) do + warn("[#{__MODULE__}] connection terminated: TCP Closed by peer") + %State{handler_pid: handler_pid} = state_data + send(handler_pid, {:switch_disconnected, disconnected_reason}) + {:stop, :normal, %{state_data | socket: nil}} + end + + defp close_connection({:tcp_error, reason} = disconnected_reason, state_data) do + warn("[#{__MODULE__}] connection terminated: TCP Error occured: #{reason}") + %State{handler_pid: handler_pid} = state_data + send(handler_pid, {:switch_disconnected, disconnected_reason}) + {:stop, :normal, %{state_data | socket: nil}} + end +end diff --git a/lib/tres/secure_channel_state.ex b/lib/tres/secure_channel_state.ex new file mode 100644 index 0000000..6ab8283 --- /dev/null +++ b/lib/tres/secure_channel_state.ex @@ -0,0 +1,68 @@ +defmodule Tres.SecureChannelState do + defstruct( + handler_pid: nil, + handler_ref: nil, + ref: nil, + socket: nil, + transport: nil, + buffer: "", + ip_addr: nil, + port: "", + datapath_id: "", + aux_id: "", + timer_ref: nil, + xid: nil, + main_monitor_ref: nil, + ping_xid: 0, + ping_timer_ref: nil, + ping_fail_count: 0, + last_received: 0, + xact_kv_ref: nil, + action_queue: :queue.new() + ) + + alias __MODULE__ + alias :tres_xact_kv, as: XACT_KV + + def new(options) do + ref = Keyword.get(options, :ref) + socket = Keyword.get(options, :socket) + transport = Keyword.get(options, :transport) + {:ok, {ip_addr, port}} = :inet.peername(socket) + {:ok, table_ref} = create_counter() + kv_ref = XACT_KV.create() + + %SecureChannelState{ + ref: ref, + socket: socket, + transport: transport, + ip_addr: :inet.ntoa(ip_addr), + port: port, + xid: table_ref, + xact_kv_ref: kv_ref + } + end + + def increment_transaction_id(table_ref) do + :ets.update_counter(table_ref, :datapath_xid, {2, 1, 0xFFFFFFFF, 0}) + end + + def set_transaction_id(table_ref, xid) do + :ets.insert(table_ref, {:datapath_xid, xid}) + end + + def get_transaction_id(table_ref) do + case :ets.lookup(table_ref, :datapath_xid) do + [{_, xid} | _] -> xid + end + end + + # private functions + + @spec create_counter() :: reference() + defp create_counter do + table_ref = :ets.new(:xid_counter, [:set, :private]) + _ = :ets.insert(table_ref, {:datapath_xid, 0}) + {:ok, table_ref} + end +end diff --git a/lib/tres/switch_registry.ex b/lib/tres/switch_registry.ex new file mode 100644 index 0000000..e901fe5 --- /dev/null +++ b/lib/tres/switch_registry.ex @@ -0,0 +1,49 @@ +defmodule Tres.SwitchRegistry do + def register({_dpid, _aux_id} = datapath_id) do + {:ok, _} = Registry.register(__MODULE__, datapath_id, []) + end + + def unregister({_dpid, _aux_id} = datapath_id) do + :ok = Registry.unregister(__MODULE__, datapath_id) + end + + def lookup_pid({_dpid, _aux_id} = datapath_id) do + case Registry.lookup(__MODULE__, datapath_id) do + [{pid, _}] -> pid + [] -> nil + end + end + + def lookup_pid(datapath_id) do + lookup_pid({datapath_id, 0}) + end + + def send_message(message, {_dpid, _aux_id} = datapath_id) do + Registry.dispatch(__MODULE__, datapath_id, &do_send_message(&1, message)) + end + + def send_message(message, dpid) when is_binary(dpid) do + send_message(message, {dpid, 0}) + end + + def get_current_xid({_dpid, _aux_id} = datapath_id) do + [{pid, _} | _] = Registry.lookup(__MODULE__, datapath_id) + :gen_statem.call(pid, :get_xid, 1000) + end + + def get_current_xid(datapath_id) do + get_current_xid({datapath_id, 0}) + end + + def monitor(datapath_id) do + datapath_id + |> lookup_pid + |> Process.monitor() + end + + # private function + + defp do_send_message(entries, message) do + for {pid, _} <- entries, do: :gen_statem.cast(pid, {:send_message, message}) + end +end diff --git a/lib/tres/utils.ex b/lib/tres/utils.ex new file mode 100644 index 0000000..5bc6c12 --- /dev/null +++ b/lib/tres/utils.ex @@ -0,0 +1,60 @@ +defmodule Tres.Utils do + import Logger + + @connection_manager Tres.SecureChannel + @default_max_connections 10 + @default_num_acceptors 10 + @default_openflow_port 6633 + + def get_callback_module do + cb_mod = get_config(:callback_module, Tres.ExampleHandler) + cb_args = get_config(:callback_args, []) + {cb_mod, cb_args} + end + + def start_openflow_listener do + max_connections = get_config(:max_connections, @default_max_connections) + num_acceptors = get_config(:num_acceptors, @default_num_acceptors) + port = get_config(:port, @default_openflow_port) + options = [max_connections: max_connections, num_acceptors: num_acceptors, port: port] + :ranch.start_listener(Tres, :ranch_tcp, options, @connection_manager, []) + end + + def send_message(message, socket, transport) do + try do + packet = Openflow.to_binary(message) + transport.send(socket, packet) + catch + _class, _reason -> + error("[#{__MODULE__}] Unencodable error: #{inspect(message)}") + end + end + + def is_multipart?(message) do + message.__struct__ + |> Module.split() + |> Enum.at(1) + |> String.match?(~r/Multipart/) + end + + def flow_command(:delete, options) do + if Keyword.get(options, :strict, false) do + :delete_strict + else + :delete + end + end + + def flow_command(:modify, options) do + if Keyword.get(options, :strict, false) do + :modify_strict + else + :modify + end + end + + # private functions + defp get_config(item, default) do + Application.get_env(:tres, item, default) + end +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..a2a0160 --- /dev/null +++ b/mix.exs @@ -0,0 +1,30 @@ +defmodule Tres.Mixfile do + use Mix.Project + + def project do + [ + app: :tres, + version: "0.1.0", + elixir: "~> 1.5", + start_permanent: Mix.env() == :prod, + escript: [main_module: Openflow.EnumGen, name: :enum_gen, path: "bin/enum_gen"], + compilers: [:erlang] ++ Mix.compilers(), + deps: deps(), + aliases: [test: "test --no-start", compile: ["escript.build"]] + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [extra_applications: [:logger, :ranch, :eovsdb], mod: {Tres.Application, []}] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:ranch, "~> 1.4.0"}, + {:eovsdb, github: "shun159/eovsdb", branch: "master"}, + {:epcap, github: "msantos/epcap", branch: "master", only: :test} + ] + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..7fb1000 --- /dev/null +++ b/mix.lock @@ -0,0 +1,10 @@ +%{"binpp": {:git, "https://github.com/jtendo/binpp.git", "64bd68d215d1a6cd35871e7c134d7fe2e46214ea", [branch: "master"]}, + "eovsdb": {:git, "https://github.com/shun159/eovsdb.git", "1ff1572708d72fd25631c681f2102407903252a3", [branch: "master"]}, + "epcap": {:git, "https://github.com/msantos/epcap.git", "9566f0420a4dcf1292c1a1afd9339c35dbdfd041", [branch: "master"]}, + "flow": {:hex, :flow, "0.12.0", "32c5a5f3ff6693e004b6c17a8c64dce2f8cdaf9564912d79427176013a586ab6", [], [{:gen_stage, "~> 0.12.0", [hex: :gen_stage, repo: "hexpm", optional: false]}], "hexpm"}, + "gen_stage": {:hex, :gen_stage, "0.12.2", "e0e347cbb1ceb5f4e68a526aec4d64b54ad721f0a8b30aa9d28e0ad749419cbb", [:mix], [], "hexpm"}, + "gen_state_machine": {:hex, :gen_state_machine, "2.0.1", "85efd5a0376929c3a4246dd943e17564a2908c7ddd7acd242d84594e785d83f8", [], [], "hexpm"}, + "jsone": {:git, "https://github.com/sile/jsone.git", "eecc9666c7165e1870b78a7a762549ae8d1c391b", [tag: "1.2.1"]}, + "pkt": {:git, "https://github.com/msantos/pkt.git", "3afb1967f34324c1dec5035a6e36232da815c2e6", [ref: "3afb196"]}, + "ranch": {:hex, :ranch, "1.4.0", "10272f95da79340fa7e8774ba7930b901713d272905d0012b06ca6d994f8826b", [:rebar3], [], "hexpm"}, + "uuid": {:git, "https://github.com/avtobiff/erlang-uuid.git", "585c2474afb4a597ae8c8bf6d21e5a9c73f18e0b", [tag: "v0.5.0"]}} diff --git a/src/tres_xact_kv.erl b/src/tres_xact_kv.erl new file mode 100644 index 0000000..fdbf225 --- /dev/null +++ b/src/tres_xact_kv.erl @@ -0,0 +1,68 @@ +-module(tres_xact_kv). + +-include_lib("stdlib/include/ms_transform.hrl"). + +-export([create/0, drop/1]). +-export([insert/3, update/3, get/2, delete/2, is_exists/2, is_empty/1]). + +-define(TABLE, xact_kv). +-define(ENTRY, xact_entry). +-define(TABLE_OPTS, [set, protected, {keypos, #?ENTRY.xid}]). + +-record(?ENTRY, {xid = 0, pending = nil, orig = nil}). + +-spec create() -> reference(). +create() -> + ets:new(?TABLE, ?TABLE_OPTS). + +-spec drop(reference()) -> true. +drop(Tid) -> + ets:delete(Tid). + +-spec insert(reference(), integer(), map()) -> true. +insert(Tid, Xid, Orig) -> + ets:insert(Tid, #?ENTRY{xid = Xid, orig = Orig}). + +-spec update(reference(), integer(), map()) -> integer(). +update(Tid, Xid, #{'__struct__' := 'Elixir.Openflow.ErrorMsg'} = Error) -> + ets:select_replace(Tid, ms_for_handle_error(Tid, Xid, Error)); +update(Tid, Xid, Msg) -> + ets:select_replace(Tid, ms_for_update(Xid, Msg)). + +-spec get(reference(), integer()) -> [term()]. +get(Tid, Xid) -> + ets:select(Tid, ms_for_get(Xid)). + +-spec delete(reference(), integer()) -> integer(). +delete(Tid, Xid) -> + ets:select_delete(Tid, ms_for_exists(Xid)). + +-spec is_exists(reference(), integer()) -> boolean(). +is_exists(Tid, Xid) -> + case ets:select(Tid, ms_for_exists(Xid)) of + [_|_] -> true; + [] -> false + end. + +-spec is_empty(reference()) -> boolean(). +is_empty(Tid) -> + case ets:info(Tid, size) of + 0 -> true; + _ -> false + end. + +%% Private functions + +ms_for_exists(Xid) -> + ets:fun2ms(fun(#?ENTRY{xid = TXid}) when TXid == Xid -> true end). + +ms_for_get(Xid) -> + ets:fun2ms(fun(#?ENTRY{xid = TXid} = E) when TXid == Xid -> E end). + +ms_for_update(Xid, Msg) -> + ets:fun2ms(fun(#?ENTRY{xid = TXid} = E) when TXid == Xid -> E#?ENTRY{pending = Msg} end). + +ms_for_handle_error(Tid, Xid, Error) -> + [#?ENTRY{orig = Orig}|_] = get(Tid, Xid), + Error1 = maps:merge(Error, #{data => Orig, xid => Xid}), + ets:fun2ms(fun(#?ENTRY{xid = TXid} = E) when TXid == Xid -> E#?ENTRY{pending = Error1} end). diff --git a/test/ofp_action_test.exs b/test/ofp_action_test.exs new file mode 100644 index 0000000..146b27d --- /dev/null +++ b/test/ofp_action_test.exs @@ -0,0 +1,630 @@ +defmodule OfpActionTest do + use ExUnit.Case + doctest Openflow + + test "Openflow.Action.NxBundle" do + test_file = "test/packet_data/nx_bundle.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + bundle = + Openflow.Action.NxBundle.new( + algorithm: :highest_random_weight, + slaves: [4, 8] + ) + + actions_bin = Openflow.Action.to_binary(bundle) + assert actions_bin == packet + assert actions == [bundle] + end + + test "Openflow.Action.NxBundleLoad" do + test_file = "test/packet_data/nx_bundle_load.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + bundle_load = + Openflow.Action.NxBundleLoad.new( + algorithm: :highest_random_weight, + slaves: [4, 8], + dst_field: :reg0 + ) + + actions_bin = Openflow.Action.to_binary(bundle_load) + assert actions_bin == packet + assert actions == [bundle_load] + end + + test "Openflow.Action.NxController" do + test_file = "test/packet_data/nx_controller.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + controller = + Openflow.Action.NxController.new( + max_len: 1234, + reason: :invalid_ttl, + id: 5678 + ) + + actions_bin = Openflow.Action.to_binary(controller) + assert actions_bin == packet + assert actions == [controller] + end + + test "Openflow.Action.NxController2" do + test_file = "test/packet_data/nx_controller2.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + controller2 = + Openflow.Action.NxController2.new( + max_len: 1234, + reason: :invalid_ttl, + userdata: <<1, 2, 3, 4, 5>>, + pause: true + ) + + assert actions == [controller2] + end + + describe "Openflow.Action.NxConntrack" do + test "with ct(alg=ftp)" do + test_file = "test/packet_data/nx_ct(alg=ftp).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(alg: 21) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(alg=tftp)" do + test_file = "test/packet_data/nx_ct(alg=tftp).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(alg: 69) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit)" do + test_file = "test/packet_data/nx_ct(commit).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(flags: [:commit]) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,force)" do + test_file = "test/packet_data/nx_ct(commit, force).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(flags: [:commit, :force]) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63]))" do + test_file = + "test/packet_data/nx_ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63])).raw" + + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxRegLoad.new(dst_field: :ct_label, value: 0, offset: 64, n_bits: 64), + Openflow.Action.NxRegLoad.new(dst_field: :ct_label, value: 0x1D, n_bits: 64) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[]))" do + test_file = "test/packet_data/nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_mark, value: 0xF009)] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[]))" do + test_file = "test/packet_data/nx_ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[])).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit, :force], + exec: [Openflow.Action.NxRegLoad.new(dst_field: :ct_mark, value: 0xF009)] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(dst))" do + test_file = "test/packet_data/nx_ct(commit,nat(dst)).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxNat.new(flags: [:dst])] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(dst=10.0.0.128-10.0.0.254,hash))" do + test_file = "test/packet_data/nx_ct(commit,nat(dst=10.0.0.128-10.0.0.254,hash)).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.128') + {:ok, ipv4_max} = :inet.parse_ipv4_address('10.0.0.254') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:dst, :protocol_hash], + ipv4_min: ipv4_min, + ipv4_max: ipv4_max + ) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src))" do + test_file = "test/packet_data/nx_ct(commit,nat(src)).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxNat.new(flags: [:src])] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src=10.0.0.240,random))" do + test_file = "test/packet_data/nx_ct(commit,nat(src=10.0.0.240,random)).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.240') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv4_min: ipv4_min + ) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent))" do + test_file = + "test/packet_data/nx_ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent)).raw" + + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.240') + {:ok, ipv4_max} = :inet.parse_ipv4_address('10.0.0.254') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :persistent], + ipv4_min: ipv4_min, + ipv4_max: ipv4_max, + proto_min: 32_768, + proto_max: 65_535 + ) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src=10.0.0.240:32768-65535,random))" do + test_file = "test/packet_data/nx_ct(commit,nat(src=10.0.0.240:32768-65535,random)).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv4_min} = :inet.parse_ipv4_address('10.0.0.240') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv4_min: ipv4_min, + proto_min: 32_768, + proto_max: 65_535 + ) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random))" do + test_file = + "test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random)).raw" + + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv6_min} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:1') + {:ok, ipv6_max} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:a18b') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv6_min: ipv6_min, + ipv6_max: ipv6_max, + proto_min: 255, + proto_max: 4096 + ) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random))" do + test_file = + "test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random)).raw" + + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv6_min} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:1') + {:ok, ipv6_max} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:a18b') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [ + Openflow.Action.NxNat.new( + flags: [:src, :protocol_random], + ipv6_min: ipv6_min, + ipv6_max: ipv6_max + ) + ] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(commit,nat(src=fe80::20c:29ff:fe88:a18b,random))" do + test_file = "test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:a18b,random)).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + {:ok, ipv6_min} = :inet.parse_ipv6_address('fe80::20c:29ff:fe88:a18b') + + ct = + Openflow.Action.NxConntrack.new( + flags: [:commit], + exec: [Openflow.Action.NxNat.new(flags: [:src, :protocol_random], ipv6_min: ipv6_min)] + ) + + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(nat)" do + test_file = "test/packet_data/nx_ct(nat).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(exec: [Openflow.Action.NxNat.new()]) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(table=10)" do + test_file = "test/packet_data/nx_ct(table=10).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(recirc_table: 10) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(zone=10)" do + test_file = "test/packet_data/nx_ct(zone=10).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(zone_imm: 10) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct(zone=NXM_NX_REG0[0..15])" do + test_file = "test/packet_data/nx_ct(zone=NXM_NX_REG0[0..15]).raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new(zone_src: :reg0, zone_offset: 0, zone_n_bits: 16) + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct" do + test_file = "test/packet_data/nx_ct.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxConntrack.new() + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with ct_clear" do + test_file = "test/packet_data/nx_ct_clear.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + ct = Openflow.Action.NxCtClear.new() + actions_bin = Openflow.Action.to_binary(ct) + assert actions_bin == packet + assert actions == [ct] + end + + test "with dec_ttl" do + test_file = "test/packet_data/nx_dec_ttl.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + dec_ttl = Openflow.Action.NxDecTtl.new() + actions_bin = Openflow.Action.to_binary(dec_ttl) + assert actions_bin == packet + assert actions == [dec_ttl] + end + + test "with dec_ttl_cnt_ids" do + test_file = "test/packet_data/nx_dec_ttl_cnt_ids.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + dec_ttl = Openflow.Action.NxDecTtlCntIds.new([32_768, 12_345, 90, 765, 1024]) + actions_bin = Openflow.Action.to_binary(dec_ttl) + assert actions_bin == packet + assert actions == [dec_ttl] + end + + test "with exit" do + test_file = "test/packet_data/nx_exit.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + exit = Openflow.Action.NxExit.new() + actions_bin = Openflow.Action.to_binary(exit) + assert actions_bin == packet + assert actions == [exit] + end + + test "with fin_timeout" do + test_file = "test/packet_data/nx_fin_timeout.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + fin_timeout = Openflow.Action.NxFinTimeout.new(idle_timeout: 10, hard_timeout: 20) + actions_bin = Openflow.Action.to_binary(fin_timeout) + assert actions_bin == packet + assert actions == [fin_timeout] + end + + test "with learn" do + test_file = "test/packet_data/nx_learn.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + learn = + Openflow.Action.NxLearn.new( + idle_timeout: 10, + hard_timeout: 20, + priority: 80, + cookie: 0x123456789ABCDEF0, + flags: [], + table_id: 2, + fin_idle_timeout: 2, + fin_hard_timeout: 4, + flow_specs: [ + Openflow.Action.NxFlowSpecMatch.new(src: :nx_vlan_tci, dst: :nx_vlan_tci, n_bits: 12), + Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), + Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port) + ] + ) + + actions_bin = Openflow.Action.to_binary(learn) + assert actions_bin == packet + assert actions == [learn] + end + + test "with learn2" do + test_file = "test/packet_data/nx_learn2.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + learn2 = + Openflow.Action.NxLearn2.new( + idle_timeout: 10, + hard_timeout: 20, + priority: 80, + cookie: 0x123456789ABCDEF0, + flags: [:write_result], + table_id: 2, + fin_idle_timeout: 2, + fin_hard_timeout: 4, + limit: 1, + result_dst: :reg0, + result_dst_offset: 8, + flow_specs: [ + Openflow.Action.NxFlowSpecMatch.new(src: :nx_vlan_tci, dst: :nx_vlan_tci, n_bits: 12), + Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), + Openflow.Action.NxFlowSpecOutput.new(src: :nx_in_port) + ] + ) + + actions_bin = Openflow.Action.to_binary(learn2) + assert actions_bin == packet + assert actions == [learn2] + end + + test "with multipath" do + test_file = "test/packet_data/nx_multipath.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + + multipath = + Openflow.Action.NxMultipath.new( + algorithm: :modulo_n, + basis: 50, + dst_field: :reg0 + ) + + actions_bin = Openflow.Action.to_binary(multipath) + assert actions_bin == packet + assert actions == [multipath] + end + + test "with note" do + test_file = "test/packet_data/nx_note.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + note = Openflow.Action.NxNote.new(<<0x11, 0xE9, 0x9A, 0xAD, 0x67, 0xF3>>) + actions_bin = Openflow.Action.to_binary(note) + assert actions_bin == packet + assert actions == [note] + end + + test "with output_reg" do + test_file = "test/packet_data/nx_output_reg.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + output_reg = Openflow.Action.NxOutputReg.new(src_field: :reg1, n_bits: 6, offset: 5) + actions_bin = Openflow.Action.to_binary(output_reg) + assert actions_bin == packet + assert actions == [output_reg] + end + + test "with output_trunc" do + test_file = "test/packet_data/nx_output_trunc.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + output_trunc = Openflow.Action.NxOutputTrunc.new(port_number: 1, max_len: 100) + actions_bin = Openflow.Action.to_binary(output_trunc) + assert actions_bin == packet + assert actions == [output_trunc] + end + + test "with pop_queue" do + test_file = "test/packet_data/nx_pop_queue.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + pop_queue = Openflow.Action.NxPopQueue.new() + actions_bin = Openflow.Action.to_binary(pop_queue) + assert actions_bin == packet + assert actions == [pop_queue] + end + + test "with reg_load" do + test_file = "test/packet_data/nx_reg_load.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + reg_load = Openflow.Action.NxRegLoad.new(dst_field: :nx_vlan_tci, value: 0xF009) + actions_bin = Openflow.Action.to_binary(reg_load) + assert actions_bin == packet + assert actions == [reg_load] + end + + test "with reg_move" do + test_file = "test/packet_data/nx_reg_move.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + reg_move = Openflow.Action.NxRegMove.new(src_field: :nx_in_port, dst_field: :nx_vlan_tci) + actions_bin = Openflow.Action.to_binary(reg_move) + assert actions_bin == packet + assert actions == [reg_move] + end + + test "with resubmit" do + test_file = "test/packet_data/nx_resubmit.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + resubmit = Openflow.Action.NxResubmit.new(5) + actions_bin = Openflow.Action.to_binary(resubmit) + assert actions_bin == packet + assert actions == [resubmit] + end + + test "with resubmit_table" do + test_file = "test/packet_data/nx_resubmit_table.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + resubmit_table = Openflow.Action.NxResubmitTable.new(in_port: 10, table_id: 5) + actions_bin = Openflow.Action.to_binary(resubmit_table) + assert actions_bin == packet + assert actions == [resubmit_table] + end + + test "with resubmit_table_ct" do + test_file = "test/packet_data/nx_resubmit_table_ct.raw" + packet = File.read!(test_file) + actions = Openflow.Action.read(packet) + resubmit_table_ct = Openflow.Action.NxResubmitTableCt.new(in_port: 10, table_id: 5) + actions_bin = Openflow.Action.to_binary(resubmit_table_ct) + assert actions_bin == packet + assert actions == [resubmit_table_ct] + end + end +end diff --git a/test/ofp_echo_test.exs b/test/ofp_echo_test.exs new file mode 100644 index 0000000..5e21fed --- /dev/null +++ b/test/ofp_echo_test.exs @@ -0,0 +1,58 @@ +defmodule OfpEchoTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_ECHO_REQUEST packet" do + {:ok, %Openflow.Echo.Request{} = echo, ""} = + "test/packet_data/ofp_echo_request.raw" + |> File.read!() + |> Openflow.read() + + assert echo.version == 4 + assert echo.xid == 0 + assert echo.data == "" + end + + test "with OFP_ECHO_REPLY packet" do + {:ok, %Openflow.Echo.Reply{} = echo, ""} = + "test/packet_data/ofp_echo_reply.raw" + |> File.read!() + |> Openflow.read() + + assert echo.version == 4 + assert echo.xid == 0 + assert echo.data == "" + end + end + + describe "Openflow.to_binary/1" do + test "with %Openflow.Echo.Request{}" do + echo = %Openflow.Echo.Request{ + version: 4, + xid: 0, + data: "" + } + + expect = + "test/packet_data/ofp_echo_request.raw" + |> File.read!() + + assert Openflow.to_binary(echo) == expect + end + + test "with %Openflow.Echo.Reply{}" do + echo = %Openflow.Echo.Reply{ + version: 4, + xid: 0, + data: "" + } + + expect = + "test/packet_data/ofp_echo_reply.raw" + |> File.read!() + + assert Openflow.to_binary(echo) == expect + end + end +end diff --git a/test/ofp_error_test.exs b/test/ofp_error_test.exs new file mode 100644 index 0000000..b49f6bf --- /dev/null +++ b/test/ofp_error_test.exs @@ -0,0 +1,77 @@ +defmodule OfpErrorTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_ERROR packet" do + {:ok, error, ""} = + "test/packet_data/ofp_error.raw" + |> File.read!() + |> Openflow.read() + + assert error.version == 4 + assert error.xid == 0 + assert error.type == :bad_action + assert error.code == :unsupported_order + assert error.data == "fugafuga" + end + end + + describe "Openflow.to_binary/1" do + test "with %Openflow.Error{}" do + error = %Openflow.ErrorMsg{ + version: 4, + xid: 0, + type: :bad_action, + code: :unsupported_order, + data: "fugafuga" + } + + expect = + "test/packet_data/ofp_error.raw" + |> File.read!() + + assert Openflow.to_binary(error) == expect + end + + test "with experimenter %Openflow.Error{}" do + error = %Openflow.ErrorMsg{ + version: 4, + xid: 0, + type: :experimenter, + exp_type: 1, + experimenter: 0xDEADBEEF, + data: "hogehoge" + } + + expect = << + 4, + 1, + 0, + 24, + 0, + 0, + 0, + 0, + 255, + 255, + 0, + 1, + 222, + 173, + 190, + 239, + 104, + 111, + 103, + 101, + 104, + 111, + 103, + 101 + >> + + assert Openflow.to_binary(error) == expect + end + end +end diff --git a/test/ofp_features_test.exs b/test/ofp_features_test.exs new file mode 100644 index 0000000..5d38572 --- /dev/null +++ b/test/ofp_features_test.exs @@ -0,0 +1,71 @@ +defmodule OfpFeaturesTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_FEATURES_REQUEST packet" do + {:ok, %Openflow.Features.Request{} = features, ""} = + "test/packet_data/ofp_features_request.raw" + |> File.read!() + |> Openflow.read() + + assert features.version == 4 + assert features.xid == 0 + end + + test "with OFP_FEATURES_REPLY packet" do + {:ok, %Openflow.Features.Reply{} = features, ""} = + "test/packet_data/ofp_features_reply.raw" + |> File.read!() + |> Openflow.read() + + assert features.version == 4 + assert features.xid == 0 + assert features.datapath_id == "0000000000000001" + assert features.n_buffers == 255 + assert features.n_tables == 255 + assert features.aux_id == 0 + + assert features.capabilities == [ + :flow_stats, + :table_stats, + :port_stats, + :group_stats, + :queue_stats + ] + end + end + + describe "Openflow.to_binary/1" do + test "with %Openflow.Features.Request{}" do + features = %Openflow.Features.Request{ + version: 4, + xid: 0 + } + + expect = + "test/packet_data/ofp_features_request.raw" + |> File.read!() + + assert Openflow.to_binary(features) == expect + end + end + + test "with %Openflow.Features.Reply{}" do + features = %Openflow.Features.Reply{ + version: 4, + xid: 0, + datapath_id: "0000000000000001", + n_buffers: 255, + n_tables: 255, + aux_id: 0, + capabilities: [:flow_stats, :table_stats, :port_stats, :group_stats, :queue_stats] + } + + expect = + "test/packet_data/ofp_features_reply.raw" + |> File.read!() + + assert Openflow.to_binary(features) == expect + end +end diff --git a/test/ofp_flow_mod_test.exs b/test/ofp_flow_mod_test.exs new file mode 100644 index 0000000..9671698 --- /dev/null +++ b/test/ofp_flow_mod_test.exs @@ -0,0 +1,301 @@ +defmodule OfpFlowModTest do + use ExUnit.Case + doctest Openflow + + @flow_mod1 "test/packet_data/4-2-ofp_flow_mod.packet" + @flow_mod2 "test/packet_data/4-3-ofp_flow_mod.packet" + @flow_mod3 "test/packet_data/4-46-ofp_flow_mod.packet" + @flow_mod4 "test/packet_data/4-60-ofp_flow_mod.packet" + @flow_mod5 "test/packet_data/libofproto-OFP13-flow_mod.packet" + @flow_mod6 "test/packet_data/libofproto-OFP13-flow_mod.truncated64" + @flow_mod7 "test/packet_data/libofproto-OFP13-flow_mod_conjunction.packet" + @flow_mod8 "test/packet_data/libofproto-OFP13-flow_mod_match_conj.packet" + + describe "Openflow.read/1" do + test "with OFP_FLOW_MOD packet(1)" do + binary = File.read!(@flow_mod1) + {: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(eth_dst: "f20ba47df8ea") + + assert fm.instructions == [ + Openflow.Instruction.WriteActions.new([ + Openflow.Action.SetField.new({:vlan_vid, 258}), + Openflow.Action.CopyTtlOut.new(), + Openflow.Action.CopyTtlIn.new(), + Openflow.Action.CopyTtlIn.new(), + Openflow.Action.PopPbb.new(), + Openflow.Action.PushPbb.new(4660), + Openflow.Action.PopMpls.new(39030), + Openflow.Action.PushMpls.new(34887), + Openflow.Action.PopVlan.new(), + Openflow.Action.PushVlan.new(33024), + Openflow.Action.DecMplsTtl.new(), + Openflow.Action.SetMplsTtl.new(10), + Openflow.Action.DecNwTtl.new(), + Openflow.Action.SetNwTtl.new(10), + Openflow.Action.Experimenter.new(101, <<0, 1, 2, 3, 4, 5, 6, 7>>), + Openflow.Action.SetQueue.new(3), + Openflow.Action.Group.new(99), + Openflow.Action.Output.new(6) + ]), + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.SetField.new({:eth_src, "010203040506"}), + Openflow.Action.SetField.new({:onf_pbb_uca, 1}) + ]) + ] + + assert Openflow.to_binary(fm) == binary + end + + test "with OFP_FLOW_MOD packet(2)" do + binary = File.read!(@flow_mod2) + {:ok, fm, ""} = Openflow.read(binary) + + assert fm.cookie == 0 + assert fm.cookie_mask == 0 + assert fm.table_id == 0 + assert fm.cookie == 0 + 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: 6, eth_src: "f20ba47df8ea") + assert fm.instructions == [Openflow.Instruction.GotoTable.new(1)] + assert Openflow.to_binary(fm) == binary + end + + test "with OFP_FLOW_MOD packet(3)" do + binary = File.read!(@flow_mod3) + {: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(eth_dst: "f20ba47df8ea") + + assert fm.instructions == [ + Openflow.Instruction.Meter.new(1), + Openflow.Instruction.WriteActions.new([Openflow.Action.Output.new(6)]) + ] + + assert Openflow.to_binary(fm) == binary + end + + test "with OFP_FLOW_MOD packet(4)" do + binary = File.read!(@flow_mod4) + {:ok, fm, ""} = Openflow.read(binary) + + assert fm.cookie == 0 + assert fm.cookie_mask == 0 + assert fm.table_id == 1 + assert fm.command == :add + assert fm.idle_timeout == 0 + assert fm.hard_timeout == 0 + assert fm.priority == 123 + assert fm.buffer_id == 0xFFFF + assert fm.out_port == :any + assert fm.out_group == :any + assert fm.flags == [] + + assert fm.match == + Openflow.Match.new( + in_port: 84_281_096, + in_phy_port: 16_909_060, + metadata: 283_686_952_306_183, + eth_type: 2054, + eth_dst: "ffffffffffff", + eth_src: "f20ba47df8ea", + vlan_vid: 999, + ip_dscp: 9, + ip_ecn: 3, + ip_proto: 99, + ipv4_src: {1, 2, 3, 4}, + ipv4_dst: {1, 2, 3, 4}, + tcp_src: 8080, + tcp_dst: 18_080, + udp_src: 28_080, + udp_dst: 55_936, + sctp_src: 48_080, + sctp_dst: 59_328, + icmpv4_type: 100, + icmpv4_code: 101, + arp_op: 1, + arp_spa: {10, 0, 0, 1}, + arp_tpa: {10, 0, 0, 3}, + arp_sha: "f20ba47df8ea", + arp_tha: "000000000000", + ipv6_src: {65152, 0, 0, 0, 61451, 42239, 65096, 10405}, + ipv6_dst: {65152, 0, 0, 0, 61451, 42239, 65029, 47068}, + ipv6_flabel: 541_473, + icmpv6_type: 200, + icmpv6_code: 201, + ipv6_nd_target: {65152, 0, 0, 0, 2656, 28415, 65151, 29927}, + ipv6_nd_sll: "00000000029a", + ipv6_nd_tll: "00000000022b", + mpls_label: 624_485, + mpls_tc: 5, + mpls_bos: 1, + pbb_isid: 11_259_375, + tunnel_id: 651_061_555_542_690_057, + ipv6_exthdr: [:auth, :frag, :router, :hop, :unrep, :unseq], + onf_pbb_uca: 1, + tun_src: {1, 2, 3, 4}, + tun_dst: {1, 2, 3, 4} + ) + + assert fm.instructions == [] + assert Openflow.to_binary(fm) == binary + end + + test "with OFP_FLOW_MOD packet(5)" do + binary = File.read!(@flow_mod5) + {:ok, fm, ""} = Openflow.read(binary) + + assert fm.cookie == 0x123456789ABCDEF0 + assert fm.cookie_mask == 0xFFFFFFFFFFFFFFFF + assert fm.table_id == 2 + assert fm.command == :add + assert fm.idle_timeout == 0 + assert fm.hard_timeout == 0 + assert fm.priority == 0 + assert fm.buffer_id == 0 + assert fm.out_port == 0 + assert fm.out_group == 0 + assert fm.flags == [] + + assert fm.match == + Openflow.Match.new( + in_port: 43981, + eth_dst: "aabbcc998877", + eth_type: 2048, + vlan_vid: 5095, + ipv4_dst: {192, 168, 2, 1}, + tunnel_id: 50_000, + tun_src: {192, 168, 2, 3}, + tun_dst: {192, 168, 2, 4} + ) + + assert fm.instructions == [ + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.PopVlan.new(), + Openflow.Action.SetField.new({:ipv4_dst, {192, 168, 2, 9}}), + Openflow.Action.NxLearn.new( + hard_timeout: 300, + priority: 1, + table_id: 99, + flow_specs: [ + Openflow.Action.NxFlowSpecMatch.new( + src: :vlan_vid, + dst: :vlan_vid, + n_bits: 12 + ), + Openflow.Action.NxFlowSpecMatch.new(src: :nx_eth_src, dst: :nx_eth_dst), + Openflow.Action.NxFlowSpecLoad.new(src: 0, dst: :vlan_vid, n_bits: 12), + Openflow.Action.NxFlowSpecLoad.new(src: :tun_id, dst: :tun_id), + Openflow.Action.NxFlowSpecOutput.new(src: :in_port) + ] + ) + ]), + Openflow.Instruction.GotoTable.new(100) + ] + + assert Openflow.to_binary(fm) == binary + end + + test "with OFP_FLOW_MOD packet(6)" do + {:error, :binary_too_small} = + @flow_mod6 + |> File.read!() + |> Openflow.read() + end + + test "with OFP_FLOW_MOD packet(7)" do + binary = File.read!(@flow_mod7) + {:ok, fm, ""} = Openflow.read(binary) + + assert fm.cookie == 0x123456789ABCDEF0 + assert fm.cookie_mask == 0xFFFFFFFFFFFFFFFF + assert fm.table_id == 4 + assert fm.command == :add + assert fm.idle_timeout == 0 + assert fm.hard_timeout == 0 + assert fm.priority == 0 + assert fm.buffer_id == 0 + assert fm.out_port == 0 + assert fm.out_group == 0 + assert fm.flags == [] + + assert fm.match == + Openflow.Match.new( + in_port: 43981, + eth_dst: "aabbcc998877", + eth_type: 2048, + vlan_vid: 5095, + ipv4_dst: {192, 168, 2, 1}, + tunnel_id: 50_000, + tun_src: {192, 168, 2, 3}, + tun_dst: {192, 168, 2, 4} + ) + + assert fm.instructions == [ + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.NxConjunction.new(clause: 1, id: 0xABCDEF, n_clauses: 2) + ]) + ] + + assert Openflow.to_binary(fm) == binary + end + + test "with OFP_FLOW_MOD packet(8)" do + binary = File.read!(@flow_mod8) + {:ok, fm, ""} = Openflow.read(binary) + + assert fm.cookie == 0x123456789ABCDEF0 + assert fm.cookie_mask == 0xFFFFFFFFFFFFFFFF + assert fm.table_id == 3 + assert fm.command == :add + assert fm.idle_timeout == 0 + assert fm.hard_timeout == 0 + assert fm.priority == 0 + assert fm.buffer_id == 0 + assert fm.out_port == 0 + assert fm.out_group == 0 + assert fm.flags == [] + assert fm.match == Openflow.Match.new(conj_id: 0xABCDEF) + + assert fm.instructions == [ + Openflow.Instruction.ApplyActions.new([ + Openflow.Action.PopVlan.new(), + Openflow.Action.SetField.new({:ipv4_dst, {192, 168, 2, 9}}) + ]), + Openflow.Instruction.GotoTable.new(100) + ] + + assert Openflow.to_binary(fm) == binary + end + end +end diff --git a/test/ofp_flow_removed_test.exs b/test/ofp_flow_removed_test.exs new file mode 100644 index 0000000..056f78f --- /dev/null +++ b/test/ofp_flow_removed_test.exs @@ -0,0 +1,58 @@ +defmodule OfpFlowRemovedTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_FLOW_REMOVED packet(with a match field)" do + {:ok, flow_removed, ""} = + "test/packet_data/4-40-ofp_flow_removed.packet" + |> File.read!() + |> Openflow.read() + + assert flow_removed.version == 4 + assert flow_removed.xid == 0 + assert flow_removed.cookie == 0 + assert flow_removed.priority == 0xFFFF + assert flow_removed.reason == :idle_timeout + assert flow_removed.table_id == 0 + assert flow_removed.duration_sec == 3 + assert flow_removed.duration_nsec == 48_825_000 + assert flow_removed.idle_timeout == 3 + assert flow_removed.hard_timeout == 0 + assert flow_removed.packet_count == 1 + assert flow_removed.byte_count == 86 + assert flow_removed.match == [eth_dst: "f20ba47df8ea"] + end + + test "with OFP_FLOW_REMOVED packet(with match fields)" do + {:ok, flow_removed, ""} = + "test/packet_data/libofproto-OFP13-flow_removed.packet" + |> File.read!() + |> Openflow.read() + + assert flow_removed.version == 4 + assert flow_removed.xid == 0 + assert flow_removed.cookie == 0x123456789ABCDEF0 + assert flow_removed.priority == 100 + assert flow_removed.reason == :idle_timeout + assert flow_removed.table_id == 1 + assert flow_removed.duration_sec == 600 + assert flow_removed.duration_nsec == 500 + assert flow_removed.idle_timeout == 400 + assert flow_removed.hard_timeout == 300 + assert flow_removed.packet_count == 200 + assert flow_removed.byte_count == 100 + + assert flow_removed.match == [ + in_port: 43_981, + eth_dst: "aabbcc998877", + eth_type: 2048, + vlan_vid: 5095, + ipv4_dst: {192, 168, 2, 1}, + tunnel_id: 50_000, + tun_src: {192, 168, 2, 3}, + tun_dst: {192, 168, 2, 4} + ] + end + end +end diff --git a/test/ofp_get_config_test.exs b/test/ofp_get_config_test.exs new file mode 100644 index 0000000..9c51812 --- /dev/null +++ b/test/ofp_get_config_test.exs @@ -0,0 +1,58 @@ +defmodule OfpGetConfigTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_GET_CONFIG_REQUEST packet" do + {:ok, %Openflow.GetConfig.Request{} = config, ""} = + "test/packet_data/ofp_get_config_request.raw" + |> File.read!() + |> Openflow.read() + + assert config.version == 4 + assert config.xid == 0 + end + + test "with OFP_GET_CONFIG_REPLY packet" do + {:ok, %Openflow.GetConfig.Reply{} = config, ""} = + "test/packet_data/ofp_get_config_reply.raw" + |> File.read!() + |> Openflow.read() + + assert config.version == 4 + assert config.xid == 0 + assert config.flags == [] + assert config.miss_send_len == 128 + end + end + + describe "Openflow.to_binary/1" do + test "with %Openflow.GetConfig.Request{}" do + config = %Openflow.GetConfig.Request{ + version: 4, + xid: 0 + } + + expect = + "test/packet_data/ofp_get_config_request.raw" + |> File.read!() + + assert Openflow.to_binary(config) == expect + end + + test "with %Openflow.GetConfig.Reply{}" do + config = %Openflow.GetConfig.Reply{ + version: 4, + xid: 0, + flags: [], + miss_send_len: 128 + } + + expect = + "test/packet_data/ofp_get_config_reply.raw" + |> File.read!() + + assert Openflow.to_binary(config) == expect + end + end +end diff --git a/test/ofp_group_mod_test.exs b/test/ofp_group_mod_test.exs new file mode 100644 index 0000000..7081095 --- /dev/null +++ b/test/ofp_group_mod_test.exs @@ -0,0 +1,28 @@ +defmodule OfpGroupModTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_GROUP_MOD packet" do + binary = File.read!("test/packet_data/4-21-ofp_group_mod.packet") + {:ok, group_mod, ""} = Openflow.read(binary) + + assert group_mod.version == 4 + assert group_mod.xid == 0 + assert group_mod.command == :add + assert group_mod.type == :all + assert group_mod.group_id == 1 + + assert group_mod.buckets == [ + Openflow.Bucket.new( + weight: 1, + watch_port: 1, + watch_group: 1, + actions: [Openflow.Action.Output.new(2)] + ) + ] + + assert Openflow.to_binary(group_mod) == binary + end + end +end diff --git a/test/ofp_hello_test.exs b/test/ofp_hello_test.exs new file mode 100644 index 0000000..5d47026 --- /dev/null +++ b/test/ofp_hello_test.exs @@ -0,0 +1,29 @@ +defmodule OfpHelloTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_HELLO packet" do + {:ok, hello, ""} = + "test/packet_data/ofp_hello.raw" + |> File.read!() + |> Openflow.read() + + assert hello.version == 4 + assert hello.xid == 0 + assert hello.elements == [versionbitmap: [30, 10, 9, 3, 2, 1]] + end + end + + describe "Openflow.to_binary/1" do + test "with %Openflow.Hello{}" do + hello = Openflow.Hello.new([30, 10, 9, 3, 2, 1]) + + expect = + "test/packet_data/ofp_hello.raw" + |> File.read!() + + assert Openflow.to_binary(hello) == expect + end + end +end diff --git a/test/ofp_packet_in_test.exs b/test/ofp_packet_in_test.exs new file mode 100644 index 0000000..b39a9a8 --- /dev/null +++ b/test/ofp_packet_in_test.exs @@ -0,0 +1,89 @@ +defmodule OfpPacketInTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_PACKET_IN packet(with simple matches)" do + {:ok, pktin, ""} = + "test/packet_data/4-4-ofp_packet_in.packet" + |> File.read!() + |> Openflow.read() + + assert pktin.version == 4 + assert pktin.xid == 0 + assert pktin.total_len == 42 + assert pktin.table_id == 1 + assert pktin.reason == :action + assert pktin.in_port == 6 + + assert pktin.match == [ + eth_type: 2054, + eth_dst: "ffffffffffff", + eth_src: "f20ba47df8ea", + arp_op: 1, + arp_spa: {10, 0, 0, 1}, + arp_tpa: {10, 0, 0, 3}, + arp_sha: "f20ba47df8ea", + arp_tha: "000000000000" + ] + end + + test "with OFP_PACKET_IN packet(with complex matches)" do + {:ok, pktin, ""} = + "test/packet_data/4-59-ofp_packet_in.packet" + |> File.read!() + |> Openflow.read() + + assert pktin.version == 4 + assert pktin.xid == 0 + assert pktin.total_len == 0 + assert pktin.table_id == 200 + assert pktin.reason == :no_match + assert pktin.in_port == 84_281_096 + + assert pktin.match == [ + in_phy_port: 16_909_060, + metadata: 283_686_952_306_183, + eth_type: 2054, + eth_dst: "ffffffffffff", + eth_src: "f20ba47df8ea", + vlan_vid: 999, + ip_dscp: 9, + ip_ecn: 3, + ip_proto: 99, + ipv4_src: {1, 2, 3, 4}, + ipv4_dst: {1, 2, 3, 4}, + tcp_src: 8080, + tcp_dst: 18080, + udp_src: 28080, + udp_dst: 55936, + sctp_src: 48080, + sctp_dst: 59328, + icmpv4_type: 100, + icmpv4_code: 101, + arp_op: 1, + arp_spa: {10, 0, 0, 1}, + arp_tpa: {10, 0, 0, 3}, + arp_sha: "f20ba47df8ea", + arp_tha: "000000000000", + ipv6_src: {65152, 0, 0, 0, 61451, 42239, 65096, 10405}, + ipv6_dst: {65152, 0, 0, 0, 61451, 42239, 65029, 47068}, + ipv6_flabel: 541_473, + icmpv6_type: 200, + icmpv6_code: 201, + ipv6_nd_target: {65152, 0, 0, 0, 2656, 28415, 65151, 29927}, + ipv6_nd_sll: "00000000029a", + ipv6_nd_tll: "00000000022b", + mpls_label: 624_485, + mpls_tc: 5, + mpls_bos: 1, + pbb_isid: 11_259_375, + tunnel_id: 651_061_555_542_690_057, + ipv6_exthdr: [:auth, :frag, :router, :hop, :unrep, :unseq], + onf_pbb_uca: 1, + tun_src: {1, 2, 3, 4}, + tun_dst: {1, 2, 3, 4} + ] + end + end +end diff --git a/test/ofp_packet_out_test.exs b/test/ofp_packet_out_test.exs new file mode 100644 index 0000000..07075da --- /dev/null +++ b/test/ofp_packet_out_test.exs @@ -0,0 +1,134 @@ +defmodule OfpPacketOutTest do + use ExUnit.Case + doctest Openflow + + @packet << + 0xF2, + 0x0B, + 0xA4, + 0xD0, + 0x3F, + 0x70, + 0xF2, + 0x0B, + 0xA4, + 0x7D, + 0xF8, + 0xEA, + 0x08, + 0x00, + 0x45, + 0x00, + 0x00, + 0x54, + 0xF8, + 0x1A, + 0x00, + 0x00, + 0xFF, + 0x01, + 0xAF, + 0x8B, + 0x0A, + 0x00, + 0x00, + 0x01, + 0x0A, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x02, + 0x08, + 0xF7, + 0x60, + 0x00, + 0x00, + 0x31, + 0xD6, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xAB, + 0x8D, + 0x2D, + 0x31, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x18, + 0x19, + 0x1A, + 0x1B, + 0x1C, + 0x1D, + 0x1E, + 0x1F, + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, + 0x26, + 0x27, + 0x28, + 0x29, + 0x2A, + 0x2B, + 0x2C, + 0x2D, + 0x2E, + 0x2F, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + >> + + describe "Openflow.read/1" do + test "with OFP_PACKET_OUT packet" do + {:ok, pktout, ""} = + "test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet" + |> File.read!() + |> Openflow.read() + + assert pktout.version == 4 + assert pktout.xid == 0 + assert pktout.buffer_id == :no_buffer + assert pktout.in_port == :controller + assert pktout.actions == [%Openflow.Action.Output{max_len: :no_buffer, port_number: :all}] + assert pktout.data == @packet + end + end + + describe "Openflow.to_binary/1" do + pktout = %Openflow.PacketOut{ + actions: [Openflow.Action.Output.new(port_number: :all)], + data: @packet + } + + expect = + "test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet" + |> File.read!() + + assert Openflow.to_binary(pktout) == expect + end +end diff --git a/test/ofp_port_mod_test.exs b/test/ofp_port_mod_test.exs new file mode 100644 index 0000000..e9725d3 --- /dev/null +++ b/test/ofp_port_mod_test.exs @@ -0,0 +1,34 @@ +defmodule OfpPortModTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_PORT_MOD packet(1)" do + binary = File.read!("test/packet_data/4-22-ofp_port_mod.packet") + {:ok, port_mod, ""} = Openflow.read(binary) + + assert port_mod.version == 4 + assert port_mod.xid == 0 + assert port_mod.number == 1 + assert port_mod.hw_addr == "001100001111" + assert port_mod.config == [] + assert port_mod.mask == [] + assert port_mod.advertise == [:fiber] + assert Openflow.to_binary(port_mod) == binary + end + end + + test "with OFP_PORT_MOD packet(2)" do + binary = File.read!("test/packet_data/libofproto-OFP13-port_mod.packet") + {:ok, port_mod, ""} = Openflow.read(binary) + + assert port_mod.version == 4 + assert port_mod.xid == 0 + assert port_mod.number == 1 + assert port_mod.hw_addr == "aabbcc998877" + assert port_mod.config == [:port_down] + assert port_mod.mask == [:port_down] + assert port_mod.advertise == [:"100mb_fd", :copper, :autoneg] + assert Openflow.to_binary(port_mod) == binary + end +end diff --git a/test/ofp_port_status_test.exs b/test/ofp_port_status_test.exs new file mode 100644 index 0000000..0c667b1 --- /dev/null +++ b/test/ofp_port_status_test.exs @@ -0,0 +1,48 @@ +defmodule OfpPortStatusTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_PORT_STATUS packet" do + {:ok, port_status, ""} = + "test/packet_data/libofproto-OFP13-port_status.packet" + |> File.read!() + |> Openflow.read() + + assert port_status.version == 4 + assert port_status.xid == 0 + assert port_status.reason == :modify + assert port_status.port.number == 1 + assert port_status.port.hw_addr == "ffffffffffff" + assert port_status.port.name == "eth0" + assert port_status.port.config == [] + assert port_status.port.state == [:live] + assert port_status.port.current_features == [:"100mb_fd", :copper, :autoneg] + assert port_status.port.advertised_features == [:"100mb_fd", :copper, :autoneg] + assert port_status.port.peer_features == [:"100mb_fd", :copper, :autoneg] + assert port_status.port.current_speed == 50_000 + assert port_status.port.max_speed == 100_000 + end + + test "with OFP_PORT_STATUS packet(with kanji port name)" do + {:ok, port_status, ""} = + "test/packet_data/4-39-ofp_port_status.packet" + |> File.read!() + |> Openflow.read() + + assert port_status.version == 4 + assert port_status.xid == 0 + assert port_status.reason == :add + assert port_status.port.number == 7 + assert port_status.port.hw_addr == "f20ba4d03f70" + assert port_status.port.name == "私のポート" + assert port_status.port.config == [] + assert port_status.port.state == [:live] + assert port_status.port.current_features == [:"100mb_fd", :copper, :autoneg] + assert port_status.port.advertised_features == [:copper, :autoneg] + assert port_status.port.peer_features == [:"100mb_fd", :copper, :autoneg] + assert port_status.port.current_speed == 5_000 + assert port_status.port.max_speed == 5_000 + end + end +end diff --git a/test/ofp_set_config_test.exs b/test/ofp_set_config_test.exs new file mode 100644 index 0000000..fd7b7e6 --- /dev/null +++ b/test/ofp_set_config_test.exs @@ -0,0 +1,35 @@ +defmodule OfpSetConfigTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_SET_CONFIG packet" do + {:ok, %Openflow.SetConfig{} = config, ""} = + "test/packet_data/ofp_set_config.raw" + |> File.read!() + |> Openflow.read() + + assert config.version == 4 + assert config.xid == 0 + assert config.flags == [] + assert config.miss_send_len == 128 + end + end + + describe "Openflow.to_binary/1" do + test "with %Openflow.SetConfig{}" do + config = %Openflow.SetConfig{ + version: 4, + xid: 0, + flags: [], + miss_send_len: 128 + } + + expect = + "test/packet_data/ofp_set_config.raw" + |> File.read!() + + assert Openflow.to_binary(config) == expect + end + end +end diff --git a/test/ofp_table_mod_test.exs b/test/ofp_table_mod_test.exs new file mode 100644 index 0000000..198e6fc --- /dev/null +++ b/test/ofp_table_mod_test.exs @@ -0,0 +1,28 @@ +defmodule OfpTableModTest do + use ExUnit.Case + doctest Openflow + + describe "Openflow.read/1" do + test "with OFP_TABLE_MOD packet(1)" do + binary = File.read!("test/packet_data/libofproto-OFP13-table_mod.packet") + {:ok, table_mod, ""} = Openflow.read(binary) + + assert table_mod.version == 4 + assert table_mod.xid == 0 + assert table_mod.table_id == :all + assert table_mod.config == 0 + assert Openflow.to_binary(table_mod) == binary + end + end + + test "with OFP_TABLE_MOD packet(2)" do + binary = File.read!("test/packet_data/4-23-ofp_table_mod.packet") + {:ok, table_mod, ""} = Openflow.read(binary) + + assert table_mod.version == 4 + assert table_mod.xid == 0 + assert table_mod.table_id == :all + assert table_mod.config == 0 + assert Openflow.to_binary(table_mod) == binary + end +end diff --git a/test/packet_data/.#nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw b/test/packet_data/.#nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw new file mode 120000 index 0000000..07c9d43 --- /dev/null +++ b/test/packet_data/.#nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw @@ -0,0 +1 @@ +shun159@shun159.19402:1510242034 \ No newline at end of file diff --git a/test/packet_data/4-0-ofp_desc_reply.packet b/test/packet_data/4-0-ofp_desc_reply.packet new file mode 100644 index 0000000..edfaa37 Binary files /dev/null and b/test/packet_data/4-0-ofp_desc_reply.packet differ diff --git a/test/packet_data/4-1-ofp_packet_out.packet b/test/packet_data/4-1-ofp_packet_out.packet new file mode 100644 index 0000000..cf6689f Binary files /dev/null and b/test/packet_data/4-1-ofp_packet_out.packet differ diff --git a/test/packet_data/4-10-ofp_hello.packet b/test/packet_data/4-10-ofp_hello.packet new file mode 100644 index 0000000..644b413 Binary files /dev/null and b/test/packet_data/4-10-ofp_hello.packet differ diff --git a/test/packet_data/4-11-ofp_flow_stats_request.packet b/test/packet_data/4-11-ofp_flow_stats_request.packet new file mode 100644 index 0000000..6b9e0a9 Binary files /dev/null and b/test/packet_data/4-11-ofp_flow_stats_request.packet differ diff --git a/test/packet_data/4-12-ofp_flow_stats_reply.packet b/test/packet_data/4-12-ofp_flow_stats_reply.packet new file mode 100644 index 0000000..c7c1ac8 Binary files /dev/null and b/test/packet_data/4-12-ofp_flow_stats_reply.packet differ diff --git a/test/packet_data/4-13-ofp_echo_request.packet b/test/packet_data/4-13-ofp_echo_request.packet new file mode 100644 index 0000000..d8d8bc4 Binary files /dev/null and b/test/packet_data/4-13-ofp_echo_request.packet differ diff --git a/test/packet_data/4-14-ofp_echo_reply.packet b/test/packet_data/4-14-ofp_echo_reply.packet new file mode 100644 index 0000000..2ac9c0d Binary files /dev/null and b/test/packet_data/4-14-ofp_echo_reply.packet differ diff --git a/test/packet_data/4-15-ofp_error_msg.packet b/test/packet_data/4-15-ofp_error_msg.packet new file mode 100644 index 0000000..196dad1 Binary files /dev/null and b/test/packet_data/4-15-ofp_error_msg.packet differ diff --git a/test/packet_data/4-16-ofp_experimenter.packet b/test/packet_data/4-16-ofp_experimenter.packet new file mode 100644 index 0000000..0b6e2dd Binary files /dev/null and b/test/packet_data/4-16-ofp_experimenter.packet differ diff --git a/test/packet_data/4-17-ofp_barrier_request.packet b/test/packet_data/4-17-ofp_barrier_request.packet new file mode 100644 index 0000000..4acb209 Binary files /dev/null and b/test/packet_data/4-17-ofp_barrier_request.packet differ diff --git a/test/packet_data/4-18-ofp_barrier_reply.packet b/test/packet_data/4-18-ofp_barrier_reply.packet new file mode 100644 index 0000000..04376c0 Binary files /dev/null and b/test/packet_data/4-18-ofp_barrier_reply.packet differ diff --git a/test/packet_data/4-19-ofp_role_request.packet b/test/packet_data/4-19-ofp_role_request.packet new file mode 100644 index 0000000..e2f3b38 Binary files /dev/null and b/test/packet_data/4-19-ofp_role_request.packet differ diff --git a/test/packet_data/4-2-ofp_flow_mod.packet b/test/packet_data/4-2-ofp_flow_mod.packet new file mode 100644 index 0000000..0c2029b Binary files /dev/null and b/test/packet_data/4-2-ofp_flow_mod.packet differ diff --git a/test/packet_data/4-20-ofp_role_reply.packet b/test/packet_data/4-20-ofp_role_reply.packet new file mode 100644 index 0000000..3f5ba39 Binary files /dev/null and b/test/packet_data/4-20-ofp_role_reply.packet differ diff --git a/test/packet_data/4-21-ofp_group_mod.packet b/test/packet_data/4-21-ofp_group_mod.packet new file mode 100644 index 0000000..3955477 Binary files /dev/null and b/test/packet_data/4-21-ofp_group_mod.packet differ diff --git a/test/packet_data/4-22-ofp_port_mod.packet b/test/packet_data/4-22-ofp_port_mod.packet new file mode 100644 index 0000000..be7044e Binary files /dev/null and b/test/packet_data/4-22-ofp_port_mod.packet differ diff --git a/test/packet_data/4-23-ofp_table_mod.packet b/test/packet_data/4-23-ofp_table_mod.packet new file mode 100644 index 0000000..02b8b02 Binary files /dev/null and b/test/packet_data/4-23-ofp_table_mod.packet differ diff --git a/test/packet_data/4-24-ofp_desc_request.packet b/test/packet_data/4-24-ofp_desc_request.packet new file mode 100644 index 0000000..b6de057 Binary files /dev/null and b/test/packet_data/4-24-ofp_desc_request.packet differ diff --git a/test/packet_data/4-25-ofp_aggregate_stats_request.packet b/test/packet_data/4-25-ofp_aggregate_stats_request.packet new file mode 100644 index 0000000..645ddac Binary files /dev/null and b/test/packet_data/4-25-ofp_aggregate_stats_request.packet differ diff --git a/test/packet_data/4-26-ofp_aggregate_stats_reply.packet b/test/packet_data/4-26-ofp_aggregate_stats_reply.packet new file mode 100644 index 0000000..3d5cd80 Binary files /dev/null and b/test/packet_data/4-26-ofp_aggregate_stats_reply.packet differ diff --git a/test/packet_data/4-27-ofp_table_stats_request.packet b/test/packet_data/4-27-ofp_table_stats_request.packet new file mode 100644 index 0000000..6fec06a Binary files /dev/null and b/test/packet_data/4-27-ofp_table_stats_request.packet differ diff --git a/test/packet_data/4-28-ofp_table_stats_reply.packet b/test/packet_data/4-28-ofp_table_stats_reply.packet new file mode 100644 index 0000000..1da72ab Binary files /dev/null and b/test/packet_data/4-28-ofp_table_stats_reply.packet differ diff --git a/test/packet_data/4-29-ofp_port_stats_request.packet b/test/packet_data/4-29-ofp_port_stats_request.packet new file mode 100644 index 0000000..d111640 Binary files /dev/null and b/test/packet_data/4-29-ofp_port_stats_request.packet differ diff --git a/test/packet_data/4-3-ofp_flow_mod.packet b/test/packet_data/4-3-ofp_flow_mod.packet new file mode 100644 index 0000000..8952a5b Binary files /dev/null and b/test/packet_data/4-3-ofp_flow_mod.packet differ diff --git a/test/packet_data/4-30-ofp_port_stats_reply.packet b/test/packet_data/4-30-ofp_port_stats_reply.packet new file mode 100644 index 0000000..8b8c182 Binary files /dev/null and b/test/packet_data/4-30-ofp_port_stats_reply.packet differ diff --git a/test/packet_data/4-31-ofp_group_features_request.packet b/test/packet_data/4-31-ofp_group_features_request.packet new file mode 100644 index 0000000..2175bb5 Binary files /dev/null and b/test/packet_data/4-31-ofp_group_features_request.packet differ diff --git a/test/packet_data/4-32-ofp_group_features_reply.packet b/test/packet_data/4-32-ofp_group_features_reply.packet new file mode 100644 index 0000000..6f7715c Binary files /dev/null and b/test/packet_data/4-32-ofp_group_features_reply.packet differ diff --git a/test/packet_data/4-33-ofp_group_desc_request.packet b/test/packet_data/4-33-ofp_group_desc_request.packet new file mode 100644 index 0000000..35add41 Binary files /dev/null and b/test/packet_data/4-33-ofp_group_desc_request.packet differ diff --git a/test/packet_data/4-34-ofp_group_desc_reply.packet b/test/packet_data/4-34-ofp_group_desc_reply.packet new file mode 100644 index 0000000..f3796cc Binary files /dev/null and b/test/packet_data/4-34-ofp_group_desc_reply.packet differ diff --git a/test/packet_data/4-35-ofp_queue_get_config_request.packet b/test/packet_data/4-35-ofp_queue_get_config_request.packet new file mode 100644 index 0000000..13072c8 Binary files /dev/null and b/test/packet_data/4-35-ofp_queue_get_config_request.packet differ diff --git a/test/packet_data/4-36-ofp_queue_get_config_reply.packet b/test/packet_data/4-36-ofp_queue_get_config_reply.packet new file mode 100644 index 0000000..898f0b3 Binary files /dev/null and b/test/packet_data/4-36-ofp_queue_get_config_reply.packet differ diff --git a/test/packet_data/4-37-ofp_queue_stats_request.packet b/test/packet_data/4-37-ofp_queue_stats_request.packet new file mode 100644 index 0000000..4baf6d7 Binary files /dev/null and b/test/packet_data/4-37-ofp_queue_stats_request.packet differ diff --git a/test/packet_data/4-38-ofp_queue_stats_reply.packet b/test/packet_data/4-38-ofp_queue_stats_reply.packet new file mode 100644 index 0000000..ad6d197 Binary files /dev/null and b/test/packet_data/4-38-ofp_queue_stats_reply.packet differ diff --git a/test/packet_data/4-39-ofp_port_status.packet b/test/packet_data/4-39-ofp_port_status.packet new file mode 100644 index 0000000..63280c7 Binary files /dev/null and b/test/packet_data/4-39-ofp_port_status.packet differ diff --git a/test/packet_data/4-4-ofp_packet_in.packet b/test/packet_data/4-4-ofp_packet_in.packet new file mode 100644 index 0000000..ebd12b5 Binary files /dev/null and b/test/packet_data/4-4-ofp_packet_in.packet differ diff --git a/test/packet_data/4-40-ofp_flow_removed.packet b/test/packet_data/4-40-ofp_flow_removed.packet new file mode 100644 index 0000000..677c2c4 Binary files /dev/null and b/test/packet_data/4-40-ofp_flow_removed.packet differ diff --git a/test/packet_data/4-41-ofp_error_msg_experimenter.packet b/test/packet_data/4-41-ofp_error_msg_experimenter.packet new file mode 100644 index 0000000..6d866b9 Binary files /dev/null and b/test/packet_data/4-41-ofp_error_msg_experimenter.packet differ diff --git a/test/packet_data/4-42-ofp_get_async_request.packet b/test/packet_data/4-42-ofp_get_async_request.packet new file mode 100644 index 0000000..4bffb26 Binary files /dev/null and b/test/packet_data/4-42-ofp_get_async_request.packet differ diff --git a/test/packet_data/4-43-ofp_get_async_reply.packet b/test/packet_data/4-43-ofp_get_async_reply.packet new file mode 100644 index 0000000..39897a9 Binary files /dev/null and b/test/packet_data/4-43-ofp_get_async_reply.packet differ diff --git a/test/packet_data/4-44-ofp_set_async.packet b/test/packet_data/4-44-ofp_set_async.packet new file mode 100644 index 0000000..de0aa1a Binary files /dev/null and b/test/packet_data/4-44-ofp_set_async.packet differ diff --git a/test/packet_data/4-45-ofp_meter_mod.packet b/test/packet_data/4-45-ofp_meter_mod.packet new file mode 100644 index 0000000..1ffbcf7 Binary files /dev/null and b/test/packet_data/4-45-ofp_meter_mod.packet differ diff --git a/test/packet_data/4-46-ofp_flow_mod.packet b/test/packet_data/4-46-ofp_flow_mod.packet new file mode 100644 index 0000000..496f1da Binary files /dev/null and b/test/packet_data/4-46-ofp_flow_mod.packet differ diff --git a/test/packet_data/4-47-ofp_meter_config_request.packet b/test/packet_data/4-47-ofp_meter_config_request.packet new file mode 100644 index 0000000..21a11e1 Binary files /dev/null and b/test/packet_data/4-47-ofp_meter_config_request.packet differ diff --git a/test/packet_data/4-48-ofp_meter_config_reply.packet b/test/packet_data/4-48-ofp_meter_config_reply.packet new file mode 100644 index 0000000..3f44326 Binary files /dev/null and b/test/packet_data/4-48-ofp_meter_config_reply.packet differ diff --git a/test/packet_data/4-49-ofp_meter_stats_request.packet b/test/packet_data/4-49-ofp_meter_stats_request.packet new file mode 100644 index 0000000..3b321af Binary files /dev/null and b/test/packet_data/4-49-ofp_meter_stats_request.packet differ diff --git a/test/packet_data/4-5-ofp_features_request.packet b/test/packet_data/4-5-ofp_features_request.packet new file mode 100644 index 0000000..7bb2775 Binary files /dev/null and b/test/packet_data/4-5-ofp_features_request.packet differ diff --git a/test/packet_data/4-50-ofp_meter_stats_reply.packet b/test/packet_data/4-50-ofp_meter_stats_reply.packet new file mode 100644 index 0000000..2317fc5 Binary files /dev/null and b/test/packet_data/4-50-ofp_meter_stats_reply.packet differ diff --git a/test/packet_data/4-51-ofp_meter_features_request.packet b/test/packet_data/4-51-ofp_meter_features_request.packet new file mode 100644 index 0000000..c4007bf Binary files /dev/null and b/test/packet_data/4-51-ofp_meter_features_request.packet differ diff --git a/test/packet_data/4-52-ofp_meter_features_reply.packet b/test/packet_data/4-52-ofp_meter_features_reply.packet new file mode 100644 index 0000000..fd9e380 Binary files /dev/null and b/test/packet_data/4-52-ofp_meter_features_reply.packet differ diff --git a/test/packet_data/4-53-ofp_port_desc_request.packet b/test/packet_data/4-53-ofp_port_desc_request.packet new file mode 100644 index 0000000..0d859f1 Binary files /dev/null and b/test/packet_data/4-53-ofp_port_desc_request.packet differ diff --git a/test/packet_data/4-54-ofp_port_desc_reply.packet b/test/packet_data/4-54-ofp_port_desc_reply.packet new file mode 100644 index 0000000..e30e9ae Binary files /dev/null and b/test/packet_data/4-54-ofp_port_desc_reply.packet differ diff --git a/test/packet_data/4-55-ofp_table_features_request.packet b/test/packet_data/4-55-ofp_table_features_request.packet new file mode 100644 index 0000000..52b9d3b Binary files /dev/null and b/test/packet_data/4-55-ofp_table_features_request.packet differ diff --git a/test/packet_data/4-56-ofp_table_features_reply.packet b/test/packet_data/4-56-ofp_table_features_reply.packet new file mode 100644 index 0000000..3a467f4 Binary files /dev/null and b/test/packet_data/4-56-ofp_table_features_reply.packet differ diff --git a/test/packet_data/4-57-ofp_group_stats_request.packet b/test/packet_data/4-57-ofp_group_stats_request.packet new file mode 100644 index 0000000..f59329e Binary files /dev/null and b/test/packet_data/4-57-ofp_group_stats_request.packet differ diff --git a/test/packet_data/4-58-ofp_group_stats_reply.packet b/test/packet_data/4-58-ofp_group_stats_reply.packet new file mode 100644 index 0000000..fe5a549 Binary files /dev/null and b/test/packet_data/4-58-ofp_group_stats_reply.packet differ diff --git a/test/packet_data/4-59-ofp_packet_in.packet b/test/packet_data/4-59-ofp_packet_in.packet new file mode 100644 index 0000000..f0879a3 Binary files /dev/null and b/test/packet_data/4-59-ofp_packet_in.packet differ diff --git a/test/packet_data/4-6-ofp_features_reply.packet b/test/packet_data/4-6-ofp_features_reply.packet new file mode 100644 index 0000000..a953633 Binary files /dev/null and b/test/packet_data/4-6-ofp_features_reply.packet differ diff --git a/test/packet_data/4-60-ofp_flow_mod.packet b/test/packet_data/4-60-ofp_flow_mod.packet new file mode 100644 index 0000000..0ca9835 Binary files /dev/null and b/test/packet_data/4-60-ofp_flow_mod.packet differ diff --git a/test/packet_data/4-61-ofp_experimenter_request.packet b/test/packet_data/4-61-ofp_experimenter_request.packet new file mode 100644 index 0000000..2ee1764 Binary files /dev/null and b/test/packet_data/4-61-ofp_experimenter_request.packet differ diff --git a/test/packet_data/4-62-ofp_experimenter_reply.packet b/test/packet_data/4-62-ofp_experimenter_reply.packet new file mode 100644 index 0000000..1f82682 Binary files /dev/null and b/test/packet_data/4-62-ofp_experimenter_reply.packet differ diff --git a/test/packet_data/4-63-onf_flow_monitor_request.packet b/test/packet_data/4-63-onf_flow_monitor_request.packet new file mode 100644 index 0000000..bf6d50e Binary files /dev/null and b/test/packet_data/4-63-onf_flow_monitor_request.packet differ diff --git a/test/packet_data/4-7-ofp_set_config.packet b/test/packet_data/4-7-ofp_set_config.packet new file mode 100644 index 0000000..43602b3 Binary files /dev/null and b/test/packet_data/4-7-ofp_set_config.packet differ diff --git a/test/packet_data/4-8-ofp_get_config_request.packet b/test/packet_data/4-8-ofp_get_config_request.packet new file mode 100644 index 0000000..78ad501 Binary files /dev/null and b/test/packet_data/4-8-ofp_get_config_request.packet differ diff --git a/test/packet_data/4-9-ofp_get_config_reply.packet b/test/packet_data/4-9-ofp_get_config_reply.packet new file mode 100644 index 0000000..b23f7bf Binary files /dev/null and b/test/packet_data/4-9-ofp_get_config_reply.packet differ diff --git a/test/packet_data/dhcp_discover.raw b/test/packet_data/dhcp_discover.raw new file mode 100644 index 0000000..55f86d1 Binary files /dev/null and b/test/packet_data/dhcp_discover.raw differ diff --git a/test/packet_data/libofproto-OFP13-echo_reply.packet b/test/packet_data/libofproto-OFP13-echo_reply.packet new file mode 100644 index 0000000..e54d380 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-echo_reply.packet differ diff --git a/test/packet_data/libofproto-OFP13-echo_request.packet b/test/packet_data/libofproto-OFP13-echo_request.packet new file mode 100644 index 0000000..a13c95d Binary files /dev/null and b/test/packet_data/libofproto-OFP13-echo_request.packet differ diff --git a/test/packet_data/libofproto-OFP13-error_msg.packet b/test/packet_data/libofproto-OFP13-error_msg.packet new file mode 100644 index 0000000..33b43ca Binary files /dev/null and b/test/packet_data/libofproto-OFP13-error_msg.packet differ diff --git a/test/packet_data/libofproto-OFP13-features_reply.packet b/test/packet_data/libofproto-OFP13-features_reply.packet new file mode 100644 index 0000000..1e5dee8 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-features_reply.packet differ diff --git a/test/packet_data/libofproto-OFP13-flow_mod.packet b/test/packet_data/libofproto-OFP13-flow_mod.packet new file mode 100644 index 0000000..8c86982 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-flow_mod.packet differ diff --git a/test/packet_data/libofproto-OFP13-flow_mod.truncated64 b/test/packet_data/libofproto-OFP13-flow_mod.truncated64 new file mode 100644 index 0000000..e69de29 diff --git a/test/packet_data/libofproto-OFP13-flow_mod_conjunction.packet b/test/packet_data/libofproto-OFP13-flow_mod_conjunction.packet new file mode 100644 index 0000000..e7e0154 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-flow_mod_conjunction.packet differ diff --git a/test/packet_data/libofproto-OFP13-flow_mod_match_conj.packet b/test/packet_data/libofproto-OFP13-flow_mod_match_conj.packet new file mode 100644 index 0000000..c377092 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-flow_mod_match_conj.packet differ diff --git a/test/packet_data/libofproto-OFP13-flow_removed.packet b/test/packet_data/libofproto-OFP13-flow_removed.packet new file mode 100644 index 0000000..c98a8f2 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-flow_removed.packet differ diff --git a/test/packet_data/libofproto-OFP13-get_config_reply.packet b/test/packet_data/libofproto-OFP13-get_config_reply.packet new file mode 100644 index 0000000..b23f7bf Binary files /dev/null and b/test/packet_data/libofproto-OFP13-get_config_reply.packet differ diff --git a/test/packet_data/libofproto-OFP13-hello.packet b/test/packet_data/libofproto-OFP13-hello.packet new file mode 100644 index 0000000..60b3118 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-hello.packet differ diff --git a/test/packet_data/libofproto-OFP13-meter_mod.packet b/test/packet_data/libofproto-OFP13-meter_mod.packet new file mode 100644 index 0000000..60870dd Binary files /dev/null and b/test/packet_data/libofproto-OFP13-meter_mod.packet differ diff --git a/test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet b/test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet new file mode 100644 index 0000000..cf6689f Binary files /dev/null and b/test/packet_data/libofproto-OFP13-ofp_packet_out_packet_library.packet differ diff --git a/test/packet_data/libofproto-OFP13-packet_in.packet b/test/packet_data/libofproto-OFP13-packet_in.packet new file mode 100644 index 0000000..817b51c Binary files /dev/null and b/test/packet_data/libofproto-OFP13-packet_in.packet differ diff --git a/test/packet_data/libofproto-OFP13-port_mod.packet b/test/packet_data/libofproto-OFP13-port_mod.packet new file mode 100644 index 0000000..105a27e Binary files /dev/null and b/test/packet_data/libofproto-OFP13-port_mod.packet differ diff --git a/test/packet_data/libofproto-OFP13-port_status.packet b/test/packet_data/libofproto-OFP13-port_status.packet new file mode 100644 index 0000000..7a2c14c Binary files /dev/null and b/test/packet_data/libofproto-OFP13-port_status.packet differ diff --git a/test/packet_data/libofproto-OFP13-set_config.packet b/test/packet_data/libofproto-OFP13-set_config.packet new file mode 100644 index 0000000..43602b3 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-set_config.packet differ diff --git a/test/packet_data/libofproto-OFP13-table_mod.packet b/test/packet_data/libofproto-OFP13-table_mod.packet new file mode 100644 index 0000000..02b8b02 Binary files /dev/null and b/test/packet_data/libofproto-OFP13-table_mod.packet differ diff --git a/test/packet_data/nx_bundle.raw b/test/packet_data/nx_bundle.raw new file mode 100644 index 0000000..5599f37 Binary files /dev/null and b/test/packet_data/nx_bundle.raw differ diff --git a/test/packet_data/nx_bundle_load.raw b/test/packet_data/nx_bundle_load.raw new file mode 100644 index 0000000..8fc3404 Binary files /dev/null and b/test/packet_data/nx_bundle_load.raw differ diff --git a/test/packet_data/nx_clone.raw b/test/packet_data/nx_clone.raw new file mode 100644 index 0000000..47e62dd Binary files /dev/null and b/test/packet_data/nx_clone.raw differ diff --git a/test/packet_data/nx_controller.raw b/test/packet_data/nx_controller.raw new file mode 100644 index 0000000..a66c407 Binary files /dev/null and b/test/packet_data/nx_controller.raw differ diff --git a/test/packet_data/nx_controller2.raw b/test/packet_data/nx_controller2.raw new file mode 100644 index 0000000..0921fa8 Binary files /dev/null and b/test/packet_data/nx_controller2.raw differ diff --git a/test/packet_data/nx_ct(alg=ftp).raw b/test/packet_data/nx_ct(alg=ftp).raw new file mode 100644 index 0000000..3549456 Binary files /dev/null and b/test/packet_data/nx_ct(alg=ftp).raw differ diff --git a/test/packet_data/nx_ct(alg=tftp).raw b/test/packet_data/nx_ct(alg=tftp).raw new file mode 100644 index 0000000..c6b5a90 Binary files /dev/null and b/test/packet_data/nx_ct(alg=tftp).raw differ diff --git a/test/packet_data/nx_ct(commit).raw b/test/packet_data/nx_ct(commit).raw new file mode 100644 index 0000000..e9e8956 Binary files /dev/null and b/test/packet_data/nx_ct(commit).raw differ diff --git a/test/packet_data/nx_ct(commit, force).raw b/test/packet_data/nx_ct(commit, force).raw new file mode 100644 index 0000000..1df60e4 Binary files /dev/null and b/test/packet_data/nx_ct(commit, force).raw differ diff --git a/test/packet_data/nx_ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63])).raw b/test/packet_data/nx_ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63])).raw new file mode 100644 index 0000000..02667c5 Binary files /dev/null and b/test/packet_data/nx_ct(commit,exec(load:0->NXM_NX_CT_LABEL[64..127],load:0x1d->NXM_NX_CT_LABEL[0..63])).raw differ diff --git a/test/packet_data/nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw b/test/packet_data/nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw new file mode 100644 index 0000000..a780a64 Binary files /dev/null and b/test/packet_data/nx_ct(commit,exec(load:0xf009->NXM_NX_CT_MARK[])).raw differ diff --git a/test/packet_data/nx_ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[])).raw b/test/packet_data/nx_ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[])).raw new file mode 100644 index 0000000..46a0644 Binary files /dev/null and b/test/packet_data/nx_ct(commit,force,exec(load:0xf009->NXM_NX_CT_MARK[])).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(dst)).raw b/test/packet_data/nx_ct(commit,nat(dst)).raw new file mode 100644 index 0000000..160d237 Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(dst)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(dst=10.0.0.128-10.0.0.254,hash)).raw b/test/packet_data/nx_ct(commit,nat(dst=10.0.0.128-10.0.0.254,hash)).raw new file mode 100644 index 0000000..2dc561d Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(dst=10.0.0.128-10.0.0.254,hash)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src)).raw b/test/packet_data/nx_ct(commit,nat(src)).raw new file mode 100644 index 0000000..028206b Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=10.0.0.240,random)).raw b/test/packet_data/nx_ct(commit,nat(src=10.0.0.240,random)).raw new file mode 100644 index 0000000..f201bb0 Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=10.0.0.240,random)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent)).raw b/test/packet_data/nx_ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent)).raw new file mode 100644 index 0000000..9176b4a Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=10.0.0.240-10.0.0.254:32768-65535,persistent)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=10.0.0.240:32768-65535,random)).raw b/test/packet_data/nx_ct(commit,nat(src=10.0.0.240:32768-65535,random)).raw new file mode 100644 index 0000000..ab1b13a Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=10.0.0.240:32768-65535,random)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random)).raw b/test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random)).raw new file mode 100644 index 0000000..fd1eb9c Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random))fd.raw b/test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random))fd.raw new file mode 100644 index 0000000..fd1eb9c Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=[fe80::20c:29ff:fe88:1]-[fe80::20c:29ff:fe88:a18b]:255-4096,random))fd.raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random)).raw b/test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random)).raw new file mode 100644 index 0000000..7f10898 Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:1-fe80::20c:29ff:fe88:a18b,random)).raw differ diff --git a/test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:a18b,random)).raw b/test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:a18b,random)).raw new file mode 100644 index 0000000..52c9c6c Binary files /dev/null and b/test/packet_data/nx_ct(commit,nat(src=fe80::20c:29ff:fe88:a18b,random)).raw differ diff --git a/test/packet_data/nx_ct(nat).raw b/test/packet_data/nx_ct(nat).raw new file mode 100644 index 0000000..86595c3 Binary files /dev/null and b/test/packet_data/nx_ct(nat).raw differ diff --git a/test/packet_data/nx_ct(table=10).raw b/test/packet_data/nx_ct(table=10).raw new file mode 100644 index 0000000..72c42ec Binary files /dev/null and b/test/packet_data/nx_ct(table=10).raw differ diff --git a/test/packet_data/nx_ct(zone=10).raw b/test/packet_data/nx_ct(zone=10).raw new file mode 100644 index 0000000..5f43a0c Binary files /dev/null and b/test/packet_data/nx_ct(zone=10).raw differ diff --git a/test/packet_data/nx_ct(zone=NXM_NX_REG0[0..15]).raw b/test/packet_data/nx_ct(zone=NXM_NX_REG0[0..15]).raw new file mode 100644 index 0000000..d91f148 Binary files /dev/null and b/test/packet_data/nx_ct(zone=NXM_NX_REG0[0..15]).raw differ diff --git a/test/packet_data/nx_ct.raw b/test/packet_data/nx_ct.raw new file mode 100644 index 0000000..96358a5 Binary files /dev/null and b/test/packet_data/nx_ct.raw differ diff --git a/test/packet_data/nx_ct_clear.raw b/test/packet_data/nx_ct_clear.raw new file mode 100644 index 0000000..8cfac67 Binary files /dev/null and b/test/packet_data/nx_ct_clear.raw differ diff --git a/test/packet_data/nx_dec_ttl.raw b/test/packet_data/nx_dec_ttl.raw new file mode 100644 index 0000000..6b77e1b Binary files /dev/null and b/test/packet_data/nx_dec_ttl.raw differ diff --git a/test/packet_data/nx_dec_ttl_cnt_ids.raw b/test/packet_data/nx_dec_ttl_cnt_ids.raw new file mode 100644 index 0000000..5338bdf Binary files /dev/null and b/test/packet_data/nx_dec_ttl_cnt_ids.raw differ diff --git a/test/packet_data/nx_exit.raw b/test/packet_data/nx_exit.raw new file mode 100644 index 0000000..f6accc1 Binary files /dev/null and b/test/packet_data/nx_exit.raw differ diff --git a/test/packet_data/nx_fin_timeout.raw b/test/packet_data/nx_fin_timeout.raw new file mode 100644 index 0000000..a4cf557 Binary files /dev/null and b/test/packet_data/nx_fin_timeout.raw differ diff --git a/test/packet_data/nx_learn.raw b/test/packet_data/nx_learn.raw new file mode 100644 index 0000000..eb372f4 Binary files /dev/null and b/test/packet_data/nx_learn.raw differ diff --git a/test/packet_data/nx_learn2.raw b/test/packet_data/nx_learn2.raw new file mode 100644 index 0000000..55e900e Binary files /dev/null and b/test/packet_data/nx_learn2.raw differ diff --git a/test/packet_data/nx_multipath.raw b/test/packet_data/nx_multipath.raw new file mode 100644 index 0000000..2dcc917 Binary files /dev/null and b/test/packet_data/nx_multipath.raw differ diff --git a/test/packet_data/nx_note.raw b/test/packet_data/nx_note.raw new file mode 100644 index 0000000..19be9f7 Binary files /dev/null and b/test/packet_data/nx_note.raw differ diff --git a/test/packet_data/nx_output_reg.raw b/test/packet_data/nx_output_reg.raw new file mode 100644 index 0000000..0dd869e Binary files /dev/null and b/test/packet_data/nx_output_reg.raw differ diff --git a/test/packet_data/nx_output_trunc.raw b/test/packet_data/nx_output_trunc.raw new file mode 100644 index 0000000..29631eb Binary files /dev/null and b/test/packet_data/nx_output_trunc.raw differ diff --git a/test/packet_data/nx_packet_in2.raw b/test/packet_data/nx_packet_in2.raw new file mode 100644 index 0000000..d293c64 Binary files /dev/null and b/test/packet_data/nx_packet_in2.raw differ diff --git a/test/packet_data/nx_packet_in2_arp.raw b/test/packet_data/nx_packet_in2_arp.raw new file mode 100644 index 0000000..cbf807f Binary files /dev/null and b/test/packet_data/nx_packet_in2_arp.raw differ diff --git a/test/packet_data/nx_pop_queue.raw b/test/packet_data/nx_pop_queue.raw new file mode 100644 index 0000000..b1dd644 Binary files /dev/null and b/test/packet_data/nx_pop_queue.raw differ diff --git a/test/packet_data/nx_reg_load.raw b/test/packet_data/nx_reg_load.raw new file mode 100644 index 0000000..c5f0b4e Binary files /dev/null and b/test/packet_data/nx_reg_load.raw differ diff --git a/test/packet_data/nx_reg_move.raw b/test/packet_data/nx_reg_move.raw new file mode 100644 index 0000000..863a204 Binary files /dev/null and b/test/packet_data/nx_reg_move.raw differ diff --git a/test/packet_data/nx_resubmit.raw b/test/packet_data/nx_resubmit.raw new file mode 100644 index 0000000..5036884 Binary files /dev/null and b/test/packet_data/nx_resubmit.raw differ diff --git a/test/packet_data/nx_resubmit_table.raw b/test/packet_data/nx_resubmit_table.raw new file mode 100644 index 0000000..a115cfd Binary files /dev/null and b/test/packet_data/nx_resubmit_table.raw differ diff --git a/test/packet_data/nx_resubmit_table_ct.raw b/test/packet_data/nx_resubmit_table_ct.raw new file mode 100644 index 0000000..ff974d5 Binary files /dev/null and b/test/packet_data/nx_resubmit_table_ct.raw differ diff --git a/test/packet_data/nx_sample.raw b/test/packet_data/nx_sample.raw new file mode 100644 index 0000000..44c2437 Binary files /dev/null and b/test/packet_data/nx_sample.raw differ diff --git a/test/packet_data/nx_sample2.raw b/test/packet_data/nx_sample2.raw new file mode 100644 index 0000000..0c3dcdd Binary files /dev/null and b/test/packet_data/nx_sample2.raw differ diff --git a/test/packet_data/nx_sample3.raw b/test/packet_data/nx_sample3.raw new file mode 100644 index 0000000..8e7c421 Binary files /dev/null and b/test/packet_data/nx_sample3.raw differ diff --git a/test/packet_data/nx_set_controller_id.raw b/test/packet_data/nx_set_controller_id.raw new file mode 100644 index 0000000..6e82765 Binary files /dev/null and b/test/packet_data/nx_set_controller_id.raw differ diff --git a/test/packet_data/nx_set_packet_in_format.raw b/test/packet_data/nx_set_packet_in_format.raw new file mode 100644 index 0000000..ae11499 Binary files /dev/null and b/test/packet_data/nx_set_packet_in_format.raw differ diff --git a/test/packet_data/nx_set_queue.raw b/test/packet_data/nx_set_queue.raw new file mode 100644 index 0000000..f7da696 Binary files /dev/null and b/test/packet_data/nx_set_queue.raw differ diff --git a/test/packet_data/nx_set_tunnel.raw b/test/packet_data/nx_set_tunnel.raw new file mode 100644 index 0000000..baa9a5c Binary files /dev/null and b/test/packet_data/nx_set_tunnel.raw differ diff --git a/test/packet_data/nx_set_tunnel64.raw b/test/packet_data/nx_set_tunnel64.raw new file mode 100644 index 0000000..0106874 Binary files /dev/null and b/test/packet_data/nx_set_tunnel64.raw differ diff --git a/test/packet_data/ofp_echo_reply.raw b/test/packet_data/ofp_echo_reply.raw new file mode 100644 index 0000000..e54d380 Binary files /dev/null and b/test/packet_data/ofp_echo_reply.raw differ diff --git a/test/packet_data/ofp_echo_request.raw b/test/packet_data/ofp_echo_request.raw new file mode 100644 index 0000000..a13c95d Binary files /dev/null and b/test/packet_data/ofp_echo_request.raw differ diff --git a/test/packet_data/ofp_error.raw b/test/packet_data/ofp_error.raw new file mode 100644 index 0000000..196dad1 Binary files /dev/null and b/test/packet_data/ofp_error.raw differ diff --git a/test/packet_data/ofp_features_reply.raw b/test/packet_data/ofp_features_reply.raw new file mode 100644 index 0000000..1e5dee8 Binary files /dev/null and b/test/packet_data/ofp_features_reply.raw differ diff --git a/test/packet_data/ofp_features_request.raw b/test/packet_data/ofp_features_request.raw new file mode 100644 index 0000000..7bb2775 Binary files /dev/null and b/test/packet_data/ofp_features_request.raw differ diff --git a/test/packet_data/ofp_get_config_reply.raw b/test/packet_data/ofp_get_config_reply.raw new file mode 100644 index 0000000..b23f7bf Binary files /dev/null and b/test/packet_data/ofp_get_config_reply.raw differ diff --git a/test/packet_data/ofp_get_config_request.raw b/test/packet_data/ofp_get_config_request.raw new file mode 100644 index 0000000..78ad501 Binary files /dev/null and b/test/packet_data/ofp_get_config_request.raw differ diff --git a/test/packet_data/ofp_hello.raw b/test/packet_data/ofp_hello.raw new file mode 100644 index 0000000..644b413 Binary files /dev/null and b/test/packet_data/ofp_hello.raw differ diff --git a/test/packet_data/ofp_set_config.raw b/test/packet_data/ofp_set_config.raw new file mode 100644 index 0000000..43602b3 Binary files /dev/null and b/test/packet_data/ofp_set_config.raw differ diff --git a/test/packet_data/ovs-ofctl-of13-action_conjunction.packet b/test/packet_data/ovs-ofctl-of13-action_conjunction.packet new file mode 100644 index 0000000..ba029b2 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_conjunction.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_controller.packet b/test/packet_data/ovs-ofctl-of13-action_controller.packet new file mode 100644 index 0000000..8fba904 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_controller.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_controller2.packet b/test/packet_data/ovs-ofctl-of13-action_controller2.packet new file mode 100644 index 0000000..7e6b046 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_controller2.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_ct.packet b/test/packet_data/ovs-ofctl-of13-action_ct.packet new file mode 100644 index 0000000..5eb733f Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_ct.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_ct_exec.packet b/test/packet_data/ovs-ofctl-of13-action_ct_exec.packet new file mode 100644 index 0000000..3f0b343 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_ct_exec.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_ct_nat.packet b/test/packet_data/ovs-ofctl-of13-action_ct_nat.packet new file mode 100644 index 0000000..e210a38 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_ct_nat.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_ct_nat_v6.packet b/test/packet_data/ovs-ofctl-of13-action_ct_nat_v6.packet new file mode 100644 index 0000000..94b2aaa Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_ct_nat_v6.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_dec_ttl_cnt_ids.packet b/test/packet_data/ovs-ofctl-of13-action_dec_ttl_cnt_ids.packet new file mode 100644 index 0000000..c4308cc Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_dec_ttl_cnt_ids.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_fintimeout.packet b/test/packet_data/ovs-ofctl-of13-action_fintimeout.packet new file mode 100644 index 0000000..78c3eab Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_fintimeout.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_learn.packet b/test/packet_data/ovs-ofctl-of13-action_learn.packet new file mode 100644 index 0000000..39c71e2 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_learn.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_note.packet b/test/packet_data/ovs-ofctl-of13-action_note.packet new file mode 100644 index 0000000..9a1491c Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_note.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_output_trunc.packet b/test/packet_data/ovs-ofctl-of13-action_output_trunc.packet new file mode 100644 index 0000000..491cf4c Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_output_trunc.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_resubmit.packet b/test/packet_data/ovs-ofctl-of13-action_resubmit.packet new file mode 100644 index 0000000..690b978 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_resubmit.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_sample.packet b/test/packet_data/ovs-ofctl-of13-action_sample.packet new file mode 100644 index 0000000..c5167ba Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_sample.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_sample2.packet b/test/packet_data/ovs-ofctl-of13-action_sample2.packet new file mode 100644 index 0000000..444f094 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_sample2.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_stack_pop.packet b/test/packet_data/ovs-ofctl-of13-action_stack_pop.packet new file mode 100644 index 0000000..d6f99e2 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_stack_pop.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-action_stack_push.packet b/test/packet_data/ovs-ofctl-of13-action_stack_push.packet new file mode 100644 index 0000000..e5d38a3 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-action_stack_push.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-match_conj.packet b/test/packet_data/ovs-ofctl-of13-match_conj.packet new file mode 100644 index 0000000..1f9c57c Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-match_conj.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-match_load_nx_register.packet b/test/packet_data/ovs-ofctl-of13-match_load_nx_register.packet new file mode 100644 index 0000000..03ce737 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-match_load_nx_register.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-match_move_nx_register.packet b/test/packet_data/ovs-ofctl-of13-match_move_nx_register.packet new file mode 100644 index 0000000..eb9cf8a Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-match_move_nx_register.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-match_pkt_mark.packet b/test/packet_data/ovs-ofctl-of13-match_pkt_mark.packet new file mode 100644 index 0000000..46ea0dc Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-match_pkt_mark.packet differ diff --git a/test/packet_data/ovs-ofctl-of13-match_pkt_mark_masked.packet b/test/packet_data/ovs-ofctl-of13-match_pkt_mark_masked.packet new file mode 100644 index 0000000..26db6b9 Binary files /dev/null and b/test/packet_data/ovs-ofctl-of13-match_pkt_mark_masked.packet differ diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..135c19a --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.configure(seed: 0) +ExUnit.start(trace: true) diff --git a/test/tres_test.exs b/test/tres_test.exs new file mode 100644 index 0000000..24ae030 --- /dev/null +++ b/test/tres_test.exs @@ -0,0 +1,4 @@ +defmodule TresTest do + use ExUnit.Case + doctest Tres +end