]secure_channel: Use counter module for transaction id

This commit is contained in:
Eishun Kondoh 2018-12-12 01:25:59 +09:00
parent 97b957742f
commit 1834d882ff
11 changed files with 74 additions and 45 deletions

2
.gitignore vendored
View file

@ -21,3 +21,5 @@ erl_crash.dump
# Examples # Examples
*/polaris/* */polaris/*
/bin/enum_gen

Binary file not shown.

View file

@ -11,7 +11,7 @@ config :tres,
callback_args: [] callback_args: []
config :logger, config :logger,
level: :info, level: :debug,
format: "$date $time [$level] $metadata$message\n", format: "$date $time [$level] $message\n",
metadata: [:application], metadata: [],
handle_otp_reports: true handle_otp_reports: true

View file

@ -5,7 +5,7 @@ defmodule LeaderExample.Leader do
require Logger require Logger
def start_link([datapath_id, args]) do def start_link(datapath_id, args) do
:locks_leader.start_link(__MODULE__, [datapath_id, args], []) :locks_leader.start_link(__MODULE__, [datapath_id, args], [])
end end

View file

@ -22,7 +22,7 @@ defmodule LearningSwitch.Ofctl do
] ]
end end
def start_link([datapath_id, args]) do def start_link(datapath_id, args) do
GenServer.start_link(__MODULE__, [datapath_id, args]) GenServer.start_link(__MODULE__, [datapath_id, args])
end end

View file

@ -26,7 +26,7 @@ defmodule PatchPanel.Openflow.Controller do
end end
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]) GenServer.start_link(__MODULE__, [datapath_id])
end end

View file

@ -21,7 +21,7 @@ defmodule SimpleRouter.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]) GenServer.start_link(__MODULE__, [datapath_id])
end end

View file

@ -10,13 +10,13 @@ defmodule Tres.ExampleHandler do
conn_ref: nil conn_ref: nil
end end
def start_link([datapath, args]) do def start_link(datapath, args) do
GenServer.start_link(__MODULE__, [datapath, args]) GenServer.start_link(__MODULE__, [datapath, args])
end end
def init([{datapath_id, aux_id}, _args]) do def init([{datapath_id, aux_id}, _args]) do
info( info(
"[#{__MODULE__}] Switch Ready: " <> "Switch Ready: " <>
"datapath_id: #{datapath_id} " <> "aux_id: #{aux_id} " <> "on #{inspect(self())}" "datapath_id: #{datapath_id} " <> "aux_id: #{aux_id} " <> "on #{inspect(self())}"
) )
@ -36,14 +36,19 @@ defmodule Tres.ExampleHandler do
{:noreply, state} {:noreply, state}
end 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 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} {:noreply, state}
end end
# `Catch all` function is required. # `Catch all` function is required.
def handle_info(info, state) do 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} {:noreply, state}
end end
@ -61,7 +66,7 @@ defmodule Tres.ExampleHandler do
defp handle_desc_stats_reply(desc, datapath_id) do defp handle_desc_stats_reply(desc, datapath_id) do
info( info(
"[#{__MODULE__}] Switch Desc: " <> "Switch Desc: " <>
"mfr = #{desc.mfr_desc} " <> "mfr = #{desc.mfr_desc} " <>
"hw = #{desc.hw_desc} " <> "sw = #{desc.sw_desc} " <> "for #{datapath_id}" "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 defp handle_port_desc_stats_reply(port_desc, datapath_id) do
for port <- port_desc.ports do for port <- port_desc.ports do
info( info(
"[#{__MODULE__}] Switch has port: " <> "Switch has port: " <>
"number = #{port.number} " <> "number = #{port.number} " <>
"hw_addr = #{port.hw_addr} " <> "hw_addr = #{port.hw_addr} " <>
"name = #{port.name} " <> "name = #{port.name} " <>

View file

@ -1,34 +1,19 @@
defmodule Tres.MessageHandlerSup do defmodule Tres.MessageHandlerSup do
use Supervisor use Supervisor
def start_link() do # API functions
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
def start_child(dpid) do def start_child(dpid) do
{cb_mod, _cb_args} = Tres.Utils.get_callback_module() {_cb_mod, cb_args} = Tres.Utils.get_callback_module()
child_spec = cb_mod.handler_spec(dpid) {:ok, pid} = Supervisor.start_child(__MODULE__, [dpid, cb_args])
{:ok, pid} = Supervisor.start_child(__MODULE__, child_spec)
:ok = Tres.SwitchRegistry.register_handler_pid(dpid, pid) :ok = Tres.SwitchRegistry.register_handler_pid(dpid, pid)
{:ok, pid} {:ok, pid}
end end
def terminate_child(dpid) do def terminate_child(dpid) do
{cb_mod, _cb_args} = Tres.Utils.get_callback_module() {cb_mod, _cb_args} = Tres.Utils.get_callback_module()
child_spec = cb_mod.handler_spec(dpid) _ = Supervisor.terminate_child(__MODULE__, {cb_mod, dpid})
_ = Supervisor.terminate_child(__MODULE__, child_spec[:id]) _ = Supervisor.delete_child(__MODULE__, {cb_mod, dpid})
_ = Supervisor.delete_child(__MODULE__, child_spec[:id])
end end
@spec count_handlers() :: non_neg_integer() @spec count_handlers() :: non_neg_integer()
@ -36,4 +21,37 @@ defmodule Tres.MessageHandlerSup do
count_value = Supervisor.count_children(__MODULE__) count_value = Supervisor.count_children(__MODULE__)
count_value[:active] count_value[:active]
end 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 end

View file

@ -56,6 +56,7 @@ defmodule Tres.SecureChannel do
end end
def handle_event(:info, {:tcp_closed, socket}, _state, %State{socket: socket} = state_data) do 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) close_connection(:tcp_closed, state_data)
end end
@ -609,7 +610,6 @@ defmodule Tres.SecureChannel do
defp close_connection(:handler_error, state_data) do defp close_connection(:handler_error, state_data) do
debug("connection terminated: Got handler error") debug("connection terminated: Got handler error")
_ = send(state_data.handler_pid, {:switch_disconnected, :handler_error})
{:stop, :normal, %{state_data | socket: nil}} {:stop, :normal, %{state_data | socket: nil}}
end end
@ -627,6 +627,7 @@ defmodule Tres.SecureChannel do
defp close_connection({:handler_down, reason}, state_data) do defp close_connection({:handler_down, reason}, state_data) do
debug("connection terminated: Handler process down by #{inspect(reason)}") debug("connection terminated: Handler process down by #{inspect(reason)}")
_ = send(state_data.handler_pid, {:switch_disconnected, :handler_error})
{:stop, :normal, %{state_data | socket: nil}} {:stop, :normal, %{state_data | socket: nil}}
end end

View file

@ -1,4 +1,6 @@
defmodule Tres.SecureChannelState do defmodule Tres.SecureChannelState do
use Bitwise
defstruct( defstruct(
handler_pid: nil, handler_pid: nil,
handler_ref: nil, handler_ref: nil,
@ -43,26 +45,27 @@ defmodule Tres.SecureChannelState do
} }
end end
def increment_transaction_id(table_ref) do @spec increment_transaction_id(:counters.counters_ref()) :: integer()
:ets.update_counter(table_ref, :datapath_xid, {2, 1, 0xFFFFFFFF, 0}) def increment_transaction_id(counter_ref) do
:ok = :counters.add(counter_ref, 1, 1)
get_transaction_id(counter_ref)
end end
def set_transaction_id(table_ref, xid) do @spec set_transaction_id(:counters.counters_ref(), integer()) :: integer()
:ets.insert(table_ref, {:datapath_xid, xid}) def set_transaction_id(counter_ref, xid) do
:ok = :counters.put(counter_ref, 1, xid)
get_transaction_id(counter_ref)
end end
def get_transaction_id(table_ref) do @spec get_transaction_id(:counters.counters_ref()) :: integer()
case :ets.lookup(table_ref, :datapath_xid) do def get_transaction_id(counter_ref) do
[{_, xid} | _] -> xid :counters.get(counter_ref, 1) &&& 0xffffffff
end
end end
# private functions # private functions
@spec create_counter() :: reference() @spec create_counter() :: reference()
defp create_counter do defp create_counter do
table_ref = :ets.new(:xid_counter, [:set, :private]) {:ok, :counters.new(1, [])}
_ = :ets.insert(table_ref, {:datapath_xid, 0})
{:ok, table_ref}
end end
end end