mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 18:18:19 +00:00
Update OpenFlow API and events.
Events now generally carry the unique ID of the backend that is given during initialization; there are a few more functions and other bugfixes. A few netcontrol tests are still broken (mostly due to a pcap update in msater).
This commit is contained in:
parent
5e2ec25a38
commit
9f3c0c9bb4
19 changed files with 186 additions and 95 deletions
|
@ -14,8 +14,6 @@ export {
|
|||
## Workers need ability to forward commands to manager.
|
||||
redef Cluster::worker2manager_events += /OpenFlow::cluster_flow_(mod|clear)/;
|
||||
|
||||
global name_to_controller: table[string] of Controller;
|
||||
|
||||
# the flow_mod function wrapper
|
||||
function flow_mod(controller: Controller, match: ofp_match, flow_mod: ofp_flow_mod): bool
|
||||
{
|
||||
|
@ -81,14 +79,33 @@ function register_controller(tpe: OpenFlow::Plugin, name: string, controller: Co
|
|||
if ( Cluster::local_node_type() != Cluster::MANAGER )
|
||||
return;
|
||||
|
||||
if ( controller$state$_name in name_to_controller )
|
||||
{
|
||||
Reporter::error("OpenFlow Controller %s was already registered. Ignored duplicate registration");
|
||||
return;
|
||||
}
|
||||
|
||||
name_to_controller[controller$state$_name] = controller;
|
||||
|
||||
if ( controller?$init )
|
||||
controller$init(controller$state);
|
||||
register_controller_impl(tpe, name, controller);
|
||||
}
|
||||
|
||||
function unregister_controller(controller: Controller)
|
||||
{
|
||||
# we only run the on the manager.
|
||||
if ( Cluster::local_node_type() != Cluster::MANAGER )
|
||||
return;
|
||||
|
||||
unregister_controller_impl(controller);
|
||||
}
|
||||
|
||||
function lookup_controller(name: string): vector of Controller
|
||||
{
|
||||
# we only run the on the manager. Otherwhise we don't have a mapping or state -> return empty
|
||||
if ( Cluster::local_node_type() != Cluster::MANAGER )
|
||||
return vector();
|
||||
|
||||
# I am not quite sure if we can actually get away with this - in the
|
||||
# current state, this means that the individual nodes cannot lookup
|
||||
# a controller by name.
|
||||
#
|
||||
# This means that there can be no reactions to things on the actual
|
||||
# worker nodes - because they cannot look up a name. On the other hand -
|
||||
# currently we also do not even send the events to the worker nodes (at least
|
||||
# not if we are using broker). Because of that I am not really feeling that
|
||||
# badly about it...
|
||||
|
||||
return lookup_controller_impl(name);
|
||||
}
|
||||
|
|
|
@ -34,26 +34,32 @@ export {
|
|||
|
||||
## Event confirming successful modification of a flow rule.
|
||||
##
|
||||
## name: The unique name of the OpenFlow controller from which this event originated.
|
||||
##
|
||||
## match: The ofp_match record which describes the flow to match.
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes the action to take.
|
||||
##
|
||||
## msg: An optional informational message by the plugin.
|
||||
global flow_mod_success: event(match: ofp_match, flow_mod: ofp_flow_mod, msg: string &default="");
|
||||
global flow_mod_success: event(name: string, match: ofp_match, flow_mod: ofp_flow_mod, msg: string &default="");
|
||||
|
||||
## Reports an error while installing a flow Rule.
|
||||
##
|
||||
## name: The unique name of the OpenFlow controller from which this event originated.
|
||||
##
|
||||
## match: The ofp_match record which describes the flow to match.
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes the action to take.
|
||||
##
|
||||
## 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(name: string, 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.
|
||||
##
|
||||
## name: The unique name of the OpenFlow controller from which this event originated.
|
||||
##
|
||||
## match: The ofp_match record which was used to create the flow.
|
||||
##
|
||||
## cookie: The cookie that was specified when creating the flow.
|
||||
|
@ -67,7 +73,7 @@ export {
|
|||
## 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);
|
||||
global flow_removed: event(name: string, 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
|
||||
## create match objects for OpenFlow.
|
||||
|
@ -113,8 +119,25 @@ export {
|
|||
##
|
||||
## controller: The controller to register
|
||||
global register_controller: function(tpe: OpenFlow::Plugin, name: string, controller: Controller);
|
||||
|
||||
## Function to unregister a controller instance. This function
|
||||
## should be called when a specific controller should no longer
|
||||
## be used.
|
||||
##
|
||||
## controller: The controller to unregister
|
||||
global unregister_controller: function(controller: Controller);
|
||||
|
||||
## Function to lookup a controller instance by name
|
||||
##
|
||||
## name: unique name of the controller to look up
|
||||
##
|
||||
## Returns: one element vector with controller, if found. Empty vector otherwhise.
|
||||
global lookup_controller: function(name: string): vector of Controller;
|
||||
}
|
||||
|
||||
global name_to_controller: table[string] of Controller;
|
||||
|
||||
|
||||
function match_conn(id: conn_id, reverse: bool &default=F): ofp_match
|
||||
{
|
||||
local dl_type = ETH_IPv4;
|
||||
|
@ -137,7 +160,7 @@ function match_conn(id: conn_id, reverse: bool &default=F): ofp_match
|
|||
orig_h = id$resp_h;
|
||||
orig_p = id$resp_p;
|
||||
resp_h = id$orig_h;
|
||||
resp_p = id$resp_p;
|
||||
resp_p = id$orig_p;
|
||||
}
|
||||
|
||||
if ( is_v6_addr(orig_h) )
|
||||
|
@ -203,3 +226,38 @@ function get_cookie_gid(cookie: count): count
|
|||
|
||||
return INVALID_COOKIE;
|
||||
}
|
||||
|
||||
# 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");
|
||||
return;
|
||||
}
|
||||
|
||||
name_to_controller[controller$state$_name] = controller;
|
||||
|
||||
if ( controller?$init )
|
||||
controller$init(controller$state);
|
||||
}
|
||||
|
||||
function unregister_controller_impl(controller: Controller)
|
||||
{
|
||||
if ( controller$state$_name in name_to_controller )
|
||||
delete name_to_controller[controller$state$_name];
|
||||
else
|
||||
Reporter::error("OpenFlow Controller %s was not registered in unregister.");
|
||||
|
||||
if ( controller?$destroy )
|
||||
controller$destroy(controller$state);
|
||||
}
|
||||
|
||||
function lookup_controller_impl(name: string): vector of Controller
|
||||
{
|
||||
if ( name in name_to_controller )
|
||||
return vector(name_to_controller[name]);
|
||||
else
|
||||
return vector();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,15 @@ function register_controller(tpe: OpenFlow::Plugin, name: string, controller: Co
|
|||
controller$state$_name = cat(tpe, name);
|
||||
controller$state$_plugin = tpe;
|
||||
|
||||
if ( controller?$init )
|
||||
controller$init(controller$state);
|
||||
register_controller_impl(tpe, name, controller);
|
||||
}
|
||||
|
||||
function unregister_controller(controller: Controller)
|
||||
{
|
||||
unregister_controller_impl(controller);
|
||||
}
|
||||
|
||||
function lookup_controller(name: string): vector of Controller
|
||||
{
|
||||
return lookup_controller_impl(name);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ export {
|
|||
broker_topic: string &optional;
|
||||
};
|
||||
|
||||
global broker_flow_mod: event(dpid: count, match: ofp_match, flow_mod: ofp_flow_mod);
|
||||
global broker_flow_clear: event(dpid: count);
|
||||
global broker_flow_mod: event(name: string, dpid: count, match: ofp_match, flow_mod: ofp_flow_mod);
|
||||
global broker_flow_clear: event(name: string, dpid: count);
|
||||
}
|
||||
|
||||
function broker_describe(state: ControllerState): string
|
||||
|
@ -43,14 +43,14 @@ function broker_describe(state: ControllerState): string
|
|||
|
||||
function broker_flow_mod_fun(state: ControllerState, match: ofp_match, flow_mod: OpenFlow::ofp_flow_mod): bool
|
||||
{
|
||||
BrokerComm::event(state$broker_topic, BrokerComm::event_args(broker_flow_mod, state$broker_dpid, match, flow_mod));
|
||||
BrokerComm::event(state$broker_topic, BrokerComm::event_args(broker_flow_mod, state$_name, state$broker_dpid, match, flow_mod));
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
function broker_flow_clear_fun(state: OpenFlow::ControllerState): bool
|
||||
{
|
||||
BrokerComm::event(state$broker_topic, BrokerComm::event_args(broker_flow_clear, state$broker_dpid));
|
||||
BrokerComm::event(state$broker_topic, BrokerComm::event_args(broker_flow_clear, state$_name, state$broker_dpid));
|
||||
|
||||
return T;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ function log_flow_mod(state: ControllerState, match: ofp_match, flow_mod: OpenFl
|
|||
{
|
||||
Log::write(OpenFlow::LOG, [$ts=network_time(), $dpid=state$log_dpid, $match=match, $flow_mod=flow_mod]);
|
||||
if ( state$log_success_event )
|
||||
event OpenFlow::flow_mod_success(match, flow_mod);
|
||||
event OpenFlow::flow_mod_success(state$_name, match, flow_mod);
|
||||
|
||||
return T;
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ function ryu_flow_mod(state: OpenFlow::ControllerState, match: ofp_match, flow_m
|
|||
# Generate our ryu_flow_mod record for the ReST API call.
|
||||
local mod: ryu_ofp_flow_mod = ryu_ofp_flow_mod(
|
||||
$dpid=state$ryu_dpid,
|
||||
$cookie=OpenFlow::generate_cookie(flow_mod$cookie),
|
||||
$cookie=flow_mod$cookie,
|
||||
$idle_timeout=flow_mod$idle_timeout,
|
||||
$hard_timeout=flow_mod$hard_timeout,
|
||||
$priority=flow_mod$priority,
|
||||
|
@ -122,7 +122,7 @@ function ryu_flow_mod(state: OpenFlow::ControllerState, match: ofp_match, flow_m
|
|||
{
|
||||
print url;
|
||||
print to_json(mod);
|
||||
event OpenFlow::flow_mod_success(match, flow_mod);
|
||||
event OpenFlow::flow_mod_success(state$_name, match, flow_mod);
|
||||
return T;
|
||||
}
|
||||
|
||||
|
@ -137,11 +137,11 @@ function ryu_flow_mod(state: OpenFlow::ControllerState, match: ofp_match, flow_m
|
|||
when ( local result = ActiveHTTP::request(request) )
|
||||
{
|
||||
if(result$code == 200)
|
||||
event OpenFlow::flow_mod_success(match, flow_mod, result$body);
|
||||
event OpenFlow::flow_mod_success(state$_name, match, flow_mod, result$body);
|
||||
else
|
||||
{
|
||||
Reporter::warning(fmt("Flow modification failed with error: %s", result$body));
|
||||
event OpenFlow::flow_mod_failure(match, flow_mod, result$body);
|
||||
event OpenFlow::flow_mod_failure(state$_name, match, flow_mod, result$body);
|
||||
return F;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,35 +108,6 @@ export {
|
|||
actions: ofp_flow_action &default=ofp_flow_action();
|
||||
} &log;
|
||||
|
||||
# Functionality using this is currently not implemented. At all.
|
||||
# ## Body of reply to OFPST_FLOW request.
|
||||
# type ofp_flow_stats: record {
|
||||
# ## ID of table flow came from.
|
||||
# table_id: count;
|
||||
# ## Description of fields.
|
||||
# match: ofp_match;
|
||||
# ## Time flow has been alive in seconds.
|
||||
# duration_sec: count;
|
||||
# ## Time flow has been alive in nanoseconds beyond
|
||||
# ## duration_sec.
|
||||
# duration_nsec: count;
|
||||
# ## Priority of the entry. Only meaningful
|
||||
# ## when this is not an exact-match entry.
|
||||
# priority: count;
|
||||
# ## Number of seconds idle before expiration.
|
||||
# idle_timeout: count;
|
||||
# ## Number of seconds before expiration.
|
||||
# hard_timeout: count;
|
||||
# ## Opaque controller-issued identifier.
|
||||
# cookie: count;
|
||||
# ## Number of packets in flow.
|
||||
# packet_count: count;
|
||||
# ## Number of bytes in flow.
|
||||
# byte_count: count;
|
||||
# ## Actions
|
||||
# actions: vector of ofp_action_output;
|
||||
# };
|
||||
|
||||
## Controller record representing an openflow controller
|
||||
type Controller: record {
|
||||
## Controller related state.
|
||||
|
@ -147,6 +118,8 @@ export {
|
|||
describe: function(state: ControllerState): string;
|
||||
## one-time initialization function.
|
||||
init: function (state: ControllerState) &optional;
|
||||
## one-time destruction function
|
||||
destroy: function (state: ControllerState) &optional;
|
||||
## flow_mod function
|
||||
flow_mod: function(state: ControllerState, match: ofp_match, flow_mod: ofp_flow_mod): bool &optional;
|
||||
## flow_clear function
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue