Skip to content

Instantly share code, notes, and snippets.

@stereocat
Created May 6, 2017 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stereocat/556a526e297251f5ac9db5307f0adf7a to your computer and use it in GitHub Desktop.
Save stereocat/556a526e297251f5ac9db5307f0adf7a to your computer and use it in GitHub Desktop.
Rewrite nettester_flowviewer
"use strict";
function build_flowdata(ssw_textarea, psw_textarea) {
var ssw_flows = build_flowdata_from(ssw_textarea);
var psw_flows = build_flowdata_from(psw_textarea);
var flows = ssw_flows.concat(psw_flows);
console.log(flows);
var nested_flows = nest_flowdata(flows);
console.log(nested_flows);
fill_flows(nested_flows);
setup_key(nested_flows);
console.log(nested_flows);
return nested_flows;
}
function nest_flowdata(flows) {
return d3.nest()
.key(function(d) { return d.switch; })
.sortKeys(d3.ascending)
.key(function(d) { return d.in_port; })
.sortKeys(function(a,b) { return a - b; })
.map(flows);
}
function build_flowdata_from(flow_table_textarea) {
var lines = flow_table_textarea.value
.split("\n")
.filter(function (thisobj) {
// discard header, empty line, and so on.
return thisobj.match(/^\s+cookie/i);
});
var numeric_values = ["priority", "in_port", "dl_vlan"];
var mac_values = ["dl_dst", "dl_src"];
return lines.map(function (line) {
// console.log("No: " + index + " line=", line);
var data = { // defaults
"switch" : flow_table_textarea.name,
"rule_str" : line, // original flow rule string
"in_port" : null,
"output" : null,
"priority" : null,
"vlan" : null,
"mac" : null,
"action_flood": false,
"flood_mark" : false
};
numeric_values.forEach(function (nvalue) {
var re = new RegExp(nvalue + "=(\\d+)");
var result = line.match(re);
if(result) {
if(nvalue === "dl_vlan") nvalue = "vlan_id";
data[nvalue] = Number(result[1]);
}
});
mac_values.forEach(function (svalue) {
var re = new RegExp(svalue + "=(\\S+)");
var result = line.match(re);
// set svg item class key by mac_address
if(result) {
data["mac"] = result[1];
}
});
var result = line.match(/actions=(\S+)/);
if(result) {
var actions_str = result[1];
if(actions_str.match(/FLOOD/)) {
// flood action only used in ssw
data.output = "FLOOD";
data.action_flood = true;
data.flood_mark = true;
}
var res;
res = actions_str.match(/output:(\d+)/);
if(res) {
data.output = Number(res[1]);
}
res = actions_str.match(/mod_vlan_vid:(\d+)/);
if(res) {
data.vlan = res[1];
}
}
return data;
});
}
function fill_mac_for_switch_flows(sw_flows) {
var isp_flows = sw_flows["$1"]; // inter switch port
isp_flows.forEach(function(flow) {
if(!flow.action_flood && flow.mac) {
sw_flows["$" + flow.output].forEach(function(target_flow) {
target_flow.mac = flow.mac;
});
}
});
}
function mark_flood_for_psw_flows(psw_flows) {
var edge_ports = Object.keys(psw_flows).filter(
function(d) { return "$1" !== d; }
);
edge_ports.forEach(function(port) {
psw_flows[port].forEach(function(flow){
// rule from psw edgeport includes flooding.
flow.flood_mark = true;
});
});
}
function gen_keys(sw, flow) {
var keys = [ "sw_" + sw.replace(/\$/g, "") ];
if(!flow.action_flood && flow.mac) {
keys.push("mac_" + flow.mac.replace(/:/g, ""));
}
if(flow.flood_mark) {
keys.push("flood");
}
if (sw === "$ssw") {
if(flow.in_port > 1) { // ssw edge port
keys.push("to_testee");
} else {
keys.push("to_tester");
}
} else {
if(flow.in_port > 1) { // psw edge port
keys.push("to_tester");
} else {
keys.push("to_testee");
}
}
return keys;
}
function setup_key(nested_flows) {
Object.keys(nested_flows).forEach(function(sw) {
var port_table = nested_flows[sw];
Object.keys(port_table).forEach(function(port) {
var port_flows = port_table[port];
port_flows.forEach(function(flow) {
flow.tags = gen_keys(sw, flow).join(" ");
});
});
});
}
function fill_flows(nested_flows) {
var ssw_flows = nested_flows["$ssw"];
fill_mac_for_switch_flows(ssw_flows);
console.log(ssw_flows);
var psw_flows = nested_flows["$psw"];
fill_mac_for_switch_flows(psw_flows);
mark_flood_for_psw_flows(psw_flows);
console.log(psw_flows);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flow viewer sample</title>
<link rel="stylesheet" type="text/css" href="flow_view.css">
</head>
<body>
<h1>Flow viewer</h1>
<p>Run http server by</p>
<pre>
ruby -rwebrick -e 'WEBrick::HTTPServer.new(:DocumentRoot => "./", :Port => 8000).start'
</pre>
<form name="flow_tables">
<p>SSW Flow-table: OVS (0xdad1c001)</p>
<textarea name="ssw" cols="100" rows="10">
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=177.909s, table=0, n_packets=4, n_bytes=370, idle_age=72, priority=0,in_port=1,dl_vlan=2025,dl_dst=00:ba:dc:ab:1e:01 actions=strip_vlan,output:2
cookie=0x0, duration=177.181s, table=0, n_packets=4, n_bytes=370, idle_age=70, priority=0,in_port=1,dl_vlan=2025,dl_dst=00:ba:dc:ab:1e:02 actions=strip_vlan,output:3
cookie=0x0, duration=176.371s, table=0, n_packets=4, n_bytes=370, idle_age=68, priority=0,in_port=1,dl_vlan=2025,dl_dst=00:ba:dc:ab:1e:03 actions=strip_vlan,output:4
cookie=0x0, duration=175.417s, table=0, n_packets=4, n_bytes=370, idle_age=65, priority=0,in_port=1,dl_vlan=2025,dl_dst=00:ba:dc:ab:1e:04 actions=strip_vlan,output:5
cookie=0x0, duration=175.417s, table=0, n_packets=12, n_bytes=768, idle_age=67, priority=2,in_port=1,dl_vlan=2025,dl_dst=ff:ff:ff:ff:ff:ff actions=strip_vlan,FLOOD
cookie=0x0, duration=174.411s, table=0, n_packets=4, n_bytes=370, idle_age=63, priority=0,in_port=1,dl_vlan=2023,dl_dst=00:ba:dc:ab:1e:05 actions=strip_vlan,output:6
cookie=0x0, duration=173.322s, table=0, n_packets=4, n_bytes=370, idle_age=61, priority=0,in_port=1,dl_vlan=2023,dl_dst=00:ba:dc:ab:1e:06 actions=strip_vlan,output:7
cookie=0x0, duration=172.162s, table=0, n_packets=4, n_bytes=370, idle_age=59, priority=0,in_port=1,dl_vlan=2023,dl_dst=00:ba:dc:ab:1e:07 actions=strip_vlan,output:8
cookie=0x0, duration=170.840s, table=0, n_packets=4, n_bytes=370, idle_age=57, priority=0,in_port=1,dl_vlan=2023,dl_dst=00:ba:dc:ab:1e:08 actions=strip_vlan,output:9
cookie=0x0, duration=170.840s, table=0, n_packets=12, n_bytes=768, idle_age=59, priority=2,in_port=1,dl_vlan=2023,dl_dst=ff:ff:ff:ff:ff:ff actions=strip_vlan,FLOOD
cookie=0x0, duration=187.658s, table=0, n_packets=0, n_bytes=0, idle_age=187, priority=1,in_port=1,dl_dst=ff:ff:ff:ff:ff:ff actions=FLOOD
cookie=0x0, duration=177.919s, table=0, n_packets=12, n_bytes=984, idle_age=72, priority=0,in_port=2 actions=mod_vlan_vid:2025,output:1
cookie=0x0, duration=177.197s, table=0, n_packets=12, n_bytes=984, idle_age=70, priority=0,in_port=3 actions=mod_vlan_vid:2025,output:1
cookie=0x0, duration=176.375s, table=0, n_packets=12, n_bytes=984, idle_age=68, priority=0,in_port=4 actions=mod_vlan_vid:2025,output:1
cookie=0x0, duration=175.457s, table=0, n_packets=12, n_bytes=984, idle_age=65, priority=0,in_port=5 actions=mod_vlan_vid:2025,output:1
cookie=0x0, duration=174.458s, table=0, n_packets=12, n_bytes=984, idle_age=63, priority=0,in_port=6 actions=mod_vlan_vid:2023,output:1
cookie=0x0, duration=173.374s, table=0, n_packets=12, n_bytes=984, idle_age=61, priority=0,in_port=7 actions=mod_vlan_vid:2023,output:1
cookie=0x0, duration=172.200s, table=0, n_packets=12, n_bytes=984, idle_age=59, priority=0,in_port=8 actions=mod_vlan_vid:2023,output:1
cookie=0x0, duration=170.899s, table=0, n_packets=12, n_bytes=984, idle_age=57, priority=0,in_port=9 actions=mod_vlan_vid:2023,output:1
</textarea>
<p>PSW Flow-table: OFS</p>
<textarea name="psw" cols="100" rows="10">
NXST_FLOW reply (xid=0x4):
cookie=0x0, duration=206.174s, table=0, n_packets=n/a, n_bytes=6489, idle_age=0, priority=0,in_port=7 actions=output:1
cookie=0x0, duration=803.871s, table=0, n_packets=n/a, n_bytes=77622, idle_age=0, in_port=15 actions=output:14
cookie=0x0, duration=205.010s, table=0, n_packets=n/a, n_bytes=5866, idle_age=7, priority=0,in_port=10 actions=output:1
cookie=0x0, duration=207.260s, table=0, n_packets=n/a, n_bytes=11640, idle_age=0, priority=0,in_port=6 actions=output:1
cookie=0x0, duration=203.698s, table=0, n_packets=n/a, n_bytes=5291, idle_age=6, priority=0,in_port=11 actions=output:1
cookie=0x0, duration=805.384s, table=0, n_packets=n/a, n_bytes=42536, idle_age=0, in_port=12 actions=output:13
cookie=0x0, duration=805.354s, table=0, n_packets=n/a, n_bytes=0, idle_age=805, in_port=13 actions=output:12
cookie=0x0, duration=805.317s, table=0, n_packets=n/a, n_bytes=3056, idle_age=90, in_port=14 actions=output:15
cookie=0x0, duration=203.709s, table=0, n_packets=n/a, n_bytes=1094, idle_age=90, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:08 actions=output:11
cookie=0x0, duration=205.020s, table=0, n_packets=n/a, n_bytes=1524, idle_age=92, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:07 actions=output:10
cookie=0x0, duration=208.276s, table=0, n_packets=n/a, n_bytes=1086, idle_age=98, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:04 actions=output:11
cookie=0x0, duration=209.998s, table=0, n_packets=n/a, n_bytes=1090, idle_age=102, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:02 actions=output:7
cookie=0x0, duration=209.194s, table=0, n_packets=n/a, n_bytes=1554, idle_age=100, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:03 actions=output:10
cookie=0x0, duration=207.273s, table=0, n_packets=n/a, n_bytes=1242, idle_age=96, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:05 actions=output:6
cookie=0x0, duration=206.186s, table=0, n_packets=n/a, n_bytes=1094, idle_age=94, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:06 actions=output:7
cookie=0x0, duration=210.724s, table=0, n_packets=n/a, n_bytes=1086, idle_age=104, priority=0,in_port=1,dl_src=00:ba:dc:ab:1e:01 actions=output:6
</textarea>
</form>
<p>View</p>
<div id="flow_view"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script src="./flow_data.js"></script>
<script src="./flow_view.js"></script>
<script type="text/javascript">
build_flowdata(
document.flow_tables.ssw,
document.flow_tables.psw);
// draw_flow_tables(ssw_flows, psw_flows);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment