Skip to content
Snippets Groups Projects
Commit 05b4b94c authored by Ryan Izard's avatar Ryan Izard
Browse files

Merge pull request #5 from hwchiu/openflow-1.3

Thanks Hung-Wei!
parents 2ccdc1bf 5fad7e12
No related branches found
No related tags found
No related merge requests found
......@@ -18,25 +18,59 @@
package net.floodlightcontroller.core.web;
import java.util.Set;
import java.util.HashSet;
import net.floodlightcontroller.core.internal.IOFSwitchService;
import net.floodlightcontroller.core.IOFSwitch;
import org.projectfloodlight.openflow.types.DatapathId;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
/**
* Get a list of switches connected to the controller
* @author readams
*/
public class ControllerSwitchesResource extends ServerResource {
public static final String DPID_ERROR = "Invalid switch DPID string. Must be a 64-bit value in the form 00:11:22:33:44:55:66:77.";
public static final String DPID_ERROR = "Invalid switch DPID string. Must be a 64-bit value in the form 00:11:22:33:44:55:66:77.";
public static class DatapathIDJsonSerializerWrapper {
private final DatapathId dpid;
private final String inetAddress;
private final long connectedSince;
public DatapathIDJsonSerializerWrapper(DatapathId dpid, String inetAddress, long connectedSince) {
this.dpid = dpid;
this.inetAddress = inetAddress;
this.connectedSince = connectedSince;
}
@JsonSerialize(using=DPIDSerializer.class)
public DatapathId getSwitchDPID() {
return dpid;
}
public String getInetAddress() {
return inetAddress;
}
public long getConnectedSince() {
return connectedSince;
}
}
@Get("json")
public Set<DatapathId> retrieve(){
public Set<DatapathIDJsonSerializerWrapper> retrieve(){
IOFSwitchService switchService =
(IOFSwitchService) getContext().getAttributes().
get(IOFSwitchService.class.getCanonicalName());
return switchService.getAllSwitchDpids();
Set<DatapathIDJsonSerializerWrapper> dpidSets = new HashSet<DatapathIDJsonSerializerWrapper>();
for(IOFSwitch sw: switchService.getAllSwitchMap().values()) {
dpidSets.add(new DatapathIDJsonSerializerWrapper(sw.getId(), sw.getInetAddress().toString(), sw.getConnectedSince().getTime()));
}
return dpidSets;
}
}
......@@ -127,6 +127,8 @@ public class SwitchResourceBase extends ServerResource {
case METER_CONFIG:
case METER_FEATURES:
case PORT_DESC:
req = sw.getOFFactory().buildPortDescStatsRequest()
.build();
case TABLE_FEATURES:
default:
log.error("Stats Request Type {} not implemented yet", statType.name());
......@@ -174,4 +176,4 @@ public class SwitchResourceBase extends ServerResource {
return getSwitchFeaturesReply(DatapathId.of(switchId));
}
}
\ No newline at end of file
}
......@@ -91,7 +91,7 @@ public class SwitchStatisticsResource extends SwitchResourceBase {
result.setStatType(OFStatsType.EXPERIMENTER);
break;
case OFStatsTypeStrings.PORT_DESC:
values = getSwitchFeaturesReply(switchId);
values = getSwitchStatistics(switchId, OFStatsType.PORT_DESC);
result.setStatType(OFStatsType.PORT_DESC);
break;
case OFStatsTypeStrings.GROUP:
......
......@@ -38,8 +38,8 @@ window.Switch = Backbone.Model.extend({
dataType:"json",
success:function (data) {
//console.log("fetched switch " + self.id + " desc");
//console.log(data[self.id][0]);
self.set(data[self.id][0]);
//console.log(data['desc']);
self.set(data['desc']);
}
});
......@@ -49,8 +49,8 @@ window.Switch = Backbone.Model.extend({
dataType:"json",
success:function (data) {
//console.log("fetched switch " + self.id + " aggregate");
//console.log(data[self.id][0]);
self.set(data[self.id][0]);
//console.log(data['aggregate']);
self.set(data['aggregate']);
}
});
self.trigger('add');
......@@ -73,19 +73,18 @@ window.Switch = Backbone.Model.extend({
dataType:"json",
success:function (data) {
//console.log("fetched switch " + self.id + " ports");
//console.log(data[self.id]);
var old_ids = self.ports.pluck('id');
//console.log("old_ids" + old_ids);
// create port models
_.each(data[self.id], function(p) {
_.each(data['port'], function(p) {
// workaround for REST serialization signed/unsigned bug
if(p.portNumber < 0) {p.portNumber = 65536 + p.portNumber};
p.id = self.id+'-'+p.portNumber;
old_ids = _.without(old_ids, p.id);
p.dropped = p.receiveDropped + p.transmitDropped;
p.errors = p.receiveCRCErrors + p.receiveErrors + p.receiveOverrunErrors +
p.errors = p.receiveCRCErrors + p.receiveFrameErrors + p.receiveOverrunErrors +
p.receiveFrameErrors + p.transmitErrors;
// this is a knda kludgy way to merge models
var m = self.ports.get(p.id);
......@@ -106,13 +105,13 @@ window.Switch = Backbone.Model.extend({
}
}),
$.ajax({
url:hackBase + "/wm/core/switch/" + self.id + '/features/json',
url:hackBase + "/wm/core/switch/" + self.id + '/port-desc/json',
dataType:"json",
success:function (data) {
//console.log("fetched switch " + self.id + " features");
//console.log(data[self.id]);
//console.log(data['portDesc']);
// update port models
_.each(data[self.id].ports, function(p) {
_.each(data['portDesc'], function(p) {
p.id = self.id+'-'+p.portNumber;
if(p.name != p.portNumber) {
p.name = p.portNumber + ' (' + p.name + ')';
......@@ -167,7 +166,7 @@ window.Switch = Backbone.Model.extend({
dataType:"json",
success:function (data) {
//console.log("fetched switch " + self.id + " flows");
var flows = data[self.id];
var flows = data['flows'];
//console.log(flows);
// create flow models
......@@ -177,81 +176,31 @@ window.Switch = Backbone.Model.extend({
// build human-readable match
f.matchHTML = '';
if(!(f.match.wildcards & (1<<0))) { // input port
f.matchHTML += "port=" + f.match.inputPort + ", ";
if(f.hasOwnProperty('match')) {
_.each(f.match, function(value , key) {
f.matchHTML += key + "=" + value +" ";
},f);
}
if(!(f.match.wildcards & (1<<1))) { // VLAN ID
f.matchHTML += "VLAN=" + f.match.dataLayerVirtualLan + ", ";
}
if(!(f.match.wildcards & (1<<20))) { // VLAN prio
f.matchHTML += "prio=" + f.match.dataLayerVirtualLanPriorityCodePoint + ", ";
}
if(!(f.match.wildcards & (1<<2))) { // src MAC
f.matchHTML += "src=<a href='/host/" + f.match.dataLayerSource + "'>" +
f.match.dataLayerSource + "</a>, ";
}
if(!(f.match.wildcards & (1<<3))) { // dest MAC
f.matchHTML += "dest=<a href='/host/" + f.match.dataLayerDestination + "'>" +
f.match.dataLayerDestination + "</a>, ";
}
if(!(f.match.wildcards & (1<<4))) { // Ethertype
// TODO print a human-readable name instead of hex
f.matchHTML += "ethertype=" + f.match.dataLayerType + ", ";
}
if(!(f.match.wildcards & (1<<5))) { // IP protocol
// TODO print a human-readable name
f.matchHTML += "proto=" + f.match.networkProtocol + ", ";
}
if(!(f.match.wildcards & (1<<6))) { // TCP/UDP source port
f.matchHTML += "IP src port=" + f.match.transportSource + ", ";
}
if(!(f.match.wildcards & (1<<7))) { // TCP/UDP dest port
f.matchHTML += "IP dest port=" + f.match.transportDestination + ", ";
}
if(!(f.match.wildcards & (32<<8))) { // src IP
f.matchHTML += "src=" + f.match.networkSource + ", ";
}
if(!(f.match.wildcards & (32<<14))) { // dest IP
f.matchHTML += "dest=" + f.match.networkDestination + ", ";
}
if(!(f.match.wildcards & (1<<21))) { // IP TOS
f.matchHTML += "TOS=" + f.match.networkTypeOfService + ", ";
}
// remove trailing ", "
f.matchHTML = f.matchHTML.substr(0, f.matchHTML.length - 2);
// build human-readable action list
f.actionText = _.reduce(f.actions, function (memo, a) {
switch (a.type) {
case "OUTPUT":
return memo + "output " + a.port + ', ';
case "OPAQUE_ENQUEUE":
return memo + "enqueue " + a.port + ':' + a.queueId + ', ';
case "STRIP_VLAN":
return memo + "strip VLAN, ";
case "SET_VLAN_ID":
return memo + "VLAN=" + a.virtualLanIdentifier + ', ';
case "SET_VLAN_PCP":
return memo + "prio=" + a.virtualLanPriorityCodePoint + ', ';
case "SET_DL_SRC":
return memo + "src=" + a.dataLayerAddress + ', ';
case "SET_DL_DST":
return memo + "dest=" + a.dataLayerAddress + ', ';
case "SET_NW_TOS":
return memo + "TOS=" + a.networkTypeOfService + ', ';
case "SET_NW_SRC":
return memo + "src=" + a.networkAddress + ', ';
case "SET_NW_DST":
return memo + "dest=" + a.networkAddress + ', ';
case "SET_TP_SRC":
return memo + "src port=" + a.transportPort + ', ';
case "SET_TP_DST":
return memo + "dest port=" + a.transportPort + ', ';
f.applyActionText = '';
f.writeActionText = '';
if(f.hasOwnProperty('instructions')) {
if(f.instructions.hasOwnProperty('apply_actions')) {
_.each(f.instructions.apply_actions, function(value, key) {
f.applyActionText += key + ":" + value +" ";
},f);
}
if(f.instructions.hasOwnProperty('write_actions')) {
_.each(f.instructions.write_actions, function(value, key) {
f.writeActionText += key + ":" + value +" ";
},f);
}
}, "");
// remove trailing ", "
f.actionText = f.actionText.substr(0, f.actionText.length - 2);
}
// build human-readable action list
f.applyActionText = f.applyActionText.substr(0, f.applyActionText.length - 2);
f.writeActionText = f.writeActionText.substr(0, f.writeActionText.length - 2);
//console.log(f);
self.flows.add(f, {silent: true});
});
......@@ -278,8 +227,8 @@ window.SwitchCollection = Backbone.Collection.extend({
//console.log("old_ids" + old_ids);
_.each(data, function(sw) {
old_ids = _.without(old_ids, sw['dpid']);
self.add({id: sw['dpid'], inetAddress: sw.inetAddress,
old_ids = _.without(old_ids, sw['switchDPID']);
self.add({id: sw['switchDPID'], inetAddress: sw.inetAddress,
connectedSince: new Date(sw.connectedSince).toLocaleString()})});
// old_ids now holds switches that no longer exist; remove them
......
<td><%= cookie %></td><td><%= priority %></td><td><%= matchHTML %></td><td><%= actionText %></td><td><%= packetCount %></td><td><%= byteCount %></td><td><%= durationSeconds %> s</td><td><%= idleTimeout %> s</td>
<td><%= cookie %></td><td><%= priority %></td><td><%= matchHTML %></td><td><%= applyActionText %></td><td><%= writeActionText %></td><td><%= packetCount %></td><td><%= byteCount %></td><td><%= durationSeconds %> s</td><td><%= idleTimeoutSec %> s</td>
......@@ -2,7 +2,7 @@
<h1>Flows (<%= nflows %>)</h1>
</div>
<table class="table table-striped flow-table">
<thead><tr><th>Cookie</th><th>Priority</th><th>Match</th><th>Action</th><th>Packets</th><th>Bytes</th><th>Age</th><th>Timeout</th></tr></thead>
<thead><tr><th>Cookie</th><th>Priority</th><th>Match</th><th>Apply Actions</th><th>Write Actions</th><th>Packets</th><th>Bytes</th><th>Age</th><th>Timeout</th></tr></thead>
<tbody>
<!-- flows will be inserted here by FlowListView:render -->
</tbody>
......@@ -16,4 +16,4 @@
<li><a href="">&rarr;</a>
</ul></div>
-->
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment