diff --git a/.gitignore b/.gitignore index 674fc49..aeed094 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ erl_crash.dump # Examples */polaris/* + +/bin/enum_gen diff --git a/bin/enum_gen b/bin/enum_gen deleted file mode 100755 index d527668..0000000 Binary files a/bin/enum_gen and /dev/null differ diff --git a/config/config.exs b/config/config.exs index 40896b3..c04ed23 100644 --- a/config/config.exs +++ b/config/config.exs @@ -11,7 +11,7 @@ config :tres, callback_args: [] config :logger, - level: :info, - format: "$date $time [$level] $metadata$message\n", - metadata: [:application], + level: :debug, + format: "$date $time [$level] $message\n", + metadata: [], handle_otp_reports: true diff --git a/examples/leader_example/lib/leader_example/leader.ex b/examples/leader_example/lib/leader_example/leader.ex index 44fad09..f895dc1 100644 --- a/examples/leader_example/lib/leader_example/leader.ex +++ b/examples/leader_example/lib/leader_example/leader.ex @@ -5,7 +5,7 @@ defmodule LeaderExample.Leader do require Logger - def start_link([datapath_id, args]) do + def start_link(datapath_id, args) do :locks_leader.start_link(__MODULE__, [datapath_id, args], []) end diff --git a/examples/learning_switch/lib/learning_switch/ofctl.ex b/examples/learning_switch/lib/learning_switch/ofctl.ex index c060fec..0abaef1 100644 --- a/examples/learning_switch/lib/learning_switch/ofctl.ex +++ b/examples/learning_switch/lib/learning_switch/ofctl.ex @@ -22,7 +22,7 @@ defmodule LearningSwitch.Ofctl do ] end - def start_link([datapath_id, args]) do + def start_link(datapath_id, args) do GenServer.start_link(__MODULE__, [datapath_id, args]) end diff --git a/examples/patch_panel/lib/patch_panel/openflow/controller.ex b/examples/patch_panel/lib/patch_panel/openflow/controller.ex index ac12470..bbecf04 100644 --- a/examples/patch_panel/lib/patch_panel/openflow/controller.ex +++ b/examples/patch_panel/lib/patch_panel/openflow/controller.ex @@ -26,7 +26,7 @@ defmodule PatchPanel.Openflow.Controller do end end - def start_link([{datapath_id, _aux_id}, _start_args]) do + def start_link({datapath_id, _aux_id}, _start_args) do GenServer.start_link(__MODULE__, [datapath_id]) end diff --git a/examples/simple_router/lib/simple_router/openflow/controller.ex b/examples/simple_router/lib/simple_router/openflow/controller.ex index 95b2146..16dfa80 100644 --- a/examples/simple_router/lib/simple_router/openflow/controller.ex +++ b/examples/simple_router/lib/simple_router/openflow/controller.ex @@ -21,7 +21,7 @@ defmodule SimpleRouter.Openflow.Controller do ] end - def start_link([{datapath_id, _aux_id}, _start_args]) do + def start_link({datapath_id, _aux_id}, _start_args) do GenServer.start_link(__MODULE__, [datapath_id]) end diff --git a/lib/tres/example_handler.ex b/lib/tres/example_handler.ex index 6a392bc..88436ca 100644 --- a/lib/tres/example_handler.ex +++ b/lib/tres/example_handler.ex @@ -10,13 +10,13 @@ defmodule Tres.ExampleHandler do conn_ref: nil end - def start_link([datapath, args]) do + 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: " <> + "Switch Ready: " <> "datapath_id: #{datapath_id} " <> "aux_id: #{aux_id} " <> "on #{inspect(self())}" ) @@ -36,14 +36,19 @@ defmodule Tres.ExampleHandler do {:noreply, state} end + def handle_info({:switch_disconnected, _reason}, state) do + :ok = warn("Switch disconnected") + {:stop, :normal, state} + end + def handle_info({:switch_hang, _datapath_id}, state) do - :ok = warn("[#{__MODULE__}] Switch possible hang: datapath_id: #{state.datapath_id}") + :ok = warn("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}") + :ok = warn("unhandled message #{inspect(info)}: #{state.datapath_id}") {:noreply, state} end @@ -61,7 +66,7 @@ defmodule Tres.ExampleHandler do defp handle_desc_stats_reply(desc, datapath_id) do info( - "[#{__MODULE__}] Switch Desc: " <> + "Switch Desc: " <> "mfr = #{desc.mfr_desc} " <> "hw = #{desc.hw_desc} " <> "sw = #{desc.sw_desc} " <> "for #{datapath_id}" ) @@ -70,7 +75,7 @@ defmodule Tres.ExampleHandler do defp handle_port_desc_stats_reply(port_desc, datapath_id) do for port <- port_desc.ports do info( - "[#{__MODULE__}] Switch has port: " <> + "Switch has port: " <> "number = #{port.number} " <> "hw_addr = #{port.hw_addr} " <> "name = #{port.name} " <> diff --git a/lib/tres/message_handler_sup.ex b/lib/tres/message_handler_sup.ex index 6797ffb..81a277f 100644 --- a/lib/tres/message_handler_sup.ex +++ b/lib/tres/message_handler_sup.ex @@ -1,34 +1,19 @@ defmodule Tres.MessageHandlerSup do use Supervisor - def start_link() do - Supervisor.start_link(__MODULE__, [], name: __MODULE__) - end - - def init(_init_args) do - children = [] - - Supervisor.init( - children, - strategy: :one_for_one, - max_restarts: 5, - max_seconds: 10 - ) - end + # API functions def start_child(dpid) do - {cb_mod, _cb_args} = Tres.Utils.get_callback_module() - child_spec = cb_mod.handler_spec(dpid) - {:ok, pid} = Supervisor.start_child(__MODULE__, child_spec) + {_cb_mod, cb_args} = Tres.Utils.get_callback_module() + {:ok, pid} = Supervisor.start_child(__MODULE__, [dpid, cb_args]) :ok = Tres.SwitchRegistry.register_handler_pid(dpid, pid) {:ok, pid} end def terminate_child(dpid) do {cb_mod, _cb_args} = Tres.Utils.get_callback_module() - child_spec = cb_mod.handler_spec(dpid) - _ = Supervisor.terminate_child(__MODULE__, child_spec[:id]) - _ = Supervisor.delete_child(__MODULE__, child_spec[:id]) + _ = Supervisor.terminate_child(__MODULE__, {cb_mod, dpid}) + _ = Supervisor.delete_child(__MODULE__, {cb_mod, dpid}) end @spec count_handlers() :: non_neg_integer() @@ -36,4 +21,37 @@ defmodule Tres.MessageHandlerSup do count_value = Supervisor.count_children(__MODULE__) count_value[:active] end + + def start_link do + Supervisor.start_link(__MODULE__, [], name: __MODULE__) + end + + # supervisor callback functions + + @impl Supervisor + def init(_init_args) do + children = [handler_spec()] + + Supervisor.init( + children, + strategy: :simple_one_for_one, + max_restarts: 10, + max_seconds: 10 + ) + end + + # private functions + + defp handler_spec do + {cb_mod, _cb_args} = Tres.Utils.get_callback_module() + + %{ + id: :undefined, + start: {cb_mod, :start_link, []}, + restart: :temporary, + shutdown: 5000, + type: :worker, + modules: [cb_mod] + } + end end diff --git a/lib/tres/secure_channel.ex b/lib/tres/secure_channel.ex index f8520e3..c89aaff 100644 --- a/lib/tres/secure_channel.ex +++ b/lib/tres/secure_channel.ex @@ -56,6 +56,7 @@ defmodule Tres.SecureChannel do end def handle_event(:info, {:tcp_closed, socket}, _state, %State{socket: socket} = state_data) do + :ok = debug("TCP disconnected with #{state_data.ip_addr}:#{state_data.port}") close_connection(:tcp_closed, state_data) end @@ -609,7 +610,6 @@ defmodule Tres.SecureChannel do defp close_connection(:handler_error, state_data) do debug("connection terminated: Got handler error") - _ = send(state_data.handler_pid, {:switch_disconnected, :handler_error}) {:stop, :normal, %{state_data | socket: nil}} end @@ -627,6 +627,7 @@ defmodule Tres.SecureChannel do defp close_connection({:handler_down, reason}, state_data) do debug("connection terminated: Handler process down by #{inspect(reason)}") + _ = send(state_data.handler_pid, {:switch_disconnected, :handler_error}) {:stop, :normal, %{state_data | socket: nil}} end diff --git a/lib/tres/secure_channel_state.ex b/lib/tres/secure_channel_state.ex index 6ab8283..e5312c0 100644 --- a/lib/tres/secure_channel_state.ex +++ b/lib/tres/secure_channel_state.ex @@ -1,4 +1,6 @@ defmodule Tres.SecureChannelState do + use Bitwise + defstruct( handler_pid: nil, handler_ref: nil, @@ -43,26 +45,27 @@ defmodule Tres.SecureChannelState do } end - def increment_transaction_id(table_ref) do - :ets.update_counter(table_ref, :datapath_xid, {2, 1, 0xFFFFFFFF, 0}) + @spec increment_transaction_id(:counters.counters_ref()) :: integer() + def increment_transaction_id(counter_ref) do + :ok = :counters.add(counter_ref, 1, 1) + get_transaction_id(counter_ref) end - def set_transaction_id(table_ref, xid) do - :ets.insert(table_ref, {:datapath_xid, xid}) + @spec set_transaction_id(:counters.counters_ref(), integer()) :: integer() + def set_transaction_id(counter_ref, xid) do + :ok = :counters.put(counter_ref, 1, xid) + get_transaction_id(counter_ref) end - def get_transaction_id(table_ref) do - case :ets.lookup(table_ref, :datapath_xid) do - [{_, xid} | _] -> xid - end + @spec get_transaction_id(:counters.counters_ref()) :: integer() + def get_transaction_id(counter_ref) do + :counters.get(counter_ref, 1) &&& 0xffffffff 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} + {:ok, :counters.new(1, [])} end end