mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Rewrite big parts of the Openflow framework.
The API now does not follow the openflow specification quite as closely, however I think it is much more usable. Furthermore, the Ryu plugin was basically completely rewritten and is now more usable for general flow manipulation. This also adds a debug mode that just outputs the json fragments that would be sent to ryu. At the moment, Ryu still assumes that every request that it receives succeeds - it is not possible to get an error message from the controller. Instead, one has to check if a flow was added by doing a second REST request. Which seems unnecessary, and also requires complete json parsing functionality. Hence we are not doing that at the moment. The alternative would be to use an external script for the actual add-and-check-operation.
This commit is contained in:
parent
4195a0066a
commit
dbc51371cb
6 changed files with 302 additions and 280 deletions
|
@ -1,3 +1,4 @@
|
|||
@load ./consts
|
||||
@load ./types
|
||||
@load ./main
|
||||
@load ./plugins
|
||||
|
|
|
@ -122,7 +122,6 @@ export {
|
|||
## which is not added, modified or deleted
|
||||
## from the bro openflow framework
|
||||
const INVALID_COOKIE = 0xffffffffffffffff;
|
||||
|
||||
# Openflow pysical port definitions
|
||||
## Maximum number of physical switch ports.
|
||||
const OFPP_MAX = 0xff00;
|
||||
|
@ -147,6 +146,17 @@ export {
|
|||
const OFPP_LOCAL = 0xfffe;
|
||||
## Not associated with a pysical port.
|
||||
const OFPP_NONE = 0xffff;
|
||||
# Openflow no buffer constant.
|
||||
const OFP_NO_BUFFER = 0xffffffff;
|
||||
## Send flow removed message when flow
|
||||
## expires or is deleted.
|
||||
const OFPFF_SEND_FLOW_REM = 0x1;
|
||||
## Check for overlapping entries first.
|
||||
const OFPFF_CHECK_OVERLAP = 0x2;
|
||||
## Remark this is for emergency.
|
||||
## Flows added with this are only used
|
||||
## when the controller is disconnected.
|
||||
const OFPFF_EMERG = 0x4;
|
||||
|
||||
## Openflow action_type definitions
|
||||
##
|
||||
|
@ -212,126 +222,4 @@ export {
|
|||
OFPC_FRAG_MASK = 3,
|
||||
};
|
||||
|
||||
## Openflow match definition.
|
||||
##
|
||||
## The openflow match record describes
|
||||
## which packets match to a specific
|
||||
## rule in a flow table.
|
||||
type ofp_match: record {
|
||||
# Wildcard fields.
|
||||
#wildcards: count &optional;
|
||||
# Input switch port.
|
||||
in_port: count &optional;
|
||||
# Ethernet source address.
|
||||
dl_src: string &optional;
|
||||
# Ethernet destination address.
|
||||
dl_dst: string &optional;
|
||||
# Input VLAN id.
|
||||
dl_vlan: count &optional;
|
||||
# Input VLAN priority.
|
||||
dl_vlan_pcp: count &optional;
|
||||
# Ethernet frame type.
|
||||
dl_type: count &default=ETH_IPv4;
|
||||
# IP ToS (actually DSCP field, 6bits).
|
||||
nw_tos: count &optional;
|
||||
# IP protocol or lower 8 bits of ARP opcode.
|
||||
nw_proto: count &default=IP_TCP;
|
||||
# IP source address.
|
||||
nw_src: addr &optional;
|
||||
# IP destination address.
|
||||
nw_dst: addr &optional;
|
||||
# TCP/UDP source port.
|
||||
tp_src: port &optional;
|
||||
# TCP/UDP destination port.
|
||||
tp_dst: port &optional;
|
||||
};
|
||||
|
||||
## Openflow actions definition.
|
||||
##
|
||||
## A action describes what should
|
||||
## happen with packets of the matching
|
||||
## flow.
|
||||
type ofp_action_output: record {
|
||||
## this should never change, but there are not
|
||||
## constants available in records
|
||||
## defaults to OFPAT_OUTPUT
|
||||
type_: ofp_action_type &default=OFPAT_OUTPUT;
|
||||
#_len: count &default=8;
|
||||
## Output port.
|
||||
port_: count &default=OFPP_FLOOD;
|
||||
#_max_len: count &optional;
|
||||
};
|
||||
|
||||
# Openflow flow_mod_flags definition
|
||||
## Send flow removed message when flow
|
||||
## expires or is deleted.
|
||||
const OFPFF_SEND_FLOW_REM = 0x1;
|
||||
## Check for overlapping entries first.
|
||||
const OFPFF_CHECK_OVERLAP = 0x2;
|
||||
## Remark this is for emergency.
|
||||
## Flows added with this are only used
|
||||
## when the controller is disconnected.
|
||||
const OFPFF_EMERG = 0x4;
|
||||
|
||||
## Openflow flow_mod definition.
|
||||
## It describes the flow to match and
|
||||
## how it should be modified.
|
||||
type ofp_flow_mod: record {
|
||||
# header: ofp_header;
|
||||
## Fields to match
|
||||
match: ofp_match;
|
||||
## Opaque controller-issued identifier.
|
||||
cookie: count &default=BRO_COOKIE_ID * COOKIE_BID_START;
|
||||
# Flow actions
|
||||
## One of OFPFC_*.
|
||||
command: ofp_flow_mod_command &default=OFPFC_ADD;
|
||||
## Idle time before discarding (seconds).
|
||||
idle_timeout: count &optional;
|
||||
## Max time before discarding (seconds).
|
||||
hard_timeout: count &optional;
|
||||
## Priority level of flow entry.
|
||||
priority: count &optional;
|
||||
## Buffered packet to apply to (or -1).
|
||||
## Not meaningful for OFPFC_DELETE*.
|
||||
buffer_id: count &optional;
|
||||
## For OFPFC_DELETE* commands, require
|
||||
## matching entries to include this as an
|
||||
## output port. A value of OFPP_NONE
|
||||
## indicates no restrictions.
|
||||
out_port: count &optional;
|
||||
## One of OFPFF_*.
|
||||
flags: count &optional;
|
||||
## A list of actions to perform.
|
||||
actions: vector of ofp_action_output;
|
||||
};
|
||||
|
||||
## Body of reply to OFPST_FLOW request.
|
||||
type ofp_flow_stats: record {
|
||||
## Length of this entry
|
||||
_length: count;
|
||||
## 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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,8 +1,59 @@
|
|||
@load ./consts
|
||||
##! Bro's openflow control framework
|
||||
##!
|
||||
##! This plugin-based framework allows to control Openflow capable
|
||||
##! switches by implementing communication to an Openflow controller
|
||||
##! via plugins. The framework has to be instantiated via the new function
|
||||
##! in one of the plugins. This framework only offers very low-level
|
||||
##! functionality; if you want to use OpenFlow capable switches, e.g.,
|
||||
##! for shunting, please look at the PACF framework, which provides higher
|
||||
##! level functions and can use the OpenFlow framework as a backend.
|
||||
|
||||
module Openflow;
|
||||
|
||||
@load ./consts
|
||||
@load ./types
|
||||
|
||||
export {
|
||||
## Global flow_mod function.
|
||||
##
|
||||
## controller: The controller which should execute the flow modification
|
||||
##
|
||||
## match: The ofp_match record which describes the flow to match.
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes the action to take.
|
||||
##
|
||||
## Returns: F on error or if the plugin does not support the operation, T when the operation was queued.
|
||||
global flow_mod: function(controller: Controller, match: ofp_match, flow_mod: ofp_flow_mod): bool;
|
||||
|
||||
## Clear the current flow table of the controller.
|
||||
##
|
||||
## controller: The controller which should execute the flow modification
|
||||
##
|
||||
## Returns: F on error or if the plugin does not support the operation, T when the operation was queued.
|
||||
global flow_clear: function(controller: Controller): bool;
|
||||
|
||||
## Event confirming successful modification of a flow rule.
|
||||
##
|
||||
## 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="");
|
||||
|
||||
## Reports an error while installing a flow Rule.
|
||||
##
|
||||
## 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="");
|
||||
|
||||
# ###
|
||||
# ### Low-level functions for cookie handling.
|
||||
# ###
|
||||
|
||||
## Function to get the unique id out of a given cookie.
|
||||
##
|
||||
## cookie: The openflow match cookie.
|
||||
|
@ -23,69 +74,24 @@ export {
|
|||
##
|
||||
## Returns: The cookie group id.
|
||||
global generate_cookie: function(cookie: count &default=0): count;
|
||||
|
||||
## Event to signal that a flow has been successfully modified.
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes
|
||||
## the flow to delete, modify or add.
|
||||
##
|
||||
## msg: Message to describe the event.
|
||||
global Openflow::flow_mod_success: event(flow_mod: ofp_flow_mod, msg: string &default="Flow successfully modified");
|
||||
|
||||
## Event to signal that a flow mod has failed.
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes
|
||||
## the flow to delete, modify or add.
|
||||
##
|
||||
## msg: Message to describe the event.
|
||||
global Openflow::flow_mod_failure: event(flow_mod: ofp_flow_mod, msg: string &default="Could not modify flow");
|
||||
|
||||
## Available openflow plugins
|
||||
type Plugin: enum {
|
||||
PLACEHOLDER,
|
||||
};
|
||||
|
||||
## Controller related state.
|
||||
## Can be redefined by plugins to
|
||||
## add state.
|
||||
type ControllerState: record {
|
||||
## Controller ip.
|
||||
host: addr &optional;
|
||||
## Controller listen port.
|
||||
host_port: count &optional;
|
||||
## Openflow switch datapath id.
|
||||
dpid: count &optional;
|
||||
## Type of the openflow plugin.
|
||||
type_: Plugin;
|
||||
} &redef;
|
||||
|
||||
## Controller record representing an openflow controller
|
||||
type Controller: record {
|
||||
## Controller related state.
|
||||
state: ControllerState;
|
||||
## flow_mod function the plugin implements
|
||||
flow_mod: function(state: ControllerState, flow_mod: ofp_flow_mod): bool;
|
||||
## flow_stats function the plugin implements if existing
|
||||
## flow_stats: function(state: ControllerState): vector of ofp_flow_stats &optional;
|
||||
};
|
||||
|
||||
## Global flow_mod function wrapper
|
||||
##
|
||||
## controller: The controller which should execute the flow modification
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes
|
||||
## the flow to delete, modify or add
|
||||
##
|
||||
## Returns: T if successfull, else F
|
||||
global flow_mod: function(controller: Controller, flow_mod: ofp_flow_mod): bool;
|
||||
}
|
||||
|
||||
# the flow_mod function wrapper
|
||||
function flow_mod(controller: Controller, flow_mod: ofp_flow_mod): bool
|
||||
function flow_mod(controller: Controller, match: ofp_match, flow_mod: ofp_flow_mod): bool
|
||||
{
|
||||
return controller$flow_mod(controller$state, flow_mod);
|
||||
if ( controller?$flow_mod )
|
||||
return controller$flow_mod(controller$state, match, flow_mod);
|
||||
else
|
||||
return F;
|
||||
}
|
||||
|
||||
function flow_clear(controller: Controller): bool
|
||||
{
|
||||
if ( controller?$flow_clear )
|
||||
return controller$flow_clear(controller$state);
|
||||
else
|
||||
return F;
|
||||
}
|
||||
|
||||
# local function to forge a flow_mod cookie for this framework.
|
||||
# all flow entries from the openflow framework should have the
|
||||
|
@ -93,39 +99,42 @@ function flow_mod(controller: Controller, flow_mod: ofp_flow_mod): bool
|
|||
function generate_cookie(cookie: count &default=0): count
|
||||
{
|
||||
local c = BRO_COOKIE_ID * COOKIE_BID_START;
|
||||
|
||||
if ( cookie >= COOKIE_UID_SIZE )
|
||||
Reporter::warning(fmt("The given cookie uid '%d' is > 32bit and will be discarded", cookie));
|
||||
else
|
||||
c += cookie;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
# local function to check if a given flow_mod cookie is forged from this framework.
|
||||
function _is_valid_cookie(cookie: count): bool
|
||||
function is_valid_cookie(cookie: count): bool
|
||||
{
|
||||
if ( cookie / COOKIE_BID_START == BRO_COOKIE_ID )
|
||||
return T;
|
||||
|
||||
Reporter::warning(fmt("The given Openflow cookie '%d' is not valid", cookie));
|
||||
|
||||
return F;
|
||||
}
|
||||
|
||||
|
||||
function get_cookie_uid(cookie: count): count
|
||||
{
|
||||
if(_is_valid_cookie(cookie))
|
||||
if( is_valid_cookie(cookie) )
|
||||
return (cookie - ((cookie / COOKIE_GID_START) * COOKIE_GID_START));
|
||||
|
||||
return INVALID_COOKIE;
|
||||
}
|
||||
|
||||
|
||||
function get_cookie_gid(cookie: count): count
|
||||
{
|
||||
if(_is_valid_cookie(cookie))
|
||||
if( is_valid_cookie(cookie) )
|
||||
return (
|
||||
(cookie - (COOKIE_BID_START * BRO_COOKIE_ID) -
|
||||
(cookie - ((cookie / COOKIE_GID_START) * COOKIE_GID_START))) /
|
||||
COOKIE_GID_START
|
||||
);
|
||||
|
||||
return INVALID_COOKIE;
|
||||
}
|
||||
|
|
|
@ -3,33 +3,13 @@
|
|||
@load base/utils/exec
|
||||
@load base/utils/json
|
||||
|
||||
module OpenflowRyu;
|
||||
module Openflow;
|
||||
|
||||
export {
|
||||
redef enum Openflow::Plugin += {
|
||||
Openflow::RYU,
|
||||
redef enum Plugin += {
|
||||
RYU,
|
||||
};
|
||||
|
||||
## Ryu error definitions.
|
||||
type Error: enum {
|
||||
## The openflow command type is not available
|
||||
## for this ryu openflow plugin.
|
||||
COMMAND_TYPE_NOT_AVAILABLE,
|
||||
## The openflow action type is not available
|
||||
## for this ryu openflow plugin.
|
||||
ACTION_TYPE_NOT_AVAILABLE,
|
||||
};
|
||||
|
||||
## Ryu error event.
|
||||
##
|
||||
## flow_mod: The openflow flow_mod record which describes
|
||||
## the flow to delete, modify or add.
|
||||
##
|
||||
## error: The error why the plugin aborted.
|
||||
##
|
||||
## msg: More detailed error description.
|
||||
global OpenflowRyu::error: event(flow_mod: Openflow::ofp_flow_mod, error: Error, msg: string &default="");
|
||||
|
||||
## Ryu controller constructor.
|
||||
##
|
||||
## host: Controller ip.
|
||||
|
@ -39,34 +19,35 @@ export {
|
|||
## dpid: Openflow switch datapath id.
|
||||
##
|
||||
## Returns: Openflow::Controller record
|
||||
global new: function(host: addr, host_port: count, dpid: count): Openflow::Controller;
|
||||
global ryu_new: function(host: addr, host_port: count, dpid: count): Openflow::Controller;
|
||||
|
||||
redef record ControllerState += {
|
||||
## Controller ip.
|
||||
ryu_host: addr &optional;
|
||||
## Controller listen port.
|
||||
ryu_port: count &optional;
|
||||
## Openflow switch datapath id.
|
||||
ryu_dpid: count &optional;
|
||||
## Enable debug mode - output JSON to stdout; do not perform actions
|
||||
ryu_debug: bool &default=F;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
# Openflow no buffer constant.
|
||||
const OFP_NO_BUFFER = 0xffffffff;
|
||||
|
||||
|
||||
# Ryu ReST API flow_mod URL-path
|
||||
const RYU_FLOWENTRY_PATH = "/stats/flowentry/";
|
||||
# Ryu ReST API flow_stats URL-path
|
||||
const RYU_FLOWSTATS_PATH = "/stats/flow/";
|
||||
|
||||
#const RYU_FLOWSTATS_PATH = "/stats/flow/";
|
||||
|
||||
# Ryu ReST API action_output type.
|
||||
type ryu_flow_action_output: record {
|
||||
type ryu_flow_action: record {
|
||||
# Ryu uses strings as its ReST API output action.
|
||||
# The type should be never changed...
|
||||
# but constants are not possible in a record.
|
||||
_type: string &default="OUTPUT";
|
||||
# The output port
|
||||
_port: count;
|
||||
_type: string;
|
||||
# The output port for type OUTPUT
|
||||
_port: count &optional;
|
||||
};
|
||||
|
||||
|
||||
# The ReST API documentation can be found at
|
||||
# https://media.readthedocs.org/pdf/ryu/latest/ryu.pdf
|
||||
# on page 278-299 (30.10.2014)
|
||||
# Ryu ReST API flow_mod type.
|
||||
type ryu_ofp_flow_mod: record {
|
||||
dpid: count;
|
||||
|
@ -76,70 +57,84 @@ type ryu_ofp_flow_mod: record {
|
|||
idle_timeout: count &optional;
|
||||
hard_timeout: count &optional;
|
||||
priority: count &optional;
|
||||
buffer_id: count &optional;
|
||||
flags: count &optional;
|
||||
match: Openflow::ofp_match;
|
||||
actions: vector of ryu_flow_action_output;
|
||||
actions: vector of ryu_flow_action;
|
||||
};
|
||||
|
||||
# Mapping between ofp flow mod commands and ryu urls
|
||||
const ryu_url: table[ofp_flow_mod_command] of string = {
|
||||
[OFPFC_ADD] = "add",
|
||||
[OFPFC_MODIFY] = "modify",
|
||||
[OFPFC_MODIFY_STRICT] = "modify_strict",
|
||||
[OFPFC_DELETE] = "delete",
|
||||
[OFPFC_DELETE_STRICT] = "delete_strict",
|
||||
};
|
||||
|
||||
# Ryu flow_mod function
|
||||
function flow_mod(state: Openflow::ControllerState, flow_mod: Openflow::ofp_flow_mod): bool
|
||||
function ryu_flow_mod(state: Openflow::ControllerState, match: ofp_match, flow_mod: Openflow::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)
|
||||
if ( state$_plugin != RYU )
|
||||
{
|
||||
switch(flow_mod$actions[i]$type_)
|
||||
{
|
||||
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_));
|
||||
Reporter::error("Ryu openflow plugin was called with state of non-ryu plugin");
|
||||
return F;
|
||||
}
|
||||
}
|
||||
|
||||
# Generate ryu_flow_actions because their type differs (using strings as type).
|
||||
local flow_actions: vector of ryu_flow_action = vector();
|
||||
|
||||
for ( i in flow_mod$out_ports )
|
||||
flow_actions[|flow_actions|] = ryu_flow_action($_type="OUTPUT", $_port=flow_mod$out_ports[i]);
|
||||
|
||||
# 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,
|
||||
local mod: ryu_ofp_flow_mod = ryu_ofp_flow_mod(
|
||||
$dpid=state$ryu_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
|
||||
$priority=flow_mod$priority,
|
||||
$flags=flow_mod$flags,
|
||||
$match=match,
|
||||
$actions=flow_actions
|
||||
);
|
||||
|
||||
# Type of the command
|
||||
local command_type: string;
|
||||
switch(flow_mod$command)
|
||||
|
||||
if ( flow_mod$command in ryu_url )
|
||||
command_type = ryu_url[flow_mod$command];
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
local url=cat("http://", cat(state$ryu_host), ":", cat(state$ryu_port), RYU_FLOWENTRY_PATH, command_type);
|
||||
|
||||
if ( state$ryu_debug )
|
||||
{
|
||||
print url;
|
||||
print to_json(mod);
|
||||
event Openflow::flow_mod_success(match, flow_mod);
|
||||
return T;
|
||||
}
|
||||
|
||||
# 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$host), ":", cat(state$host_port), RYU_FLOWENTRY_PATH, command_type),
|
||||
$url=url,
|
||||
$method="POST",
|
||||
$client_data=to_json(_flow_mod)
|
||||
$client_data=to_json(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);
|
||||
event Openflow::flow_mod_success(match, 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);
|
||||
event Openflow::flow_mod_failure(match, flow_mod, result$body);
|
||||
return F;
|
||||
}
|
||||
}
|
||||
|
@ -147,8 +142,31 @@ function flow_mod(state: Openflow::ControllerState, flow_mod: Openflow::ofp_flow
|
|||
return T;
|
||||
}
|
||||
|
||||
# Ryu controller constructor
|
||||
function new(host: addr, host_port: count, dpid: count): Openflow::Controller
|
||||
function ryu_flow_clear(state: Openflow::ControllerState): bool
|
||||
{
|
||||
return [$state=[$host=host, $host_port=host_port, $type_=Openflow::RYU, $dpid=dpid], $flow_mod=flow_mod];
|
||||
local url=cat("http://", cat(state$ryu_host), ":", cat(state$ryu_port), RYU_FLOWENTRY_PATH, "clear", "/", state$ryu_dpid);
|
||||
|
||||
if ( state$ryu_debug )
|
||||
{
|
||||
print url;
|
||||
return T;
|
||||
}
|
||||
|
||||
local request: ActiveHTTP::Request = ActiveHTTP::Request(
|
||||
$url=url,
|
||||
$method="DELETE"
|
||||
);
|
||||
|
||||
when ( local result = ActiveHTTP::request(request) )
|
||||
{
|
||||
}
|
||||
|
||||
return T;
|
||||
}
|
||||
|
||||
# Ryu controller constructor
|
||||
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],
|
||||
$flow_mod=ryu_flow_mod, $flow_clear=ryu_flow_clear];
|
||||
}
|
||||
|
|
111
scripts/base/frameworks/openflow/types.bro
Normal file
111
scripts/base/frameworks/openflow/types.bro
Normal file
|
@ -0,0 +1,111 @@
|
|||
module Openflow;
|
||||
|
||||
@load ./consts
|
||||
|
||||
export {
|
||||
## Available openflow plugins
|
||||
type Plugin: enum {
|
||||
## Internal placeholder plugin
|
||||
INVALID,
|
||||
};
|
||||
|
||||
## Controller related state.
|
||||
## Can be redefined by plugins to
|
||||
## add state.
|
||||
type ControllerState: record {
|
||||
## Internally set to the plugin used.
|
||||
_plugin: Plugin;
|
||||
} &redef;
|
||||
|
||||
## Openflow match definition.
|
||||
##
|
||||
## The openflow match record describes
|
||||
## which packets match to a specific
|
||||
## rule in a flow table.
|
||||
type ofp_match: record {
|
||||
# Input switch port.
|
||||
in_port: count &optional;
|
||||
# Ethernet source address.
|
||||
dl_src: string &optional;
|
||||
# Ethernet destination address.
|
||||
dl_dst: string &optional;
|
||||
# Input VLAN id.
|
||||
dl_vlan: count &optional;
|
||||
# Input VLAN priority.
|
||||
dl_vlan_pcp: count &optional;
|
||||
# Ethernet frame type.
|
||||
dl_type: count &optional;
|
||||
# IP ToS (actually DSCP field, 6bits).
|
||||
nw_tos: count &optional;
|
||||
# IP protocol or lower 8 bits of ARP opcode.
|
||||
nw_proto: count &optional;
|
||||
# IP source address.
|
||||
nw_src: addr &optional;
|
||||
# IP destination address.
|
||||
nw_dst: addr &optional;
|
||||
# TCP/UDP source port.
|
||||
tp_src: port &optional;
|
||||
# TCP/UDP destination port.
|
||||
tp_dst: port &optional;
|
||||
};
|
||||
|
||||
## Openflow flow_mod definition, describing the action to perform.
|
||||
type ofp_flow_mod: record {
|
||||
## Opaque controller-issued identifier.
|
||||
# This is optional in the specification - but let's force
|
||||
# it so we always can identify our flows...
|
||||
cookie: count; # &default=BRO_COOKIE_ID * COOKIE_BID_START;
|
||||
# Flow actions
|
||||
## One of OFPFC_*.
|
||||
command: ofp_flow_mod_command; # &default=OFPFC_ADD;
|
||||
## Idle time before discarding (seconds).
|
||||
idle_timeout: count &default=0;
|
||||
## Max time before discarding (seconds).
|
||||
hard_timeout: count &default=0;
|
||||
## Priority level of flow entry.
|
||||
priority: count &default=0;
|
||||
## Bitmap of the OFPFF_* flags
|
||||
flags: count &default=0;
|
||||
## Output ports to send data to.
|
||||
out_ports: vector of count &default=vector();
|
||||
};
|
||||
|
||||
# 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.
|
||||
state: ControllerState;
|
||||
## flow_mod function
|
||||
flow_mod: function(state: ControllerState, match: ofp_match, flow_mod: ofp_flow_mod): bool &optional;
|
||||
## flow_clear function
|
||||
flow_clear: function(state: ControllerState): bool &optional;
|
||||
};
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
##! Functions to assist with generating JSON data from Bro data scructures.
|
||||
|
||||
# We might want to implement this in core somtime, this looks... hacky at best.
|
||||
|
||||
@load base/utils/strings
|
||||
|
||||
export {
|
||||
## A function to convert arbitrary Bro data into a JSON string.
|
||||
##
|
||||
## v: The value to convert to JSON. Typically a record.
|
||||
|
@ -13,10 +11,7 @@ export {
|
|||
## fields with the &log attribute to be included in the JSON.
|
||||
##
|
||||
## returns: a JSON formatted string.
|
||||
global to_json: function(v: any, only_loggable: bool &default=F, field_escape_pattern: pattern &default=/^_/): string;
|
||||
}
|
||||
|
||||
function convert(v: any, only_loggable: bool &default=F, field_escape_pattern: pattern &default=/^_/): string
|
||||
function to_json(v: any, only_loggable: bool &default=F, field_escape_pattern: pattern &default=/^_/): string
|
||||
{
|
||||
local tn = type_name(v);
|
||||
switch ( tn )
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue