mirror of
https://github.com/zeek/zeek.git
synced 2025-10-12 19:48:20 +00:00
add support for switches notifying openflow and pacf about flow removal.
I just noticed - the OpenFlow events also really should send the instance of openflow that they are with them. That is a... tad complicated though due to a number of reasons (among others how the events are currently generated), so this will have to wait for a bit.
This commit is contained in:
parent
c0111bc4d2
commit
5f0a630116
8 changed files with 63 additions and 8 deletions
|
@ -50,6 +50,25 @@ export {
|
||||||
## msg: Message to describe the event.
|
## msg: Message to describe the event.
|
||||||
global flow_mod_failure: event(match: ofp_match, flow_mod: ofp_flow_mod, msg: string &default="");
|
global flow_mod_failure: event(match: ofp_match, flow_mod: ofp_flow_mod, msg: string &default="");
|
||||||
|
|
||||||
|
## Reports that a flow was removed by the switch because of either the hard or the idle timeout.
|
||||||
|
## This message is only generated by controllers that indicate that they support flow removal
|
||||||
|
## in supports_flow_removed.
|
||||||
|
##
|
||||||
|
## match: The ofp_match record which was used to create the flow.
|
||||||
|
##
|
||||||
|
## cookie: The cookie that was specified when creating the flow.
|
||||||
|
##
|
||||||
|
## priority: The priority that was specified when creating the flow.
|
||||||
|
##
|
||||||
|
## reason: The reason for flow removal (OFPRR_*)
|
||||||
|
##
|
||||||
|
## duration_sec: duration of the flow in seconds
|
||||||
|
##
|
||||||
|
## packet_count: packet count of the flow
|
||||||
|
##
|
||||||
|
## byte_count: byte count of the flow
|
||||||
|
global flow_removed: event(match: ofp_match, cookie: count, priority: count, reason: count, duration_sec: count, idle_timeout: count, packet_count: count, byte_count: count);
|
||||||
|
|
||||||
## Convert a conn_id record into an ofp_match record that can be used to
|
## Convert a conn_id record into an ofp_match record that can be used to
|
||||||
## create match objects for OpenFlow.
|
## create match objects for OpenFlow.
|
||||||
##
|
##
|
||||||
|
|
|
@ -63,6 +63,6 @@ function broker_new(host: addr, host_port: port, topic: string, dpid: count): Op
|
||||||
BrokerComm::subscribe_to_events(topic); # openflow success and failure events are directly sent back via the other plugin via broker.
|
BrokerComm::subscribe_to_events(topic); # openflow success and failure events are directly sent back via the other plugin via broker.
|
||||||
|
|
||||||
return [$state=[$broker_host=host, $broker_port=host_port, $broker_dpid=dpid, $broker_topic=topic, $_plugin=OpenFlow::BROKER],
|
return [$state=[$broker_host=host, $broker_port=host_port, $broker_dpid=dpid, $broker_topic=topic, $_plugin=OpenFlow::BROKER],
|
||||||
$flow_mod=broker_flow_mod_fun, $flow_clear=broker_flow_clear_fun, $describe=broker_describe];
|
$flow_mod=broker_flow_mod_fun, $flow_clear=broker_flow_clear_fun, $describe=broker_describe, $supports_flow_removed=T];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,5 +68,5 @@ function log_describe(state: ControllerState): string
|
||||||
function log_new(dpid: count, success_event: bool &default=T): OpenFlow::Controller
|
function log_new(dpid: count, success_event: bool &default=T): OpenFlow::Controller
|
||||||
{
|
{
|
||||||
return [$state=[$log_dpid=dpid, $log_success_event=success_event, $_plugin=OpenFlow::LOG],
|
return [$state=[$log_dpid=dpid, $log_success_event=success_event, $_plugin=OpenFlow::LOG],
|
||||||
$flow_mod=log_flow_mod, $flow_clear=ryu_flow_clear, $describe=log_describe];
|
$flow_mod=log_flow_mod, $flow_clear=ryu_flow_clear, $describe=log_describe, $supports_flow_removed=F];
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,5 +180,5 @@ function ryu_describe(state: ControllerState): string
|
||||||
function ryu_new(host: addr, host_port: count, dpid: count): OpenFlow::Controller
|
function ryu_new(host: addr, host_port: count, dpid: count): OpenFlow::Controller
|
||||||
{
|
{
|
||||||
return [$state=[$ryu_host=host, $ryu_port=host_port, $ryu_dpid=dpid, $_plugin=OpenFlow::RYU],
|
return [$state=[$ryu_host=host, $ryu_port=host_port, $ryu_dpid=dpid, $_plugin=OpenFlow::RYU],
|
||||||
$flow_mod=ryu_flow_mod, $flow_clear=ryu_flow_clear, $describe=ryu_describe];
|
$flow_mod=ryu_flow_mod, $flow_clear=ryu_flow_clear, $describe=ryu_describe, $supports_flow_removed=F];
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,8 @@ export {
|
||||||
type Controller: record {
|
type Controller: record {
|
||||||
## Controller related state.
|
## Controller related state.
|
||||||
state: ControllerState;
|
state: ControllerState;
|
||||||
|
## Does the controller support the flow_removed event?
|
||||||
|
supports_flow_removed: bool;
|
||||||
## function that describes the controller. Has to be implemented.
|
## function that describes the controller. Has to be implemented.
|
||||||
describe: function(state: ControllerState): string;
|
describe: function(state: ControllerState): string;
|
||||||
## flow_mod function
|
## flow_mod function
|
||||||
|
|
|
@ -118,11 +118,13 @@ export {
|
||||||
##
|
##
|
||||||
## r: The rule now removed.
|
## r: The rule now removed.
|
||||||
##
|
##
|
||||||
|
## i: Additional flow information, if supported by the protocol.
|
||||||
|
##
|
||||||
## plugin: The name of the plugin that had the rule in place and now
|
## plugin: The name of the plugin that had the rule in place and now
|
||||||
## removed it.
|
## removed it.
|
||||||
##
|
##
|
||||||
## msg: An optional informational message by the plugin.
|
## msg: An optional informational message by the plugin.
|
||||||
global rule_timeout: event(r: Rule, p: PluginState);
|
global rule_timeout: event(r: Rule, i: FlowInfo, p: PluginState);
|
||||||
|
|
||||||
## Reports an error when operating on a rule.
|
## Reports an error when operating on a rule.
|
||||||
##
|
##
|
||||||
|
@ -428,7 +430,7 @@ event rule_expire(r: Rule, p: PluginState)
|
||||||
# Remove already.
|
# Remove already.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
event rule_timeout(r, p);
|
event rule_timeout(r, FlowInfo(), p);
|
||||||
remove_rule(r$id);
|
remove_rule(r$id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +450,7 @@ event rule_removed(r: Rule, p: PluginState, msg: string &default="")
|
||||||
log_rule(r, "REMOVE", SUCCEEDED, p);
|
log_rule(r, "REMOVE", SUCCEEDED, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
event rule_timeout(r: Rule, p: PluginState)
|
event rule_timeout(r: Rule, i: FlowInfo, p: PluginState)
|
||||||
{
|
{
|
||||||
delete rules[r$id];
|
delete rules[r$id];
|
||||||
log_rule(r, "EXPIRE", TIMEOUT, p);
|
log_rule(r, "EXPIRE", TIMEOUT, p);
|
||||||
|
|
|
@ -30,13 +30,18 @@ export {
|
||||||
|
|
||||||
## the time interval after which an openflow message is considered to be timed out
|
## the time interval after which an openflow message is considered to be timed out
|
||||||
## and we delete it from our internal tracking.
|
## and we delete it from our internal tracking.
|
||||||
const openflow_timeout = 20secs &redef;
|
const openflow_message_timeout = 20secs &redef;
|
||||||
|
|
||||||
|
## the time interval after we consider a flow timed out. This should be fairly high (or
|
||||||
|
## even disabled) if you expect a lot of long flows. However, one also will have state
|
||||||
|
## buildup for quite a while if keeping this around...
|
||||||
|
const openflow_flow_timeout = 24hrs &redef;
|
||||||
|
|
||||||
## Instantiates an openflow plugin for the PACF framework.
|
## Instantiates an openflow plugin for the PACF framework.
|
||||||
global create_openflow: function(controller: OpenFlow::Controller, config: OfConfig &default=[]) : PluginState;
|
global create_openflow: function(controller: OpenFlow::Controller, config: OfConfig &default=[]) : PluginState;
|
||||||
}
|
}
|
||||||
|
|
||||||
global of_messages: table[count, OpenFlow::ofp_flow_mod_command] of OfTable &create_expire=openflow_timeout
|
global of_messages: table[count, OpenFlow::ofp_flow_mod_command] of OfTable &create_expire=openflow_message_timeout
|
||||||
&expire_func=function(t: table[count, OpenFlow::ofp_flow_mod_command] of OfTable, idx: any): interval
|
&expire_func=function(t: table[count, OpenFlow::ofp_flow_mod_command] of OfTable, idx: any): interval
|
||||||
{
|
{
|
||||||
local rid: count;
|
local rid: count;
|
||||||
|
@ -49,6 +54,8 @@ global of_messages: table[count, OpenFlow::ofp_flow_mod_command] of OfTable &cre
|
||||||
return 0secs;
|
return 0secs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
global of_flows: table[count] of OfTable &create_expire=openflow_flow_timeout;
|
||||||
|
|
||||||
function openflow_name(p: PluginState) : string
|
function openflow_name(p: PluginState) : string
|
||||||
{
|
{
|
||||||
return fmt("Openflow - %s", p$of_controller$describe(p$of_controller$state));
|
return fmt("Openflow - %s", p$of_controller$describe(p$of_controller$state));
|
||||||
|
@ -301,6 +308,9 @@ event OpenFlow::flow_mod_success(match: OpenFlow::ofp_match, flow_mod: OpenFlow:
|
||||||
local p = of_messages[id,flow_mod$command]$p;
|
local p = of_messages[id,flow_mod$command]$p;
|
||||||
delete of_messages[id,flow_mod$command];
|
delete of_messages[id,flow_mod$command];
|
||||||
|
|
||||||
|
if ( p$of_controller$supports_flow_removed )
|
||||||
|
of_flows[id] = OfTable($p=p, $r=r);
|
||||||
|
|
||||||
if ( flow_mod$command == OpenFlow::OFPFC_ADD )
|
if ( flow_mod$command == OpenFlow::OFPFC_ADD )
|
||||||
event Pacf::rule_added(r, p, msg);
|
event Pacf::rule_added(r, p, msg);
|
||||||
else if ( flow_mod$command == OpenFlow::OFPFC_DELETE || flow_mod$command == OpenFlow::OFPFC_DELETE_STRICT )
|
else if ( flow_mod$command == OpenFlow::OFPFC_DELETE || flow_mod$command == OpenFlow::OFPFC_DELETE_STRICT )
|
||||||
|
@ -320,6 +330,18 @@ event OpenFlow::flow_mod_failure(match: OpenFlow::ofp_match, flow_mod: OpenFlow:
|
||||||
event Pacf::rule_error(r, p, msg);
|
event Pacf::rule_error(r, p, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event OpenFlow::flow_removed(match: OpenFlow::ofp_match, cookie: count, priority: count, reason: count, duration_sec: count, idle_timeout: count, packet_count: count, byte_count: count)
|
||||||
|
{
|
||||||
|
local id = OpenFlow::get_cookie_uid(cookie);
|
||||||
|
if ( id !in of_flows )
|
||||||
|
return;
|
||||||
|
|
||||||
|
local r = of_flows[id]$r;
|
||||||
|
local p = of_flows[id]$p;
|
||||||
|
|
||||||
|
event Pacf::rule_timeout(r, FlowInfo($duration=double_to_interval(duration_sec+0.0), $packet_count=packet_count, $byte_count=byte_count), p);
|
||||||
|
}
|
||||||
|
|
||||||
global openflow_plugin = Plugin(
|
global openflow_plugin = Plugin(
|
||||||
$name=openflow_name,
|
$name=openflow_name,
|
||||||
$can_expire = T,
|
$can_expire = T,
|
||||||
|
|
|
@ -105,6 +105,16 @@ export {
|
||||||
id: count &default=0; ##< Internally determined unique ID for this rule. Will be set when added.
|
id: count &default=0; ##< Internally determined unique ID for this rule. Will be set when added.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
## Information of a flow that can be provided by switches when the flow times out.
|
||||||
|
## Currently this is heavily influenced by the data that OpenFlow returns by default.
|
||||||
|
## That being said - their design makes sense and this is probably the data one
|
||||||
|
## can expect to be available.
|
||||||
|
type FlowInfo: record {
|
||||||
|
duration: interval &optional; ##< total duration of the rule
|
||||||
|
packet_count: count &optional; ##< number of packets exchanged over connections matched by the rule
|
||||||
|
byte_count: count &optional; ##< total bytes exchanged over connections matched by the rule
|
||||||
|
};
|
||||||
|
|
||||||
## Type of notifications that the framework supports. Each type lists the
|
## Type of notifications that the framework supports. Each type lists the
|
||||||
## :bro:id:`Notification` argument(s) it uses, if any.
|
## :bro:id:`Notification` argument(s) it uses, if any.
|
||||||
##
|
##
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue