stubbed out ovsdb client handler

This commit is contained in:
Helge
2020-11-18 16:50:11 -08:00
parent 16a55f12a4
commit 0cd907bd70
4 changed files with 396 additions and 129 deletions

View File

@@ -16,7 +16,7 @@
-ifdef(debug).
-define(DBGTRC(Msg), io:format("~s:~s (~p) => ~s~n",[?MODULE,?FUNCTION_NAME,?LINE,Msg])).
-define(DBGSTR(Msg), io_lib:format("~s:~s (~B) => -s~n",[?MODULE,?FUNCTION_NAME,?LINE,Msg])).
-define(DBGSTR(Msg), io_lib:format("~s:~s (~B) => ~s~n",[?MODULE,?FUNCTION_NAME,?LINE,Msg])).
-define(DBGSTR(FMsg,Args), io_lib:format("~s:~s (~B) => " FMsg "~n",[?MODULE,?FUNCTION_NAME,?LINE] ++ [Args])).
-else.
-define(DBGTRC(Msg), true).

214
src/ovsdb_ap.erl Normal file
View File

@@ -0,0 +1,214 @@
%%%----------------------------------------------------------------------------
%%% @author helge
%%% @copyright (C) 2020, Arilia Wireless Inc.
%%% @doc
%%%
%%% @end
%%% Created : 16. Nov 2020 12:44 p.m.
%%%----------------------------------------------------------------------------
-module(ovsdb_ap).
-author("helge").
-behaviour(gen_server).
-include("../include/common.hrl").
-define(SERVER, ?MODULE).
%%-----------------------------------------------------------------------------
%% @doc The SPEC for starting a AP node is a proplist with the following fileds.
%%
%% {manager, ::pid()} - the pid of the simmanager used to get configuration.
%% {ap_serial, ::string()} - the serial number of the AP.
%% {ap_type, ::binary()} - type of AP to simulate e.g. EA8300.
%% {uuid, ::term()} - arbitrary unique id to identify this simnode AP.
%% @end
%%-----------------------------------------------------------------------------
%% API
-export([start/2]).
-export([uuid/1]).
%% gen_server callbacks
-export([init/1, handle_cast/2, handle_call/3, handle_info/2, terminate/2, code_change/3]).
%% data structures
-record(ap_state, {
sim_node :: pid(), % controlling simnode
sim_manager :: pid(), % manager to be contacted to get configuration
serial :: string(), % serial number of the access point
type :: binary(), % device type e.g. EA8300
uuid :: term(), % unique ID for this AP node
timer :: owls_timers:tms(),
status = init :: init | ready | running | stopped, % internal status
config = #{} :: map(),
statistics = #{} :: map()
}).
%%%============================================================================
%%% API
%%%============================================================================
-spec start (Handler, Spec) -> {ok, Pid} | {error, Reason} when
Handler :: pid(),
Spec :: proplists:proplist(),
Pid :: pid(),
Reason :: term().
start (Handler, Spec) ->
gen_server:start(?MODULE, {Handler, Spec}, []).
-spec uuid (Node) -> Uuid when
Node :: pid(),
Uuid :: term().
uuid (Node) ->
gen_server:call(Node,ap_uuid).
%%%============================================================================
%%% GEN_SERVER callbacks
%%%============================================================================
-spec init ({Handler, Spec}) -> {ok, State} when
Handler :: pid(),
Spec :: proplists:proplist(),
State :: #ap_state{}.
init ({Handler,Spec}) ->
process_flag(trap_exit, true),
InitialState = prepare_state(Handler,Spec),
gen_server:cast(self(),start_up),
{ok, InitialState}.
-spec handle_cast (Request, State) -> {noreply, NewState} | {stop, Reason, NewState} when
Request :: term(),
State :: #ap_state{},
NewState :: #ap_state{},
Reason :: string().
handle_cast (start_up, State) ->
{ok, NewState} = startup_ap(State),
State#ap_state.sim_node ! {ready, {self(), State#ap_state.uuid}},
{noreply, NewState};
handle_cast (R,State) ->
?L_E(?DBGSTR("got unknown request: ~p",[R])),
{noreply, State}.
-spec handle_call (Request, From, State) -> {reply, Reply, NewState} | {stop, Reason, Reply, NewState} when
Request :: term(),
From :: {pid(),Tag::term()},
State :: #ap_state{},
Reply :: term(),
Reason :: term(),
NewState :: #ap_state{}.
handle_call (ap_uuid,_,State) ->
{reply, State#ap_state.uuid, State};
handle_call (Request, From, State) ->
?L_E(?DBGSTR("got unknow request ~p from ~p",[Request,From])),
{reply, invalid, State}.
-spec handle_info (Msg, State) -> {noreply, NewState} when
Msg :: term(),
State :: #ap_state{},
NewState :: #ap_state{}.
handle_info({'EXIT', _Pid, _Reason}, State) ->
%% @TODO: implement proper restart strategy for linked processes
{noreply, State};
handle_info (Msg,State) ->
?L_E(?DBGSTR("got unexpected info message ~p",[Msg])),
{noreply, State}.
-spec terminate (Reason, State) -> ok when
Reason :: shutdown | normal,
State :: #ap_state{}.
terminate (_Reason, _State) ->
ok.
-spec code_change (OldVersion, OldState, Extra) -> {ok, NewState} when
OldVersion :: term(),
OldState ::#ap_state{},
Extra :: term(),
NewState :: #ap_state{}.
code_change (_,OldState,_) ->
?L_E(?DBGSTR("code change requested")),
{ok, OldState}.
%%%============================================================================
%%% internal functions
%%%============================================================================
%---------prepare_state/2----------------convert Spec proplist into internal state
-spec prepare_state (Node, Spec) -> State when
Node :: pid(),
Spec :: proplists:proplist(),
State :: #ap_state{}.
prepare_state (Node,Spec) ->
#ap_state{
sim_node = Node,
sim_manager = proplists:get_value(manager,Spec,Node),
serial = proplists:get_value(ap_serial,Spec,"1P000000000"),
type = proplists:get_value(ap_type,Spec,<<"EA8300">>),
uuid = proplists:get_value(uuid,Spec,erlang:phash2({node(),erlang:system_time()})),
timer = owls_timers:new(millisecond)
}.
%--------startup_ap/1--------------------initiate startup sequence
-spec startup_ap (State) -> {ok, NewState} | {error, Reason} when
State :: #ap_state{},
NewState :: #ap_state{},
Reason :: string().
startup_ap (#ap_state{status=init}=State) ->
{ok,State#ap_state{status=ready}};
startup_ap (_) ->
{error,"not in initial state, cant start-up"}.

View File

@@ -1,128 +0,0 @@
%%%-------------------------------------------------------------------
%%% @author helge
%%% @copyright (C) 2020, Arilia Wireless Inc.
%%% @doc
%%%
%%% @end
%%% Created : 16. Nov 2020 12:44 p.m.
%%%-------------------------------------------------------------------
-module(ovsdb_client).
-author("helge").
-behaviour(gen_server).
-include("../include/common.hrl").
-define(SERVER, ?MODULE).
%% API
-export([start_link/2]).
%% gen_server callbacks
-export([init/1, handle_cast/2, handle_call/3]). %, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
%% data structures
-record(client_state, {
sim_node :: pid(), % controlling simnode
sim_manager :: pid(), % manager to be contacted to get configuration
serial :: string(), % serial number of the access point
type :: binary(), % device type e.g. EA8300
timer :: owls_timers:tms(),
satus = init :: init | ready | running | stopped, % internal status
config = #{} :: map(),
statistics = #{} :: map()
}).
%%%============================================================================
%%% API
%%%============================================================================
-spec start_link(CallbackNode::pid(), Spec::proplists:proplist()) ->
{ok, Pid :: pid()}.
start_link(Node,Spec) ->
gen_server:start_link(?MODULE, {Node,Spec}, []).
%%%============================================================================
%%% GEN_SERVER callbacks
%%%============================================================================
-spec init ({Node, Spec}) -> {ok, State} when
Node :: pid(),
Spec :: proplists:proplist(),
State :: #client_state{}.
init ({Node,Spec}) ->
InitialState = prepare_state(Node,Spec),
gen_server:cast(self(),start_up),
{ok, InitialState}.
-spec handle_cast (Request, State) -> {noreply, NewState} | {stop, Reason, NewState} when
Request :: term(),
State :: #client_state{},
NewState :: #client_state{},
Reason :: string().
handle_cast (start_up, State) ->
%TODO: startup
{noreply, State};
handle_cast (R,State) ->
?L_E(?DBGSTR("got unknown request: ~p",[R])),
{noreply, State}.
-spec handle_call (Request, From, State) -> {reply, Reply, NewState} | {stop, Reason, Reply, NewState} when
Request :: term(),
From :: {pid(),Tag::term()},
State :: #client_state{},
Reply :: term(),
Reason :: term(),
NewState :: #client_state{}.
handle_call (Request, From, State) ->
?L_E(?DBGSTR("got unknow request ~p from ~p",[Request,From])),
{reply, invalid, State}.
%%%============================================================================
%%% internal functions
%%%============================================================================
%---------prepare_state------------------convert Spec proplist into internal state
-spec prepare_state (Node, Spec) -> State when
Node :: pid(),
Spec :: proplists:proplist(),
State :: #client_state{}.
prepare_state (Node,Spec) ->
#client_state{
sim_node = Node,
sim_manager = proplists:get_value(manager,Spec,Node),
serial = proplists:get_value(ap_serial,Spec,"1P000000000"),
type = proplists:get_value(ap_type,Spec,<<"EA8300">>),
timer = owls_timers:new(millisecond)
}.

View File

@@ -0,0 +1,181 @@
%%%-----------------------------------------------------------------------------
%%% @author helge
%%% @copyright (C) 2020, Arilia Wireless Inc.
%%% @doc
%%%
%%% @end
%%% Created : 18. November 2020 @ 15:29:05
%%%-----------------------------------------------------------------------------
-module(ovsdb_client_handler).
-author("helge").
-behaviour(gen_server).
-define(SERVER, ?MODULE).
%% API
-export([start_link/0]).
-export([set_configuration/1, start/0, stop/0, pause/0, resume/0, cancel/0, report/0]).
%% gen_server callbacks
-export([init/1, handle_cast/2, handle_call/3, handle_info/2, terminate/2, code_change/3]).
%% data structures
-record(hdl_state, {
clients = [] :: [{Id::term(),pid()}],
config :: term()
}).
%%%============================================================================
%%% API
%%%============================================================================
-spec start_link () -> {ok, Pid} | {error, Reason} when
Pid :: pid(),
Reason :: term().
start_link () ->
gen_server:start_link({local, ?SERVER},?MODULE, [], []).
-spec set_configuration (Cfg) -> {ok, set} | {error, Reason} when
Cfg :: term(),
Reason :: term().
set_configuration (Cfg) ->
gen_server:call(?SERVER,{set_config, Cfg}).
-spec start () -> {ok, started} | {timeout, Reason} | {error, Reason} when
Reason :: term().
start () ->
gen_server:call(?SERVER,start_sim).
-spec stop () -> ok.
stop () ->
gen_server:cast(?SERVER,stop_sim).
-spec pause () -> {ok, paused} | {timeout, Reason} | {error, Reason} when
Reason :: term().
pause () ->
gen_server:call(?SERVER,pause_sim).
-spec resume () -> {ok, resumed} | {timeout, Reason} | {error, Reason} when
Reason :: term().
resume () ->
gen_server:call(?SERVER,resume_sim).
-spec cancel () -> {ok, cancelled} | {timeout, Reason} | {error, Reason} when
Reason :: term().
cancel () ->
gen_server:call(?SERVER,cancel_sim).
-spec report () -> {ok, Report} | {error, Reason} when
Report :: term(),
Reason :: term().
report () ->
gen_server:call(?SERVER,get_report).
%%%============================================================================
%%% GEN_SERVER callbacks
%%%============================================================================
-spec init (Args) -> {ok, State} when
Args :: term(),
State :: #hdl_state{}.
init (_) ->
{ok, #hdl_state{}}.
-spec handle_cast (Request, State) -> {noreply, NewState} | {stop, Reason, NewState} when
Request :: term(),
State :: #hdl_state{},
NewState :: #hdl_state{},
Reason :: term().
handle_cast (_,State) ->
{noreply, State}.
-spec handle_call (Request, From, State) -> {reply, Reply, NewState} | {stop, Reason, Reply, NewState} when
Request :: term(),
From :: {pid(),Tag::term()},
State :: #hdl_state{},
Reply :: term(),
Reason :: term(),
NewState :: #hdl_state{}.
handle_call (_, _, State) ->
{reply, invalid, State}.
-spec handle_info (Msg, State) -> {noreply, NewState} when
Msg :: term(),
State :: #hdl_state{},
NewState :: #hdl_state{}.
handle_info(_, State) ->
{noreply, State}.
-spec terminate (Reason, State) -> ok when
Reason :: shutdown | {shutdown, term()} | normal,
State :: #hdl_state{}.
terminate (_Reason, _State) ->
ok.
-spec code_change (OldVersion, OldState, Extra) -> {ok, NewState} when
OldVersion :: term(),
OldState ::#hdl_state{},
Extra :: term(),
NewState :: #hdl_state{}.
code_change (_,OldState,_) ->
{ok, OldState}.
%%%============================================================================
%%% internal functions
%%%============================================================================