Add signaling of succesful initialization of plugins to NetControl.

This does not really have many user-facing changes. The one big change
is that users now should initialize plugins in the

NetControl::init()

event instead of bro_init.

Once all plugins finished initializing and the NetControl framework
starts operations, the NetControl::init_done() event is raised.

Rules that are sent to NetControl before the plugins have finished
initializing are ignored - this is important when several plugins that
require external connections have to be initialized at the beginning.
Without this delay, rules could end up at the wrong plugin.
This commit is contained in:
Johanna Amann 2016-03-08 14:49:22 -08:00
parent d9459fc59a
commit 42e4072673
31 changed files with 371 additions and 113 deletions

View file

@ -51,6 +51,10 @@ event OpenFlow::cluster_flow_mod(name: string, match: ofp_match, flow_mod: ofp_f
}
local c = name_to_controller[name];
if ( ! c$state$_activated )
return;
if ( c?$flow_mod )
c$flow_mod(c$state, match, flow_mod);
}
@ -65,6 +69,9 @@ event OpenFlow::cluster_flow_clear(name: string)
local c = name_to_controller[name];
if ( ! c$state$_activated )
return;
if ( c?$flow_clear )
c$flow_clear(c$state);
}

View file

@ -127,6 +127,18 @@ export {
## controller: The controller to unregister
global unregister_controller: function(controller: Controller);
## Function to signal that a controller finished activation and is
## ready to use. Will throw the ``OpenFlow::controller_activated``
## event.
global controller_init_done: function(controller: Controller);
## Event that is raised once a controller finishes initialization
## and is completely activated.
## name: unique name of this controller instance.
##
## controller: The controller that finished activation.
global OpenFlow::controller_activated: event(name: string, controller: Controller);
## Function to lookup a controller instance by name
##
## name: unique name of the controller to look up
@ -227,13 +239,25 @@ function get_cookie_gid(cookie: count): count
return INVALID_COOKIE;
}
function controller_init_done(controller: Controller)
{
if ( controller$state$_name !in name_to_controller )
{
Reporter::error(fmt("Openflow initialized unknown plugin %s successfully?", controller$state$_name));
return;
}
controller$state$_activated = T;
event OpenFlow::controller_activated(controller$state$_name, controller);
}
# Functions that are called from cluster.bro and non-cluster.bro
function register_controller_impl(tpe: OpenFlow::Plugin, name: string, controller: Controller)
{
if ( controller$state$_name in name_to_controller )
{
Reporter::error("OpenFlow Controller %s was already registered. Ignored duplicate registration");
Reporter::error(fmt("OpenFlow Controller %s was already registered. Ignored duplicate registration", controller$state$_name));
return;
}
@ -241,6 +265,8 @@ function register_controller_impl(tpe: OpenFlow::Plugin, name: string, controlle
if ( controller?$init )
controller$init(controller$state);
else
controller_init_done(controller);
}
function unregister_controller_impl(controller: Controller)

View file

@ -5,6 +5,9 @@ module OpenFlow;
# the flow_mod function wrapper
function flow_mod(controller: Controller, match: ofp_match, flow_mod: ofp_flow_mod): bool
{
if ( ! controller$state$_activated )
return F;
if ( controller?$flow_mod )
return controller$flow_mod(controller$state, match, flow_mod);
else
@ -13,6 +16,9 @@ function flow_mod(controller: Controller, match: ofp_match, flow_mod: ofp_flow_m
function flow_clear(controller: Controller): bool
{
if ( ! controller$state$_activated )
return F;
if ( controller?$flow_clear )
return controller$flow_clear(controller$state);
else

View file

@ -36,6 +36,8 @@ export {
global broker_flow_clear: event(name: string, dpid: count);
}
global broker_peers: table[port, string] of Controller;
function broker_describe(state: ControllerState): string
{
return fmt("Broker-%s:%d-%d", state$broker_host, state$broker_port, state$broker_dpid);
@ -62,6 +64,17 @@ function broker_init(state: OpenFlow::ControllerState)
BrokerComm::subscribe_to_events(state$broker_topic); # openflow success and failure events are directly sent back via the other plugin via broker.
}
event BrokerComm::outgoing_connection_established(peer_address: string, peer_port: port, peer_name: string)
{
if ( [peer_port, peer_address] !in broker_peers )
# ok, this one was none of ours...
return;
local p = broker_peers[peer_port, peer_address];
controller_init_done(p);
delete broker_peers[peer_port, peer_address];
}
# broker controller constructor
function broker_new(name: string, host: addr, host_port: port, topic: string, dpid: count): OpenFlow::Controller
{
@ -70,6 +83,11 @@ function broker_new(name: string, host: addr, host_port: port, topic: string, dp
register_controller(OpenFlow::BROKER, name, c);
if ( [host_port, cat(host)] in broker_peers )
Reporter::warning(fmt("Peer %s:%s was added to NetControl acld plugin twice.", host, host_port));
else
broker_peers[host_port, cat(host)] = c;
return c;
}

View file

@ -17,6 +17,8 @@ export {
_plugin: Plugin &optional;
## Internally set to the unique name of the controller.
_name: string &optional;
## Internally set to true once the controller is activated
_activated: bool &default=F;
} &redef;
## Openflow match definition.
@ -116,7 +118,7 @@ export {
supports_flow_removed: bool;
## function that describes the controller. Has to be implemented.
describe: function(state: ControllerState): string;
## one-time initialization function.
## one-time initialization function. If defined, controller_init_done has to be called once initialization finishes.
init: function (state: ControllerState) &optional;
## one-time destruction function
destroy: function (state: ControllerState) &optional;