diff --git a/scripts/base/frameworks/openflow/main.bro b/scripts/base/frameworks/openflow/main.bro index e3cabcb939..a55e32a063 100644 --- a/scripts/base/frameworks/openflow/main.bro +++ b/scripts/base/frameworks/openflow/main.bro @@ -212,7 +212,7 @@ export { ## Body of reply to OFPST_FLOW request. type ofp_flow_stats: record { ## Length of this entry - length: count; + _length: count; ## ID of table flow came from. table_id: count; ## Description of fields. @@ -247,7 +247,24 @@ export { ## the flow to delete, modify or add. ## ## Returns: T, if successful, else F. - global flow_mod: function(dpid: count, flow_mod: ofp_flow_mod): bool; + global flow_mod: function(dpid: count, flow_mod: ofp_flow_mod): bool + &default=function(dpid: count, flow_mod:ofp_flow_mod): bool + { + Reporter::warning("Openflow::flow_mod function not implemented. Please load the right Openflow plugin"); + return F; + }; + + ## Function to get flow stats from the openflow switch/router + ## + ## dpid: The openflow controller datapath id. + ## + ## Returns: list with the installed flows and their statistics + global flow_stats: function(dpid: count): vector of ofp_flow_stats + &default=function(dpid: count): vector of ofp_flow_stats + { + Reporter::warning("Openflow::flow_stats function not implemented. Please load the right Openflow plugin"); + return vector(); + }; ## Function to get the unique id out of a given cookie ## @@ -285,18 +302,28 @@ export { type FlowModFunc: function(dpid: count, flow_mod: ofp_flow_mod): bool; +# Flow Statistics function prototype +type FlowStatsFunc: function(dpid: count): vector of ofp_flow_stats; + + # Hook for registering openflow plugins global register_openflow_plugin: hook(); -# Function for plugins to call when they -# register their flow_mod function. +# Function for plugins to call when they register their flow_mod function. function register_openflow_mod_func(func: FlowModFunc) { flow_mod = func; } +# Function for plugins to call when they register their flow_stats function. +function register_openflow_stats_func(func: FlowStatsFunc) + { + flow_stats = func; + } + + # local function to forge a flow_mod cookie for this framework. # all flow entries from the openflow framework should have the # 42 bit of the cookie set. @@ -316,7 +343,7 @@ 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 a valid", cookie)); + Reporter::warning(fmt("The given Openflow cookie '%d' is not valid", cookie)); return F; } diff --git a/scripts/base/frameworks/openflow/plugins/ryu.bro b/scripts/base/frameworks/openflow/plugins/ryu.bro index 6d30a0cf6d..a3360c3098 100644 --- a/scripts/base/frameworks/openflow/plugins/ryu.bro +++ b/scripts/base/frameworks/openflow/plugins/ryu.bro @@ -43,6 +43,8 @@ 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/"; # Ryu ReST API action_output type. @@ -85,7 +87,7 @@ hook register_openflow_plugin() # Check if the controller_ip has been redefined. if(controller_ip == "0.0.0.0") { - Reporter::warning(fmt("The constant Openflow::controller_ip must be redefined")); + Reporter::warning("The constant Openflow::controller_ip must be redefined"); event Openflow::ryu_error(flow_mod, CONTROLLER_IP_REDEF, cat(controller_ip)); return F; } @@ -124,7 +126,7 @@ hook register_openflow_plugin() command_type = "delete"; break; default: - Reporter::warning(fmt("The given Openflow command type '%s' is not available", result$body)); + 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; } @@ -150,4 +152,7 @@ hook register_openflow_plugin() return T; } ); + + # TODO: implement when a JSON -> record converter exists + # register_openflow_stats_func(); } diff --git a/scripts/base/frameworks/openflow/utils/json.bro b/scripts/base/frameworks/openflow/utils/json.bro index c482314698..44b722b190 100644 --- a/scripts/base/frameworks/openflow/utils/json.bro +++ b/scripts/base/frameworks/openflow/utils/json.bro @@ -12,8 +12,19 @@ export { ## ## returns: a JSON formatted string. global convert: function(v: any, only_loggable: bool &default=F, field_escape_pattern: pattern &default=/^_/): string; + + global jsonToRecord: function(input: string): any; } +function jsonToRecord(input: string): any + { + local lhs: table[count] of string; + lhs = split1(input, / /); + for (i in lhs) + print lhs[i]; + return lhs; + } + function convert(v: any, only_loggable: bool &default=F, field_escape_pattern: pattern &default=/^_/): string { local tn = type_name(v); diff --git a/scripts/site/openflow-shunt.bro b/scripts/site/openflow-shunt.bro index d10ce853e8..0a46b14a4d 100644 --- a/scripts/site/openflow-shunt.bro +++ b/scripts/site/openflow-shunt.bro @@ -19,9 +19,9 @@ const idle_timeout = 30; const hard_timeout = 0; const in_port = 3; const out_port = 1; - global delete_flow: bool = F; + export { ## Number of bytes transferred before shunting a flow. const size_threshold = 1024000 &redef; @@ -35,22 +35,14 @@ export { global shunt_triggered: event(c: connection); } + function size_callback(c: connection, cnt: count): interval { - # print flow traffic. - print fmt( - "%s:%s <-> %s:%s reached %s/%s", - c$id$orig_h, - port_to_count(c$id$orig_p), - c$id$resp_h, - port_to_count(c$id$resp_p), - c$orig$num_bytes_ip + c$resp$num_bytes_ip, - size_threshold - ); + # print Openflow::flow_stats(dpid); # if traffic exceeds the given threshold, remove flow. if ( c$orig$num_bytes_ip + c$resp$num_bytes_ip >= size_threshold ) { - # create openflow flow_mod add records from connection data and given default constants + # create openflow flow_mod add records from connection data and give default constants local actions: vector of Openflow::ofp_action_output; local reverse_actions: vector of Openflow::ofp_action_output; actions[|actions|] = Openflow::ofp_action_output($_port=out_port); @@ -120,21 +112,26 @@ function size_callback(c: connection, cnt: count): interval return poll_interval; } + event connection_established(c: connection) { print fmt("new connection"); ConnPolling::watch(c, size_callback, 0, 0secs); } + event Openflow::flow_mod_success(flow_mod: Openflow::ofp_flow_mod, msg: string) { print fmt("succsess, %s", cat(flow_mod)); } + event Openflow::flow_mod_failure(flow_mod: Openflow::ofp_flow_mod, msg: string) { print fmt("failed, %s", cat(flow_mod)); } + + event Openflow::ryu_error(flow_mod: Openflow::ofp_flow_mod, error: Openflow::RyuError, msg: string) { print fmt("ERROR: %s, msg: %s\n%s", error, msg, flow_mod);