From 70a1426d2c348b24993197cf39c4095ca7ef7266 Mon Sep 17 00:00:00 2001 From: Ryan Izard <rizard@g.clemson.edu> Date: Tue, 23 Dec 2014 11:51:30 -0500 Subject: [PATCH] Added support for features request message via the REST API. Changed the case of some JSON keys to camel. --- .../core/web/AllSwitchStatisticsResource.java | 360 ++-- .../core/web/SwitchStatisticsResource.java | 7 +- .../web/serializers/StatsReplySerializer.java | 1540 +++++++++-------- 3 files changed, 982 insertions(+), 925 deletions(-) diff --git a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java index 657a2d2fe..3a7624943 100644 --- a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.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; @@ -39,165 +39,173 @@ import org.slf4j.LoggerFactory; * @author readams */ public class AllSwitchStatisticsResource extends SwitchResourceBase { - protected static Logger log = - LoggerFactory.getLogger(AllSwitchStatisticsResource.class); - - @Get("json") - public Map<String, StatsReply> retrieve() { - String statType = (String) getRequestAttributes().get(CoreWebRoutable.STR_STAT_TYPE); - - return retrieveInternal(statType); - } - - private Map<String, StatsReply> retrieveInternal(String statType) { - HashMap<String, StatsReply> model = new HashMap<String, StatsReply>(); - - OFStatsType type = null; - REQUESTTYPE rType = null; - - switch (statType) { - case OFStatsTypeStrings.PORT: - type = OFStatsType.PORT; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.QUEUE: - type = OFStatsType.QUEUE; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.FLOW: - type = OFStatsType.FLOW; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.AGGREGATE: - type = OFStatsType.AGGREGATE; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.DESC: - type = OFStatsType.DESC; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.TABLE: - type = OFStatsType.TABLE; - rType = REQUESTTYPE.OFSTATS; - break; - - case OFStatsTypeStrings.GROUP: - type = OFStatsType.GROUP; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.GROUP_DESC: - type = OFStatsType.GROUP_DESC; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.GROUP_FEATURES: - type = OFStatsType.GROUP_FEATURES; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.METER: - type = OFStatsType.METER; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.METER_CONFIG: - type = OFStatsType.METER_CONFIG; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.METER_FEATURES: - type = OFStatsType.METER_FEATURES; - rType = REQUESTTYPE.OFSTATS; - break; - case OFStatsTypeStrings.FEATURES: - rType = REQUESTTYPE.OFFEATURES; - break; - default: - return model; - } - - IOFSwitchService switchService = (IOFSwitchService) getContext().getAttributes(). - get(IOFSwitchService.class.getCanonicalName()); - - Set<DatapathId> switchDpids = switchService.getAllSwitchDpids(); - List<GetConcurrentStatsThread> activeThreads = new ArrayList<GetConcurrentStatsThread>(switchDpids.size()); - List<GetConcurrentStatsThread> pendingRemovalThreads = new ArrayList<GetConcurrentStatsThread>(); - GetConcurrentStatsThread t; - for (DatapathId l : switchDpids) { - t = new GetConcurrentStatsThread(l, rType, type); - activeThreads.add(t); - t.start(); - } - - // Join all the threads after the timeout. Set a hard timeout - // of 12 seconds for the threads to finish. If the thread has not - // finished the switch has not replied yet and therefore we won't - // add the switch's stats to the reply. - for (int iSleepCycles = 0; iSleepCycles < 12; iSleepCycles++) { - for (GetConcurrentStatsThread curThread : activeThreads) { - if (curThread.getState() == State.TERMINATED) { - if (rType == REQUESTTYPE.OFSTATS) { - model.put(curThread.getSwitchId().toString(), new StatsReply(curThread.getSwitchId(), curThread.getStatisticsReply(), type)); - } else if (rType == REQUESTTYPE.OFFEATURES) { - model.put(curThread.getSwitchId().toString(), new StatsReply(curThread.getSwitchId(), curThread.getFeaturesReply(), type)); - } - pendingRemovalThreads.add(curThread); - } - } - - // remove the threads that have completed the queries to the switches - for (GetConcurrentStatsThread curThread : pendingRemovalThreads) { - activeThreads.remove(curThread); - } - // clear the list so we don't try to double remove them - pendingRemovalThreads.clear(); - - // if we are done finish early so we don't always get the worst case - if (activeThreads.isEmpty()) { - break; - } - - // sleep for 1 s here - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - log.error("Interrupted while waiting for statistics", e); - } - } - - return model; - } - - protected class GetConcurrentStatsThread extends Thread { - private List<OFStatsReply> switchReply; - private DatapathId switchId; - private OFStatsType statType; - private REQUESTTYPE requestType; - private OFFeaturesReply featuresReply; - - public GetConcurrentStatsThread(DatapathId switchId, REQUESTTYPE requestType, OFStatsType statType) { - this.switchId = switchId; - this.requestType = requestType; - this.statType = statType; - this.switchReply = null; - this.featuresReply = null; - } - - public List<OFStatsReply> getStatisticsReply() { - return switchReply; - } - - public OFFeaturesReply getFeaturesReply() { - return featuresReply; - } - - public DatapathId getSwitchId() { - return switchId; - } - - @Override - public void run() { - if ((requestType == REQUESTTYPE.OFSTATS) && (statType != null)) { - switchReply = getSwitchStatistics(switchId, statType); - } else if (requestType == REQUESTTYPE.OFFEATURES) { - featuresReply = getSwitchFeaturesReply(switchId); - } - } - } + protected static Logger log = + LoggerFactory.getLogger(AllSwitchStatisticsResource.class); + + @Get("json") + public Map<String, StatsReply> retrieve() { + String statType = (String) getRequestAttributes().get(CoreWebRoutable.STR_STAT_TYPE); + + return retrieveInternal(statType); + } + + private Map<String, StatsReply> retrieveInternal(String statType) { + HashMap<String, StatsReply> model = new HashMap<String, StatsReply>(); + + OFStatsType type = null; + REQUESTTYPE rType = null; + + switch (statType) { + case OFStatsTypeStrings.PORT: + type = OFStatsType.PORT; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.PORT_DESC: + type = OFStatsType.PORT_DESC; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.QUEUE: + type = OFStatsType.QUEUE; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.FLOW: + type = OFStatsType.FLOW; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.AGGREGATE: + type = OFStatsType.AGGREGATE; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.DESC: + type = OFStatsType.DESC; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.TABLE: + type = OFStatsType.TABLE; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.TABLE_FEATURES: + type = OFStatsType.TABLE_FEATURES; + rType = REQUESTTYPE.OFSTATS; + break; + + case OFStatsTypeStrings.GROUP: + type = OFStatsType.GROUP; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.GROUP_DESC: + type = OFStatsType.GROUP_DESC; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.GROUP_FEATURES: + type = OFStatsType.GROUP_FEATURES; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.METER: + type = OFStatsType.METER; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.METER_CONFIG: + type = OFStatsType.METER_CONFIG; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.METER_FEATURES: + type = OFStatsType.METER_FEATURES; + rType = REQUESTTYPE.OFSTATS; + break; + case OFStatsTypeStrings.FEATURES: + rType = REQUESTTYPE.OFFEATURES; + break; + default: + return model; + } + + IOFSwitchService switchService = (IOFSwitchService) getContext().getAttributes(). + get(IOFSwitchService.class.getCanonicalName()); + + Set<DatapathId> switchDpids = switchService.getAllSwitchDpids(); + List<GetConcurrentStatsThread> activeThreads = new ArrayList<GetConcurrentStatsThread>(switchDpids.size()); + List<GetConcurrentStatsThread> pendingRemovalThreads = new ArrayList<GetConcurrentStatsThread>(); + GetConcurrentStatsThread t; + for (DatapathId l : switchDpids) { + t = new GetConcurrentStatsThread(l, rType, type); + activeThreads.add(t); + t.start(); + } + + // Join all the threads after the timeout. Set a hard timeout + // of 12 seconds for the threads to finish. If the thread has not + // finished the switch has not replied yet and therefore we won't + // add the switch's stats to the reply. + for (int iSleepCycles = 0; iSleepCycles < 12; iSleepCycles++) { + for (GetConcurrentStatsThread curThread : activeThreads) { + if (curThread.getState() == State.TERMINATED) { + if (rType == REQUESTTYPE.OFSTATS) { + model.put(curThread.getSwitchId().toString(), new StatsReply(curThread.getSwitchId(), curThread.getStatisticsReply(), type)); + } else if (rType == REQUESTTYPE.OFFEATURES) { + model.put(curThread.getSwitchId().toString(), new StatsReply(curThread.getSwitchId(), curThread.getFeaturesReply(), type)); + } + pendingRemovalThreads.add(curThread); + } + } + + // remove the threads that have completed the queries to the switches + for (GetConcurrentStatsThread curThread : pendingRemovalThreads) { + activeThreads.remove(curThread); + } + // clear the list so we don't try to double remove them + pendingRemovalThreads.clear(); + + // if we are done finish early so we don't always get the worst case + if (activeThreads.isEmpty()) { + break; + } + + // sleep for 1 s here + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + log.error("Interrupted while waiting for statistics", e); + } + } + + return model; + } + + protected class GetConcurrentStatsThread extends Thread { + private List<OFStatsReply> switchReply; + private DatapathId switchId; + private OFStatsType statType; + private REQUESTTYPE requestType; + private OFFeaturesReply featuresReply; + + public GetConcurrentStatsThread(DatapathId switchId, REQUESTTYPE requestType, OFStatsType statType) { + this.switchId = switchId; + this.requestType = requestType; + this.statType = statType; + this.switchReply = null; + this.featuresReply = null; + } + + public List<OFStatsReply> getStatisticsReply() { + return switchReply; + } + + public OFFeaturesReply getFeaturesReply() { + return featuresReply; + } + + public DatapathId getSwitchId() { + return switchId; + } + + @Override + public void run() { + if ((requestType == REQUESTTYPE.OFSTATS) && (statType != null)) { + switchReply = getSwitchStatistics(switchId, statType); + } else if (requestType == REQUESTTYPE.OFFEATURES) { + featuresReply = getSwitchFeaturesReply(switchId); + } + } + } } diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java index 2b79909da..89733f1d1 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java @@ -54,9 +54,7 @@ public class SwitchStatisticsResource extends SwitchResourceBase { } // 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? - + if (!switchId.equals(DatapathId.NONE) && switchService.getSwitch(switchId) != null) { // at this point, the switch DPID is valid AND exists; what about the OFStatsType? switch (statType) { case OFStatsTypeStrings.PORT: @@ -119,6 +117,9 @@ public class SwitchStatisticsResource extends SwitchResourceBase { values = getSwitchFeaturesReply(switchId); result.setStatType(OFStatsType.EXPERIMENTER); break; + case OFStatsTypeStrings.FEATURES: + values = getSwitchFeaturesReply(switchId); + result.setStatType(null); // we will assume anything in "values" with a null stattype is "features" default: log.error("Invalid or unimplemented stat request type {}", statType); break; diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java index 9bc3bcb4b..fcd5d9945 100644 --- a/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/StatsReplySerializer.java @@ -29,8 +29,10 @@ import com.fasterxml.jackson.databind.SerializerProvider; import net.floodlightcontroller.core.web.OFStatsTypeStrings; import net.floodlightcontroller.core.web.StatsReply; +import org.projectfloodlight.openflow.protocol.OFActionType; import org.projectfloodlight.openflow.protocol.OFBucket; import org.projectfloodlight.openflow.protocol.OFBucketCounter; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; import org.projectfloodlight.openflow.protocol.OFFlowStatsReply; import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry; import org.projectfloodlight.openflow.protocol.OFDescStatsReply; @@ -80,21 +82,26 @@ import org.projectfloodlight.openflow.protocol.ver13.OFFlowModFlagsSerializerVer import org.projectfloodlight.openflow.protocol.ver13.OFMeterBandTypeSerializerVer13; // Use Loxigen's serializer import org.projectfloodlight.openflow.protocol.ver13.OFPortFeaturesSerializerVer13; +import org.projectfloodlight.openflow.protocol.ver13.OFStatsReplyFlagsSerializerVer13; import org.projectfloodlight.openflow.protocol.ver13.OFTableFeaturePropTypeSerializerVer13; import org.projectfloodlight.openflow.protocol.ver12.OFFlowModFlagsSerializerVer12; +import org.projectfloodlight.openflow.protocol.ver12.OFPortConfigSerializerVer12; import org.projectfloodlight.openflow.protocol.ver12.OFPortFeaturesSerializerVer12; +import org.projectfloodlight.openflow.protocol.ver12.OFPortStateSerializerVer12; +import org.projectfloodlight.openflow.protocol.ver12.OFStatsReplyFlagsSerializerVer12; import org.projectfloodlight.openflow.protocol.ver11.OFFlowModFlagsSerializerVer11; +import org.projectfloodlight.openflow.protocol.ver11.OFPortConfigSerializerVer11; import org.projectfloodlight.openflow.protocol.ver11.OFPortFeaturesSerializerVer11; -import org.projectfloodlight.openflow.protocol.ver10.OFPortFeaturesSerializerVer10; -import org.projectfloodlight.openflow.protocol.ver13.OFPortStateSerializerVer13; -import org.projectfloodlight.openflow.protocol.ver12.OFPortStateSerializerVer12; import org.projectfloodlight.openflow.protocol.ver11.OFPortStateSerializerVer11; +import org.projectfloodlight.openflow.protocol.ver11.OFStatsReplyFlagsSerializerVer11; +import org.projectfloodlight.openflow.protocol.ver10.OFPortConfigSerializerVer10; +import org.projectfloodlight.openflow.protocol.ver10.OFPortFeaturesSerializerVer10; import org.projectfloodlight.openflow.protocol.ver10.OFPortStateSerializerVer10; +import org.projectfloodlight.openflow.protocol.ver10.OFStatsReplyFlagsSerializerVer10; +import org.projectfloodlight.openflow.protocol.ver13.OFPortStateSerializerVer13; import org.projectfloodlight.openflow.protocol.ver13.OFPortConfigSerializerVer13; import org.projectfloodlight.openflow.protocol.ver14.OFFlowModFlagsSerializerVer14; -import org.projectfloodlight.openflow.protocol.ver12.OFPortConfigSerializerVer12; -import org.projectfloodlight.openflow.protocol.ver11.OFPortConfigSerializerVer11; -import org.projectfloodlight.openflow.protocol.ver10.OFPortConfigSerializerVer10; +import org.projectfloodlight.openflow.protocol.ver14.OFStatsReplyFlagsSerializerVer14; import org.projectfloodlight.openflow.protocol.OFAggregateStatsReply; import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.types.U32; @@ -113,744 +120,785 @@ import org.slf4j.LoggerFactory; * @author Ryan Izard, ryan.izard@bigswitch.com, rizard@g.clemson.edu */ public class StatsReplySerializer extends JsonSerializer<StatsReply> { - protected static Logger logger = LoggerFactory.getLogger(StatsReplySerializer.class); - @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 - serializePortReply((List<OFPortStatsReply>) reply.getValues(), jGen); - 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 - serializeAggregateReply((List<OFAggregateStatsReply>) reply.getValues(), jGen); - break; - case DESC: - // handle desc - serializeDescReply((List<OFDescStatsReply>) reply.getValues(), jGen); - break; - case GROUP: - // handle group stats - serializeGroupReply((List<OFGroupStatsReply>) reply.getValues(), jGen); - break; - case GROUP_DESC: - // handle group desc - serializeGroupDescReply((List<OFGroupDescStatsReply>) reply.getValues(), jGen); - break; - case GROUP_FEATURES: - // handle group features - serializeGroupFeaturesReply((List<OFGroupFeaturesStatsReply>) reply.getValues(), jGen); - break; - case METER: - // handle meter stats - serializeMeterReply((List<OFMeterStatsReply>) reply.getValues(), jGen); - break; - case METER_CONFIG: - // handle meter config - serializeMeterConfigReply((List<OFMeterConfigStatsReply>) reply.getValues(), jGen); - break; - case METER_FEATURES: - // handle meter features - serializeMeterFeaturesReply((List<OFMeterFeaturesStatsReply>) reply.getValues(), jGen); - break; - case TABLE: - // handle table - serializeTableReply((List<OFTableStatsReply>) reply.getValues(), jGen); - break; - case TABLE_FEATURES: - //handle table features - serializeTableFeaturesReply((List<OFTableFeaturesStatsReply>) reply.getValues(), jGen); - break; - case PORT_DESC: - serializePortDescReply((List<OFPortDescStatsReply>) reply.getValues(), jGen); - break; - case EXPERIMENTER: - break; - default: - break; - } - jGen.writeEndObject(); - } - - /*** - * Serializes the Group Statistics Reply - * @author Naveen - * @param groupReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeGroupReply(List<OFGroupStatsReply> groupReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - - OFGroupStatsReply groupReply = groupReplies.get(0); // we will get only one GroupReply and it will contains many OFGroupStatsEntry ? - jGen.writeStringField("version", groupReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("group"); - jGen.writeStartArray(); - for(OFGroupStatsEntry entry : groupReply.getEntries()) { - jGen.writeStartObject(); - jGen.writeStringField("groupNumber",entry.getGroup().toString()); - jGen.writeNumberField("refCount", entry.getRefCount()); - jGen.writeNumberField("packetCount", entry.getPacketCount().getValue()); - jGen.writeNumberField("byteCount", entry.getByteCount().getValue()); - jGen.writeFieldName("BucketCounters"); - jGen.writeStartArray(); - for(OFBucketCounter bCounter : entry.getBucketStats()) { - jGen.writeStartObject(); - jGen.writeNumberField("packetCount", bCounter.getPacketCount().getValue()); - jGen.writeNumberField("byteCount", bCounter.getByteCount().getValue()); - jGen.writeEndObject(); - }//end of for loop - BucketCounter - jGen.writeEndArray(); - if (OFVersion.OF_13 == entry.getVersion()) { - jGen.writeNumberField("durationSec", entry.getDurationSec()); - jGen.writeNumberField("durationNsec", entry.getDurationNsec()); - } - jGen.writeEndObject(); - }//end of for loop - groupStats - jGen.writeEndArray(); - } - - /*** - * Serializes Group Desc Reply - * @author Naveen - * @param groupDescReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeGroupDescReply(List<OFGroupDescStatsReply> groupDescReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFGroupDescStatsReply groupDescReply = groupDescReplies.get(0); - jGen.writeStringField("version", groupDescReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("groupDesc"); - jGen.writeStartArray(); - for(OFGroupDescStatsEntry entry : groupDescReply.getEntries()) { - jGen.writeStartObject(); - jGen.writeStringField("groupType",entry.getGroupType().toString()); - jGen.writeStringField("groupNumber",entry.getGroup().toString()); - jGen.writeFieldName("Buckets"); - jGen.writeStartArray(); - for(OFBucket buckets : entry.getBuckets()) { - jGen.writeStartObject(); - jGen.writeNumberField("weight", buckets.getWeight()); - jGen.writeNumberField("watchPortNumber", buckets.getWatchPort().getPortNumber()); - jGen.writeStringField("watchGroup", buckets.getWatchGroup().toString()); - OFActionListSerializer.serializeActions(jGen, buckets.getActions()); - jGen.writeEndObject(); - }//End of for loop - buckets - jGen.writeEndArray();//end of buckets - jGen.writeEndObject();//end of group Desc iteration - }//End of for loop - GroupDescStats - jGen.writeEndArray();//end of group Desc - } - - /*** - * Serializes Group Feature Reply - * @author Naveen - * @param groupFeaturesReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeGroupFeaturesReply(List<OFGroupFeaturesStatsReply> groupFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - - OFGroupFeaturesStatsReply groupFeaturesReply = groupFeaturesReplies.get(0); - jGen.writeStringField("version", groupFeaturesReply.getVersion().toString()); //return the enum name - - jGen.writeFieldName("groupFeatures"); - jGen.writeStartObject(); - jGen.writeNumberField("capabilities",groupFeaturesReply.getCapabilities()); - jGen.writeNumberField("maxGroupsAll",groupFeaturesReply.getMaxGroupsAll()); - jGen.writeNumberField("maxGroupsSelect",groupFeaturesReply.getMaxGroupsSelect()); - jGen.writeNumberField("maxGroupsIndirect",groupFeaturesReply.getMaxGroupsIndirect()); - jGen.writeNumberField("maxGroupsFf",groupFeaturesReply.getMaxGroupsFf()); - jGen.writeNumberField("actionsAll",groupFeaturesReply.getActionsAll()); - jGen.writeNumberField("actionsSelect",groupFeaturesReply.getActionsSelect()); - jGen.writeNumberField("actionsIndirect",groupFeaturesReply.getActionsIndirect()); - jGen.writeNumberField("actionsFf",groupFeaturesReply.getActionsFf()); - - jGen.writeEndObject();//end of group Feature - } - - /*** - * Serializes the Meter Statistics Reply - * @author Naveen - * @param meterReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeMeterReply(List<OFMeterStatsReply> meterReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFMeterStatsReply meterReply = meterReplies.get(0); // we will get only one meterReply and it will contains many OFMeterStatsEntry ? - jGen.writeStringField("version", meterReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("meter"); - jGen.writeStartArray(); - for(OFMeterStats entry : meterReply.getEntries()) { - jGen.writeStartObject(); - jGen.writeNumberField("meterId",entry.getMeterId()); - jGen.writeNumberField("flowCount", entry.getFlowCount()); - jGen.writeNumberField("packetInCount", entry.getPacketInCount().getValue()); - jGen.writeNumberField("byteInCount", entry.getByteInCount().getValue()); - jGen.writeFieldName("MeterBandStats"); - jGen.writeStartArray(); - for(OFMeterBandStats bandStats : entry.getBandStats()) { - jGen.writeStartObject(); - jGen.writeNumberField("packetBandCount", bandStats.getPacketBandCount().getValue()); - jGen.writeNumberField("byteBandCount", bandStats.getByteBandCount().getValue()); - jGen.writeEndObject(); - }//End of for loop - bandStats - jGen.writeEndArray(); - - jGen.writeNumberField("durationSec", entry.getDurationSec()); - jGen.writeNumberField("durationNsec", entry.getDurationNsec()); - jGen.writeEndObject(); - }//End of for loop - MeterStats - jGen.writeEndArray(); - } - - /*** - * Serializes Meter Feature Reply - * @author Naveen - * @param meterFeaturesReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeMeterFeaturesReply(List<OFMeterFeaturesStatsReply> meterFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFMeterFeaturesStatsReply meterFeaturesReply = meterFeaturesReplies.get(0); - jGen.writeStringField("version", meterFeaturesReply.getVersion().toString()); //return the enum name - - OFMeterFeatures meterFeatures = meterFeaturesReply.getFeatures(); - jGen.writeFieldName("meterFeatures"); - jGen.writeStartObject(); - - jGen.writeNumberField("maxGroupsAll",meterFeatures.getMaxMeter()); - jGen.writeNumberField("maxGroupsSelect",meterFeatures.getBandTypes()); - jGen.writeNumberField("capabilities",meterFeatures.getCapabilities()); - jGen.writeNumberField("maxGroupsIndirect",meterFeatures.getMaxBands()); - jGen.writeNumberField("maxGroupsFf",meterFeatures.getMaxColor()); - - jGen.writeEndObject();//end of group Feature - } - - /*** - * Serializes Meter Config Reply - * @author Naveen - * @param meterConfigReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeMeterConfigReply(List<OFMeterConfigStatsReply> meterConfigReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFMeterConfigStatsReply meterConfigReply = meterConfigReplies.get(0); - jGen.writeStringField("version", meterConfigReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("meterConfig"); - jGen.writeStartArray(); - for(OFMeterBand band : meterConfigReply.getEntries()) { - jGen.writeStartObject(); - short type = (short)band.getType(); - jGen.writeNumberField("bandType",type); - - switch (type) { - case OFMeterBandTypeSerializerVer13.DROP_VAL: - OFMeterBandDrop bandDrop = (OFMeterBandDrop) band; - jGen.writeNumberField("rate", bandDrop.getRate()); - jGen.writeNumberField("burstSize", bandDrop.getBurstSize()); - break; - - case OFMeterBandTypeSerializerVer13.DSCP_REMARK_VAL: - OFMeterBandDscpRemark bandDscp = (OFMeterBandDscpRemark) band; - jGen.writeNumberField("rate", bandDscp.getRate()); - jGen.writeNumberField("burstSize", bandDscp.getBurstSize()); - jGen.writeNumberField("precLevel", bandDscp.getPrecLevel()); - break; - - case OFMeterBandTypeSerializerVer13.EXPERIMENTER_VAL: - OFMeterBandExperimenter bandExp = (OFMeterBandExperimenter) band; - jGen.writeNumberField("rate", bandExp.getRate()); - jGen.writeNumberField("burstSize", bandExp.getBurstSize()); - jGen.writeNumberField("experimenter", bandExp.getExperimenter()); - break; - - default: - // shouldn't ever get here - break; - }//end of Switch Case - - jGen.writeEndObject(); - }//end of for loop - jGen.writeEndArray(); - } - - /*** - * Serializes Table Statistics - * @author Naveen - * @param tableReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeTableReply(List<OFTableStatsReply> tableReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - - OFTableStatsReply tableReply = tableReplies.get(0); // we will get only one tableReply and it will contains many OFTableStatsEntry ? - jGen.writeStringField("version", tableReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("table"); - jGen.writeStartArray(); - for(OFTableStatsEntry entry : tableReply.getEntries()) { - jGen.writeStartObject(); - - //Fields common to all OF versions - //For OF 1.3, only these fields are applicable - jGen.writeStringField("tableId",entry.getTableId().toString()); - jGen.writeNumberField("activeCount", entry.getActiveCount()); - jGen.writeNumberField("lookUpCount", entry.getLookupCount().getValue()); - jGen.writeNumberField("matchCount", entry.getMatchedCount().getValue()); - - //Fields Applicable only for specific Versions - switch (entry.getVersion()) { - case OF_12: - //Fields applicable only to OF 1.2 - jGen.writeNumberField("writeSetFields", entry.getWriteSetfields().getValue()); - jGen.writeNumberField("applySetFields", entry.getApplySetfields().getValue()); - jGen.writeNumberField("metaDataMatch", entry.getMetadataMatch().getValue()); - jGen.writeNumberField("metaDataWrite", entry.getMetadataWrite().getValue()); - case OF_11: - //Fields applicable to OF 1.1 & 1.2 - jGen.writeStringField("match", entry.getMatch().toString()); - jGen.writeNumberField("instructions", entry.getInstructions()); - jGen.writeNumberField("writeActions", entry.getWriteActions()); - jGen.writeNumberField("applyActions", entry.getApplyActions()); - jGen.writeNumberField("config", entry.getConfig()); - case OF_10: - //Fields applicable to OF 1.0, 1.1 & 1.2 - jGen.writeStringField("name",entry.getName()); - jGen.writeNumberField("wildcards", entry.getWildcards()); - jGen.writeNumberField("maxEntries", entry.getMaxEntries()); - break; - default: - //no extra fields for OF_13 - break; - }//End of switch case - jGen.writeEndObject(); - }//End of for loop - jGen.writeEndArray(); - } - - /*** - * Serializes Table Features Reply - * @author Naveen - * @param tableFeaturesReplies - * @param jGen - * @throws IOException - * @throws JsonProcessingException - */ - public void serializeTableFeaturesReply(List<OFTableFeaturesStatsReply> tableFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - - OFTableFeaturesStatsReply tableFeaturesReply = tableFeaturesReplies.get(0); - jGen.writeStringField("version", tableFeaturesReply.getVersion().toString()); //return the enum name - - jGen.writeFieldName("tableFeatures"); - jGen.writeStartArray(); - for(OFTableFeatures tableFeature : tableFeaturesReply.getEntries()) { - jGen.writeStartObject(); - jGen.writeNumberField("tableId", tableFeature.getTableId().getValue()); - jGen.writeStringField("name", tableFeature.getName()); - jGen.writeNumberField("metadataMatch", tableFeature.getMetadataMatch().getValue()); - jGen.writeNumberField("metadataWrite", tableFeature.getMetadataWrite().getValue()); - jGen.writeNumberField("config", tableFeature.getConfig()); - jGen.writeNumberField("maxEntries", tableFeature.getMaxEntries()); - - jGen.writeFieldName("properties"); - jGen.writeStartArray(); - for (OFTableFeatureProp properties : tableFeature.getProperties()) { - jGen.writeStartObject(); - short type = (short)properties.getType(); - jGen.writeNumberField("tableFeaturePropType",type); - - switch (type) { - case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_VAL: - OFTableFeaturePropInstructions propInstruct = (OFTableFeaturePropInstructions) properties; - jGen.writeFieldName("instructions"); - jGen.writeStartArray(); - for (OFInstructionId id : propInstruct.getInstructionIds()) { - jGen.writeStartObject(); - jGen.writeString(id.getType().toString()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_MISS_VAL: - OFTableFeaturePropInstructionsMiss propInstructMiss = (OFTableFeaturePropInstructionsMiss) properties; - jGen.writeFieldName("instructionsMiss"); - jGen.writeStartArray(); - for (OFInstructionId id : propInstructMiss.getInstructionIds()) { - jGen.writeStartObject(); - jGen.writeString(id.getType().toString()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_VAL: - OFTableFeaturePropNextTables propNxtTables = (OFTableFeaturePropNextTables) properties; - jGen.writeFieldName("nextTables"); - jGen.writeStartArray(); - for (U8 id : propNxtTables.getNextTableIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_MISS_VAL: - OFTableFeaturePropNextTablesMiss propNxtTablesMiss = (OFTableFeaturePropNextTablesMiss) properties; - jGen.writeFieldName("nextTablesMiss"); - jGen.writeStartArray(); - for (U8 id : propNxtTablesMiss.getNextTableIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_VAL: - OFTableFeaturePropWriteActions propWrAct = (OFTableFeaturePropWriteActions) properties; - jGen.writeFieldName("writeActions"); - jGen.writeStartArray(); - for (OFActionId id : propWrAct.getActionIds()) { - jGen.writeStartObject(); - jGen.writeString(id.getType().toString()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_MISS_VAL: - OFTableFeaturePropWriteActionsMiss propWrActMiss = (OFTableFeaturePropWriteActionsMiss) properties; - jGen.writeFieldName("writeActionsMiss"); - jGen.writeStartArray(); - for (OFActionId id : propWrActMiss.getActionIds()) { - jGen.writeStartObject(); - jGen.writeString(id.getType().toString()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_VAL: - OFTableFeaturePropApplyActions propAppAct = (OFTableFeaturePropApplyActions) properties; - jGen.writeFieldName("applyActions"); - jGen.writeStartArray(); - for (OFActionId id : propAppAct.getActionIds()) { - jGen.writeStartObject(); - jGen.writeString(id.getType().toString()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_MISS_VAL: - OFTableFeaturePropApplyActionsMiss propAppActMiss = (OFTableFeaturePropApplyActionsMiss) properties; - jGen.writeFieldName("applyActionsMiss"); - jGen.writeStartArray(); - for (OFActionId id : propAppActMiss.getActionIds()) { - jGen.writeStartObject(); - jGen.writeString(id.getType().toString()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.MATCH_VAL: - OFTableFeaturePropMatch propMatch = (OFTableFeaturePropMatch) properties; - jGen.writeFieldName("match"); - jGen.writeStartArray(); - for (U32 id : propMatch.getOxmIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.WILDCARDS_VAL: - OFTableFeaturePropWildcards propWildcards = (OFTableFeaturePropWildcards) properties; - jGen.writeFieldName("wildcards"); - jGen.writeStartArray(); - for (U32 id : propWildcards.getOxmIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_VAL: - OFTableFeaturePropWriteSetfield propWrSetfield = (OFTableFeaturePropWriteSetfield) properties; - jGen.writeFieldName("writeSetfield"); - jGen.writeStartArray(); - for (U32 id : propWrSetfield.getOxmIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_MISS_VAL: - OFTableFeaturePropWriteSetfieldMiss propWrSetfieldMiss = (OFTableFeaturePropWriteSetfieldMiss) properties; - jGen.writeFieldName("writeSetfieldMiss"); - jGen.writeStartArray(); - for (U32 id : propWrSetfieldMiss.getOxmIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_VAL: - OFTableFeaturePropApplySetfield propAppSetfield = (OFTableFeaturePropApplySetfield) properties; - jGen.writeFieldName("applySetfield"); - jGen.writeStartArray(); - for (U32 id : propAppSetfield.getOxmIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_MISS_VAL: - OFTableFeaturePropApplySetfieldMiss propAppSetfieldMiss = (OFTableFeaturePropApplySetfieldMiss) properties; - jGen.writeFieldName("applySetfieldMiss"); - jGen.writeStartArray(); - for (U32 id : propAppSetfieldMiss.getOxmIds()) { - jGen.writeStartObject(); - jGen.writeNumber(id.getValue()); - jGen.writeEndObject(); - } - jGen.writeEndArray(); - break; - case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_VAL: - OFTableFeaturePropExperimenter propExp = (OFTableFeaturePropExperimenter) properties; - jGen.writeFieldName("experimenter"); - jGen.writeStartObject(); - jGen.writeNumberField("subType", propExp.getSubtype()); - jGen.writeNumberField("experimenter", propExp.getExperimenter()); - jGen.writeStringField("subType", propExp.getExperimenterData().toString()); - jGen.writeEndObject(); - break; - case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_MISS_VAL: - OFTableFeaturePropExperimenterMiss propExpMiss = (OFTableFeaturePropExperimenterMiss) properties; - jGen.writeFieldName("experimenterMiss"); - jGen.writeStartObject(); - jGen.writeNumberField("subType", propExpMiss.getSubtype()); - jGen.writeNumberField("experimenter", propExpMiss.getExperimenter()); - jGen.writeStringField("subType", propExpMiss.getExperimenterData().toString()); - jGen.writeEndObject(); - break; - default: - // shouldn't ever get here - break; - }//end of Switch Case - jGen.writeEndObject(); - }//end of for loop - properties - jGen.writeEndObject(); - }//end of for loop - features - jGen.writeEndArray(); - } - - - public static void serializePortReply(List<OFPortStatsReply> portReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFPortStatsReply portReply = portReplies.get(0); // we will get only one PortReply and it will contains many OFPortStatsEntry ? - jGen.writeStringField("version", portReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("port"); - jGen.writeStartArray(); - for(OFPortStatsEntry entry : portReply.getEntries()) { - jGen.writeStartObject(); - jGen.writeStringField("portNumber",entry.getPortNo().toString()); - jGen.writeNumberField("receivePackets", entry.getRxPackets().getValue()); - jGen.writeNumberField("transmitPackets", entry.getTxPackets().getValue()); - jGen.writeNumberField("receiveBytes", entry.getRxBytes().getValue()); - jGen.writeNumberField("transmitBytes", entry.getTxBytes().getValue()); - jGen.writeNumberField("receiveDropped", entry.getRxDropped().getValue()); - jGen.writeNumberField("transmitDropped", entry.getTxDropped().getValue()); - jGen.writeNumberField("receiveErrors", entry.getRxErrors().getValue()); - jGen.writeNumberField("transmitErrors", entry.getTxErrors().getValue()); - jGen.writeNumberField("receiveFrameErrors", entry.getRxFrameErr().getValue()); - jGen.writeNumberField("receiveOverrunErrors", entry.getRxOverErr().getValue()); - jGen.writeNumberField("receiveCRCErrors", entry.getRxCrcErr().getValue()); - jGen.writeNumberField("collisions", entry.getCollisions().getValue()); - if (OFVersion.OF_13 == entry.getVersion()) { - jGen.writeNumberField("durationSec", entry.getDurationSec()); - jGen.writeNumberField("durationNsec", entry.getDurationNsec()); - } - jGen.writeEndObject(); - } - jGen.writeEndArray(); - } - - public static void serializeFlowReply(List<OFFlowStatsReply> flowReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - for (OFFlowStatsReply flowReply : flowReplies) { // for each flow stats reply - //Dose the switch will reply multiple OFFlowStatsReply ? - //Or we juse need to use the first item of the list. - List<OFFlowStatsEntry> entries = flowReply.getEntries(); - jGen.writeFieldName("flows"); - jGen.writeStartArray(); - for (OFFlowStatsEntry entry : entries) { // for each flow - jGen.writeStartObject(); - // list flow stats/info - jGen.writeStringField("version", entry.getVersion().toString()); // return the enum name - jGen.writeNumberField("cookie", entry.getCookie().getValue()); - jGen.writeStringField("tableId", entry.getTableId().toString()); - jGen.writeNumberField("packetCount", entry.getPacketCount().getValue()); - jGen.writeNumberField("byteCount", entry.getByteCount().getValue()); - jGen.writeNumberField("durationSeconds", entry.getDurationSec()); - jGen.writeNumberField("priority", entry.getPriority()); - jGen.writeNumberField("idleTimeoutSec", entry.getIdleTimeout()); - jGen.writeNumberField("hardTimeoutSec", entry.getHardTimeout()); - switch (entry.getVersion()) { - case OF_10: - // flags not supported - break; - case OF_11: - jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer11.toWireValue(entry.getFlags())); - break; - case OF_12: - jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer12.toWireValue(entry.getFlags())); - break; - case OF_13: - jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer13.toWireValue(entry.getFlags())); - break; - case OF_14: - jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer14.toWireValue(entry.getFlags())); - break; - default: - logger.error("Could not decode OFVersion {}", entry.getVersion()); - break; - } - - MatchSerializer.serializeMatch(jGen, entry.getMatch()); - - // handle OF1.1+ instructions with actions within - if (entry.getVersion() == OFVersion.OF_10) { - jGen.writeObjectFieldStart("actions"); - OFActionListSerializer.serializeActions(jGen, entry.getActions()); - jGen.writeEndObject(); - } else { - OFInstructionListSerializer.serializeInstructionList(jGen, entry.getInstructions()); - } - - jGen.writeEndObject(); - } // end for each OFFlowStatsReply entry - jGen.writeEndArray(); - } // end for each OFStatsReply - } // end method - - public static void serializeDescReply(List<OFDescStatsReply> descReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFDescStatsReply descReply = descReplies.get(0); // There is only one descReply from the switch - jGen.writeObjectFieldStart("desc"); - jGen.writeStringField("version", descReply.getVersion().toString()); //return the enum name - jGen.writeStringField("manufacturerDescription", descReply.getMfrDesc()); - jGen.writeStringField("hardwareDescription", descReply.getHwDesc()); - jGen.writeStringField("softwareDescription", descReply.getSwDesc()); - jGen.writeStringField("serialNumber", descReply.getSerialNum()); - jGen.writeStringField("datapathDescription", descReply.getDpDesc()); - jGen.writeEndObject(); // end match - } - - public static void serializeAggregateReply(List<OFAggregateStatsReply> aggregateReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFAggregateStatsReply aggregateReply = aggregateReplies.get(0); // There are only one aggregateReply from the switch - jGen.writeObjectFieldStart("aggregate"); - jGen.writeStringField("version", aggregateReply.getVersion().toString()); //return the enum name - jGen.writeNumberField("flowCount", aggregateReply.getFlowCount()); - jGen.writeNumberField("packetCount", aggregateReply.getPacketCount().getValue()); - jGen.writeNumberField("byteCount", aggregateReply.getByteCount().getValue()); - jGen.writeEndObject(); // end match - } - - public static void serializePortDescReply(List<OFPortDescStatsReply> portDescReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ - OFPortDescStatsReply portDescReply = portDescReplies.get(0); // we will get only one PortDescReply and it will contains many OFPortDescStatsEntry ? - jGen.writeStringField("version", portDescReply.getVersion().toString()); //return the enum name - jGen.writeFieldName("portDesc"); - jGen.writeStartArray(); - for(OFPortDesc entry : portDescReply.getEntries()) { - jGen.writeStartObject(); - jGen.writeStringField("portNumber",entry.getPortNo().toString()); - jGen.writeStringField("hardwareAddress", entry.getHwAddr().toString()); - jGen.writeStringField("name", entry.getName()); - switch(entry.getVersion()) { - case OF_10: - jGen.writeNumberField("config", OFPortConfigSerializerVer10.toWireValue(entry.getConfig())); - jGen.writeNumberField("state", OFPortStateSerializerVer10.toWireValue(entry.getState())); - jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getCurr())); - jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getAdvertised())); - jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getSupported())); - jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getPeer())); - break; - case OF_11: - jGen.writeNumberField("config", OFPortConfigSerializerVer11.toWireValue(entry.getConfig())); - jGen.writeNumberField("state", OFPortStateSerializerVer11.toWireValue(entry.getState())); - jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getCurr())); - jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getAdvertised())); - jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getSupported())); - jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getPeer())); - break; - case OF_12: - jGen.writeNumberField("config", OFPortConfigSerializerVer12.toWireValue(entry.getConfig())); - jGen.writeNumberField("state", OFPortStateSerializerVer12.toWireValue(entry.getState())); - jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getCurr())); - jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getAdvertised())); - jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getSupported())); - jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getPeer())); - break; - case OF_13: - jGen.writeNumberField("config", OFPortConfigSerializerVer13.toWireValue(entry.getConfig())); - jGen.writeNumberField("state", OFPortStateSerializerVer13.toWireValue(entry.getState())); - jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getCurr())); - jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getAdvertised())); - jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getSupported())); - jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getPeer())); - break; - case OF_14: - // TODO - logger.error("OF1.4 OFPortDesc serializer not implemented"); - } - if (OFVersion.OF_10 != entry.getVersion()) { - jGen.writeNumberField("currSpeed",entry.getCurrSpeed()); - jGen.writeNumberField("maxSpeed",entry.getMaxSpeed()); - } - jGen.writeEndObject(); - } - jGen.writeEndArray(); - } + protected static Logger logger = LoggerFactory.getLogger(StatsReplySerializer.class); + @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(" ", "An error has occurred while proccesing your request,"); + jGen.writeStringField(" *", "which might be due to one or more of the following:"); + jGen.writeStringField(" * ", "-- An invalid DPID and/or stats/features request."); + jGen.writeStringField(" **", "-- The switch is not connected to the controller."); + jGen.writeStringField("* ", "-- The request specified is not supported by the switch's OpenFlow version."); + jGen.writeEndObject(); + jGen.writeObjectFieldStart("Valid statistics and features strings 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.METER_FEATURES); + jGen.writeStringField("C)", OFStatsTypeStrings.PORT); + jGen.writeStringField("D)", OFStatsTypeStrings.PORT_DESC); + jGen.writeStringField("E)", OFStatsTypeStrings.QUEUE); + jGen.writeStringField("F)", OFStatsTypeStrings.TABLE); + jGen.writeStringField("G)", 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(); + + if (reply.getStatType() == null) { // must be an OFFeaturesReply. getValues() was already checked for null above. + serializeFeaturesReply((OFFeaturesReply) reply.getValues(), jGen); + } else { + switch (reply.getStatType()) { + case PORT: + serializePortReply((List<OFPortStatsReply>) reply.getValues(), jGen); + break; + case QUEUE: + // handle queue + break; + case FLOW: + serializeFlowReply((List<OFFlowStatsReply>) reply.getValues(), jGen); + break; + case AGGREGATE: + serializeAggregateReply((List<OFAggregateStatsReply>) reply.getValues(), jGen); + break; + case DESC: + serializeDescReply((List<OFDescStatsReply>) reply.getValues(), jGen); + break; + case GROUP: + serializeGroupReply((List<OFGroupStatsReply>) reply.getValues(), jGen); + break; + case GROUP_DESC: + serializeGroupDescReply((List<OFGroupDescStatsReply>) reply.getValues(), jGen); + break; + case GROUP_FEATURES: + serializeGroupFeaturesReply((List<OFGroupFeaturesStatsReply>) reply.getValues(), jGen); + break; + case METER: + serializeMeterReply((List<OFMeterStatsReply>) reply.getValues(), jGen); + break; + case METER_CONFIG: + serializeMeterConfigReply((List<OFMeterConfigStatsReply>) reply.getValues(), jGen); + break; + case METER_FEATURES: + serializeMeterFeaturesReply((List<OFMeterFeaturesStatsReply>) reply.getValues(), jGen); + break; + case TABLE: + serializeTableReply((List<OFTableStatsReply>) reply.getValues(), jGen); + break; + case TABLE_FEATURES: + serializeTableFeaturesReply((List<OFTableFeaturesStatsReply>) reply.getValues(), jGen); + break; + case PORT_DESC: + serializePortDescReply((List<OFPortDescStatsReply>) reply.getValues(), jGen); + break; + case EXPERIMENTER: + break; + default: + break; + } + } + jGen.writeEndObject(); + } + + public static void serializeFeaturesReply(OFFeaturesReply fr, JsonGenerator jGen) throws IOException, JsonProcessingException { + /* Common to All OF Versions */ + jGen.writeStringField("capabilities", fr.getCapabilities().toString()); + jGen.writeStringField("dpid", fr.getDatapathId().toString()); + jGen.writeNumberField("buffers", fr.getNBuffers()); + jGen.writeNumberField("tables", fr.getNTables()); + jGen.writeStringField("version", fr.getVersion().toString()); + + if (fr.getVersion().compareTo(OFVersion.OF_13) < 0) { // OF1.3+ break this out into port_config + serializePortDesc(fr.getPorts(), jGen); + } + if (fr.getVersion().compareTo(OFVersion.OF_10) == 0) { + String actions = "["; + for (OFActionType action : fr.getActions()) { + actions = actions + action.toString() + ", "; + } + actions = actions.substring(0, actions.length() - 2); // remove ending space+comma + actions = actions + "]"; + jGen.writeStringField("actions", actions); + } + } + + /*** + * Serializes the Group Statistics Reply + * @author Naveen + * @param groupReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeGroupReply(List<OFGroupStatsReply> groupReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + + OFGroupStatsReply groupReply = groupReplies.get(0); // we will get only one GroupReply and it will contains many OFGroupStatsEntry + jGen.writeStringField("version", groupReply.getVersion().toString()); //return the enum name + jGen.writeFieldName("group"); + jGen.writeStartArray(); + for(OFGroupStatsEntry entry : groupReply.getEntries()) { + jGen.writeStartObject(); + jGen.writeStringField("groupNumber",entry.getGroup().toString()); + jGen.writeNumberField("refCount", entry.getRefCount()); + jGen.writeNumberField("packetCount", entry.getPacketCount().getValue()); + jGen.writeNumberField("byteCount", entry.getByteCount().getValue()); + jGen.writeFieldName("bucketCounters"); + jGen.writeStartArray(); + for(OFBucketCounter bCounter : entry.getBucketStats()) { + jGen.writeStartObject(); + jGen.writeNumberField("packetCount", bCounter.getPacketCount().getValue()); + jGen.writeNumberField("byteCount", bCounter.getByteCount().getValue()); + jGen.writeEndObject(); + }//end of for loop - BucketCounter + jGen.writeEndArray(); + if (OFVersion.OF_13 == entry.getVersion()) { + jGen.writeNumberField("durationSec", entry.getDurationSec()); + jGen.writeNumberField("durationNsec", entry.getDurationNsec()); + } + jGen.writeEndObject(); + }//end of for loop - groupStats + jGen.writeEndArray(); + } + + /*** + * Serializes Group Desc Reply + * @author Naveen + * @param groupDescReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeGroupDescReply(List<OFGroupDescStatsReply> groupDescReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFGroupDescStatsReply groupDescReply = groupDescReplies.get(0); + jGen.writeStringField("version", groupDescReply.getVersion().toString()); //return the enum name + jGen.writeFieldName("groupDesc"); + jGen.writeStartArray(); + for(OFGroupDescStatsEntry entry : groupDescReply.getEntries()) { + jGen.writeStartObject(); + jGen.writeStringField("groupType",entry.getGroupType().toString()); + jGen.writeStringField("groupNumber",entry.getGroup().toString()); + jGen.writeFieldName("buckets"); + jGen.writeStartArray(); + for(OFBucket buckets : entry.getBuckets()) { + jGen.writeStartObject(); + jGen.writeNumberField("weight", buckets.getWeight()); + jGen.writeNumberField("watchPortNumber", buckets.getWatchPort().getPortNumber()); + jGen.writeStringField("watchGroup", buckets.getWatchGroup().toString()); + OFActionListSerializer.serializeActions(jGen, buckets.getActions()); + jGen.writeEndObject(); + }//End of for loop - buckets + jGen.writeEndArray();//end of buckets + jGen.writeEndObject();//end of group Desc iteration + }//End of for loop - GroupDescStats + jGen.writeEndArray();//end of group Desc + } + + /*** + * Serializes Group Feature Reply + * @author Naveen + * @param groupFeaturesReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeGroupFeaturesReply(List<OFGroupFeaturesStatsReply> groupFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + + OFGroupFeaturesStatsReply groupFeaturesReply = groupFeaturesReplies.get(0); + jGen.writeStringField("version", groupFeaturesReply.getVersion().toString()); //return the enum name + + jGen.writeFieldName("groupFeatures"); + jGen.writeStartObject(); + jGen.writeNumberField("capabilities",groupFeaturesReply.getCapabilities()); + jGen.writeNumberField("maxGroupsAll",groupFeaturesReply.getMaxGroupsAll()); + jGen.writeNumberField("maxGroupsSelect",groupFeaturesReply.getMaxGroupsSelect()); + jGen.writeNumberField("maxGroupsIndirect",groupFeaturesReply.getMaxGroupsIndirect()); + jGen.writeNumberField("maxGroupsFf",groupFeaturesReply.getMaxGroupsFf()); + jGen.writeNumberField("actionsAll",groupFeaturesReply.getActionsAll()); + jGen.writeNumberField("actionsSelect",groupFeaturesReply.getActionsSelect()); + jGen.writeNumberField("actionsIndirect",groupFeaturesReply.getActionsIndirect()); + jGen.writeNumberField("actionsFf",groupFeaturesReply.getActionsFf()); + + jGen.writeEndObject();//end of group Feature + } + + /*** + * Serializes the Meter Statistics Reply + * @author Naveen + * @param meterReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeMeterReply(List<OFMeterStatsReply> meterReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFMeterStatsReply meterReply = meterReplies.get(0); // we will get only one meterReply and it will contains many OFMeterStatsEntry ? + jGen.writeStringField("version", meterReply.getVersion().toString()); //return the enum name + jGen.writeFieldName("meter"); + jGen.writeStartArray(); + for(OFMeterStats entry : meterReply.getEntries()) { + jGen.writeStartObject(); + jGen.writeNumberField("meterId",entry.getMeterId()); + jGen.writeNumberField("flowCount", entry.getFlowCount()); + jGen.writeNumberField("packetInCount", entry.getPacketInCount().getValue()); + jGen.writeNumberField("byteInCount", entry.getByteInCount().getValue()); + jGen.writeFieldName("meterBandStats"); + jGen.writeStartArray(); + for(OFMeterBandStats bandStats : entry.getBandStats()) { + jGen.writeStartObject(); + jGen.writeNumberField("packetBandCount", bandStats.getPacketBandCount().getValue()); + jGen.writeNumberField("byteBandCount", bandStats.getByteBandCount().getValue()); + jGen.writeEndObject(); + }//End of for loop - bandStats + jGen.writeEndArray(); + + jGen.writeNumberField("durationSec", entry.getDurationSec()); + jGen.writeNumberField("durationNsec", entry.getDurationNsec()); + jGen.writeEndObject(); + }//End of for loop - MeterStats + jGen.writeEndArray(); + } + + /*** + * Serializes Meter Feature Reply + * @author Naveen + * @param meterFeaturesReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeMeterFeaturesReply(List<OFMeterFeaturesStatsReply> meterFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFMeterFeaturesStatsReply meterFeaturesReply = meterFeaturesReplies.get(0); + jGen.writeStringField("version", meterFeaturesReply.getVersion().toString()); //return the enum name + + OFMeterFeatures meterFeatures = meterFeaturesReply.getFeatures(); + jGen.writeFieldName("meterFeatures"); + jGen.writeStartObject(); + + jGen.writeNumberField("maxGroupsAll",meterFeatures.getMaxMeter()); + jGen.writeNumberField("maxGroupsSelect",meterFeatures.getBandTypes()); + jGen.writeNumberField("capabilities",meterFeatures.getCapabilities()); + jGen.writeNumberField("maxGroupsIndirect",meterFeatures.getMaxBands()); + jGen.writeNumberField("maxGroupsFf",meterFeatures.getMaxColor()); + + jGen.writeEndObject();//end of group Feature + } + + /*** + * Serializes Meter Config Reply + * @author Naveen + * @param meterConfigReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeMeterConfigReply(List<OFMeterConfigStatsReply> meterConfigReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFMeterConfigStatsReply meterConfigReply = meterConfigReplies.get(0); + jGen.writeStringField("version", meterConfigReply.getVersion().toString()); //return the enum name + jGen.writeFieldName("meterConfig"); + jGen.writeStartArray(); + for(OFMeterBand band : meterConfigReply.getEntries()) { + jGen.writeStartObject(); + short type = (short)band.getType(); + jGen.writeNumberField("bandType",type); + + switch (type) { + case OFMeterBandTypeSerializerVer13.DROP_VAL: + OFMeterBandDrop bandDrop = (OFMeterBandDrop) band; + jGen.writeNumberField("rate", bandDrop.getRate()); + jGen.writeNumberField("burstSize", bandDrop.getBurstSize()); + break; + + case OFMeterBandTypeSerializerVer13.DSCP_REMARK_VAL: + OFMeterBandDscpRemark bandDscp = (OFMeterBandDscpRemark) band; + jGen.writeNumberField("rate", bandDscp.getRate()); + jGen.writeNumberField("burstSize", bandDscp.getBurstSize()); + jGen.writeNumberField("precLevel", bandDscp.getPrecLevel()); + break; + + case OFMeterBandTypeSerializerVer13.EXPERIMENTER_VAL: + OFMeterBandExperimenter bandExp = (OFMeterBandExperimenter) band; + jGen.writeNumberField("rate", bandExp.getRate()); + jGen.writeNumberField("burstSize", bandExp.getBurstSize()); + jGen.writeNumberField("experimenter", bandExp.getExperimenter()); + break; + + default: + // shouldn't ever get here + break; + }//end of Switch Case + + jGen.writeEndObject(); + }//end of for loop + jGen.writeEndArray(); + } + + /*** + * Serializes Table Statistics + * @author Naveen + * @param tableReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeTableReply(List<OFTableStatsReply> tableReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + + OFTableStatsReply tableReply = tableReplies.get(0); // we will get only one tableReply and it will contains many OFTableStatsEntry ? + jGen.writeStringField("version", tableReply.getVersion().toString()); //return the enum name + jGen.writeFieldName("table"); + jGen.writeStartArray(); + for(OFTableStatsEntry entry : tableReply.getEntries()) { + jGen.writeStartObject(); + + //Fields common to all OF versions + //For OF 1.3, only these fields are applicable + jGen.writeStringField("tableId",entry.getTableId().toString()); + jGen.writeNumberField("activeCount", entry.getActiveCount()); + jGen.writeNumberField("lookUpCount", entry.getLookupCount().getValue()); + jGen.writeNumberField("matchCount", entry.getMatchedCount().getValue()); + + //Fields Applicable only for specific Versions + switch (entry.getVersion()) { + case OF_12: + //Fields applicable only to OF 1.2 + jGen.writeNumberField("writeSetFields", entry.getWriteSetfields().getValue()); + jGen.writeNumberField("applySetFields", entry.getApplySetfields().getValue()); + jGen.writeNumberField("metaDataMatch", entry.getMetadataMatch().getValue()); + jGen.writeNumberField("metaDataWrite", entry.getMetadataWrite().getValue()); + case OF_11: + //Fields applicable to OF 1.1 & 1.2 + jGen.writeStringField("match", entry.getMatch().toString()); + jGen.writeNumberField("instructions", entry.getInstructions()); + jGen.writeNumberField("writeActions", entry.getWriteActions()); + jGen.writeNumberField("applyActions", entry.getApplyActions()); + jGen.writeNumberField("config", entry.getConfig()); + case OF_10: + //Fields applicable to OF 1.0, 1.1 & 1.2 + jGen.writeStringField("name",entry.getName()); + jGen.writeNumberField("wildcards", entry.getWildcards()); + jGen.writeNumberField("maxEntries", entry.getMaxEntries()); + break; + default: + //no extra fields for OF_13 + break; + }//End of switch case + jGen.writeEndObject(); + }//End of for loop + jGen.writeEndArray(); + } + + /*** + * Serializes Table Features Reply + * @author Naveen + * @param tableFeaturesReplies + * @param jGen + * @throws IOException + * @throws JsonProcessingException + */ + public static void serializeTableFeaturesReply(List<OFTableFeaturesStatsReply> tableFeaturesReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + + OFTableFeaturesStatsReply tableFeaturesReply = tableFeaturesReplies.get(0); + jGen.writeStringField("version", tableFeaturesReply.getVersion().toString()); //return the enum name + + jGen.writeFieldName("tableFeatures"); + jGen.writeStartArray(); + for(OFTableFeatures tableFeature : tableFeaturesReply.getEntries()) { + jGen.writeStartObject(); + jGen.writeNumberField("tableId", tableFeature.getTableId().getValue()); + jGen.writeStringField("name", tableFeature.getName()); + jGen.writeNumberField("metadataMatch", tableFeature.getMetadataMatch().getValue()); + jGen.writeNumberField("metadataWrite", tableFeature.getMetadataWrite().getValue()); + jGen.writeNumberField("config", tableFeature.getConfig()); + jGen.writeNumberField("maxEntries", tableFeature.getMaxEntries()); + + jGen.writeFieldName("properties"); + jGen.writeStartArray(); + for (OFTableFeatureProp properties : tableFeature.getProperties()) { + jGen.writeStartObject(); + short type = (short)properties.getType(); + jGen.writeNumberField("tableFeaturePropType",type); + + switch (type) { + case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_VAL: + OFTableFeaturePropInstructions propInstruct = (OFTableFeaturePropInstructions) properties; + jGen.writeFieldName("instructions"); + jGen.writeStartArray(); + for (OFInstructionId id : propInstruct.getInstructionIds()) { + jGen.writeStartObject(); + jGen.writeString(id.getType().toString()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.INSTRUCTIONS_MISS_VAL: + OFTableFeaturePropInstructionsMiss propInstructMiss = (OFTableFeaturePropInstructionsMiss) properties; + jGen.writeFieldName("instructionsMiss"); + jGen.writeStartArray(); + for (OFInstructionId id : propInstructMiss.getInstructionIds()) { + jGen.writeStartObject(); + jGen.writeString(id.getType().toString()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_VAL: + OFTableFeaturePropNextTables propNxtTables = (OFTableFeaturePropNextTables) properties; + jGen.writeFieldName("nextTables"); + jGen.writeStartArray(); + for (U8 id : propNxtTables.getNextTableIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.NEXT_TABLES_MISS_VAL: + OFTableFeaturePropNextTablesMiss propNxtTablesMiss = (OFTableFeaturePropNextTablesMiss) properties; + jGen.writeFieldName("nextTablesMiss"); + jGen.writeStartArray(); + for (U8 id : propNxtTablesMiss.getNextTableIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_VAL: + OFTableFeaturePropWriteActions propWrAct = (OFTableFeaturePropWriteActions) properties; + jGen.writeFieldName("writeActions"); + jGen.writeStartArray(); + for (OFActionId id : propWrAct.getActionIds()) { + jGen.writeStartObject(); + jGen.writeString(id.getType().toString()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.WRITE_ACTIONS_MISS_VAL: + OFTableFeaturePropWriteActionsMiss propWrActMiss = (OFTableFeaturePropWriteActionsMiss) properties; + jGen.writeFieldName("writeActionsMiss"); + jGen.writeStartArray(); + for (OFActionId id : propWrActMiss.getActionIds()) { + jGen.writeStartObject(); + jGen.writeString(id.getType().toString()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_VAL: + OFTableFeaturePropApplyActions propAppAct = (OFTableFeaturePropApplyActions) properties; + jGen.writeFieldName("applyActions"); + jGen.writeStartArray(); + for (OFActionId id : propAppAct.getActionIds()) { + jGen.writeStartObject(); + jGen.writeString(id.getType().toString()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.APPLY_ACTIONS_MISS_VAL: + OFTableFeaturePropApplyActionsMiss propAppActMiss = (OFTableFeaturePropApplyActionsMiss) properties; + jGen.writeFieldName("applyActionsMiss"); + jGen.writeStartArray(); + for (OFActionId id : propAppActMiss.getActionIds()) { + jGen.writeStartObject(); + jGen.writeString(id.getType().toString()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.MATCH_VAL: + OFTableFeaturePropMatch propMatch = (OFTableFeaturePropMatch) properties; + jGen.writeFieldName("match"); + jGen.writeStartArray(); + for (U32 id : propMatch.getOxmIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.WILDCARDS_VAL: + OFTableFeaturePropWildcards propWildcards = (OFTableFeaturePropWildcards) properties; + jGen.writeFieldName("wildcards"); + jGen.writeStartArray(); + for (U32 id : propWildcards.getOxmIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_VAL: + OFTableFeaturePropWriteSetfield propWrSetfield = (OFTableFeaturePropWriteSetfield) properties; + jGen.writeFieldName("writeSetfield"); + jGen.writeStartArray(); + for (U32 id : propWrSetfield.getOxmIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.WRITE_SETFIELD_MISS_VAL: + OFTableFeaturePropWriteSetfieldMiss propWrSetfieldMiss = (OFTableFeaturePropWriteSetfieldMiss) properties; + jGen.writeFieldName("writeSetfieldMiss"); + jGen.writeStartArray(); + for (U32 id : propWrSetfieldMiss.getOxmIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_VAL: + OFTableFeaturePropApplySetfield propAppSetfield = (OFTableFeaturePropApplySetfield) properties; + jGen.writeFieldName("applySetfield"); + jGen.writeStartArray(); + for (U32 id : propAppSetfield.getOxmIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.APPLY_SETFIELD_MISS_VAL: + OFTableFeaturePropApplySetfieldMiss propAppSetfieldMiss = (OFTableFeaturePropApplySetfieldMiss) properties; + jGen.writeFieldName("applySetfieldMiss"); + jGen.writeStartArray(); + for (U32 id : propAppSetfieldMiss.getOxmIds()) { + jGen.writeStartObject(); + jGen.writeNumber(id.getValue()); + jGen.writeEndObject(); + } + jGen.writeEndArray(); + break; + case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_VAL: + OFTableFeaturePropExperimenter propExp = (OFTableFeaturePropExperimenter) properties; + jGen.writeFieldName("experimenter"); + jGen.writeStartObject(); + jGen.writeNumberField("subType", propExp.getSubtype()); + jGen.writeNumberField("experimenter", propExp.getExperimenter()); + jGen.writeStringField("subType", propExp.getExperimenterData().toString()); + jGen.writeEndObject(); + break; + case OFTableFeaturePropTypeSerializerVer13.EXPERIMENTER_MISS_VAL: + OFTableFeaturePropExperimenterMiss propExpMiss = (OFTableFeaturePropExperimenterMiss) properties; + jGen.writeFieldName("experimenterMiss"); + jGen.writeStartObject(); + jGen.writeNumberField("subType", propExpMiss.getSubtype()); + jGen.writeNumberField("experimenter", propExpMiss.getExperimenter()); + jGen.writeStringField("subType", propExpMiss.getExperimenterData().toString()); + jGen.writeEndObject(); + break; + default: + // shouldn't ever get here + break; + }//end of Switch Case + jGen.writeEndObject(); + }//end of for loop - properties + jGen.writeEndObject(); + }//end of for loop - features + jGen.writeEndArray(); + } + + + public static void serializePortReply(List<OFPortStatsReply> portReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFPortStatsReply portReply = portReplies.get(0); // we will get only one PortReply and it will contains many OFPortStatsEntry ? + jGen.writeStringField("version", portReply.getVersion().toString()); //return the enum name + jGen.writeFieldName("port"); + jGen.writeStartArray(); + for(OFPortStatsEntry entry : portReply.getEntries()) { + jGen.writeStartObject(); + jGen.writeStringField("portNumber",entry.getPortNo().toString()); + jGen.writeNumberField("receivePackets", entry.getRxPackets().getValue()); + jGen.writeNumberField("transmitPackets", entry.getTxPackets().getValue()); + jGen.writeNumberField("receiveBytes", entry.getRxBytes().getValue()); + jGen.writeNumberField("transmitBytes", entry.getTxBytes().getValue()); + jGen.writeNumberField("receiveDropped", entry.getRxDropped().getValue()); + jGen.writeNumberField("transmitDropped", entry.getTxDropped().getValue()); + jGen.writeNumberField("receiveErrors", entry.getRxErrors().getValue()); + jGen.writeNumberField("transmitErrors", entry.getTxErrors().getValue()); + jGen.writeNumberField("receiveFrameErrors", entry.getRxFrameErr().getValue()); + jGen.writeNumberField("receiveOverrunErrors", entry.getRxOverErr().getValue()); + jGen.writeNumberField("receiveCRCErrors", entry.getRxCrcErr().getValue()); + jGen.writeNumberField("collisions", entry.getCollisions().getValue()); + if (OFVersion.OF_13 == entry.getVersion()) { + jGen.writeNumberField("durationSec", entry.getDurationSec()); + jGen.writeNumberField("durationNsec", entry.getDurationNsec()); + } + jGen.writeEndObject(); + } + jGen.writeEndArray(); + } + + public static void serializeFlowReply(List<OFFlowStatsReply> flowReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + for (OFFlowStatsReply flowReply : flowReplies) { // for each flow stats reply + //Dose the switch will reply multiple OFFlowStatsReply ? + //Or we juse need to use the first item of the list. + List<OFFlowStatsEntry> entries = flowReply.getEntries(); + jGen.writeFieldName("flows"); + jGen.writeStartArray(); + for (OFFlowStatsEntry entry : entries) { // for each flow + jGen.writeStartObject(); + // list flow stats/info + jGen.writeStringField("version", entry.getVersion().toString()); // return the enum name + jGen.writeNumberField("cookie", entry.getCookie().getValue()); + jGen.writeStringField("tableId", entry.getTableId().toString()); + jGen.writeNumberField("packetCount", entry.getPacketCount().getValue()); + jGen.writeNumberField("byteCount", entry.getByteCount().getValue()); + jGen.writeNumberField("durationSeconds", entry.getDurationSec()); + jGen.writeNumberField("priority", entry.getPriority()); + jGen.writeNumberField("idleTimeoutSec", entry.getIdleTimeout()); + jGen.writeNumberField("hardTimeoutSec", entry.getHardTimeout()); + switch (entry.getVersion()) { + case OF_10: + // flags not supported + break; + case OF_11: + jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer11.toWireValue(entry.getFlags())); + break; + case OF_12: + jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer12.toWireValue(entry.getFlags())); + break; + case OF_13: + jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer13.toWireValue(entry.getFlags())); + break; + case OF_14: + jGen.writeNumberField("flags", OFFlowModFlagsSerializerVer14.toWireValue(entry.getFlags())); + break; + default: + logger.error("Could not decode OFVersion {}", entry.getVersion()); + break; + } + + MatchSerializer.serializeMatch(jGen, entry.getMatch()); + + // handle OF1.1+ instructions with actions within + if (entry.getVersion() == OFVersion.OF_10) { + jGen.writeObjectFieldStart("actions"); + OFActionListSerializer.serializeActions(jGen, entry.getActions()); + jGen.writeEndObject(); + } else { + OFInstructionListSerializer.serializeInstructionList(jGen, entry.getInstructions()); + } + + jGen.writeEndObject(); + } // end for each OFFlowStatsReply entry + jGen.writeEndArray(); + } // end for each OFStatsReply + } // end method + + public static void serializeDescReply(List<OFDescStatsReply> descReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFDescStatsReply descReply = descReplies.get(0); // There is only one descReply from the switch + jGen.writeObjectFieldStart("desc"); + jGen.writeStringField("version", descReply.getVersion().toString()); //return the enum name + jGen.writeStringField("manufacturerDescription", descReply.getMfrDesc()); + jGen.writeStringField("hardwareDescription", descReply.getHwDesc()); + jGen.writeStringField("softwareDescription", descReply.getSwDesc()); + jGen.writeStringField("serialNumber", descReply.getSerialNum()); + jGen.writeStringField("datapathDescription", descReply.getDpDesc()); + jGen.writeEndObject(); // end match + } + + public static void serializeAggregateReply(List<OFAggregateStatsReply> aggregateReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFAggregateStatsReply aggregateReply = aggregateReplies.get(0); // There are only one aggregateReply from the switch + jGen.writeObjectFieldStart("aggregate"); + jGen.writeStringField("version", aggregateReply.getVersion().toString()); //return the enum name + jGen.writeNumberField("flowCount", aggregateReply.getFlowCount()); + jGen.writeNumberField("packetCount", aggregateReply.getPacketCount().getValue()); + jGen.writeNumberField("byteCount", aggregateReply.getByteCount().getValue()); + switch (aggregateReply.getVersion()) { + case OF_10: + jGen.writeNumberField("flags", OFStatsReplyFlagsSerializerVer10.toWireValue(aggregateReply.getFlags())); + break; + case OF_11: + jGen.writeNumberField("flags", OFStatsReplyFlagsSerializerVer11.toWireValue(aggregateReply.getFlags())); + break; + case OF_12: + jGen.writeNumberField("flags", OFStatsReplyFlagsSerializerVer12.toWireValue(aggregateReply.getFlags())); + break; + case OF_13: + jGen.writeNumberField("flags", OFStatsReplyFlagsSerializerVer13.toWireValue(aggregateReply.getFlags())); + break; + case OF_14: + jGen.writeNumberField("flags", OFStatsReplyFlagsSerializerVer14.toWireValue(aggregateReply.getFlags())); + break; + default: + break; + } + jGen.writeEndObject(); // end match + } + + public static void serializePortDescReply(List<OFPortDescStatsReply> portDescReplies, JsonGenerator jGen) throws IOException, JsonProcessingException{ + OFPortDescStatsReply portDescReply = portDescReplies.get(0); // we will get only one PortDescReply and it will contains many OFPortDescStatsEntry ? + jGen.writeStringField("version", portDescReply.getVersion().toString()); //return the enum name + serializePortDesc(portDescReply.getEntries(), jGen); + } + + public static void serializePortDesc(List<OFPortDesc> portDescList, JsonGenerator jGen) throws IOException, JsonProcessingException { + jGen.writeFieldName("portDesc"); + jGen.writeStartArray(); + for(OFPortDesc entry : portDescList) { + jGen.writeStartObject(); + jGen.writeStringField("portNumber",entry.getPortNo().toString()); + jGen.writeStringField("hardwareAddress", entry.getHwAddr().toString()); + jGen.writeStringField("name", entry.getName()); + switch(entry.getVersion()) { + case OF_10: + jGen.writeNumberField("config", OFPortConfigSerializerVer10.toWireValue(entry.getConfig())); + jGen.writeNumberField("state", OFPortStateSerializerVer10.toWireValue(entry.getState())); + jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getCurr())); + jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getAdvertised())); + jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getSupported())); + jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer10.toWireValue(entry.getPeer())); + break; + case OF_11: + jGen.writeNumberField("config", OFPortConfigSerializerVer11.toWireValue(entry.getConfig())); + jGen.writeNumberField("state", OFPortStateSerializerVer11.toWireValue(entry.getState())); + jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getCurr())); + jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getAdvertised())); + jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getSupported())); + jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer11.toWireValue(entry.getPeer())); + break; + case OF_12: + jGen.writeNumberField("config", OFPortConfigSerializerVer12.toWireValue(entry.getConfig())); + jGen.writeNumberField("state", OFPortStateSerializerVer12.toWireValue(entry.getState())); + jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getCurr())); + jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getAdvertised())); + jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getSupported())); + jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer12.toWireValue(entry.getPeer())); + break; + case OF_13: + jGen.writeNumberField("config", OFPortConfigSerializerVer13.toWireValue(entry.getConfig())); + jGen.writeNumberField("state", OFPortStateSerializerVer13.toWireValue(entry.getState())); + jGen.writeNumberField("currentFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getCurr())); + jGen.writeNumberField("advertisedFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getAdvertised())); + jGen.writeNumberField("supportedFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getSupported())); + jGen.writeNumberField("peerFeatures", OFPortFeaturesSerializerVer13.toWireValue(entry.getPeer())); + break; + case OF_14: + // TODO + logger.error("OF1.4 OFPortDesc serializer not implemented"); + } + if (OFVersion.OF_10 != entry.getVersion()) { + jGen.writeNumberField("currSpeed",entry.getCurrSpeed()); + jGen.writeNumberField("maxSpeed",entry.getMaxSpeed()); + } + jGen.writeEndObject(); + } + jGen.writeEndArray(); + } } -- GitLab