NetControl: add rule exists as state besides added and failure.

Rules that are already existing will, by default, not automatically be
timed out by NetControl.
This commit is contained in:
Johanna Amann 2016-03-24 15:06:07 -07:00
parent bbbfac3af9
commit 34ad4cf638
17 changed files with 230 additions and 69 deletions

View file

@ -11,13 +11,15 @@ export {
## This is the event used to transport remove_rule calls to the manager.
global cluster_netcontrol_remove_rule: event(id: string);
## This is the event used to transport delete_rule calls to the manager.
global cluster_netcontrol_delete_rule: event(id: string);
}
## Workers need ability to forward commands to manager.
redef Cluster::worker2manager_events += /NetControl::cluster_netcontrol_(add|remove)_rule/;
redef Cluster::worker2manager_events += /NetControl::cluster_netcontrol_(add|remove|delete)_rule/;
## Workers need to see the result events from the manager.
redef Cluster::manager2worker_events += /NetControl::rule_(added|removed|timeout|error)/;
redef Cluster::manager2worker_events += /NetControl::rule_(added|removed|timeout|error|exists)/;
function activate(p: PluginState, priority: int)
{
@ -44,6 +46,17 @@ function add_rule(r: Rule) : string
}
}
function delete_rule(id: string) : bool
{
if ( Cluster::local_node_type() == Cluster::MANAGER )
return delete_rule_impl(id);
else
{
event NetControl::cluster_netcontrol_delete_rule(id);
return T; # well, we can't know here. So - just hope...
}
}
function remove_rule(id: string) : bool
{
if ( Cluster::local_node_type() == Cluster::MANAGER )
@ -56,6 +69,11 @@ function remove_rule(id: string) : bool
}
@if ( Cluster::local_node_type() == Cluster::MANAGER )
event NetControl::cluster_netcontrol_delete_rule(id: string)
{
delete_rule_impl(id);
}
event NetControl::cluster_netcontrol_add_rule(r: Rule)
{
add_rule_impl(r);
@ -73,9 +91,17 @@ event rule_expire(r: Rule, p: PluginState) &priority=-5
rule_expire_impl(r, p);
}
event rule_exists(r: Rule, p: PluginState, msg: string &default="") &priority=5
{
rule_added_impl(r, p, T, msg);
if ( r?$expire && r$expire > 0secs && ! p$plugin$can_expire )
schedule r$expire { rule_expire(r, p) };
}
event rule_added(r: Rule, p: PluginState, msg: string &default="") &priority=5
{
rule_added_impl(r, p, msg);
rule_added_impl(r, p, F, msg);
if ( r?$expire && r$expire > 0secs && ! p$plugin$can_expire )
schedule r$expire { rule_expire(r, p) };

View file

@ -126,6 +126,17 @@ export {
## asynchronously and thus go wrong at that point.
global remove_rule: function(id: string) : bool;
## Deletes a rule without removing in from the backends to which it has been
## added before. This mean that no messages will be sent to the switches to which
## the rule has been added; if it is not removed from them by a separate mechanism,
## it will stay installed and not be removed later.
##
## id: The rule to delete, specified as the ID returned by :bro:id:`add_rule` .
##
## Returns: True if removal is successful, or sent to manager.
## False if the rule could not be found.
global delete_rule: function(id: string) : bool;
## Searches all rules affecting a certain IP address.
##
## ip: The ip address to search for
@ -151,6 +162,19 @@ export {
## msg: An optional informational message by the plugin.
global rule_added: event(r: Rule, p: PluginState, msg: string &default="");
## Signals that a rule that was supposed to be put in place was already
## existing at the specified plugin. Rules that already have been existing
## continue to be tracked like normal, but no timeout calls will be sent
## to the specified plugins. Removal of the rule from the hardware can
## still be forced by manually issuing a remove_rule call.
##
## r: The rule that was already in place.
##
## p: The plugin that reported that the rule already was in place.
##
## msg: An optional informational message by the plugin.
global rule_exists: event(r: Rule, p: PluginState, msg: string &default="");
## Reports that a rule was removed due to a remove: function() call.
##
## r: The rule now removed.
@ -211,6 +235,7 @@ export {
type InfoState: enum {
REQUESTED,
SUCCEEDED,
EXISTS,
FAILED,
REMOVED,
TIMEOUT,
@ -260,6 +285,8 @@ redef record Rule += {
_plugin_ids: set[count] &default=count_set();
##< Internally set to the plugins on which the rule is currently active.
_active_plugin_ids: set[count] &default=count_set();
##< Internally set to plugins where the rule should not be removed upon timeout.
_no_expire_plugins: set[count] &default=count_set();
##< Track if the rule was added succesfully by all responsible plugins.
_added: bool &default=F;
};
@ -736,6 +763,29 @@ function add_rule_impl(rule: Rule) : string
return "";
}
function rule_cleanup(r: Rule)
{
if ( |r$_active_plugin_ids| > 0 )
return;
remove_subnet_entry(r);
delete rule_entities[r$entity, r$ty];
delete rules[r$id];
}
function delete_rule_impl(id: string): bool
{
if ( id !in rules )
return F;
local rule = rules[id];
rule$_active_plugin_ids = set();
rule_cleanup(rule);
}
function remove_rule_plugin(r: Rule, p: PluginState): bool
{
local success = T;
@ -784,10 +834,21 @@ function rule_expire_impl(r: Rule, p: PluginState) &priority=-5
# Removed already.
return;
event NetControl::rule_timeout(r, FlowInfo(), p); # timeout implementation will handle the removal
local rule = rules[r$id];
if ( p$_id in rule$_no_expire_plugins )
{
# in this case - don't log anything, just remove the plugin from the rule
# and cleaup
delete rule$_active_plugin_ids[p$_id];
delete rule$_no_expire_plugins[p$_id];
rule_cleanup(rule);
}
else
event NetControl::rule_timeout(r, FlowInfo(), p); # timeout implementation will handle the removal
}
function rule_added_impl(r: Rule, p: PluginState, msg: string &default="")
function rule_added_impl(r: Rule, p: PluginState, exists: bool, msg: string &default="")
{
if ( r$id !in rules )
{
@ -803,7 +864,15 @@ function rule_added_impl(r: Rule, p: PluginState, msg: string &default="")
return;
}
log_rule(r, "ADD", SUCCEEDED, p, msg);
# The rule was already existing on the backend. Mark this so we don't timeout
# it on this backend.
if ( exists )
{
add rule$_no_expire_plugins[p$_id];
log_rule(r, "ADD", EXISTS, p, msg);
}
else
log_rule(r, "ADD", SUCCEEDED, p, msg);
add rule$_active_plugin_ids[p$_id];
if ( |rule$_plugin_ids| == |rule$_active_plugin_ids| )
@ -813,17 +882,6 @@ function rule_added_impl(r: Rule, p: PluginState, msg: string &default="")
}
}
function rule_cleanup(r: Rule)
{
if ( |r$_active_plugin_ids| > 0 )
return;
remove_subnet_entry(r);
delete rule_entities[r$entity, r$ty];
delete rules[r$id];
}
function rule_removed_impl(r: Rule, p: PluginState, msg: string &default="")
{
if ( r$id !in rules )

View file

@ -12,6 +12,11 @@ function add_rule(r: Rule) : string
return add_rule_impl(r);
}
function delete_rule(id: string) : bool
{
return delete_rule_impl(id);
}
function remove_rule(id: string) : bool
{
return remove_rule_impl(id);
@ -22,9 +27,17 @@ event rule_expire(r: Rule, p: PluginState) &priority=-5
rule_expire_impl(r, p);
}
event rule_exists(r: Rule, p: PluginState, msg: string &default="") &priority=5
{
rule_added_impl(r, p, T, msg);
if ( r?$expire && r$expire > 0secs && ! p$plugin$can_expire )
schedule r$expire { rule_expire(r, p) };
}
event rule_added(r: Rule, p: PluginState, msg: string &default="") &priority=5
{
rule_added_impl(r, p, msg);
rule_added_impl(r, p, F, msg);
if ( r?$expire && r$expire > 0secs && ! p$plugin$can_expire )
schedule r$expire { rule_expire(r, p) };

View file

@ -64,6 +64,7 @@ export {
## Events that are sent from Broker to us
global acld_rule_added: event(id: count, r: Rule, msg: string);
global acld_rule_removed: event(id: count, r: Rule, msg: string);
global acld_rule_exists: event(id: count, r: Rule, msg: string);
global acld_rule_error: event(id: count, r: Rule, msg: string);
}
@ -98,6 +99,19 @@ event NetControl::acld_rule_added(id: count, r: Rule, msg: string)
event NetControl::rule_added(r, p, msg);
}
event NetControl::acld_rule_exists(id: count, r: Rule, msg: string)
{
if ( id !in netcontrol_acld_id )
{
Reporter::error(fmt("NetControl acld plugin with id %d not found, aborting", id));
return;
}
local p = netcontrol_acld_id[id];
event NetControl::rule_exists(r, p, msg);
}
event NetControl::acld_rule_removed(id: count, r: Rule, msg: string)
{
if ( id !in netcontrol_acld_id )

View file

@ -46,6 +46,7 @@ export {
global broker_rule_added: event(id: count, r: Rule, msg: string);
global broker_rule_removed: event(id: count, r: Rule, msg: string);
global broker_rule_exists: event(id: count, r: Rule, msg: string);
global broker_rule_error: event(id: count, r: Rule, msg: string);
global broker_rule_timeout: event(id: count, r: Rule, i: FlowInfo);
}
@ -68,6 +69,19 @@ event NetControl::broker_rule_added(id: count, r: Rule, msg: string)
event NetControl::rule_added(r, p, msg);
}
event NetControl::broker_rule_exists(id: count, r: Rule, msg: string)
{
if ( id !in netcontrol_broker_id )
{
Reporter::error(fmt("NetControl broker plugin with id %d not found, aborting", id));
return;
}
local p = netcontrol_broker_id[id];
event NetControl::rule_exists(r, p, msg);
}
event NetControl::broker_rule_removed(id: count, r: Rule, msg: string)
{
if ( id !in netcontrol_broker_id )