diff --git a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java index 169faaf9c1ca8f04630d1b885e1bff47cba09611..de90067ae5411bb835dcca4bff21be839c61f01f 100644 --- a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java @@ -30,7 +30,6 @@ import org.projectfloodlight.openflow.protocol.OFFeaturesReply; import org.projectfloodlight.openflow.protocol.OFStatsReply; import org.projectfloodlight.openflow.protocol.OFStatsType; import org.projectfloodlight.openflow.types.DatapathId; -import org.projectfloodlight.openflow.util.HexString; import org.restlet.resource.Get; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -100,9 +99,9 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase { for (GetConcurrentStatsThread curThread : activeThreads) { if (curThread.getState() == State.TERMINATED) { if (rType == REQUESTTYPE.OFSTATS) { - model.put(HexString.toHexString(curThread.getSwitchId().getLong()), curThread.getStatisticsReply()); + model.put(curThread.getSwitchId().toString(), curThread.getStatisticsReply()); } else if (rType == REQUESTTYPE.OFFEATURES) { - model.put(HexString.toHexString(curThread.getSwitchId().getLong()), curThread.getFeaturesReply()); + model.put(curThread.getSwitchId().toString(), curThread.getFeaturesReply()); } pendingRemovalThreads.add(curThread); } diff --git a/src/main/java/net/floodlightcontroller/core/web/StatsReplySerializer.java b/src/main/java/net/floodlightcontroller/core/web/StatsReplySerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..d39bac142fff7d8ed9a5d82761879a7b5c290c71 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/StatsReplySerializer.java @@ -0,0 +1,430 @@ +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 new file mode 100644 index 0000000000000000000000000000000000000000..d3e2f83365dcb5417926d9bce366e9e3c2172d7b --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/StatsReplyToJson.java @@ -0,0 +1,17 @@ +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 9730a82b80ef14184371fff8f77792bf289b1582..daa78b4956aa4f17187e5c26b1d4080b9a4e30de 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java @@ -17,33 +17,23 @@ package net.floodlightcontroller.core.web; -import java.util.Collections; import java.util.List; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.annotations.LogMessageDoc; import net.floodlightcontroller.core.internal.IOFSwitchService; import org.projectfloodlight.openflow.protocol.OFFeaturesReply; import org.projectfloodlight.openflow.protocol.match.Match; -import org.projectfloodlight.openflow.protocol.queueprop.OFQueueProp; import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.TableId; import org.projectfloodlight.openflow.protocol.OFFeaturesRequest; -import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; -import org.projectfloodlight.openflow.protocol.OFQueueProperties; import org.projectfloodlight.openflow.protocol.OFStatsReply; import org.projectfloodlight.openflow.protocol.OFStatsRequest; -import org.projectfloodlight.openflow.protocol.OFAggregateStatsRequest; -import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; -import org.projectfloodlight.openflow.protocol.OFPortStatsRequest; -import org.projectfloodlight.openflow.protocol.OFQueueStatsRequest; import org.projectfloodlight.openflow.protocol.OFStatsType; -import org.projectfloodlight.openflow.util.HexString; import org.restlet.resource.ResourceException; import org.restlet.resource.ServerResource; import org.slf4j.Logger; diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java index a70d120ae59ff618d8ae57a3b59601cb2e66bbec..22d931fcf580e71f735f909dd8725f5c4bb4bb5d 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java @@ -26,6 +26,10 @@ 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 @@ -35,6 +39,7 @@ public class SwitchStatisticsResource extends SwitchResourceBase { 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; diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties index b9da2671aeb41291f9683458ced2acc60b3342e4..2aaab9fdaba5ce189f597a519d3c3066e5c84374 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.forwarding.Forwarding,\ +net.floodlightcontroller.testmodule.TestModule,\ net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager,\ net.floodlightcontroller.ui.web.StaticWebRoutable,\ net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl