secure_channel: Use counter module for transaction id
This commit is contained in:
parent
97b957742f
commit
4ea72c73b4
11 changed files with 74 additions and 45 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -21,3 +21,5 @@ erl_crash.dump
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
*/polaris/*
|
*/polaris/*
|
||||||
|
|
||||||
|
/bin/enum_gen
|
||||||
|
|
|
||||||
BIN
bin/enum_gen
BIN
bin/enum_gen
Binary file not shown.
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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} " <>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue