From 270d01b626435db296ed9c7ba16f533ec7c56271 Mon Sep 17 00:00:00 2001 From: Eishun Kondoh Date: Wed, 5 Jun 2019 01:18:25 +0900 Subject: [PATCH] example: Add example for NXAST_LEARN --- examples/nx_learning_switch/.formatter.exs | 4 + examples/nx_learning_switch/.gitignore | 24 +++++ examples/nx_learning_switch/README.md | 3 + examples/nx_learning_switch/config/config.exs | 17 ++++ .../lib/nx_learning_switch.ex | 93 +++++++++++++++++++ examples/nx_learning_switch/mix.exs | 27 ++++++ examples/nx_learning_switch/mix.lock | 3 + .../test/nx_learning_switch_test.exs | 8 ++ .../nx_learning_switch/test/test_helper.exs | 1 + 9 files changed, 180 insertions(+) create mode 100644 examples/nx_learning_switch/.formatter.exs create mode 100644 examples/nx_learning_switch/.gitignore create mode 100644 examples/nx_learning_switch/README.md create mode 100644 examples/nx_learning_switch/config/config.exs create mode 100644 examples/nx_learning_switch/lib/nx_learning_switch.ex create mode 100644 examples/nx_learning_switch/mix.exs create mode 100644 examples/nx_learning_switch/mix.lock create mode 100644 examples/nx_learning_switch/test/nx_learning_switch_test.exs create mode 100644 examples/nx_learning_switch/test/test_helper.exs diff --git a/examples/nx_learning_switch/.formatter.exs b/examples/nx_learning_switch/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/examples/nx_learning_switch/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/examples/nx_learning_switch/.gitignore b/examples/nx_learning_switch/.gitignore new file mode 100644 index 0000000..3db6a2c --- /dev/null +++ b/examples/nx_learning_switch/.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 third-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"). +nx_learning_switch-*.tar + diff --git a/examples/nx_learning_switch/README.md b/examples/nx_learning_switch/README.md new file mode 100644 index 0000000..927c08c --- /dev/null +++ b/examples/nx_learning_switch/README.md @@ -0,0 +1,3 @@ +# NxLearningSwitch + +Example for a very simple-minded MAC learning switch diff --git a/examples/nx_learning_switch/config/config.exs b/examples/nx_learning_switch/config/config.exs new file mode 100644 index 0000000..b8b6603 --- /dev/null +++ b/examples/nx_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: NxLearningSwitch, + callback_args: [] + +config :logger, + level: :debug, + format: "$date $time [$level] $metadata$message\n", + metadata: [:application], + handle_otp_reports: true diff --git a/examples/nx_learning_switch/lib/nx_learning_switch.ex b/examples/nx_learning_switch/lib/nx_learning_switch.ex new file mode 100644 index 0000000..08214a1 --- /dev/null +++ b/examples/nx_learning_switch/lib/nx_learning_switch.ex @@ -0,0 +1,93 @@ +defmodule NxLearningSwitch do + @moduledoc """ + Emulates Layer2 switch + """ + + use GenServer + use Tres.Controller + + import Logger + + # API functions + + def start_link(datapath_id, _args) do + GenServer.start_link(__MODULE__, [datapath_id]) + end + + # GenServer callback functions + + @impl GenServer + def init([{datapath_id, _aux_id}]) do + :ok = info("Connected: datapath_id: #{datapath_id}") + {:ok, datapath_id, {:continue, :init}} + end + + @impl GenServer + def handle_continue(:init, datapath_id) do + :ok = l2_learning_flow(datapath_id) + :ok = l2_flooding_flows(datapath_id) + {:noreply, datapath_id} + end + + @impl GenServer + def handle_call(_request, _from, state) do + {:reply, :ok, state} + end + + @impl GenServer + def handle_cast(_request, state) do + {:noreply, state} + end + + @impl GenServer + def handle_info({:switch_disconnected, reason}, datapath_id) do + :ok = warn("Disconnected: datapath_id: #{datapath_id} by #{inspect(reason)}") + {:stop, :normal, datapath_id} + end + + @impl GenServer + def handle_info(_info, state) do + {:noreply, state} + end + + ## private functions + + defp l2_learning_flow(datapath_id) do + send_flow_mod_add( + datapath_id, + table_id: 0, + instructions: ApplyActions.new([ + NxLearn.new( + table_id: 1, + priority: 2, + hard_timeout: 10, + flow_specs: [ + NxFlowSpecMatch.new( + src: :nx_eth_src, + dst: :nx_eth_dst + ), + NxFlowSpecMatch.new( + src: :nx_vlan_tci, + dst: :nx_vlan_tci, + offset: 0, + n_bits: 12 + ), + NxFlowSpecOutput.new( + src: :nx_in_port + ) + ] + ), + NxResubmitTable.new(1) + ]) + ) + end + + defp l2_flooding_flows(datapath_id) do + send_flow_mod_add( + datapath_id, + table_id: 1, + priority: 0, + instructions: ApplyActions.new(Output.new(:flood)) + ) + end +end diff --git a/examples/nx_learning_switch/mix.exs b/examples/nx_learning_switch/mix.exs new file mode 100644 index 0000000..0d6c717 --- /dev/null +++ b/examples/nx_learning_switch/mix.exs @@ -0,0 +1,27 @@ +defmodule NxLearningSwitch.MixProject do + use Mix.Project + + def project do + [ + app: :nx_learning_switch, + version: "0.1.0", + elixir: "~> 1.8", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:tres, path: "../../../tres"} + ] + end +end diff --git a/examples/nx_learning_switch/mix.lock b/examples/nx_learning_switch/mix.lock new file mode 100644 index 0000000..becf0a3 --- /dev/null +++ b/examples/nx_learning_switch/mix.lock @@ -0,0 +1,3 @@ +%{ + "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"}, +} diff --git a/examples/nx_learning_switch/test/nx_learning_switch_test.exs b/examples/nx_learning_switch/test/nx_learning_switch_test.exs new file mode 100644 index 0000000..a9e8311 --- /dev/null +++ b/examples/nx_learning_switch/test/nx_learning_switch_test.exs @@ -0,0 +1,8 @@ +defmodule NxLearningSwitchTest do + use ExUnit.Case + doctest NxLearningSwitch + + test "greets the world" do + assert NxLearningSwitch.hello() == :world + end +end diff --git a/examples/nx_learning_switch/test/test_helper.exs b/examples/nx_learning_switch/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/examples/nx_learning_switch/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start()