mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
[ADD] reworked code to new design suggested by seth.
The openflow framework now supports multiple controllers. The design now looks a bit object oriented and a new() function creates a controller record. Moved the JSON script from the JSON namespace into a openflow specific OpenflowJSON namespace
This commit is contained in:
parent
fef8476690
commit
d80cc9ea10
4 changed files with 158 additions and 166 deletions
|
@ -4,19 +4,16 @@
|
|||
@load base/utils/active-http
|
||||
|
||||
|
||||
module Openflow;
|
||||
module OpenflowRyu;
|
||||
|
||||
|
||||
export {
|
||||
## The Ryu openflow controller IP.
|
||||
const controller_ip = "0.0.0.0" &redef;
|
||||
## The port where the ReST API listens on.
|
||||
const controller_port = "8080" &redef;
|
||||
redef enum Openflow::Plugin += {
|
||||
Openflow::RYU,
|
||||
};
|
||||
|
||||
## Ryu error definitions.
|
||||
type RyuError: enum {
|
||||
## The controller IP needs to be redefined.
|
||||
CONTROLLER_IP_REDEF,
|
||||
type Error: enum {
|
||||
## The openflow command type is not available
|
||||
## for this ryu openflow plugin.
|
||||
COMMAND_TYPE_NOT_AVAILABLE,
|
||||
|
@ -33,7 +30,18 @@ export {
|
|||
## error: The error why the plugin aborted.
|
||||
##
|
||||
## msg: More detailed error description.
|
||||
global Openflow::ryu_error: event(flow_mod: ofp_flow_mod, error: RyuError, msg: string &default="");
|
||||
global OpenflowRyu::error: event(flow_mod: Openflow::ofp_flow_mod, error: Error, msg: string &default="");
|
||||
|
||||
## Ryu controller constructor.
|
||||
##
|
||||
## ip: Controller ip.
|
||||
##
|
||||
## port_: Controller listen port.
|
||||
##
|
||||
## dpid: Openflow switch datapath id.
|
||||
##
|
||||
## Returns: Openflow::Controller record
|
||||
global new: function(ip: addr, port_: count, dpid: count): Openflow::Controller;
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,7 +70,7 @@ type ryu_flow_action_output: record {
|
|||
# https://media.readthedocs.org/pdf/ryu/latest/ryu.pdf
|
||||
# on page 278-299 (30.10.2014)
|
||||
# Ryu ReST API flow_mod type.
|
||||
type ryu_flow_mod: record {
|
||||
type ryu_ofp_flow_mod: record {
|
||||
dpid: count;
|
||||
cookie: count &optional;
|
||||
cookie_mask: count &optional;
|
||||
|
@ -77,82 +85,73 @@ type ryu_flow_mod: record {
|
|||
};
|
||||
|
||||
|
||||
# Hook to register the Ryu openflow plugin's flow_mod function
|
||||
# as the one the openflow framework should use.
|
||||
hook register_openflow_plugin()
|
||||
# Ryu flow_mod function
|
||||
function flow_mod(state: Openflow::ControllerState, flow_mod: Openflow::ofp_flow_mod): bool
|
||||
{
|
||||
register_openflow_mod_func(
|
||||
function(dpid: count, flow_mod: ofp_flow_mod): bool
|
||||
# Generate ryu_flow_actions because their type differs (using strings as type).
|
||||
local _flow_actions: vector of ryu_flow_action_output;
|
||||
for(i in flow_mod$actions)
|
||||
{
|
||||
switch(flow_mod$actions[i]$type_)
|
||||
{
|
||||
# Check if the controller_ip has been redefined.
|
||||
if(controller_ip == "0.0.0.0")
|
||||
{
|
||||
Reporter::warning("The constant Openflow::controller_ip must be redefined");
|
||||
event Openflow::ryu_error(flow_mod, CONTROLLER_IP_REDEF, cat(controller_ip));
|
||||
case Openflow::OFPAT_OUTPUT:
|
||||
_flow_actions[|_flow_actions|] = ryu_flow_action_output($_port=flow_mod$actions[i]$port_);
|
||||
break;
|
||||
default:
|
||||
Reporter::warning(fmt("The given Openflow action type '%s' is not available", flow_mod$actions[i]$type_));
|
||||
event OpenflowRyu::error(flow_mod, ACTION_TYPE_NOT_AVAILABLE, cat(flow_mod$actions[i]$type_));
|
||||
return F;
|
||||
}
|
||||
# Generate ryu_flow_actions because their type differs (using strings as type).
|
||||
local _flow_actions: vector of ryu_flow_action_output;
|
||||
for(i in flow_mod$actions)
|
||||
{
|
||||
switch(flow_mod$actions[i]$_type)
|
||||
{
|
||||
case OFPAT_OUTPUT:
|
||||
_flow_actions[|_flow_actions|] = ryu_flow_action_output($_port=flow_mod$actions[i]$_port);
|
||||
break;
|
||||
default:
|
||||
Reporter::warning(fmt("The given Openflow action type '%s' is not available", flow_mod$actions[i]$_type));
|
||||
event Openflow::ryu_error(flow_mod, ACTION_TYPE_NOT_AVAILABLE, cat(flow_mod$actions[i]$_type));
|
||||
return F;
|
||||
}
|
||||
}
|
||||
# Generate our ryu_flow_mod record for the ReST API call.
|
||||
local _flow_mod: ryu_flow_mod = ryu_flow_mod(
|
||||
$dpid=dpid,
|
||||
$cookie=generate_cookie(flow_mod$cookie),
|
||||
$idle_timeout=flow_mod$idle_timeout,
|
||||
$hard_timeout=flow_mod$hard_timeout,
|
||||
$match=flow_mod$match,
|
||||
$actions=_flow_actions
|
||||
);
|
||||
# Type of the command
|
||||
local command_type: string;
|
||||
switch(flow_mod$command)
|
||||
{
|
||||
case OFPFC_ADD:
|
||||
command_type = "add";
|
||||
break;
|
||||
case OFPFC_DELETE:
|
||||
command_type = "delete";
|
||||
break;
|
||||
default:
|
||||
Reporter::warning(fmt("The given Openflow command type '%s' is not available", cat(flow_mod$command)));
|
||||
event Openflow::ryu_error(flow_mod, COMMAND_TYPE_NOT_AVAILABLE, cat(flow_mod$command));
|
||||
return F;
|
||||
}
|
||||
# Create the ActiveHTTP request and convert the record to a Ryu ReST API JSON string
|
||||
local request: ActiveHTTP::Request = ActiveHTTP::Request(
|
||||
$url=cat("http://", controller_ip, ":", controller_port, RYU_FLOWENTRY_PATH, command_type),
|
||||
$method="POST",
|
||||
$client_data=JSON::convert(_flow_mod)
|
||||
);
|
||||
# Execute call to Ryu's ReST API
|
||||
when(local result = ActiveHTTP::request(request))
|
||||
{
|
||||
if(result$code == 200)
|
||||
event Openflow::flow_mod_success(flow_mod, result$body);
|
||||
else
|
||||
{
|
||||
Reporter::warning(fmt("Flow modification failed with error: %s", result$body));
|
||||
event Openflow::flow_mod_failure(flow_mod, result$body);
|
||||
return F;
|
||||
}
|
||||
}
|
||||
|
||||
return T;
|
||||
}
|
||||
}
|
||||
# Generate our ryu_flow_mod record for the ReST API call.
|
||||
local _flow_mod: ryu_ofp_flow_mod = ryu_ofp_flow_mod(
|
||||
$dpid=state$dpid,
|
||||
$cookie=Openflow::generate_cookie(flow_mod$cookie),
|
||||
$idle_timeout=flow_mod$idle_timeout,
|
||||
$hard_timeout=flow_mod$hard_timeout,
|
||||
$match=flow_mod$match,
|
||||
$actions=_flow_actions
|
||||
);
|
||||
# Type of the command
|
||||
local command_type: string;
|
||||
switch(flow_mod$command)
|
||||
{
|
||||
case Openflow::OFPFC_ADD:
|
||||
command_type = "add";
|
||||
break;
|
||||
case Openflow::OFPFC_DELETE:
|
||||
command_type = "delete";
|
||||
break;
|
||||
default:
|
||||
Reporter::warning(fmt("The given Openflow command type '%s' is not available", cat(flow_mod$command)));
|
||||
event OpenflowRyu::error(flow_mod, COMMAND_TYPE_NOT_AVAILABLE, cat(flow_mod$command));
|
||||
return F;
|
||||
}
|
||||
# Create the ActiveHTTP request and convert the record to a Ryu ReST API JSON string
|
||||
local request: ActiveHTTP::Request = ActiveHTTP::Request(
|
||||
$url=cat("http://", cat(state$ip), ":", cat(state$port_), RYU_FLOWENTRY_PATH, command_type),
|
||||
$method="POST",
|
||||
$client_data=OpenflowJSON::convert(_flow_mod)
|
||||
);
|
||||
# Execute call to Ryu's ReST API
|
||||
when(local result = ActiveHTTP::request(request))
|
||||
{
|
||||
if(result$code == 200)
|
||||
event Openflow::flow_mod_success(flow_mod, result$body);
|
||||
else
|
||||
{
|
||||
Reporter::warning(fmt("Flow modification failed with error: %s", result$body));
|
||||
event Openflow::flow_mod_failure(flow_mod, result$body);
|
||||
return F;
|
||||
}
|
||||
}
|
||||
|
||||
# TODO: implement when a JSON -> record converter exists
|
||||
# register_openflow_stats_func();
|
||||
return T;
|
||||
}
|
||||
|
||||
|
||||
# Ryu controller constructor
|
||||
function new(ip: addr, port_: count, dpid: count): Openflow::Controller
|
||||
{
|
||||
return [$state=[$ip=ip, $port_=port_, $type_=Openflow::RYU, $dpid=dpid], $flow_mod=flow_mod];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue