diff --git a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java index de90067ae5411bb835dcca4bff21be839c61f01f..cd4f77f917001048338bebe74d100e1bbe19d535 100644 --- a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java @@ -54,28 +54,36 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { OFStatsType type = null; REQUESTTYPE rType = null; - if (statType.equals("port")) { - type = OFStatsType.PORT; + switch (statType) { + case OFStatsTypeStrings.PORT: + type = OFStatsType.PORT; rType = REQUESTTYPE.OFSTATS; - } else if (statType.equals("queue")) { - type = OFStatsType.QUEUE; + break; + case OFStatsTypeStrings.QUEUE: + type = OFStatsType.QUEUE; rType = REQUESTTYPE.OFSTATS; - } else if (statType.equals("flow")) { - type = OFStatsType.FLOW; + break; + case OFStatsTypeStrings.FLOW: + type = OFStatsType.FLOW; rType = REQUESTTYPE.OFSTATS; - } else if (statType.equals("aggregate")) { - type = OFStatsType.AGGREGATE; + break; + case OFStatsTypeStrings.AGGREGATE: + type = OFStatsType.AGGREGATE; rType = REQUESTTYPE.OFSTATS; - } else if (statType.equals("desc")) { - type = OFStatsType.DESC; + break; + case OFStatsTypeStrings.DESC: + type = OFStatsType.DESC; rType = REQUESTTYPE.OFSTATS; - } else if (statType.equals("table")) { - type = OFStatsType.TABLE; + break; + case OFStatsTypeStrings.TABLE: + type = OFStatsType.TABLE; rType = REQUESTTYPE.OFSTATS; - } else if (statType.equals("features")) { + break; + case OFStatsTypeStrings.FEATURES: rType = REQUESTTYPE.OFFEATURES; - } else { - return model; + break; + default: + return model; } IOFSwitchService switchService = diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java index a4fe5d657184b8ce479d15887227f0f725fa04b8..8c1927863da5bd2b53b7be4baf74e4796a8d55a7 100644 --- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java @@ -29,6 +29,14 @@ import org.restlet.routing.Router; * @author readams */ public class CoreWebRoutable implements RestletRoutable { + // define the parts of each path the user can define in the REST message at runtime + // access these same strings where the attributes are parsed + public static final String STR_SWITCH_ID = "switchId"; + public static final String STR_STAT_TYPE = "statType"; + public static final String STR_CTR_TITLE = "counterTitle"; + public static final String STR_CTR_NAME = "counterName"; + public static final String STR_LAYER = "layer"; + @Override public String basePath() { return "/wm/core"; @@ -39,13 +47,13 @@ public class CoreWebRoutable implements RestletRoutable { Router router = new Router(context); router.attach("/module/all/json", ModuleLoaderResource.class); router.attach("/module/loaded/json", LoadedModuleLoaderResource.class); - router.attach("/switch/{switchId}/role/json", SwitchRoleResource.class); - router.attach("/switch/all/{statType}/json", AllSwitchStatisticsResource.class); - router.attach("/switch/{switchId}/{statType}/json", SwitchStatisticsResource.class); + router.attach("/switch/{" + STR_SWITCH_ID + "}/role/json", SwitchRoleResource.class); + router.attach("/switch/all/{" + STR_STAT_TYPE + "}/json", AllSwitchStatisticsResource.class); + router.attach("/switch/{" + STR_SWITCH_ID + "}/{" + STR_STAT_TYPE + "}/json", SwitchStatisticsResource.class); router.attach("/controller/switches/json", ControllerSwitchesResource.class); - router.attach("/counter/{counterTitle}/json", CounterResource.class); - router.attach("/counter/{switchId}/{counterName}/json", SwitchCounterResource.class); - router.attach("/counter/categories/{switchId}/{counterName}/{layer}/json", SwitchCounterCategoriesResource.class); + router.attach("/counter/{" + STR_CTR_TITLE + "}/json", CounterResource.class); + router.attach("/counter/{" + STR_SWITCH_ID + "}/{" + STR_CTR_NAME + "}/json", SwitchCounterResource.class); + router.attach("/counter/categories/{" + STR_SWITCH_ID + "}/{" + STR_CTR_NAME + "}/{" + STR_LAYER + "}/json", SwitchCounterCategoriesResource.class); router.attach("/memory/json", ControllerMemoryResource.class); router.attach("/packettrace/json", PacketTraceResource.class); router.attach("/storage/tables/json", StorageSourceTablesResource.class); diff --git a/src/main/java/net/floodlightcontroller/core/web/StatsReply.java b/src/main/java/net/floodlightcontroller/core/web/StatsReply.java new file mode 100644 index 0000000000000000000000000000000000000000..a705fa987075a4becee5c63b353502104493c187 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/StatsReply.java @@ -0,0 +1,45 @@ +package net.floodlightcontroller.core.web; + + +import org.projectfloodlight.openflow.protocol.OFStatsType; +import org.projectfloodlight.openflow.types.DatapathId; + +import net.floodlightcontroller.core.web.serializers.StatsReplySerializer; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +@JsonSerialize(using=StatsReplySerializer.class) +public class StatsReply { + private DatapathId datapath; + private Object values; + private OFStatsType statType; + + public StatsReply() {} + + public StatsReply(DatapathId dpid, Object values, OFStatsType type){ + this.datapath = dpid; + this.values = values; + this.statType = type; + } + public void setDatapathId(DatapathId dpid){ + this.datapath = dpid; + } + public void setValues(Object values){ + this.values = values; + } + public void setStatType(OFStatsType type){ + this.statType = type; + } + public DatapathId getDatapathId(){ + return datapath; + } + public Object getValues(){ + return values; + } + public OFStatsType getStatType(){ + return statType; + } + +} + + diff --git a/src/main/java/net/floodlightcontroller/core/web/StatsReplySerializer.java b/src/main/java/net/floodlightcontroller/core/web/StatsReplySerializer.java deleted file mode 100644 index d39bac142fff7d8ed9a5d82761879a7b5c290c71..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/web/StatsReplySerializer.java +++ /dev/null @@ -1,430 +0,0 @@ -package net.floodlightcontroller.core.web; - -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import net.floodlightcontroller.util.MatchUtils; - -import org.projectfloodlight.openflow.protocol.OFActionType; -import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; -import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; -import org.projectfloodlight.openflow.protocol.OFInstructionType; -import org.projectfloodlight.openflow.protocol.OFStatsReply; -import org.projectfloodlight.openflow.protocol.OFStatsType; -import org.projectfloodlight.openflow.protocol.OFVersion; -import org.projectfloodlight.openflow.protocol.action.OFAction; -import org.projectfloodlight.openflow.protocol.action.OFActionEnqueue; -import org.projectfloodlight.openflow.protocol.action.OFActionGroup; -import org.projectfloodlight.openflow.protocol.action.OFActionOutput; -import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls; -import org.projectfloodlight.openflow.protocol.action.OFActionPopPbb; -import org.projectfloodlight.openflow.protocol.action.OFActionPopVlan; -import org.projectfloodlight.openflow.protocol.action.OFActionPushMpls; -import org.projectfloodlight.openflow.protocol.action.OFActionPushPbb; -import org.projectfloodlight.openflow.protocol.action.OFActionPushVlan; -import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst; -import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc; -import org.projectfloodlight.openflow.protocol.action.OFActionSetField; -import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst; -import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc; -import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue; -import org.projectfloodlight.openflow.protocol.action.OFActionSetTpDst; -import org.projectfloodlight.openflow.protocol.action.OFActionSetTpSrc; -import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp; -import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid; -import org.projectfloodlight.openflow.protocol.action.OFActionStripVlan; -import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; -import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; -import org.projectfloodlight.openflow.protocol.instruction.OFInstructionExperimenter; -import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable; -import org.projectfloodlight.openflow.protocol.instruction.OFInstructionMeter; -import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions; -import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteMetadata; -import org.projectfloodlight.openflow.protocol.match.Match; -import org.projectfloodlight.openflow.protocol.match.MatchField; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmArpOp; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmArpSha; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmArpSpa; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmArpTha; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmArpTpa; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthDst; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthType; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv4Code; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIcmpv4Type; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpDscp; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpEcn; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpProto; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Dst; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Src; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmMetadata; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsLabel; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmMplsTc; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmSctpDst; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmSctpSrc; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmTcpDst; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmTcpSrc; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmUdpDst; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmUdpSrc; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanPcp; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmVlanVid; - -import com.fasterxml.jackson.core.JsonGenerationException; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; - -public class StatsReplySerializer extends JsonSerializer<Map<String, Object>> { - - @Override - public void serialize(Map<String, Object> statsReply, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { - // Map<String, Object> ==> Map<Switch-DPID-String, List<OFStatsReply>> - // It should be safe to cast the Object as a List of OFStatsReply's - String dpidStr = statsReply.keySet().iterator().next(); // there's got to be a simpler way to get the key - List<OFStatsReply> srList = (List<OFStatsReply>) statsReply.get(dpidStr); - - for (OFStatsReply sr : srList) { - OFStatsType t = sr.getStatsType(); - switch (t) { - case FLOW: - List<OFFlowStatsEntry> entries = ((OFFlowStatsReply) sr).getEntries(); - for (OFFlowStatsEntry entry : entries) { - // list flow stats/info - jsonGenerator.writeStartObject(); - jsonGenerator.writeStringField("switch", dpidStr); - jsonGenerator.writeStartObject(); - jsonGenerator.writeStringField("version", entry.getVersion().toString()); // return the enum name - jsonGenerator.writeNumberField("cookie", entry.getCookie().getValue()); - jsonGenerator.writeNumberField("table-id", entry.getTableId().getValue()); - jsonGenerator.writeNumberField("packet-count", entry.getPacketCount().getValue()); - jsonGenerator.writeNumberField("byte-count", entry.getByteCount().getValue()); - jsonGenerator.writeNumberField("duration-sec", entry.getDurationSec()); - jsonGenerator.writeNumberField("priority", entry.getPriority()); - jsonGenerator.writeNumberField("idle-timeout-sec", entry.getIdleTimeout()); - jsonGenerator.writeNumberField("hard-timeout-sec", entry.getHardTimeout()); - jsonGenerator.writeNumberField("flags", entry.getFlags()); - // list flow matches - jsonGenerator.writeObjectFieldStart("match"); // TODO does this create the object already? - jsonGenerator.writeStartObject(); - Match m = entry.getMatch(); - if (m.get(MatchField.IN_PORT) != null) { - jsonGenerator.writeNumberField("in-port", m.get(MatchField.IN_PORT).getPortNumber()); - } - if (m.get(MatchField.IN_PHY_PORT) != null) { - jsonGenerator.writeNumberField("in-phy-port", m.get(MatchField.IN_PHY_PORT).getPortNumber()); - } - if (m.get(MatchField.ARP_OP) != null) { - jsonGenerator.writeNumberField("arp-op", m.get(MatchField.ARP_OP).getOpcode()); - } - if (m.get(MatchField.ARP_SHA) != null) { - jsonGenerator.writeStringField("arp-sha", m.get(MatchField.ARP_SHA).toString()); - } - if (m.get(MatchField.ARP_SPA) != null) { - jsonGenerator.writeStringField("arp-spa", m.get(MatchField.ARP_SPA).toString()); - } - if (m.get(MatchField.ARP_THA) != null) { - jsonGenerator.writeStringField("arp-tha", m.get(MatchField.ARP_THA).toString()); - } - if (m.get(MatchField.ARP_TPA) != null) { - jsonGenerator.writeStringField("arp-tpa", m.get(MatchField.ARP_TPA).toString()); - } - if (m.get(MatchField.ETH_TYPE) != null) { - jsonGenerator.writeNumberField("eth-type", m.get(MatchField.ETH_TYPE).getValue()); - } - if (m.get(MatchField.ETH_SRC) != null) { - jsonGenerator.writeStringField("eth-src", m.get(MatchField.ETH_SRC).toString()); - } - if (m.get(MatchField.ETH_DST) != null) { - jsonGenerator.writeStringField("eth-dst", m.get(MatchField.ETH_DST).toString()); - } - if (m.get(MatchField.VLAN_VID) != null) { - jsonGenerator.writeNumberField("vlan-vid", m.get(MatchField.VLAN_VID).getVlan()); - } - if (m.get(MatchField.VLAN_PCP) != null) { - jsonGenerator.writeNumberField("vlan-pcp", m.get(MatchField.VLAN_PCP).getValue()); // TODO not sure if this will format correctly - } - if (m.get(MatchField.ICMPV4_TYPE) != null) { - jsonGenerator.writeNumberField("icmpv4-type", m.get(MatchField.ICMPV4_TYPE).getType()); - } - if (m.get(MatchField.ICMPV4_CODE) != null) { - jsonGenerator.writeNumberField("icmpv4-code", m.get(MatchField.ICMPV4_CODE).getCode()); - } - if (m.get(MatchField.ICMPV6_TYPE) != null) { - jsonGenerator.writeNumberField("icmpv6-type", m.get(MatchField.ICMPV6_TYPE).getValue()); - } - if (m.get(MatchField.ICMPV6_CODE) != null) { - jsonGenerator.writeNumberField("icmpv6-code", m.get(MatchField.ICMPV6_CODE).getValue()); - } - if (m.get(MatchField.IN_PORT) != null) { - jsonGenerator.writeNumberField("in-port", m.get(MatchField.IN_PORT).getPortNumber()); - } - if (m.get(MatchField.IP_DSCP) != null) { - jsonGenerator.writeNumberField("ip-dscp", m.get(MatchField.IP_DSCP).getDscpValue()); // TODO not sure if this will format correctly - } - if (m.get(MatchField.IP_ECN) != null) { - jsonGenerator.writeNumberField("ip-ecn", m.get(MatchField.IP_ECN).getEcnValue()); // TODO not sure if this will format correctly - } - if (m.get(MatchField.IP_PROTO) != null) { - jsonGenerator.writeNumberField("ip-proto", m.get(MatchField.IP_PROTO).getIpProtocolNumber()); - } - if (m.get(MatchField.IPV4_SRC) != null) { - jsonGenerator.writeStringField("ipv4-src", m.get(MatchField.IPV4_SRC).toString()); - } - if (m.get(MatchField.IPV4_DST) != null) { - jsonGenerator.writeStringField("ipv4-dst", m.get(MatchField.IPV4_DST).toString()); - } - if (m.get(MatchField.IPV6_SRC) != null) { - jsonGenerator.writeStringField("ipv6-src", m.get(MatchField.IPV6_SRC).toString()); - } - if (m.get(MatchField.IPV6_DST) != null) { - jsonGenerator.writeStringField("ipv6-dst", m.get(MatchField.IPV6_DST).toString()); - } - if (m.get(MatchField.IPV6_FLABEL) != null) { - jsonGenerator.writeNumberField("ipv6-flow-label", m.get(MatchField.IPV6_FLABEL).getIPv6FlowLabelValue()); - } - if (m.get(MatchField.IPV6_ND_SLL) != null) { - jsonGenerator.writeNumberField("ipv6-nd-ssl", m.get(MatchField.IPV6_ND_SLL).getLong()); - } - if (m.get(MatchField.IPV6_ND_TARGET) != null) { - jsonGenerator.writeNumberField("ipv6-nd-target", m.get(MatchField.IPV6_ND_TARGET).getZeroCompressStart()); // TODO not sure how to format this - } - if (m.get(MatchField.IPV6_ND_TLL) != null) { - jsonGenerator.writeNumberField("ipv6-nd-ttl", m.get(MatchField.IPV6_ND_TLL).getLong()); - } - if (m.get(MatchField.METADATA) != null) { - jsonGenerator.writeNumberField("metadata", m.get(MatchField.METADATA).getValue().getValue()); - } - if (m.get(MatchField.MPLS_LABEL) != null) { - jsonGenerator.writeNumberField("mpls-label", m.get(MatchField.MPLS_LABEL).getValue()); - } - if (m.get(MatchField.MPLS_TC) != null) { - jsonGenerator.writeNumberField("mpls-tc", m.get(MatchField.MPLS_TC).getValue()); - } - if (m.get(MatchField.SCTP_SRC) != null) { - jsonGenerator.writeNumberField("sctp-src", m.get(MatchField.SCTP_SRC).getPort()); - } - if (m.get(MatchField.SCTP_DST) != null) { - jsonGenerator.writeNumberField("sctp-dst", m.get(MatchField.SCTP_DST).getPort()); - } - if (m.get(MatchField.TCP_SRC) != null) { - jsonGenerator.writeNumberField("tcp-src", m.get(MatchField.TCP_SRC).getPort()); - } - if (m.get(MatchField.TCP_DST) != null) { - jsonGenerator.writeNumberField("tcp-dst", m.get(MatchField.TCP_DST).getPort()); - } - if (m.get(MatchField.UDP_SRC) != null) { - jsonGenerator.writeNumberField("udp-src", m.get(MatchField.UDP_SRC).getPort()); - } - if (m.get(MatchField.UDP_DST) != null) { - jsonGenerator.writeNumberField("udp-dst", m.get(MatchField.UDP_DST).getPort()); - } - jsonGenerator.writeEndObject(); // end match - - // begin actions/instructions - if (entry.getVersion() == OFVersion.OF_10) { - List<OFAction> actions = entry.getActions(); - jsonGenerator.writeObjectFieldStart("actions"); - jsonGenerator.writeStartObject(); - if (actions.isEmpty()) { - jsonGenerator.writeString("none/drop"); - } - for (OFAction a : actions) { - switch (a.getType()) { - case OUTPUT: - jsonGenerator.writeNumberField("output", ((OFActionOutput)a).getPort().getPortNumber()); - break; - case ENQUEUE: - jsonGenerator.writeNumberField("enqueue", ((OFActionEnqueue)a).getPort().getPortNumber()); - break; - case SET_DL_SRC: - jsonGenerator.writeStringField("eth-src", ((OFActionSetDlSrc)a).toString()); - break; - case SET_DL_DST: - jsonGenerator.writeStringField("eth-dst", ((OFActionSetDlDst)a).toString()); - break; - case SET_VLAN_VID: - jsonGenerator.writeNumberField("vlan-vid", ((OFActionSetVlanVid)a).getVlanVid().getVlan()); - break; - case SET_VLAN_PCP: - jsonGenerator.writeNumberField("vlan-pcp", ((OFActionSetVlanPcp)a).getVlanPcp().getValue()); - break; - case STRIP_VLAN: - jsonGenerator.writeString("strip-vlan"); - break; - case SET_NW_SRC: - jsonGenerator.writeStringField("ipv4-src", ((OFActionSetNwSrc)a).getNwAddr().toString()); - break; - case SET_NW_DST: - jsonGenerator.writeStringField("ipv4-dst", ((OFActionSetNwDst)a).getNwAddr().toString()); - break; - case SET_TP_SRC: - jsonGenerator.writeNumberField("tp-src", ((OFActionSetTpSrc)a).getTpPort().getPort()); - break; - case SET_TP_DST: - jsonGenerator.writeNumberField("tp-dst", ((OFActionSetTpDst)a).getTpPort().getPort()); - break; - default: - // these are all the valid OF1.0 actions - break; - } - } - jsonGenerator.writeEndObject(); // end actions - } else { - // handle OF1.1+ instructions with actions within - List<OFInstruction> instructions = entry.getInstructions(); - jsonGenerator.writeArrayFieldStart("instructions"); - jsonGenerator.writeStartArray(); // array of instructions, each which have objects - if (instructions.isEmpty()) { - jsonGenerator.writeStringField("none", "drop"); - } else { - for (OFInstruction i : instructions) { - switch (i.getType()) { - case CLEAR_ACTIONS: - jsonGenerator.writeObjectFieldStart("clear-actions"); - break; - case WRITE_METADATA: - jsonGenerator.writeStartObject(); - jsonGenerator.writeNumberField("write-metadata", ((OFInstructionWriteMetadata)i).getMetadata().getValue()); - jsonGenerator.writeNumberField("mask", ((OFInstructionWriteMetadata)i).getMetadataMask().getValue()); - break; - case EXPERIMENTER: - jsonGenerator.writeStartObject(); - jsonGenerator.writeNumberField("experimenter", ((OFInstructionExperimenter)i).getExperimenter()); - break; - case GOTO_TABLE: - jsonGenerator.writeStartObject(); - jsonGenerator.writeNumberField("goto-table", ((OFInstructionGotoTable)i).getTableId().getValue()); - break; - case METER: - jsonGenerator.writeStartObject(); - jsonGenerator.writeNumberField("meter", ((OFInstructionMeter)i).getMeterId()); - break; - case APPLY_ACTIONS: - jsonGenerator.writeObjectFieldStart("apply-actions"); - serializeActions(jsonGenerator, ((OFInstructionApplyActions)i).getActions()); // side effect: jsonGenerator appended to - break; - case WRITE_ACTIONS: - jsonGenerator.writeObjectFieldStart("write-actions"); - serializeActions(jsonGenerator, ((OFInstructionWriteActions)i).getActions()); // side effect: jsonGenerator appended to - default: - // shouldn't ever get here - break; - } // end switch on instruction - jsonGenerator.writeEndObject(); // end specific instruction - } // end for instructions - } // end not-empty instructions (else) - } // end process OF1.1+ actions (i.e. look through instructions) - } // end for each OFFlowStatsReply entry - } // end case for FLOW - } // end for each OFStatsReply - } // end method - - public static void serializeActions(JsonGenerator jsonGenerator, List<OFAction> actions) throws IOException, JsonProcessingException { - jsonGenerator.writeStartObject(); - if (actions.isEmpty()) { - jsonGenerator.writeStringField("none", "drop"); - } - for (OFAction a : actions) { // these should only be OF1.1+ (i.e. OF1.3 supported actions, set-field with oxm's, etc) - switch (a.getType()) { - case OUTPUT: - jsonGenerator.writeNumberField("output", ((OFActionOutput)a).getPort().getPortNumber()); - break; - case SET_QUEUE: - jsonGenerator.writeNumberField("queue", ((OFActionSetQueue)a).getQueueId()); - break; - case GROUP: - jsonGenerator.writeNumberField("group", ((OFActionGroup)a).getGroup().getGroupNumber()); - break; - case PUSH_VLAN: - jsonGenerator.writeNumberField("push-vlan", ((OFActionPushVlan)a).getEthertype().getValue()); - break; - case PUSH_MPLS: - jsonGenerator.writeNumberField("push-mpls", ((OFActionPushMpls)a).getEthertype().getValue()); - break; - case PUSH_PBB: - jsonGenerator.writeNumberField("push-pbb", ((OFActionPushPbb)a).getEthertype().getValue()); - break; - case POP_VLAN: - jsonGenerator.writeString("pop-vlan"); - break; - case POP_MPLS: - jsonGenerator.writeNumberField("pop-mpls", ((OFActionPopMpls)a).getEthertype().getValue()); - break; - case POP_PBB: - jsonGenerator.writeString("pop-pbb"); - break; - case SET_FIELD: - if (((OFActionSetField)a).getField() instanceof OFOxmArpOp) { - jsonGenerator.writeNumberField("arp-op", ((OFOxmArpOp) ((OFActionSetField) a).getField()).getValue().getOpcode()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSha) { - jsonGenerator.writeStringField("arp-sha", ((OFOxmArpSha) ((OFActionSetField) a).getField()).getValue().toString()); // macaddress formats string already - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTha) { - jsonGenerator.writeStringField("arp-tha", ((OFOxmArpTha) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSpa) { - jsonGenerator.writeStringField("arp-spa", ((OFOxmArpSpa) ((OFActionSetField) a).getField()).getValue().toString()); // ipaddress formats string already - } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTpa) { - jsonGenerator.writeStringField("arp-tpa", ((OFOxmArpTpa) ((OFActionSetField) a).getField()).getValue().toString()); - } - /* DATA LAYER */ - else if (((OFActionSetField)a).getField() instanceof OFOxmEthType) { - jsonGenerator.writeNumberField("eth-type", ((OFOxmEthType) ((OFActionSetField) a).getField()).getValue().getValue()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmEthSrc) { - jsonGenerator.writeStringField("eth-src", ((OFOxmEthSrc) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmEthDst) { - jsonGenerator.writeStringField("eth-dst", ((OFOxmEthDst) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanVid) { - jsonGenerator.writeNumberField("vlan-vid", ((OFOxmVlanVid) ((OFActionSetField) a).getField()).getValue().getVlan()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanPcp) { - jsonGenerator.writeNumberField("vlan-pcp", ((OFOxmVlanPcp) ((OFActionSetField) a).getField()).getValue().getValue()); - } - /* ICMP */ - else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Code) { - jsonGenerator.writeNumberField("icmpv4-code", ((OFOxmIcmpv4Code) ((OFActionSetField) a).getField()).getValue().getCode()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Type) { - jsonGenerator.writeNumberField("icmpv4-type", ((OFOxmIcmpv4Type) ((OFActionSetField) a).getField()).getValue().getType()); - } - /* NETWORK LAYER */ - else if (((OFActionSetField)a).getField() instanceof OFOxmIpProto) { - jsonGenerator.writeNumberField("ip-proto", ((OFOxmIpProto) ((OFActionSetField) a).getField()).getValue().getIpProtocolNumber()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Src) { - jsonGenerator.writeStringField("ipv4-src", ((OFOxmIpv4Src) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Dst) { - jsonGenerator.writeStringField("ipv4-dst", ((OFOxmIpv4Dst) ((OFActionSetField) a).getField()).getValue().toString()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { - jsonGenerator.writeNumberField("ip-ecn", ((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmIpDscp) { - jsonGenerator.writeNumberField("ip-dscp", ((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue()); - } - /* TRANSPORT LAYER, TCP, UDP, and SCTP */ - else if (((OFActionSetField)a).getField() instanceof OFOxmTcpSrc) { - jsonGenerator.writeNumberField("tcp-src", ((OFOxmTcpSrc) ((OFActionSetField) a).getField()).getValue().getPort()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmTcpDst) { - jsonGenerator.writeNumberField("tcp-dst", ((OFOxmTcpDst) ((OFActionSetField) a).getField()).getValue().getPort()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpSrc) { - jsonGenerator.writeNumberField("udp-src", ((OFOxmUdpSrc) ((OFActionSetField) a).getField()).getValue().getPort()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpDst) { - jsonGenerator.writeNumberField("udp-dst", ((OFOxmUdpDst) ((OFActionSetField) a).getField()).getValue().getPort()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpSrc) { - jsonGenerator.writeNumberField("sctp-src", ((OFOxmSctpSrc) ((OFActionSetField) a).getField()).getValue().getPort()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpDst) { - jsonGenerator.writeNumberField("sctp-dst", ((OFOxmSctpDst) ((OFActionSetField) a).getField()).getValue().getPort()); - } - /* MPLS */ - else if (((OFActionSetField)a).getField() instanceof OFOxmMplsLabel) { - jsonGenerator.writeNumberField("mpls-label", ((OFOxmMplsLabel) ((OFActionSetField) a).getField()).getValue().getValue()); - } else if (((OFActionSetField)a).getField() instanceof OFOxmMplsTc) { - jsonGenerator.writeNumberField("mpls-tc", ((OFOxmMplsTc) ((OFActionSetField) a).getField()).getValue().getValue()); - } // MPLS_BOS not implemented in loxi - /* METADATA */ - else if (((OFActionSetField)a).getField() instanceof OFOxmMetadata) { - jsonGenerator.writeNumberField("metadata", ((OFOxmMetadata) ((OFActionSetField) a).getField()).getValue().getValue().getValue()); - } else { - // need to get a logger in here somehow log.error("Could not decode Set-Field action field: {}", ((OFActionSetField) a)); - } - } - } - } -} - diff --git a/src/main/java/net/floodlightcontroller/core/web/StatsReplyToJson.java b/src/main/java/net/floodlightcontroller/core/web/StatsReplyToJson.java deleted file mode 100644 index d3e2f83365dcb5417926d9bce366e9e3c2172d7b..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/web/StatsReplyToJson.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.floodlightcontroller.core.web; - -import java.util.List; -import java.util.Map; - -import org.projectfloodlight.openflow.protocol.OFStatsReply; - -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -@JsonSerialize(using = StatsReplySerializer.class) -public class StatsReplyToJson { - private Map<String, List<OFStatsReply>> toserialize; - - StatsReplyToJson(Map<String, List<OFStatsReply>> serializeMe) { - toserialize = serializeMe; - } -} diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java index daa78b4956aa4f17187e5c26b1d4080b9a4e30de..99b4d2d830849d948e7788188eaf5215d31e3ccf 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java @@ -1,19 +1,19 @@ /** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* Licensed under the Apache License, Version 2.0 (the "License"); you may -* not use this file except in compliance with the License. You may obtain -* a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -**/ + * Copyright 2011, Big Switch Networks, Inc. + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + **/ package net.floodlightcontroller.core.web; @@ -48,107 +48,125 @@ import com.google.common.util.concurrent.ListenableFuture; * */ public class SwitchResourceBase extends ServerResource { - protected static Logger log = LoggerFactory.getLogger(SwitchResourceBase.class); - - public enum REQUESTTYPE { - OFSTATS, - OFFEATURES - } - - @Override - protected void doInit() throws ResourceException { - super.doInit(); - - } - - @LogMessageDoc(level="ERROR", - message="Failure retrieving statistics from switch {switch}", - explanation="An error occurred while retrieving statistics" + - "from the switch", - recommendation=LogMessageDoc.CHECK_SWITCH + " " + - LogMessageDoc.GENERIC_ACTION) - protected List<OFStatsReply> getSwitchStatistics(DatapathId switchId, - OFStatsType statType) { - IOFSwitchService switchService = - (IOFSwitchService) getContext().getAttributes(). - get(IOFSwitchService.class.getCanonicalName()); - - IOFSwitch sw = switchService.getSwitch(switchId); - ListenableFuture<?> future; - List<OFStatsReply> values = null; - if (sw != null) { - OFStatsRequest<?> req; - if (statType == OFStatsType.FLOW) { - Match match = sw.getOFFactory().buildMatch().build(); - req = sw.getOFFactory().buildFlowStatsRequest() - .setMatch(match) - .setOutPort(OFPort.ANY) - .setTableId(TableId.ALL) - .build(); - } else if (statType == OFStatsType.AGGREGATE) { - Match match = sw.getOFFactory().buildMatch().build(); - req = sw.getOFFactory().buildAggregateStatsRequest() - .setMatch(match) - .setOutPort(OFPort.ANY) - .setTableId(TableId.ALL) - .build(); - } else if (statType == OFStatsType.PORT) { - req = sw.getOFFactory().buildPortStatsRequest() - .setPortNo(OFPort.ANY) - .build(); - } else if (statType == OFStatsType.QUEUE) { - req = sw.getOFFactory().buildQueueStatsRequest() - .setPortNo(OFPort.ANY) - .setQueueId(UnsignedLong.MAX_VALUE.longValue()) - .build(); - } else if (statType == OFStatsType.DESC || - statType == OFStatsType.TABLE) { - // pass - nothing todo besides set the type above - req = sw.getOFFactory().buildDescStatsRequest() - .build(); - } else { - //TODO @Ryan what to do about no matches in the if...elseif statements? - req = sw.getOFFactory().buildDescStatsRequest().build(); - } - try { - future = sw.writeStatsRequest(req); - values = (List<OFStatsReply>) future.get(10, TimeUnit.SECONDS); - } catch (Exception e) { - log.error("Failure retrieving statistics from switch " + sw, e); - } - } - return values; - } - - protected List<OFStatsReply> getSwitchStatistics(String switchId, OFStatsType statType) { - return getSwitchStatistics(DatapathId.of(switchId), statType); - } - - protected OFFeaturesReply getSwitchFeaturesReply(DatapathId switchId) { - IOFSwitchService switchService = - (IOFSwitchService) getContext().getAttributes(). - get(IOFSwitchService.class.getCanonicalName()); - - IOFSwitch sw = switchService.getSwitch(switchId); - Future<OFFeaturesReply> future; - OFFeaturesReply featuresReply = null; - //TODO @Ryan The only thing to set in an OFFeaturesRequest is the XID. I'm not sure - // if it matters what I set it to. Will it have a default value of the next available? - OFFeaturesRequest featuresRequest = sw.getOFFactory().buildFeaturesRequest().build(); - if (sw != null) { - try { - future = sw.writeRequest(featuresRequest); - featuresReply = future.get(10, TimeUnit.SECONDS); - } catch (Exception e) { - log.error("Failure getting features reply from switch" + sw, e); - } - } - - return featuresReply; - } - - protected OFFeaturesReply getSwitchFeaturesReply(String switchId) { - return getSwitchFeaturesReply(DatapathId.of(switchId)); - } + protected static Logger log = LoggerFactory.getLogger(SwitchResourceBase.class); + + public enum REQUESTTYPE { + OFSTATS, + OFFEATURES + } + + @Override + protected void doInit() throws ResourceException { + super.doInit(); + + } + + @SuppressWarnings("unchecked") + @LogMessageDoc(level="ERROR", + message="Failure retrieving statistics from switch {switch}", + explanation="An error occurred while retrieving statistics" + + "from the switch", + recommendation=LogMessageDoc.CHECK_SWITCH + " " + + LogMessageDoc.GENERIC_ACTION) + protected List<OFStatsReply> getSwitchStatistics(DatapathId switchId, + OFStatsType statType) { + IOFSwitchService switchService = + (IOFSwitchService) getContext().getAttributes(). + get(IOFSwitchService.class.getCanonicalName()); + + IOFSwitch sw = switchService.getSwitch(switchId); + ListenableFuture<?> future; + List<OFStatsReply> values = null; + Match match; + if (sw != null) { + OFStatsRequest<?> req = null; + switch (statType) { + case FLOW: + match = sw.getOFFactory().buildMatch().build(); + req = sw.getOFFactory().buildFlowStatsRequest() + .setMatch(match) + .setOutPort(OFPort.ANY) + .setTableId(TableId.ALL) + .build(); + break; + case AGGREGATE: + match = sw.getOFFactory().buildMatch().build(); + req = sw.getOFFactory().buildAggregateStatsRequest() + .setMatch(match) + .setOutPort(OFPort.ANY) + .setTableId(TableId.ALL) + .build(); + break; + case PORT: + req = sw.getOFFactory().buildPortStatsRequest() + .setPortNo(OFPort.ANY) + .build(); + break; + case QUEUE: + req = sw.getOFFactory().buildQueueStatsRequest() + .setPortNo(OFPort.ANY) + .setQueueId(UnsignedLong.MAX_VALUE.longValue()) + .build(); + break; + case DESC: + case TABLE: + // pass - nothing todo besides set the type above + req = sw.getOFFactory().buildDescStatsRequest() + .build(); + break; + case EXPERIMENTER: //TODO @Ryan support new OF1.1+ stats types + case GROUP: + case GROUP_DESC: + case GROUP_FEATURES: + case METER: + case METER_CONFIG: + case METER_FEATURES: + case PORT_DESC: + case TABLE_FEATURES: + default: + log.error("Stats Request Type {} not implemented yet", statType.name()); + break; + } + + try { + if (req != null) { + future = sw.writeStatsRequest(req); + values = (List<OFStatsReply>) future.get(10, TimeUnit.SECONDS); + } + } catch (Exception e) { + log.error("Failure retrieving statistics from switch " + sw, e); + } + } + return values; + } + + protected List<OFStatsReply> getSwitchStatistics(String switchId, OFStatsType statType) { + return getSwitchStatistics(DatapathId.of(switchId), statType); + } + + protected OFFeaturesReply getSwitchFeaturesReply(DatapathId switchId) { + IOFSwitchService switchService = + (IOFSwitchService) getContext().getAttributes(). + get(IOFSwitchService.class.getCanonicalName()); + + IOFSwitch sw = switchService.getSwitch(switchId); + Future<OFFeaturesReply> future; + OFFeaturesReply featuresReply = null; + OFFeaturesRequest featuresRequest = sw.getOFFactory().buildFeaturesRequest().build(); + if (sw != null) { + try { + future = sw.writeRequest(featuresRequest); + featuresReply = future.get(10, TimeUnit.SECONDS); + } catch (Exception e) { + log.error("Failure getting features reply from switch" + sw, e); + } + } + + return featuresReply; + } + + protected OFFeaturesReply getSwitchFeaturesReply(String switchId) { + return getSwitchFeaturesReply(DatapathId.of(switchId)); + } } \ No newline at end of file diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java index 22d931fcf580e71f735f909dd8725f5c4bb4bb5d..a6e7ad5e3d1145e9eed765f3333a735506a46aad 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java @@ -1,24 +1,24 @@ /** -* Copyright 2011, Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* Licensed under the Apache License, Version 2.0 (the "License"); you may -* not use this file except in compliance with the License. You may obtain -* a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -**/ + * Copyright 2011, Big Switch Networks, Inc. + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + **/ package net.floodlightcontroller.core.web; -import java.util.HashMap; -import java.util.Map; +import net.floodlightcontroller.core.internal.IOFSwitchService; +import net.floodlightcontroller.core.web.StatsReply; import org.projectfloodlight.openflow.protocol.OFStatsType; import org.projectfloodlight.openflow.types.DatapathId; @@ -26,44 +26,110 @@ import org.restlet.resource.Get; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize.Typing; - /** * Return switch statistics information for specific switches * @author readams */ public class SwitchStatisticsResource extends SwitchResourceBase { - protected static Logger log = - LoggerFactory.getLogger(SwitchStatisticsResource.class); + protected static Logger log = + LoggerFactory.getLogger(SwitchStatisticsResource.class); - @Get("json") - @JsonSerialize(using = StatsReplySerializer.class) - public Map<String, Object> retrieve() { - HashMap<String,Object> result = new HashMap<String,Object>(); - Object values = null; - - String switchId = (String) getRequestAttributes().get("switchId"); - String statType = (String) getRequestAttributes().get("statType"); - - if (statType.equals("port")) { - values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.PORT); - } else if (statType.equals("queue")) { - values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.QUEUE); - } else if (statType.equals("flow")) { - values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.FLOW); - } else if (statType.equals("aggregate")) { - values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.AGGREGATE); - } else if (statType.equals("desc")) { - values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.DESC); - } else if (statType.equals("table")) { - values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.TABLE); - } else if (statType.equals("features")) { - values = getSwitchFeaturesReply(switchId); - } + @Get("json") + public StatsReply retrieve(){ + StatsReply result = new StatsReply(); + Object values = null; // set for error detection in serializer + String switchIdStr = (String) getRequestAttributes().get(CoreWebRoutable.STR_SWITCH_ID); + DatapathId switchId; + String statType = (String) getRequestAttributes().get(CoreWebRoutable.STR_STAT_TYPE); - result.put(switchId, values); - return result; - } + IOFSwitchService switchService = (IOFSwitchService) getContext().getAttributes(). + get(IOFSwitchService.class.getCanonicalName()); + + // prevent input errors and give error to user if bad switch DPID + try { + switchId = DatapathId.of(switchIdStr); + } catch (NumberFormatException | NullPointerException e) { // new Java 7 shorthand...reduces duplicated code in each catch + switchId = DatapathId.NONE; // set for error detection in serializer + } + + // stop if the DPID is invalid or is not presently connected + if (!switchId.equals(DatapathId.NONE) && switchService.getSwitch(switchId) != null) { + // TODO these strings should be defined someplace. StatsReply.java? + + // at this point, the switch DPID is valid AND exists; what about the OFStatsType? + switch (statType) { + case OFStatsTypeStrings.PORT: + values = getSwitchStatistics(switchId, OFStatsType.PORT); + result.setStatType(OFStatsType.PORT); + break; + case OFStatsTypeStrings.QUEUE: + values = getSwitchStatistics(switchId, OFStatsType.QUEUE); + result.setStatType(OFStatsType.QUEUE); + break; + case OFStatsTypeStrings.FLOW: + values = getSwitchStatistics(switchId, OFStatsType.FLOW); + result.setStatType(OFStatsType.FLOW); + break; + case OFStatsTypeStrings.AGGREGATE: + values = getSwitchStatistics(switchId, OFStatsType.AGGREGATE); + result.setStatType(OFStatsType.AGGREGATE); + break; + case OFStatsTypeStrings.DESC: + values = getSwitchStatistics(switchId, OFStatsType.DESC); + result.setStatType(OFStatsType.DESC); + break; + case OFStatsTypeStrings.TABLE: + values = getSwitchStatistics(switchId, OFStatsType.TABLE); + result.setStatType(OFStatsType.TABLE); + break; + case OFStatsTypeStrings.TABLE_FEATURES: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.TABLE_FEATURES); + break; + case OFStatsTypeStrings.EXPERIMENTER: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.EXPERIMENTER); + break; + case OFStatsTypeStrings.PORT_DESC: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.PORT_DESC); + break; + case OFStatsTypeStrings.GROUP: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.GROUP); + break; + case OFStatsTypeStrings.GROUP_DESC: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.GROUP_DESC); + break; + case OFStatsTypeStrings.GROUP_FEATURES: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.GROUP_FEATURES); + break; + case OFStatsTypeStrings.METER: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.METER); + break; + case OFStatsTypeStrings.METER_CONFIG: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.METER_CONFIG); + break; + case OFStatsTypeStrings.METER_FEATURES: + values = getSwitchFeaturesReply(switchId); + result.setStatType(OFStatsType.METER_FEATURES); + break; + default: + log.error("Invalid or unimplemented stat request type {}", statType); + break; + } + } else { + log.error("Invalid or disconnected switch {}", switchIdStr); + // if there was an error, the serializer will + } + + result.setDatapathId(switchId); + result.setValues(values); // values can only be a List<OFStatsReply> or an OFFeaturesReply + // if values is set to null (the default), the serializer will kick back a response to the user via the REST API + return result; + } } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java index f5f3aea8c93f9a5769ad3eb8aa536755cf83e802..0373e2e58bb0c96ccf75e584bb8da2e9738a8094 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java @@ -23,7 +23,8 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import org.projectfloodlight.openflow.util.HexString; + +import org.projectfloodlight.openflow.types.MacAddress; /** * Serialize a MAC as colon-separated hexadecimal @@ -34,7 +35,7 @@ public class ByteArrayMACSerializer extends JsonSerializer<byte[]> { public void serialize(byte[] mac, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException { - jGen.writeString(HexString.toHexString(mac)); + jGen.writeString(MacAddress.of(mac).toString()); } } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java index 8436577cdb75eb9e70c7c39a9faf4c55ecca5926..fd4abd4a5c2896cb22f6706be0f2317580026165 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java @@ -34,7 +34,7 @@ public class DPIDSerializer extends JsonSerializer<DatapathId> { public void serialize(DatapathId dpid, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException { - jGen.writeString(HexString.toHexString(dpid.getLong(), 8)); + jGen.writeString(dpid.toString()); } } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/IPv4Serializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/IPv4Serializer.java index db93b66ac46af312c37f59c36febe4357389e188..cdff9e890a8b0f1a73069a7c3b476f68719ac28c 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/IPv4Serializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/IPv4Serializer.java @@ -19,7 +19,7 @@ package net.floodlightcontroller.core.web.serializers; import java.io.IOException; -import net.floodlightcontroller.packet.IPv4; +import org.projectfloodlight.openflow.types.IPv4Address; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; @@ -35,7 +35,7 @@ public class IPv4Serializer extends JsonSerializer<Integer> { public void serialize(Integer i, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException { - jGen.writeString(IPv4.fromIPv4Address(i)); + jGen.writeString(IPv4Address.of(i).toString()); } } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java deleted file mode 100644 index c7ea09b8364fa9b6e740da82b2a3f55ec6458fb8..0000000000000000000000000000000000000000 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java +++ /dev/null @@ -1,40 +0,0 @@ -/** -* Copyright 2011,2012 Big Switch Networks, Inc. -* Originally created by David Erickson, Stanford University -* -* Licensed under the Apache License, Version 2.0 (the "License"); you may -* not use this file except in compliance with the License. You may obtain -* a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -* License for the specific language governing permissions and limitations -* under the License. -**/ - -package net.floodlightcontroller.core.web.serializers; - -import java.io.IOException; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import org.projectfloodlight.openflow.util.HexString; - -/** - * Serialize a MAC as colon-separated hexadecimal - */ -public class MACSerializer extends JsonSerializer<Long> { - - @Override - public void serialize(Long dpid, JsonGenerator jGen, - SerializerProvider serializer) - throws IOException, JsonProcessingException { - jGen.writeString(HexString.toHexString(dpid, 6)); - } - -} diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..e9766245a8e25905470715aed9ef8eff563ba75d --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java @@ -0,0 +1,499 @@ +/** + * Copyright 2011,2012 Big Switch Networks, Inc. + * Originally created by David Erickson, Stanford University + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + **/ + +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; +import java.util.List; +import java.util.Iterator; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonGenerator.Feature; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import net.floodlightcontroller.core.web.OFStatsTypeStrings; +import net.floodlightcontroller.core.web.StatsReply; +import net.floodlightcontroller.util.ActionUtils; +import net.floodlightcontroller.util.InstructionUtils; +import net.floodlightcontroller.util.MatchUtils; + +import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; +import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.protocol.match.*; +import org.projectfloodlight.openflow.protocol.oxm.*; +import org.projectfloodlight.openflow.protocol.instruction.*; +import org.projectfloodlight.openflow.protocol.action.*; + +/** + * Serialize a DPID as colon-separated hexadecimal + */ +public class StatsReplySerializer extends JsonSerializer<StatsReply> { + @SuppressWarnings("unchecked") + @Override + public void serialize(StatsReply reply, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException { + // Return a nice error to user if the request we're about to serialize was bad + if (reply.getValues() == null) { + jGen.writeStartObject(); + jGen.writeObjectFieldStart("ERROR"); + jGen.writeStringField("1)", "Invalid DPID and/or stats/features request, or"); + jGen.writeStringField("2)", "The switch might also be disconncted from the controller"); + jGen.writeEndObject(); + jGen.writeObjectFieldStart("Valid OFStatsTypes are"); + jGen.writeStringField("1)", OFStatsTypeStrings.AGGREGATE); + jGen.writeStringField("2)", OFStatsTypeStrings.DESC); + jGen.writeStringField("3)", OFStatsTypeStrings.EXPERIMENTER); + jGen.writeStringField("4)", OFStatsTypeStrings.FEATURES); + jGen.writeStringField("5)", OFStatsTypeStrings.FLOW); + jGen.writeStringField("6)", OFStatsTypeStrings.GROUP); + jGen.writeStringField("7)", OFStatsTypeStrings.GROUP_DESC); + jGen.writeStringField("8)", OFStatsTypeStrings.GROUP_FEATURES); + jGen.writeStringField("9)", OFStatsTypeStrings.METER); + jGen.writeStringField("A)", OFStatsTypeStrings.METER_CONFIG); + jGen.writeStringField("B)", OFStatsTypeStrings.PORT); + jGen.writeStringField("C)", OFStatsTypeStrings.PORT_DESC); + jGen.writeStringField("D)", OFStatsTypeStrings.QUEUE); + jGen.writeStringField("E)", OFStatsTypeStrings.TABLE); + jGen.writeStringField("F)", OFStatsTypeStrings.TABLE_FEATURES); + jGen.writeEndObject(); + jGen.writeEndObject(); + return; + } + + jGen.configure(Feature.WRITE_NUMBERS_AS_STRINGS, true); // IMHO this just looks nicer and is easier to read if everything is quoted + jGen.writeStartObject(); + jGen.writeStringField("dpid", reply.getDatapathId().toString()); + switch (reply.getStatType()) { + case PORT: + // handle port + break; + case QUEUE: + // handle queue + break; + case FLOW: + // handle flow. Can safely cast to List<OFFlowStatsReply>. + serializeFlowReply((List<OFFlowStatsReply>) reply.getValues(), jGen); + break; + case AGGREGATE: + // handle aggregate + break; + case DESC: + // handle desc + break; + case TABLE: + // handle table + break; + case TABLE_FEATURES: + // handle features + break; + // TODO need to handle new OF1.1+ stats reply types + case EXPERIMENTER: + break; + case GROUP: + break; + case GROUP_DESC: + break; + case GROUP_FEATURES: + break; + case METER: + break; + case METER_CONFIG: + break; + case METER_FEATURES: + break; + case PORT_DESC: + break; + default: + break; + } + jGen.writeEndObject(); + } + + public void serializeFlowReply(List<OFFlowStatsReply> flowReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + int flowCount = 0; + for (OFFlowStatsReply flowReply : flowReplies) { // for each flow stats reply + List<OFFlowStatsEntry> entries = flowReply.getEntries(); + for (OFFlowStatsEntry entry : entries) { // for each flow + // list flow stats/info + jGen.writeObjectFieldStart("flow" + Integer.toString(flowCount++)); // need to have different object names or JSON parser might only show the last one + jGen.writeStringField("version", entry.getVersion().toString()); // return the enum name + jGen.writeNumberField("cookie", entry.getCookie().getValue()); + jGen.writeNumberField("table_id", entry.getTableId().getValue()); + jGen.writeNumberField("packet_count", entry.getPacketCount().getValue()); + jGen.writeNumberField("byte_count", entry.getByteCount().getValue()); + jGen.writeNumberField("duration_sec", entry.getDurationSec()); + jGen.writeNumberField("priority", entry.getPriority()); + jGen.writeNumberField("idle_timeout_sec", entry.getIdleTimeout()); + jGen.writeNumberField("hard_timeout_sec", entry.getHardTimeout()); + jGen.writeNumberField("flags", entry.getFlags()); + // list flow matches + jGen.writeObjectFieldStart("match"); + Iterator<MatchField<?>> mi = entry.getMatch().getMatchFields().iterator(); // get iter to any match field type + Match m = entry.getMatch(); + + while (mi.hasNext()) { + MatchField<?> mf = mi.next(); + switch (mf.id) { + case IN_PORT: + jGen.writeNumberField(MatchUtils.STR_IN_PORT, m.get(MatchField.IN_PORT).getPortNumber()); + break; + case IN_PHY_PORT: + jGen.writeNumberField(MatchUtils.STR_IN_PHYS_PORT, m.get(MatchField.IN_PHY_PORT).getPortNumber()); + break; + case ARP_OP: + jGen.writeNumberField(MatchUtils.STR_ARP_OPCODE, m.get(MatchField.ARP_OP).getOpcode()); + break; + case ARP_SHA: + jGen.writeStringField(MatchUtils.STR_ARP_SHA, m.get(MatchField.ARP_SHA).toString()); + break; + case ARP_SPA: + jGen.writeStringField(MatchUtils.STR_ARP_SPA, m.get(MatchField.ARP_SPA).toString()); + break; + case ARP_THA: + jGen.writeStringField(MatchUtils.STR_ARP_DHA, m.get(MatchField.ARP_THA).toString()); + break; + case ARP_TPA: + jGen.writeStringField(MatchUtils.STR_ARP_DPA, m.get(MatchField.ARP_TPA).toString()); + break; + case ETH_TYPE: + jGen.writeNumberField(MatchUtils.STR_DL_TYPE, m.get(MatchField.ETH_TYPE).getValue()); + break; + case ETH_SRC: + jGen.writeStringField(MatchUtils.STR_DL_SRC, m.get(MatchField.ETH_SRC).toString()); + break; + case ETH_DST: + jGen.writeStringField(MatchUtils.STR_DL_DST, m.get(MatchField.ETH_DST).toString()); + break; + case VLAN_VID: + jGen.writeNumberField(MatchUtils.STR_DL_VLAN, m.get(MatchField.VLAN_VID).getVlan()); + break; + case VLAN_PCP: + jGen.writeNumberField(MatchUtils.STR_DL_VLAN_PCP, m.get(MatchField.VLAN_PCP).getValue()); + break; + case ICMPV4_TYPE: + jGen.writeNumberField(MatchUtils.STR_ICMP_TYPE, m.get(MatchField.ICMPV4_TYPE).getType()); + break; + case ICMPV4_CODE: + jGen.writeNumberField(MatchUtils.STR_ICMP_CODE, m.get(MatchField.ICMPV4_CODE).getCode()); + break; + case ICMPV6_TYPE: + jGen.writeNumberField(MatchUtils.STR_ICMPV6_TYPE, m.get(MatchField.ICMPV6_TYPE).getValue()); + break; + case ICMPV6_CODE: + jGen.writeNumberField(MatchUtils.STR_ICMPV6_CODE, m.get(MatchField.ICMPV6_CODE).getValue()); + break; + case IP_DSCP: + jGen.writeNumberField(MatchUtils.STR_NW_DSCP, m.get(MatchField.IP_DSCP).getDscpValue()); + break; + case IP_ECN: + jGen.writeNumberField(MatchUtils.STR_NW_ECN, m.get(MatchField.IP_ECN).getEcnValue()); + break; + case IP_PROTO: + jGen.writeNumberField(MatchUtils.STR_NW_PROTO, m.get(MatchField.IP_PROTO).getIpProtocolNumber()); + break; + case IPV4_SRC: + jGen.writeStringField(MatchUtils.STR_NW_SRC, m.get(MatchField.IPV4_SRC).toString()); + break; + case IPV4_DST: + jGen.writeStringField(MatchUtils.STR_NW_DST, m.get(MatchField.IPV4_DST).toString()); + break; + case IPV6_SRC: + jGen.writeStringField(MatchUtils.STR_IPV6_SRC, m.get(MatchField.IPV6_SRC).toString()); + break; + case IPV6_DST: + jGen.writeStringField(MatchUtils.STR_IPV6_DST, m.get(MatchField.IPV6_DST).toString()); + break; + case IPV6_FLABEL: + jGen.writeNumberField(MatchUtils.STR_IPV6_FLOW_LABEL, m.get(MatchField.IPV6_FLABEL).getIPv6FlowLabelValue()); + break; + case IPV6_ND_SLL: + jGen.writeNumberField(MatchUtils.STR_IPV6_ND_SSL, m.get(MatchField.IPV6_ND_SLL).getLong()); + break; + case IPV6_ND_TARGET: + jGen.writeNumberField(MatchUtils.STR_IPV6_ND_TARGET, m.get(MatchField.IPV6_ND_TARGET).getZeroCompressStart()); + break; + case IPV6_ND_TLL: + jGen.writeNumberField(MatchUtils.STR_IPV6_ND_TTL, m.get(MatchField.IPV6_ND_TLL).getLong()); + break; + case METADATA: + jGen.writeNumberField(MatchUtils.STR_METADATA, m.get(MatchField.METADATA).getValue().getValue()); + break; + case MPLS_LABEL: + jGen.writeNumberField(MatchUtils.STR_MPLS_LABEL, m.get(MatchField.MPLS_LABEL).getValue()); + break; + case MPLS_TC: + jGen.writeNumberField(MatchUtils.STR_MPLS_TC, m.get(MatchField.MPLS_TC).getValue()); + break; + case SCTP_SRC: + jGen.writeNumberField(MatchUtils.STR_SCTP_SRC, m.get(MatchField.SCTP_SRC).getPort()); + break; + case SCTP_DST: + jGen.writeNumberField(MatchUtils.STR_SCTP_DST, m.get(MatchField.SCTP_DST).getPort()); + break; + case TCP_SRC: + jGen.writeNumberField(MatchUtils.STR_TCP_SRC, m.get(MatchField.TCP_SRC).getPort()); + break; + case TCP_DST: + jGen.writeNumberField(MatchUtils.STR_TCP_DST, m.get(MatchField.TCP_DST).getPort()); + break; + case UDP_SRC: + jGen.writeNumberField(MatchUtils.STR_UDP_SRC, m.get(MatchField.UDP_SRC).getPort()); + break; + case UDP_DST: + jGen.writeNumberField(MatchUtils.STR_UDP_DST, m.get(MatchField.UDP_DST).getPort()); + break; + default: + // either a BSN or unknown match type + break; + } // end switch of match type + } // end while over non-wildcarded matches + + jGen.writeEndObject(); // end match + + // handle OF1.1+ instructions with actions within + if (entry.getVersion() == OFVersion.OF_10) { + serializeActions(jGen, entry.getActions()); + } else { + List<OFInstruction> instructions = entry.getInstructions(); + jGen.writeObjectFieldStart("instructions"); + if (instructions.isEmpty()) { + jGen.writeStringField("none", "drop"); + } else { + for (OFInstruction i : instructions) { + switch (i.getType()) { + case CLEAR_ACTIONS: + jGen.writeObjectFieldStart(InstructionUtils.STR_CLEAR_ACTIONS); + break; + case WRITE_METADATA: + jGen.writeStartObject(); + jGen.writeNumberField(InstructionUtils.STR_WRITE_METADATA, ((OFInstructionWriteMetadata)i).getMetadata().getValue()); + jGen.writeNumberField(InstructionUtils.STR_WRITE_METADATA + "_mask", ((OFInstructionWriteMetadata)i).getMetadataMask().getValue()); + break; + case EXPERIMENTER: + jGen.writeStartObject(); + jGen.writeNumberField(InstructionUtils.STR_EXPERIMENTER, ((OFInstructionExperimenter)i).getExperimenter()); + break; + case GOTO_TABLE: + jGen.writeStartObject(); + jGen.writeNumberField(InstructionUtils.STR_GOTO_TABLE, ((OFInstructionGotoTable)i).getTableId().getValue()); + break; + case METER: + jGen.writeStartObject(); + jGen.writeNumberField(InstructionUtils.STR_GOTO_METER, ((OFInstructionMeter)i).getMeterId()); + break; + case APPLY_ACTIONS: + jGen.writeObjectFieldStart(InstructionUtils.STR_APPLY_ACTIONS); + serializeActions(jGen, ((OFInstructionApplyActions)i).getActions()); + break; + case WRITE_ACTIONS: + jGen.writeObjectFieldStart(InstructionUtils.STR_WRITE_ACTIONS); + serializeActions(jGen, ((OFInstructionWriteActions)i).getActions()); + default: + // shouldn't ever get here + break; + } // end switch on instruction + jGen.writeEndObject(); // end specific instruction + } // end for instructions + jGen.writeEndObject(); + } // end process instructions (OF1.1+ only) + } // end not-empty instructions (else) + jGen.writeEndObject(); + } // end for each OFFlowStatsReply entry + } // end for each OFStatsReply + } // end method + + /** + * Write a JSON string given a list of OFAction. Supports OF1.0 - OF1.3. + * This is the only place actions are serialized, for any OF version. Because + * some OF version share actions, it makes sense to have them in one place. + * @param jsonGenerator + * @param actions + * @throws IOException + * @throws JsonProcessingException + */ + public void serializeActions(JsonGenerator jsonGenerator, List<OFAction> actions) throws IOException, JsonProcessingException { + //jsonGenerator.writeStartObject(); + if (actions.isEmpty()) { + jsonGenerator.writeStringField("none", "drop"); + } + for (OFAction a : actions) { + switch (a.getType()) { + case OUTPUT: //TODO @Ryan need to reference the predefined string constants for each of the actions/oxms + jsonGenerator.writeNumberField(ActionUtils.STR_OUTPUT, ((OFActionOutput)a).getPort().getPortNumber()); + break; + /* begin OF1.0 ONLY actions */ + case SET_VLAN_VID: + jsonGenerator.writeNumberField(ActionUtils.STR_VLAN_SET_VID, ((OFActionSetVlanVid)a).getVlanVid().getVlan()); + break; + case SET_VLAN_PCP: + jsonGenerator.writeNumberField(ActionUtils.STR_VLAN_SET_PCP, ((OFActionSetVlanPcp)a).getVlanPcp().getValue()); + break; + case SET_QUEUE: + jsonGenerator.writeNumberField(ActionUtils.STR_QUEUE_SET, ((OFActionSetQueue)a).getQueueId()); + break; + case SET_DL_SRC: + jsonGenerator.writeStringField(ActionUtils.STR_DL_SRC_SET, ((OFActionSetDlSrc)a).getDlAddr().toString()); + break; + case SET_DL_DST: + jsonGenerator.writeStringField(ActionUtils.STR_DL_DST_SET, ((OFActionSetDlDst)a).getDlAddr().toString()); + break; + case SET_NW_SRC: + jsonGenerator.writeStringField(ActionUtils.STR_NW_SRC_SET, ((OFActionSetNwSrc)a).getNwAddr().toString()); + break; + case SET_NW_DST: + jsonGenerator.writeStringField(ActionUtils.STR_NW_DST_SET, ((OFActionSetNwDst)a).getNwAddr().toString()); + break; + case SET_NW_TOS: + jsonGenerator.writeNumberField(ActionUtils.STR_NW_TOS_SET, ((OFActionSetNwTos)a).getNwTos()); + break; + case SET_TP_SRC: + jsonGenerator.writeNumberField(ActionUtils.STR_TP_SRC_SET, ((OFActionSetTpSrc)a).getTpPort().getPort()); + break; + case SET_TP_DST: + jsonGenerator.writeNumberField(ActionUtils.STR_TP_DST_SET, ((OFActionSetTpDst)a).getTpPort().getPort()); + break; + /* end OF1.0 ONLY actions; begin OF1.1+ actions */ + case ENQUEUE: + jsonGenerator.writeNumberField(ActionUtils.STR_ENQUEUE, ((OFActionEnqueue)a).getPort().getPortNumber()); + break; + case GROUP: + jsonGenerator.writeNumberField(ActionUtils.STR_GROUP, ((OFActionGroup)a).getGroup().getGroupNumber()); + break; + case STRIP_VLAN: + jsonGenerator.writeString(ActionUtils.STR_VLAN_STRIP); + break; + case PUSH_VLAN: + jsonGenerator.writeNumberField(ActionUtils.STR_VLAN_PUSH, ((OFActionPushVlan)a).getEthertype().getValue()); + break; + case PUSH_MPLS: + jsonGenerator.writeNumberField(ActionUtils.STR_MPLS_PUSH, ((OFActionPushMpls)a).getEthertype().getValue()); + break; + case PUSH_PBB: + jsonGenerator.writeNumberField(ActionUtils.STR_PBB_PUSH, ((OFActionPushPbb)a).getEthertype().getValue()); + break; + case POP_VLAN: + jsonGenerator.writeString(ActionUtils.STR_VLAN_POP); + break; + case POP_MPLS: + jsonGenerator.writeNumberField(ActionUtils.STR_MPLS_POP, ((OFActionPopMpls)a).getEthertype().getValue()); + break; + case POP_PBB: + jsonGenerator.writeString(ActionUtils.STR_PBB_POP); + break; + case COPY_TTL_IN: + jsonGenerator.writeString(ActionUtils.STR_TTL_IN_COPY); + break; + case COPY_TTL_OUT: + jsonGenerator.writeString(ActionUtils.STR_TTL_OUT_COPY); + break; + case DEC_NW_TTL: + jsonGenerator.writeString(ActionUtils.STR_NW_TTL_DEC); + break; + case DEC_MPLS_TTL: + jsonGenerator.writeString(ActionUtils.STR_MPLS_TTL_DEC); + break; + case SET_MPLS_LABEL: + jsonGenerator.writeNumberField(ActionUtils.STR_MPLS_LABEL_SET, ((OFActionSetMplsLabel)a).getMplsLabel()); + break; + case SET_MPLS_TC: + jsonGenerator.writeNumberField(ActionUtils.STR_MPLS_TC_SET, ((OFActionSetMplsTc)a).getMplsTc()); + break; + case SET_MPLS_TTL: + jsonGenerator.writeNumberField(ActionUtils.STR_MPLS_TTL_SET, ((OFActionSetMplsTtl)a).getMplsTtl()); + break; + case SET_NW_ECN: + jsonGenerator.writeNumberField(ActionUtils.STR_NW_ECN_SET, ((OFActionSetNwEcn)a).getNwEcn().getEcnValue()); + break; + case SET_NW_TTL: + jsonGenerator.writeNumberField(ActionUtils.STR_NW_TTL_SET, ((OFActionSetNwTtl)a).getNwTtl()); + break; + case EXPERIMENTER: + jsonGenerator.writeNumberField(ActionUtils.STR_EXPERIMENTER, ((OFActionExperimenter)a).getExperimenter()); + break; + case SET_FIELD: + if (((OFActionSetField)a).getField() instanceof OFOxmArpOp) { + jsonGenerator.writeNumberField(MatchUtils.STR_ARP_OPCODE, ((OFOxmArpOp) ((OFActionSetField) a).getField()).getValue().getOpcode()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSha) { + jsonGenerator.writeStringField(MatchUtils.STR_ARP_SHA, ((OFOxmArpSha) ((OFActionSetField) a).getField()).getValue().toString()); // macaddress formats string already + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTha) { + jsonGenerator.writeStringField(MatchUtils.STR_ARP_DHA, ((OFOxmArpTha) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpSpa) { + jsonGenerator.writeStringField(MatchUtils.STR_ARP_SPA, ((OFOxmArpSpa) ((OFActionSetField) a).getField()).getValue().toString()); // ipaddress formats string already + } else if (((OFActionSetField)a).getField() instanceof OFOxmArpTpa) { + jsonGenerator.writeStringField(MatchUtils.STR_ARP_DPA, ((OFOxmArpTpa) ((OFActionSetField) a).getField()).getValue().toString()); + } + /* DATA LAYER */ + else if (((OFActionSetField)a).getField() instanceof OFOxmEthType) { + jsonGenerator.writeNumberField(MatchUtils.STR_DL_TYPE, ((OFOxmEthType) ((OFActionSetField) a).getField()).getValue().getValue()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmEthSrc) { + jsonGenerator.writeStringField(MatchUtils.STR_DL_SRC, ((OFOxmEthSrc) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmEthDst) { + jsonGenerator.writeStringField(MatchUtils.STR_DL_DST, ((OFOxmEthDst) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanVid) { + jsonGenerator.writeNumberField(MatchUtils.STR_DL_VLAN, ((OFOxmVlanVid) ((OFActionSetField) a).getField()).getValue().getVlan()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmVlanPcp) { + } + /* ICMP */ + else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Code) { + jsonGenerator.writeNumberField(MatchUtils.STR_ICMP_CODE, ((OFOxmIcmpv4Code) ((OFActionSetField) a).getField()).getValue().getCode()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIcmpv4Type) { + jsonGenerator.writeNumberField(MatchUtils.STR_ICMP_TYPE, ((OFOxmIcmpv4Type) ((OFActionSetField) a).getField()).getValue().getType()); + } + /* NETWORK LAYER */ + else if (((OFActionSetField)a).getField() instanceof OFOxmIpProto) { + jsonGenerator.writeNumberField(MatchUtils.STR_NW_PROTO, ((OFOxmIpProto) ((OFActionSetField) a).getField()).getValue().getIpProtocolNumber()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Src) { + jsonGenerator.writeStringField(MatchUtils.STR_NW_SRC, ((OFOxmIpv4Src) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Dst) { + jsonGenerator.writeStringField(MatchUtils.STR_NW_DST, ((OFOxmIpv4Dst) ((OFActionSetField) a).getField()).getValue().toString()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { + jsonGenerator.writeNumberField(MatchUtils.STR_NW_ECN, ((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmIpDscp) { + jsonGenerator.writeNumberField(MatchUtils.STR_NW_DSCP, ((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue()); + } + /* TRANSPORT LAYER, TCP, UDP, and SCTP */ + else if (((OFActionSetField)a).getField() instanceof OFOxmTcpSrc) { + jsonGenerator.writeNumberField(MatchUtils.STR_TCP_SRC, ((OFOxmTcpSrc) ((OFActionSetField) a).getField()).getValue().getPort()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmTcpDst) { + jsonGenerator.writeNumberField(MatchUtils.STR_TCP_DST, ((OFOxmTcpDst) ((OFActionSetField) a).getField()).getValue().getPort()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpSrc) { + jsonGenerator.writeNumberField(MatchUtils.STR_UDP_SRC, ((OFOxmUdpSrc) ((OFActionSetField) a).getField()).getValue().getPort()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmUdpDst) { + jsonGenerator.writeNumberField(MatchUtils.STR_UDP_DST, ((OFOxmUdpDst) ((OFActionSetField) a).getField()).getValue().getPort()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpSrc) { + jsonGenerator.writeNumberField(MatchUtils.STR_SCTP_SRC, ((OFOxmSctpSrc) ((OFActionSetField) a).getField()).getValue().getPort()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmSctpDst) { + jsonGenerator.writeNumberField(MatchUtils.STR_SCTP_DST, ((OFOxmSctpDst) ((OFActionSetField) a).getField()).getValue().getPort()); + } + /* MPLS */ + else if (((OFActionSetField)a).getField() instanceof OFOxmMplsLabel) { + jsonGenerator.writeNumberField(MatchUtils.STR_MPLS_LABEL, ((OFOxmMplsLabel) ((OFActionSetField) a).getField()).getValue().getValue()); + } else if (((OFActionSetField)a).getField() instanceof OFOxmMplsTc) { + jsonGenerator.writeNumberField(MatchUtils.STR_MPLS_TC, ((OFOxmMplsTc) ((OFActionSetField) a).getField()).getValue().getValue()); + } // MPLS_BOS not implemented in loxi + /* METADATA */ + else if (((OFActionSetField)a).getField() instanceof OFOxmMetadata) { + jsonGenerator.writeNumberField(MatchUtils.STR_METADATA, ((OFOxmMetadata) ((OFActionSetField) a).getField()).getValue().getValue().getValue()); + } else { + // need to get a logger in here somehow log.error("Could not decode Set-Field action field: {}", ((OFActionSetField) a)); + } + } // end switch over action type + } // end for over all actions + } // end method +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java index eda51cc1d45e5d1f713bb9a301d770a962ad2fdc..6723bdd112fec3ad91436b5f377f25b0e2335d73 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java @@ -20,8 +20,9 @@ package net.floodlightcontroller.devicemanager.internal; import java.util.Date; import net.floodlightcontroller.core.web.serializers.IPv4Serializer; -import net.floodlightcontroller.core.web.serializers.MACSerializer; import net.floodlightcontroller.core.web.serializers.DPIDSerializer; +import net.floodlightcontroller.core.web.serializers.MacSerializer; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -128,7 +129,7 @@ public class Entity implements Comparable<Entity> { // Getters/Setters // *************** - @JsonSerialize(using=MACSerializer.class) + @JsonSerialize(using=MacSerializer.class) public MacAddress getMacAddress() { return macAddress; } diff --git a/src/main/java/net/floodlightcontroller/util/MatchUtils.java b/src/main/java/net/floodlightcontroller/util/MatchUtils.java index 449055aeacbb4365071d5f8348f5f12595271650..6345f1038c620e4f0d976d07646a320b4162387d 100644 --- a/src/main/java/net/floodlightcontroller/util/MatchUtils.java +++ b/src/main/java/net/floodlightcontroller/util/MatchUtils.java @@ -48,6 +48,7 @@ public class MatchUtils { * expect the JSON string to be formatted using these strings for the applicable fields. */ public static final String STR_IN_PORT = "ingress_port"; + public static final String STR_IN_PHYS_PORT = "ingress_phys_port"; public static final String STR_DL_DST = "dl_dst"; public static final String STR_DL_SRC = "dl_src"; @@ -56,7 +57,13 @@ public class MatchUtils { public static final String STR_DL_VLAN_PCP = "dl_vpcp"; public static final String STR_NW_DST = "nw_dst"; - public static final String STR_NW_SRC = "nw_src"; + public static final String STR_NW_SRC = "nw_src"; // should change these to IP, since they don't apply to anything else really + public static final String STR_IPV6_DST = "ipv6_dst"; + public static final String STR_IPV6_SRC = "ipv6_src"; + public static final String STR_IPV6_FLOW_LABEL = "ipv6_flow_label"; + public static final String STR_IPV6_ND_SSL = "ipv6_nd_ssl"; + public static final String STR_IPV6_ND_TARGET = "ipv6_nd_target"; + public static final String STR_IPV6_ND_TTL = "ipv6_nd_ttl"; public static final String STR_NW_PROTO = "nw_proto"; public static final String STR_NW_TOS = "nw_tos"; public static final String STR_NW_ECN = "nw_ecn"; @@ -73,6 +80,8 @@ public class MatchUtils { public static final String STR_ICMP_TYPE = "icmp_type"; public static final String STR_ICMP_CODE = "icmp_code"; + public static final String STR_ICMPV6_TYPE = "icmpv6_type"; + public static final String STR_ICMPV6_CODE = "icmpv6_code"; public static final String STR_ARP_OPCODE = "arp_opcode"; public static final String STR_ARP_SHA = "arp_sha"; diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties index 2aaab9fdaba5ce189f597a519d3c3066e5c84374..b9da2671aeb41291f9683458ced2acc60b3342e4 100644 --- a/src/main/resources/floodlightdefault.properties +++ b/src/main/resources/floodlightdefault.properties @@ -10,7 +10,7 @@ net.floodlightcontroller.debugevent.DebugEventService,\ net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher,\ net.floodlightcontroller.restserver.RestApiServer,\ net.floodlightcontroller.topology.TopologyManager,\ -net.floodlightcontroller.testmodule.TestModule,\ +net.floodlightcontroller.forwarding.Forwarding,\ net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager,\ net.floodlightcontroller.ui.web.StaticWebRoutable,\ net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl