Committed by
Gerrit Code Review
[ONOS-2225] Add codecs with unit test for FlowObjective REST API
* Add codec for FilteringObjective * Add codec for ForwardingObjective * Add codec for NextObjective Change-Id: I715aa7f1969697468692459052fd27cc65ca2363
Showing
15 changed files
with
1398 additions
and
0 deletions
| ... | @@ -43,6 +43,9 @@ import org.onosproject.net.flow.TrafficSelector; | ... | @@ -43,6 +43,9 @@ import org.onosproject.net.flow.TrafficSelector; |
| 43 | import org.onosproject.net.flow.TrafficTreatment; | 43 | import org.onosproject.net.flow.TrafficTreatment; |
| 44 | import org.onosproject.net.flow.criteria.Criterion; | 44 | import org.onosproject.net.flow.criteria.Criterion; |
| 45 | import org.onosproject.net.flow.instructions.Instruction; | 45 | import org.onosproject.net.flow.instructions.Instruction; |
| 46 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 47 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 48 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 46 | import org.onosproject.net.group.Group; | 49 | import org.onosproject.net.group.Group; |
| 47 | import org.onosproject.net.group.GroupBucket; | 50 | import org.onosproject.net.group.GroupBucket; |
| 48 | import org.onosproject.net.intent.ConnectivityIntent; | 51 | import org.onosproject.net.intent.ConnectivityIntent; |
| ... | @@ -109,6 +112,9 @@ public class CodecManager implements CodecService { | ... | @@ -109,6 +112,9 @@ public class CodecManager implements CodecService { |
| 109 | registerCodec(TableStatisticsEntry.class, new TableStatisticsEntryCodec()); | 112 | registerCodec(TableStatisticsEntry.class, new TableStatisticsEntryCodec()); |
| 110 | registerCodec(PortStatistics.class, new PortStatisticsCodec()); | 113 | registerCodec(PortStatistics.class, new PortStatisticsCodec()); |
| 111 | registerCodec(Metric.class, new MetricCodec()); | 114 | registerCodec(Metric.class, new MetricCodec()); |
| 115 | + registerCodec(FilteringObjective.class, new FilteringObjectiveCodec()); | ||
| 116 | + registerCodec(ForwardingObjective.class, new ForwardingObjectiveCodec()); | ||
| 117 | + registerCodec(NextObjective.class, new NextObjectiveCodec()); | ||
| 112 | log.info("Started"); | 118 | log.info("Started"); |
| 113 | } | 119 | } |
| 114 | 120 | ... | ... |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 21 | +import org.onosproject.codec.CodecContext; | ||
| 22 | +import org.onosproject.codec.JsonCodec; | ||
| 23 | +import org.onosproject.core.ApplicationId; | ||
| 24 | +import org.onosproject.core.CoreService; | ||
| 25 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 26 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 27 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; | ||
| 28 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 29 | +import org.slf4j.Logger; | ||
| 30 | + | ||
| 31 | +import java.util.stream.IntStream; | ||
| 32 | + | ||
| 33 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 34 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
| 35 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * Filtering Objective Codec. | ||
| 39 | + */ | ||
| 40 | +public class FilteringObjectiveCodec extends JsonCodec<FilteringObjective> { | ||
| 41 | + private final Logger log = getLogger(getClass()); | ||
| 42 | + | ||
| 43 | + // JSON field names | ||
| 44 | + private static final String ID = "id"; | ||
| 45 | + private static final String TYPE = "type"; | ||
| 46 | + private static final String KEY = "key"; | ||
| 47 | + private static final String META = "meta"; | ||
| 48 | + private static final String OPERATION = "operation"; | ||
| 49 | + private static final String CONDITIONS = "conditions"; | ||
| 50 | + | ||
| 51 | + // messages to be printed out | ||
| 52 | + private static final String MISSING_MEMBER_MESSAGE = | ||
| 53 | + " member is required in FilteringObjective"; | ||
| 54 | + private static final String NOT_NULL_MESSAGE = | ||
| 55 | + "FilteringObjective cannot be null"; | ||
| 56 | + private static final String INVALID_TYPE_MESSAGE = | ||
| 57 | + "The requested type {} is not defined in FilteringObjective."; | ||
| 58 | + private static final String INVALID_OP_MESSAGE = | ||
| 59 | + "The requested operation {} is not defined for FilteringObjective."; | ||
| 60 | + | ||
| 61 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
| 62 | + | ||
| 63 | + @Override | ||
| 64 | + public ObjectNode encode(FilteringObjective filteringObjective, CodecContext context) { | ||
| 65 | + | ||
| 66 | + checkNotNull(filteringObjective, NOT_NULL_MESSAGE); | ||
| 67 | + | ||
| 68 | + final JsonCodec<Criterion> criterionCodec = context.codec(Criterion.class); | ||
| 69 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
| 70 | + | ||
| 71 | + // encode common properties | ||
| 72 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
| 73 | + ObjectNode result = och.encode(filteringObjective, context); | ||
| 74 | + | ||
| 75 | + // encode id | ||
| 76 | + result.put(ID, filteringObjective.id()); | ||
| 77 | + | ||
| 78 | + // encode type | ||
| 79 | + result.put(TYPE, filteringObjective.type().toString()); | ||
| 80 | + | ||
| 81 | + // encode key | ||
| 82 | + if (filteringObjective.key() != null) { | ||
| 83 | + ObjectNode criterionNode = criterionCodec.encode(filteringObjective.key(), context); | ||
| 84 | + result.set(KEY, criterionNode); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // encode meta | ||
| 88 | + if (filteringObjective.meta() != null) { | ||
| 89 | + ObjectNode trafficTreatmentNode = trafficTreatmentCodec.encode(filteringObjective.meta(), context); | ||
| 90 | + result.set(META, trafficTreatmentNode); | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + // encode conditions | ||
| 94 | + ArrayNode conditions = context.mapper().createArrayNode(); | ||
| 95 | + filteringObjective.conditions().forEach(c -> { | ||
| 96 | + ObjectNode criterionJson = criterionCodec.encode(c, context); | ||
| 97 | + conditions.add(criterionJson); | ||
| 98 | + }); | ||
| 99 | + result.set(CONDITIONS, conditions); | ||
| 100 | + | ||
| 101 | + return result; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + @Override | ||
| 105 | + public FilteringObjective decode(ObjectNode json, CodecContext context) { | ||
| 106 | + if (json == null || !json.isObject()) { | ||
| 107 | + return null; | ||
| 108 | + } | ||
| 109 | + | ||
| 110 | + CoreService coreService = context.getService(CoreService.class); | ||
| 111 | + | ||
| 112 | + final JsonCodec<Criterion> criterionCodec = context.codec(Criterion.class); | ||
| 113 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
| 114 | + | ||
| 115 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
| 116 | + | ||
| 117 | + DefaultFilteringObjective.Builder baseBuilder = DefaultFilteringObjective.builder(); | ||
| 118 | + final DefaultFilteringObjective.Builder builder = | ||
| 119 | + (DefaultFilteringObjective.Builder) och.decode(json, baseBuilder, context); | ||
| 120 | + | ||
| 121 | + // application id | ||
| 122 | + ApplicationId appId = coreService.registerApplication(REST_APP_ID); | ||
| 123 | + builder.fromApp(appId); | ||
| 124 | + | ||
| 125 | + // decode type | ||
| 126 | + String typeStr = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asText(); | ||
| 127 | + | ||
| 128 | + switch (typeStr) { | ||
| 129 | + case "PERMIT": | ||
| 130 | + builder.permit(); | ||
| 131 | + break; | ||
| 132 | + case "DENY": | ||
| 133 | + builder.deny(); | ||
| 134 | + break; | ||
| 135 | + default: | ||
| 136 | + log.warn(INVALID_TYPE_MESSAGE, typeStr); | ||
| 137 | + return null; | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | + // decode key | ||
| 141 | + JsonNode keyJson = json.get(KEY); | ||
| 142 | + if (keyJson != null) { | ||
| 143 | + Criterion key = criterionCodec.decode((ObjectNode) keyJson, context); | ||
| 144 | + builder.withKey(key); | ||
| 145 | + } | ||
| 146 | + | ||
| 147 | + // decode conditions | ||
| 148 | + JsonNode conditionsJson = json.get(CONDITIONS); | ||
| 149 | + checkNotNull(conditionsJson); | ||
| 150 | + if (conditionsJson != null) { | ||
| 151 | + IntStream.range(0, conditionsJson.size()).forEach(i -> { | ||
| 152 | + ObjectNode conditionJson = get(conditionsJson, i); | ||
| 153 | + builder.addCondition(criterionCodec.decode(conditionJson, context)); | ||
| 154 | + }); | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + // decode meta | ||
| 158 | + JsonNode metaJson = json.get(META); | ||
| 159 | + if (metaJson != null) { | ||
| 160 | + TrafficTreatment trafficTreatment = trafficTreatmentCodec.decode((ObjectNode) metaJson, context); | ||
| 161 | + builder.withMeta(trafficTreatment); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + // decode operation | ||
| 165 | + String opStr = nullIsIllegal(json.get(OPERATION), OPERATION + MISSING_MEMBER_MESSAGE).asText(); | ||
| 166 | + FilteringObjective filteringObjective; | ||
| 167 | + | ||
| 168 | + switch (opStr) { | ||
| 169 | + case "ADD": | ||
| 170 | + filteringObjective = builder.add(); | ||
| 171 | + break; | ||
| 172 | + case "REMOVE": | ||
| 173 | + filteringObjective = builder.remove(); | ||
| 174 | + break; | ||
| 175 | + default: | ||
| 176 | + log.warn(INVALID_OP_MESSAGE, opStr); | ||
| 177 | + return null; | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + return filteringObjective; | ||
| 181 | + } | ||
| 182 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | +import org.onosproject.codec.CodecContext; | ||
| 21 | +import org.onosproject.codec.JsonCodec; | ||
| 22 | +import org.onosproject.core.ApplicationId; | ||
| 23 | +import org.onosproject.core.CoreService; | ||
| 24 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 25 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 26 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
| 27 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 28 | +import org.slf4j.Logger; | ||
| 29 | + | ||
| 30 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 31 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
| 32 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 33 | + | ||
| 34 | +/** | ||
| 35 | + * Forwarding Objective Codec. | ||
| 36 | + */ | ||
| 37 | +public class ForwardingObjectiveCodec extends JsonCodec<ForwardingObjective> { | ||
| 38 | + private final Logger log = getLogger(getClass()); | ||
| 39 | + | ||
| 40 | + // JSON field names | ||
| 41 | + private static final String ID = "id"; | ||
| 42 | + private static final String SELECTOR = "selector"; | ||
| 43 | + private static final String FLAG = "flag"; | ||
| 44 | + private static final String OPERATION = "operation"; | ||
| 45 | + private static final String NEXT_ID = "nextId"; | ||
| 46 | + private static final String TREATMENT = "treatment"; | ||
| 47 | + | ||
| 48 | + // messages to be printed out | ||
| 49 | + private static final String MISSING_MEMBER_MESSAGE = | ||
| 50 | + " member is required in ForwardingObjective"; | ||
| 51 | + private static final String NOT_NULL_MESSAGE = | ||
| 52 | + "ForwardingObjective cannot be null"; | ||
| 53 | + private static final String INVALID_FLAG_MESSAGE = | ||
| 54 | + "The requested flag {} is not defined in ForwardingObjective."; | ||
| 55 | + private static final String INVALID_OP_MESSAGE = | ||
| 56 | + "The requested operation {} is not defined for FilteringObjective."; | ||
| 57 | + | ||
| 58 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
| 59 | + | ||
| 60 | + @Override | ||
| 61 | + public ObjectNode encode(ForwardingObjective forwardingObjective, CodecContext context) { | ||
| 62 | + | ||
| 63 | + checkNotNull(forwardingObjective, NOT_NULL_MESSAGE); | ||
| 64 | + | ||
| 65 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
| 66 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
| 67 | + | ||
| 68 | + // encode common properties | ||
| 69 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
| 70 | + ObjectNode result = och.encode(forwardingObjective, context); | ||
| 71 | + | ||
| 72 | + // encode id | ||
| 73 | + result.put(ID, forwardingObjective.id()); | ||
| 74 | + | ||
| 75 | + // encode flag | ||
| 76 | + result.put(FLAG, forwardingObjective.flag().toString()); | ||
| 77 | + | ||
| 78 | + // encode op | ||
| 79 | + result.put(OPERATION, forwardingObjective.op().toString()); | ||
| 80 | + | ||
| 81 | + // encode selector | ||
| 82 | + ObjectNode trafficSelectorNode = | ||
| 83 | + trafficSelectorCodec.encode(forwardingObjective.selector(), context); | ||
| 84 | + result.set(SELECTOR, trafficSelectorNode); | ||
| 85 | + | ||
| 86 | + // encode nextId | ||
| 87 | + if (forwardingObjective.nextId() != null) { | ||
| 88 | + result.put(NEXT_ID, forwardingObjective.nextId()); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + // encode treatment | ||
| 92 | + if (forwardingObjective.treatment() != null) { | ||
| 93 | + ObjectNode trafficTreatmentNode = | ||
| 94 | + trafficTreatmentCodec.encode(forwardingObjective.treatment(), context); | ||
| 95 | + result.set(TREATMENT, trafficTreatmentNode); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + return result; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @Override | ||
| 102 | + public ForwardingObjective decode(ObjectNode json, CodecContext context) { | ||
| 103 | + if (json == null || !json.isObject()) { | ||
| 104 | + return null; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + CoreService coreService = context.getService(CoreService.class); | ||
| 108 | + | ||
| 109 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
| 110 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
| 111 | + | ||
| 112 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
| 113 | + | ||
| 114 | + DefaultForwardingObjective.Builder baseBuilder = DefaultForwardingObjective.builder(); | ||
| 115 | + final DefaultForwardingObjective.Builder builder = | ||
| 116 | + (DefaultForwardingObjective.Builder) och.decode(json, baseBuilder, context); | ||
| 117 | + | ||
| 118 | + // application id | ||
| 119 | + ApplicationId appId = coreService.registerApplication(REST_APP_ID); | ||
| 120 | + builder.fromApp(appId); | ||
| 121 | + | ||
| 122 | + // decode flag | ||
| 123 | + String flagStr = nullIsIllegal(json.get(FLAG), FLAG + MISSING_MEMBER_MESSAGE).asText(); | ||
| 124 | + switch (flagStr) { | ||
| 125 | + case "SPECIFIC": | ||
| 126 | + builder.withFlag(ForwardingObjective.Flag.SPECIFIC); | ||
| 127 | + break; | ||
| 128 | + case "VERSATILE": | ||
| 129 | + builder.withFlag(ForwardingObjective.Flag.VERSATILE); | ||
| 130 | + break; | ||
| 131 | + default: | ||
| 132 | + log.warn(INVALID_FLAG_MESSAGE, flagStr); | ||
| 133 | + return null; | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + // decode selector | ||
| 137 | + JsonNode selectorJson = json.get(SELECTOR); | ||
| 138 | + if (selectorJson != null) { | ||
| 139 | + TrafficSelector trafficSelector = trafficSelectorCodec.decode((ObjectNode) selectorJson, context); | ||
| 140 | + builder.withSelector(trafficSelector); | ||
| 141 | + } | ||
| 142 | + | ||
| 143 | + // decode treatment | ||
| 144 | + JsonNode treatmentJson = json.get(TREATMENT); | ||
| 145 | + if (treatmentJson != null) { | ||
| 146 | + TrafficTreatment trafficTreatment = trafficTreatmentCodec.decode((ObjectNode) treatmentJson, context); | ||
| 147 | + builder.withTreatment(trafficTreatment); | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + // decode nextId | ||
| 151 | + JsonNode nextIdJson = json.get(NEXT_ID); | ||
| 152 | + if (nextIdJson != null) { | ||
| 153 | + builder.nextStep(nextIdJson.asInt()); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + // decode operation | ||
| 157 | + String opStr = nullIsIllegal(json.get(OPERATION), OPERATION + MISSING_MEMBER_MESSAGE).asText(); | ||
| 158 | + ForwardingObjective forwardingObjective; | ||
| 159 | + | ||
| 160 | + switch (opStr) { | ||
| 161 | + case "ADD": | ||
| 162 | + forwardingObjective = builder.add(); | ||
| 163 | + break; | ||
| 164 | + case "REMOVE": | ||
| 165 | + forwardingObjective = builder.remove(); | ||
| 166 | + break; | ||
| 167 | + default: | ||
| 168 | + log.warn(INVALID_OP_MESSAGE, opStr); | ||
| 169 | + return null; | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + return forwardingObjective; | ||
| 173 | + } | ||
| 174 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 20 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 21 | +import org.onosproject.codec.CodecContext; | ||
| 22 | +import org.onosproject.codec.JsonCodec; | ||
| 23 | +import org.onosproject.core.ApplicationId; | ||
| 24 | +import org.onosproject.core.CoreService; | ||
| 25 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 26 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 27 | +import org.onosproject.net.flowobjective.DefaultNextObjective; | ||
| 28 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 29 | +import org.slf4j.Logger; | ||
| 30 | + | ||
| 31 | +import java.util.stream.IntStream; | ||
| 32 | + | ||
| 33 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 34 | +import static org.onlab.util.Tools.nullIsIllegal; | ||
| 35 | +import static org.slf4j.LoggerFactory.getLogger; | ||
| 36 | + | ||
| 37 | +/** | ||
| 38 | + * Next Objective Codec. | ||
| 39 | + */ | ||
| 40 | +public class NextObjectiveCodec extends JsonCodec<NextObjective> { | ||
| 41 | + | ||
| 42 | + private final Logger log = getLogger(getClass()); | ||
| 43 | + | ||
| 44 | + // JSON field names | ||
| 45 | + private static final String ID = "id"; | ||
| 46 | + private static final String TYPE = "type"; | ||
| 47 | + private static final String OPERATION = "operation"; | ||
| 48 | + private static final String TREATMENTS = "treatments"; | ||
| 49 | + private static final String META = "meta"; | ||
| 50 | + | ||
| 51 | + // messages to be printed out | ||
| 52 | + private static final String MISSING_MEMBER_MESSAGE = | ||
| 53 | + " member is required in NextObjective"; | ||
| 54 | + private static final String NOT_NULL_MESSAGE = | ||
| 55 | + "NextObjective cannot be null"; | ||
| 56 | + private static final String INVALID_TYPE_MESSAGE = | ||
| 57 | + "The requested flag {} is not defined in NextObjective."; | ||
| 58 | + private static final String INVALID_OP_MESSAGE = | ||
| 59 | + "The requested operation {} is not defined for NextObjective."; | ||
| 60 | + | ||
| 61 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
| 62 | + | ||
| 63 | + @Override | ||
| 64 | + public ObjectNode encode(NextObjective nextObjective, CodecContext context) { | ||
| 65 | + | ||
| 66 | + checkNotNull(nextObjective, NOT_NULL_MESSAGE); | ||
| 67 | + | ||
| 68 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
| 69 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
| 70 | + | ||
| 71 | + // encode common properties | ||
| 72 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
| 73 | + ObjectNode result = och.encode(nextObjective, context); | ||
| 74 | + | ||
| 75 | + // encode id | ||
| 76 | + result.put(ID, nextObjective.id()); | ||
| 77 | + | ||
| 78 | + // encode type | ||
| 79 | + result.put(TYPE, nextObjective.type().toString()); | ||
| 80 | + | ||
| 81 | + // encode operation | ||
| 82 | + result.put(OPERATION, nextObjective.op().toString()); | ||
| 83 | + | ||
| 84 | + // encode treatments | ||
| 85 | + ArrayNode treatments = context.mapper().createArrayNode(); | ||
| 86 | + nextObjective.next().forEach(t -> { | ||
| 87 | + ObjectNode treatmentJson = trafficTreatmentCodec.encode(t, context); | ||
| 88 | + treatments.add(treatmentJson); | ||
| 89 | + }); | ||
| 90 | + result.set(TREATMENTS, treatments); | ||
| 91 | + | ||
| 92 | + // encode meta | ||
| 93 | + if (nextObjective.meta() != null) { | ||
| 94 | + ObjectNode trafficSelectorNode = trafficSelectorCodec.encode(nextObjective.meta(), context); | ||
| 95 | + result.set(META, trafficSelectorNode); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + return result; | ||
| 99 | + } | ||
| 100 | + | ||
| 101 | + @Override | ||
| 102 | + public NextObjective decode(ObjectNode json, CodecContext context) { | ||
| 103 | + if (json == null || !json.isObject()) { | ||
| 104 | + return null; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + CoreService coreService = context.getService(CoreService.class); | ||
| 108 | + | ||
| 109 | + final JsonCodec<TrafficSelector> trafficSelectorCodec = context.codec(TrafficSelector.class); | ||
| 110 | + final JsonCodec<TrafficTreatment> trafficTreatmentCodec = context.codec(TrafficTreatment.class); | ||
| 111 | + | ||
| 112 | + ObjectiveCodecHelper och = new ObjectiveCodecHelper(); | ||
| 113 | + | ||
| 114 | + DefaultNextObjective.Builder baseBuilder = DefaultNextObjective.builder(); | ||
| 115 | + final DefaultNextObjective.Builder builder = | ||
| 116 | + (DefaultNextObjective.Builder) och.decode(json, baseBuilder, context); | ||
| 117 | + | ||
| 118 | + // decode id | ||
| 119 | + JsonNode idJson = json.get(ID); | ||
| 120 | + checkNotNull(idJson); | ||
| 121 | + builder.withId(idJson.asInt()); | ||
| 122 | + | ||
| 123 | + // decode application id | ||
| 124 | + ApplicationId appId = coreService.registerApplication(REST_APP_ID); | ||
| 125 | + builder.fromApp(appId); | ||
| 126 | + | ||
| 127 | + // decode type | ||
| 128 | + String typeStr = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asText(); | ||
| 129 | + | ||
| 130 | + switch (typeStr) { | ||
| 131 | + case "HASHED": | ||
| 132 | + builder.withType(NextObjective.Type.HASHED); | ||
| 133 | + break; | ||
| 134 | + case "BROADCAST": | ||
| 135 | + builder.withType(NextObjective.Type.BROADCAST); | ||
| 136 | + break; | ||
| 137 | + case "FAILOVER": | ||
| 138 | + builder.withType(NextObjective.Type.FAILOVER); | ||
| 139 | + break; | ||
| 140 | + case "SIMPLE": | ||
| 141 | + builder.withType(NextObjective.Type.SIMPLE); | ||
| 142 | + break; | ||
| 143 | + default: | ||
| 144 | + log.warn(INVALID_TYPE_MESSAGE, typeStr); | ||
| 145 | + return null; | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + // decode treatments | ||
| 149 | + JsonNode treatmentsJson = json.get(TREATMENTS); | ||
| 150 | + checkNotNull(treatmentsJson); | ||
| 151 | + if (treatmentsJson != null) { | ||
| 152 | + IntStream.range(0, treatmentsJson.size()).forEach(i -> { | ||
| 153 | + ObjectNode treatmentJson = get(treatmentsJson, i); | ||
| 154 | + builder.addTreatment(trafficTreatmentCodec.decode(treatmentJson, context)); | ||
| 155 | + }); | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + // decode meta | ||
| 159 | + JsonNode metaJson = json.get(META); | ||
| 160 | + if (metaJson != null) { | ||
| 161 | + TrafficSelector trafficSelector = trafficSelectorCodec.decode((ObjectNode) metaJson, context); | ||
| 162 | + builder.withMeta(trafficSelector); | ||
| 163 | + } | ||
| 164 | + | ||
| 165 | + // decode operation | ||
| 166 | + String opStr = nullIsIllegal(json.get(OPERATION), OPERATION + MISSING_MEMBER_MESSAGE).asText(); | ||
| 167 | + NextObjective nextObjective; | ||
| 168 | + | ||
| 169 | + switch (opStr) { | ||
| 170 | + case "ADD": | ||
| 171 | + nextObjective = builder.add(); | ||
| 172 | + break; | ||
| 173 | + case "REMOVE": | ||
| 174 | + nextObjective = builder.remove(); | ||
| 175 | + break; | ||
| 176 | + default: | ||
| 177 | + log.warn(INVALID_OP_MESSAGE, opStr); | ||
| 178 | + return null; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + return nextObjective; | ||
| 182 | + } | ||
| 183 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 19 | +import org.onosproject.codec.CodecContext; | ||
| 20 | +import org.onosproject.net.flowobjective.Objective; | ||
| 21 | + | ||
| 22 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * Objective Codec Helper. | ||
| 26 | + */ | ||
| 27 | +public class ObjectiveCodecHelper { | ||
| 28 | + | ||
| 29 | + // JSON field names | ||
| 30 | + private static final String ID = "id"; | ||
| 31 | + private static final String APP_ID = "appId"; | ||
| 32 | + private static final String OPERATION = "operation"; | ||
| 33 | + private static final String PERMANENT = "isPermanent"; | ||
| 34 | + private static final String PRIORITY = "priority"; | ||
| 35 | + private static final String TIMEOUT = "timeout"; | ||
| 36 | + public static final String REST_APP_ID = "org.onosproject.rest"; | ||
| 37 | + | ||
| 38 | + public ObjectNode encode(Objective objective, CodecContext context) { | ||
| 39 | + checkNotNull(objective, "Objective cannot be null"); | ||
| 40 | + | ||
| 41 | + ObjectNode result = context.mapper().createObjectNode() | ||
| 42 | + .put(ID, objective.id()) | ||
| 43 | + .put(OPERATION, objective.op().toString()) | ||
| 44 | + .put(PERMANENT, String.valueOf(objective.permanent())) | ||
| 45 | + .put(PRIORITY, objective.priority()) | ||
| 46 | + .put(TIMEOUT, objective.timeout()); | ||
| 47 | + | ||
| 48 | + if (objective.appId() != null) { | ||
| 49 | + result.put(APP_ID, objective.appId().toString()); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + return result; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + public Objective.Builder decode(ObjectNode json, Objective.Builder builder, CodecContext context) { | ||
| 56 | + if (json == null || !json.isObject()) { | ||
| 57 | + return null; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + // permanent | ||
| 61 | + boolean permanent = false; | ||
| 62 | + if (json.get(PERMANENT) != null) { | ||
| 63 | + permanent = json.get(PERMANENT).asBoolean(); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + // timeout | ||
| 67 | + int timeoutInt = 0; | ||
| 68 | + if (json.get(TIMEOUT) != null) { | ||
| 69 | + timeoutInt = json.get(TIMEOUT).asInt(); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + // priority | ||
| 73 | + int priorityInt = 0; | ||
| 74 | + if (json.get(PRIORITY) != null) { | ||
| 75 | + priorityInt = json.get(PRIORITY).asInt(); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + if (permanent) { | ||
| 79 | + builder.makePermanent() | ||
| 80 | + .makeTemporary(timeoutInt) | ||
| 81 | + .withPriority(priorityInt); | ||
| 82 | + } else { | ||
| 83 | + builder.makeTemporary(timeoutInt) | ||
| 84 | + .withPriority(priorityInt); | ||
| 85 | + } | ||
| 86 | + return builder; | ||
| 87 | + } | ||
| 88 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | +import org.junit.Before; | ||
| 21 | +import org.junit.Test; | ||
| 22 | +import org.onlab.packet.VlanId; | ||
| 23 | +import org.onosproject.codec.JsonCodec; | ||
| 24 | +import org.onosproject.core.CoreService; | ||
| 25 | +import org.onosproject.net.flow.criteria.Criteria; | ||
| 26 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 27 | +import org.onosproject.net.flowobjective.DefaultFilteringObjective; | ||
| 28 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 29 | + | ||
| 30 | +import java.io.IOException; | ||
| 31 | +import java.io.InputStream; | ||
| 32 | + | ||
| 33 | +import static org.easymock.EasyMock.createMock; | ||
| 34 | +import static org.easymock.EasyMock.expect; | ||
| 35 | +import static org.easymock.EasyMock.replay; | ||
| 36 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 37 | +import static org.hamcrest.Matchers.is; | ||
| 38 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 39 | +import static org.onosproject.codec.impl.FilteringObjectiveJsonMatcher.matchesFilteringObjective; | ||
| 40 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
| 41 | + | ||
| 42 | +/** | ||
| 43 | + * Unit tests for FilteringObjective Codec. | ||
| 44 | + */ | ||
| 45 | +public class FilteringObjectiveCodecTest { | ||
| 46 | + | ||
| 47 | + MockCodecContext context; | ||
| 48 | + JsonCodec<FilteringObjective> filteringObjectiveCodec; | ||
| 49 | + final CoreService mockCoreService = createMock(CoreService.class); | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * Sets up for each test. | ||
| 53 | + * Creates a context and fetches the FilteringObjective codec. | ||
| 54 | + */ | ||
| 55 | + @Before | ||
| 56 | + public void setUp() { | ||
| 57 | + context = new MockCodecContext(); | ||
| 58 | + filteringObjectiveCodec = context.codec(FilteringObjective.class); | ||
| 59 | + assertThat(filteringObjectiveCodec, notNullValue()); | ||
| 60 | + | ||
| 61 | + expect(mockCoreService.registerApplication(FilteringObjectiveCodec.REST_APP_ID)) | ||
| 62 | + .andReturn(APP_ID).anyTimes(); | ||
| 63 | + replay(mockCoreService); | ||
| 64 | + context.registerService(CoreService.class, mockCoreService); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * Tests encoding of a FilteringObjective object. | ||
| 69 | + */ | ||
| 70 | + @Test | ||
| 71 | + public void testFilteringObjectiveEncode() { | ||
| 72 | + | ||
| 73 | + Criterion condition1 = Criteria.matchVlanId(VlanId.ANY); | ||
| 74 | + Criterion condition2 = Criteria.matchEthType((short) 0x8844); | ||
| 75 | + | ||
| 76 | + FilteringObjective filteringObj = DefaultFilteringObjective.builder() | ||
| 77 | + .makePermanent() | ||
| 78 | + .permit() | ||
| 79 | + .fromApp(APP_ID) | ||
| 80 | + .withPriority(60) | ||
| 81 | + .addCondition(condition1) | ||
| 82 | + .addCondition(condition2) | ||
| 83 | + .add(); | ||
| 84 | + | ||
| 85 | + // TODO: need to add test case for TrafficTreatment (META in filteringObj) | ||
| 86 | + | ||
| 87 | + ObjectNode filteringObjJson = filteringObjectiveCodec.encode(filteringObj, context); | ||
| 88 | + assertThat(filteringObjJson, matchesFilteringObjective(filteringObj)); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * Test decoding of a FilteringObjective object. | ||
| 93 | + */ | ||
| 94 | + @Test | ||
| 95 | + public void testFilteringObjectiveDecode() throws IOException { | ||
| 96 | + FilteringObjective filteringObjective = getFilteringObjective("FilteringObjective.json"); | ||
| 97 | + | ||
| 98 | + assertThat(filteringObjective.type(), is(FilteringObjective.Type.PERMIT)); | ||
| 99 | + assertThat(filteringObjective.priority(), is(60)); | ||
| 100 | + assertThat(filteringObjective.timeout(), is(1)); | ||
| 101 | + assertThat(filteringObjective.op(), is(FilteringObjective.Operation.ADD)); | ||
| 102 | + assertThat(filteringObjective.permanent(), is(false)); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + /** | ||
| 106 | + * Reads in a filteringObjective from the given resource and decodes it. | ||
| 107 | + * | ||
| 108 | + * @param resourceName resource to use to read the JSON for the rule | ||
| 109 | + * @return decoded filteringObjective | ||
| 110 | + * @throws IOException if processing the resource fails | ||
| 111 | + */ | ||
| 112 | + private FilteringObjective getFilteringObjective(String resourceName) throws IOException { | ||
| 113 | + InputStream jsonStream = FilteringObjectiveCodecTest.class.getResourceAsStream(resourceName); | ||
| 114 | + JsonNode json = context.mapper().readTree(jsonStream); | ||
| 115 | + assertThat(json, notNullValue()); | ||
| 116 | + FilteringObjective filteringObjective = filteringObjectiveCodec.decode((ObjectNode) json, context); | ||
| 117 | + assertThat(filteringObjective, notNullValue()); | ||
| 118 | + return filteringObjective; | ||
| 119 | + } | ||
| 120 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import org.hamcrest.Description; | ||
| 20 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
| 21 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 22 | +import org.onosproject.net.flowobjective.FilteringObjective; | ||
| 23 | + | ||
| 24 | +/** | ||
| 25 | + * Hamcrest matcher for filteringObjective. | ||
| 26 | + */ | ||
| 27 | +public final class FilteringObjectiveJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
| 28 | + | ||
| 29 | + final FilteringObjective filteringObj; | ||
| 30 | + | ||
| 31 | + private FilteringObjectiveJsonMatcher(FilteringObjective filteringObjective) { | ||
| 32 | + this.filteringObj = filteringObjective; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + protected boolean matchesSafely(JsonNode jsonFilteringObj, Description description) { | ||
| 37 | + | ||
| 38 | + ObjectiveJsonMatcher.matchesObjective(filteringObj).matchesSafely(jsonFilteringObj); | ||
| 39 | + | ||
| 40 | + // check id | ||
| 41 | + int jsonId = jsonFilteringObj.get("id").asInt(); | ||
| 42 | + int id = filteringObj.id(); | ||
| 43 | + if (jsonId != id) { | ||
| 44 | + description.appendText("id was " + jsonId); | ||
| 45 | + return false; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + // check type | ||
| 49 | + String jsonType = jsonFilteringObj.get("type").asText(); | ||
| 50 | + String type = filteringObj.type().toString(); | ||
| 51 | + if (!jsonType.equals(type)) { | ||
| 52 | + description.appendText("type was " + jsonType); | ||
| 53 | + return false; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + // check size of condition array | ||
| 57 | + JsonNode jsonConditions = jsonFilteringObj.get("conditions"); | ||
| 58 | + if (jsonConditions.size() != filteringObj.conditions().size()) { | ||
| 59 | + description.appendText("conditions size was " + jsonConditions.size()); | ||
| 60 | + return false; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + // check conditions | ||
| 64 | + for (Criterion c : filteringObj.conditions()) { | ||
| 65 | + boolean conditionFound = false; | ||
| 66 | + for (int cIndex = 0; cIndex < jsonConditions.size(); cIndex++) { | ||
| 67 | + CriterionJsonMatcher criterionMatcher = CriterionJsonMatcher.matchesCriterion(c); | ||
| 68 | + if (criterionMatcher.matches(jsonConditions.get(cIndex))) { | ||
| 69 | + conditionFound = true; | ||
| 70 | + break; | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + if (!conditionFound) { | ||
| 74 | + description.appendText("condition not found " + c.toString()); | ||
| 75 | + return false; | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + return true; | ||
| 80 | + } | ||
| 81 | + | ||
| 82 | + @Override | ||
| 83 | + public void describeTo(Description description) { | ||
| 84 | + description.appendText(filteringObj.toString()); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + /** | ||
| 88 | + * Factory to allocate a filteringObjective matcher. | ||
| 89 | + * | ||
| 90 | + * @param filteringObj filteringObjective object we are looking for | ||
| 91 | + * @return matcher | ||
| 92 | + */ | ||
| 93 | + public static FilteringObjectiveJsonMatcher matchesFilteringObjective(FilteringObjective filteringObj) { | ||
| 94 | + return new FilteringObjectiveJsonMatcher(filteringObj); | ||
| 95 | + } | ||
| 96 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | +import org.junit.Before; | ||
| 21 | +import org.junit.Test; | ||
| 22 | +import org.onlab.packet.VlanId; | ||
| 23 | +import org.onosproject.codec.JsonCodec; | ||
| 24 | +import org.onosproject.core.CoreService; | ||
| 25 | +import org.onosproject.net.flow.DefaultTrafficSelector; | ||
| 26 | +import org.onosproject.net.flow.TrafficSelector; | ||
| 27 | +import org.onosproject.net.flow.criteria.Criteria; | ||
| 28 | +import org.onosproject.net.flow.criteria.Criterion; | ||
| 29 | +import org.onosproject.net.flowobjective.DefaultForwardingObjective; | ||
| 30 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 31 | + | ||
| 32 | +import java.io.IOException; | ||
| 33 | +import java.io.InputStream; | ||
| 34 | + | ||
| 35 | +import static org.easymock.EasyMock.createMock; | ||
| 36 | +import static org.easymock.EasyMock.expect; | ||
| 37 | +import static org.easymock.EasyMock.replay; | ||
| 38 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 39 | +import static org.hamcrest.Matchers.is; | ||
| 40 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 41 | +import static org.onosproject.codec.impl.ForwardingObjectiveJsonMatcher.matchesForwardingObjective; | ||
| 42 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
| 43 | + | ||
| 44 | +/** | ||
| 45 | + * Unit tests for ForwardingObjective Codec. | ||
| 46 | + */ | ||
| 47 | +public class ForwardingObjectiveCodecTest { | ||
| 48 | + | ||
| 49 | + MockCodecContext context; | ||
| 50 | + JsonCodec<ForwardingObjective> forwardingObjectiveCodec; | ||
| 51 | + final CoreService mockCoreService = createMock(CoreService.class); | ||
| 52 | + | ||
| 53 | + /** | ||
| 54 | + * Sets up for each test. | ||
| 55 | + * Creates a context and fetches the ForwardingObjective codec. | ||
| 56 | + */ | ||
| 57 | + @Before | ||
| 58 | + public void setUp() { | ||
| 59 | + context = new MockCodecContext(); | ||
| 60 | + forwardingObjectiveCodec = context.codec(ForwardingObjective.class); | ||
| 61 | + assertThat(forwardingObjectiveCodec, notNullValue()); | ||
| 62 | + | ||
| 63 | + expect(mockCoreService.registerApplication(ForwardingObjectiveCodec.REST_APP_ID)) | ||
| 64 | + .andReturn(APP_ID).anyTimes(); | ||
| 65 | + replay(mockCoreService); | ||
| 66 | + context.registerService(CoreService.class, mockCoreService); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + /** | ||
| 70 | + * Tests encoding of a ForwardingObjective object. | ||
| 71 | + */ | ||
| 72 | + @Test | ||
| 73 | + public void testForwardingObjectiveEncode() { | ||
| 74 | + | ||
| 75 | + Criterion criterion1 = Criteria.matchVlanId(VlanId.ANY); | ||
| 76 | + Criterion criterion2 = Criteria.matchEthType((short) 0x8844); | ||
| 77 | + TrafficSelector selector = DefaultTrafficSelector.builder() | ||
| 78 | + .add(criterion1) | ||
| 79 | + .add(criterion2) | ||
| 80 | + .build(); | ||
| 81 | + | ||
| 82 | + ForwardingObjective forwardingObj = DefaultForwardingObjective.builder() | ||
| 83 | + .makePermanent() | ||
| 84 | + .fromApp(APP_ID) | ||
| 85 | + .withPriority(60) | ||
| 86 | + .withFlag(ForwardingObjective.Flag.SPECIFIC) | ||
| 87 | + .nextStep(1) | ||
| 88 | + .withSelector(selector) | ||
| 89 | + .add(); | ||
| 90 | + | ||
| 91 | + ObjectNode forwardingObjJson = forwardingObjectiveCodec.encode(forwardingObj, context); | ||
| 92 | + assertThat(forwardingObjJson, matchesForwardingObjective(forwardingObj)); | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + /** | ||
| 96 | + * Test decoding of a ForwardingObjective object. | ||
| 97 | + */ | ||
| 98 | + @Test | ||
| 99 | + public void testForwardingObjectiveDecode() throws IOException { | ||
| 100 | + ForwardingObjective forwardingObjective = getForwardingObjective("ForwardingObjective.json"); | ||
| 101 | + | ||
| 102 | + assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC)); | ||
| 103 | + assertThat(forwardingObjective.priority(), is(60)); | ||
| 104 | + assertThat(forwardingObjective.timeout(), is(1)); | ||
| 105 | + assertThat(forwardingObjective.op(), is(ForwardingObjective.Operation.ADD)); | ||
| 106 | + assertThat(forwardingObjective.permanent(), is(false)); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * Reads in a forwardingObjectiveJsonCodec from the given resource and decodes it. | ||
| 111 | + * | ||
| 112 | + * @param resourceName resource to use to read the JSON for the rule | ||
| 113 | + * @return decoded forwardingObjectiveJsonCodec | ||
| 114 | + * @throws IOException if processing the resource fails | ||
| 115 | + */ | ||
| 116 | + private ForwardingObjective getForwardingObjective(String resourceName) throws IOException { | ||
| 117 | + InputStream jsonStream = ForwardingObjectiveCodecTest.class.getResourceAsStream(resourceName); | ||
| 118 | + JsonNode json = context.mapper().readTree(jsonStream); | ||
| 119 | + assertThat(json, notNullValue()); | ||
| 120 | + ForwardingObjective forwardingObjective = forwardingObjectiveCodec.decode((ObjectNode) json, context); | ||
| 121 | + assertThat(forwardingObjective, notNullValue()); | ||
| 122 | + return forwardingObjective; | ||
| 123 | + } | ||
| 124 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import org.hamcrest.Description; | ||
| 20 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
| 21 | +import org.onosproject.net.flowobjective.ForwardingObjective; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Hamcrest matcher for forwardingObjective. | ||
| 25 | + */ | ||
| 26 | +public final class ForwardingObjectiveJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
| 27 | + | ||
| 28 | + final ForwardingObjective forwardingObjective; | ||
| 29 | + | ||
| 30 | + private ForwardingObjectiveJsonMatcher(ForwardingObjective forwardingObjective) { | ||
| 31 | + this.forwardingObjective = forwardingObjective; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + protected boolean matchesSafely(JsonNode jsonForwardingObj, Description description) { | ||
| 36 | + | ||
| 37 | + ObjectiveJsonMatcher.matchesObjective(forwardingObjective).matchesSafely(jsonForwardingObj); | ||
| 38 | + | ||
| 39 | + // check id | ||
| 40 | + int jsonId = jsonForwardingObj.get("id").asInt(); | ||
| 41 | + int id = forwardingObjective.id(); | ||
| 42 | + if (jsonId != id) { | ||
| 43 | + description.appendText("id was " + jsonId); | ||
| 44 | + return false; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + // check nextId | ||
| 48 | + int jsonNextId = jsonForwardingObj.get("nextId").asInt(); | ||
| 49 | + int nextId = forwardingObjective.nextId(); | ||
| 50 | + if (jsonNextId != nextId) { | ||
| 51 | + description.appendText("nextId was " + jsonNextId); | ||
| 52 | + return false; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + // check flag | ||
| 56 | + String jsonFlag = jsonForwardingObj.get("flag").asText(); | ||
| 57 | + String flag = forwardingObjective.flag().toString(); | ||
| 58 | + if (!jsonFlag.equals(flag)) { | ||
| 59 | + description.appendText("flag was " + jsonFlag); | ||
| 60 | + return false; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + return true; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + @Override | ||
| 67 | + public void describeTo(Description description) { | ||
| 68 | + description.appendText(forwardingObjective.toString()); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * Factory to allocate a forwardingObjective matcher. | ||
| 73 | + * | ||
| 74 | + * @param forwardingObjective forwardingObjective object we are looking for | ||
| 75 | + * @return matcher | ||
| 76 | + */ | ||
| 77 | + public static ForwardingObjectiveJsonMatcher matchesForwardingObjective(ForwardingObjective forwardingObjective) { | ||
| 78 | + return new ForwardingObjectiveJsonMatcher(forwardingObjective); | ||
| 79 | + } | ||
| 80 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 20 | +import org.junit.Before; | ||
| 21 | +import org.junit.Test; | ||
| 22 | +import org.onosproject.codec.JsonCodec; | ||
| 23 | +import org.onosproject.core.CoreService; | ||
| 24 | +import org.onosproject.net.flow.DefaultTrafficTreatment; | ||
| 25 | +import org.onosproject.net.flow.TrafficTreatment; | ||
| 26 | +import org.onosproject.net.flowobjective.DefaultNextObjective; | ||
| 27 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 28 | + | ||
| 29 | +import java.io.IOException; | ||
| 30 | +import java.io.InputStream; | ||
| 31 | + | ||
| 32 | +import static org.easymock.EasyMock.createMock; | ||
| 33 | +import static org.easymock.EasyMock.expect; | ||
| 34 | +import static org.easymock.EasyMock.replay; | ||
| 35 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
| 36 | +import static org.hamcrest.Matchers.is; | ||
| 37 | +import static org.hamcrest.Matchers.notNullValue; | ||
| 38 | +import static org.onosproject.codec.impl.NextObjectiveJsonMatcher.matchesNextObjective; | ||
| 39 | +import static org.onosproject.net.NetTestTools.APP_ID; | ||
| 40 | + | ||
| 41 | +/** | ||
| 42 | + * Unit tests for NextObjective Codec. | ||
| 43 | + */ | ||
| 44 | +public class NextObjectiveCodecTest { | ||
| 45 | + | ||
| 46 | + MockCodecContext context; | ||
| 47 | + JsonCodec<NextObjective> nextObjectiveCodec; | ||
| 48 | + final CoreService mockCoreService = createMock(CoreService.class); | ||
| 49 | + | ||
| 50 | + /** | ||
| 51 | + * Sets up for each test. | ||
| 52 | + * Creates a context and fetches the NextObjective codec. | ||
| 53 | + */ | ||
| 54 | + @Before | ||
| 55 | + public void setUp() { | ||
| 56 | + context = new MockCodecContext(); | ||
| 57 | + nextObjectiveCodec = context.codec(NextObjective.class); | ||
| 58 | + assertThat(nextObjectiveCodec, notNullValue()); | ||
| 59 | + | ||
| 60 | + expect(mockCoreService.registerApplication(NextObjectiveCodec.REST_APP_ID)) | ||
| 61 | + .andReturn(APP_ID).anyTimes(); | ||
| 62 | + replay(mockCoreService); | ||
| 63 | + context.registerService(CoreService.class, mockCoreService); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * Tests encoding of a NextObjective object. | ||
| 68 | + */ | ||
| 69 | + @Test | ||
| 70 | + public void testNextObjectiveEncode() { | ||
| 71 | + | ||
| 72 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); | ||
| 73 | + | ||
| 74 | + NextObjective nextObj = DefaultNextObjective.builder() | ||
| 75 | + .makePermanent() | ||
| 76 | + .withType(NextObjective.Type.HASHED) | ||
| 77 | + .fromApp(APP_ID) | ||
| 78 | + .withPriority(60) | ||
| 79 | + .withId(5) | ||
| 80 | + .addTreatment(treatment) | ||
| 81 | + .add(); | ||
| 82 | + | ||
| 83 | + ObjectNode nextObjJson = nextObjectiveCodec.encode(nextObj, context); | ||
| 84 | + assertThat(nextObjJson, matchesNextObjective(nextObj)); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + /** | ||
| 88 | + * Test decoding of a NextObjective object. | ||
| 89 | + */ | ||
| 90 | + @Test | ||
| 91 | + public void testNextObjectiveDecode() throws IOException { | ||
| 92 | + NextObjective nextObjective = getNextObjective("NextObjective.json"); | ||
| 93 | + | ||
| 94 | + assertThat(nextObjective.type(), is(NextObjective.Type.FAILOVER)); | ||
| 95 | + assertThat(nextObjective.op(), is(NextObjective.Operation.ADD)); | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + /** | ||
| 99 | + * Reads in a nextObjective from the given resource and decodes it. | ||
| 100 | + * | ||
| 101 | + * @param resourceName resource to use to read the JSON for the rule | ||
| 102 | + * @return decoded nextObjective | ||
| 103 | + * @throws IOException if processing the resource fails | ||
| 104 | + */ | ||
| 105 | + private NextObjective getNextObjective(String resourceName) throws IOException { | ||
| 106 | + InputStream jsonStream = NextObjectiveCodecTest.class.getResourceAsStream(resourceName); | ||
| 107 | + JsonNode json = context.mapper().readTree(jsonStream); | ||
| 108 | + assertThat(json, notNullValue()); | ||
| 109 | + NextObjective nextObjective = nextObjectiveCodec.decode((ObjectNode) json, context); | ||
| 110 | + assertThat(nextObjective, notNullValue()); | ||
| 111 | + return nextObjective; | ||
| 112 | + } | ||
| 113 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import org.hamcrest.Description; | ||
| 20 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
| 21 | +import org.onosproject.net.flowobjective.NextObjective; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * Hamcrest matcher for nextObjective. | ||
| 25 | + */ | ||
| 26 | +public final class NextObjectiveJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
| 27 | + | ||
| 28 | + final NextObjective nextObjective; | ||
| 29 | + | ||
| 30 | + private NextObjectiveJsonMatcher(NextObjective nextObjective) { | ||
| 31 | + this.nextObjective = nextObjective; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + @Override | ||
| 35 | + protected boolean matchesSafely(JsonNode jsonNextObj, Description description) { | ||
| 36 | + ObjectiveJsonMatcher.matchesObjective(nextObjective).matchesSafely(jsonNextObj); | ||
| 37 | + | ||
| 38 | + // check id | ||
| 39 | + int jsonId = jsonNextObj.get("id").asInt(); | ||
| 40 | + int id = nextObjective.id(); | ||
| 41 | + if (jsonId != id) { | ||
| 42 | + description.appendText("id was " + jsonId); | ||
| 43 | + return false; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + // check type | ||
| 47 | + String jsonType = jsonNextObj.get("type").asText(); | ||
| 48 | + String type = nextObjective.type().toString(); | ||
| 49 | + if (!jsonType.equals(type)) { | ||
| 50 | + description.appendText("type was " + jsonType); | ||
| 51 | + return false; | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + // check size of treatment array | ||
| 55 | + JsonNode jsonTreatments = jsonNextObj.get("treatments"); | ||
| 56 | + if (jsonTreatments.size() != nextObjective.next().size()) { | ||
| 57 | + description.appendText("treatments size was " + jsonTreatments.size()); | ||
| 58 | + return false; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + // TODO: need to check the content of treatment collection | ||
| 62 | + | ||
| 63 | + // TODO: need to check the content of selector instance | ||
| 64 | + | ||
| 65 | + return true; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + @Override | ||
| 69 | + public void describeTo(Description description) { | ||
| 70 | + description.appendText(nextObjective.toString()); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * Factory to allocate a nextObjective matcher. | ||
| 75 | + * | ||
| 76 | + * @param nextObjective nextObjective object we are looking for | ||
| 77 | + * @return matcher | ||
| 78 | + */ | ||
| 79 | + public static NextObjectiveJsonMatcher matchesNextObjective(NextObjective nextObjective) { | ||
| 80 | + return new NextObjectiveJsonMatcher(nextObjective); | ||
| 81 | + } | ||
| 82 | +} |
| 1 | +/* | ||
| 2 | + * Copyright 2016 Open Networking Laboratory | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | +package org.onosproject.codec.impl; | ||
| 17 | + | ||
| 18 | +import com.fasterxml.jackson.databind.JsonNode; | ||
| 19 | +import org.onosproject.net.flowobjective.Objective; | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * Hamcrest matcher for instructions. | ||
| 23 | + */ | ||
| 24 | +public final class ObjectiveJsonMatcher { | ||
| 25 | + | ||
| 26 | + final Objective objective; | ||
| 27 | + | ||
| 28 | + private ObjectiveJsonMatcher(Objective objective) { | ||
| 29 | + this.objective = objective; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + protected boolean matchesSafely(JsonNode jsonObjective) { | ||
| 33 | + | ||
| 34 | + // check operation | ||
| 35 | + String jsonOp = jsonObjective.get("operation").asText(); | ||
| 36 | + String op = objective.op().toString(); | ||
| 37 | + if (!jsonOp.equals(op)) { | ||
| 38 | + return false; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + // check permanent | ||
| 42 | + boolean jsonPermanent = jsonObjective.get("isPermanent").asBoolean(); | ||
| 43 | + boolean permanent = objective.permanent(); | ||
| 44 | + if (jsonPermanent != permanent) { | ||
| 45 | + return false; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + // check priority | ||
| 49 | + int jsonPriority = jsonObjective.get("priority").asInt(); | ||
| 50 | + int priority = objective.priority(); | ||
| 51 | + if (jsonPriority != priority) { | ||
| 52 | + return false; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + // check timeout | ||
| 56 | + int jsonTimeout = jsonObjective.get("timeout").asInt(); | ||
| 57 | + int timeout = objective.timeout(); | ||
| 58 | + if (jsonTimeout != timeout) { | ||
| 59 | + return false; | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + return true; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + /** | ||
| 66 | + * Factory to allocate a ObjectiveJsonMatcher. | ||
| 67 | + * | ||
| 68 | + * @param objective objective object we are looking for | ||
| 69 | + * @return matcher | ||
| 70 | + */ | ||
| 71 | + public static ObjectiveJsonMatcher matchesObjective(Objective objective) { | ||
| 72 | + return new ObjectiveJsonMatcher(objective); | ||
| 73 | + } | ||
| 74 | +} |
| 1 | +{ | ||
| 2 | + "priority": 60, | ||
| 3 | + "isPermanent": "false", | ||
| 4 | + "timeout": 1, | ||
| 5 | + "type": "PERMIT", | ||
| 6 | + "operation": "ADD", | ||
| 7 | + "conditions": [ | ||
| 8 | + { | ||
| 9 | + "type": "IN_PORT", | ||
| 10 | + "port": 23 | ||
| 11 | + } | ||
| 12 | + ], | ||
| 13 | + "meta": { | ||
| 14 | + "instructions": [ | ||
| 15 | + { | ||
| 16 | + "type": "OUTPUT", | ||
| 17 | + "port": -3 | ||
| 18 | + }, | ||
| 19 | + { | ||
| 20 | + "type": "DROP" | ||
| 21 | + } | ||
| 22 | + ], | ||
| 23 | + "deferred": [] | ||
| 24 | + } | ||
| 25 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +{ | ||
| 2 | + "priority": 60, | ||
| 3 | + "isPermanent": "false", | ||
| 4 | + "timeout": 1, | ||
| 5 | + "flag": "SPECIFIC", | ||
| 6 | + "operation": "ADD", | ||
| 7 | + "selector": { | ||
| 8 | + "criteria": [ | ||
| 9 | + { | ||
| 10 | + "type": "ETH_TYPE", | ||
| 11 | + "ethType": "0x806" | ||
| 12 | + } | ||
| 13 | + ] | ||
| 14 | + }, | ||
| 15 | + "treatment": | ||
| 16 | + { | ||
| 17 | + "instructions": | ||
| 18 | + [ | ||
| 19 | + {"type":"OUTPUT","port":-3}, | ||
| 20 | + {"type":"DROP"} | ||
| 21 | + ], | ||
| 22 | + "deferred":[] | ||
| 23 | + } | ||
| 24 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | +{ | ||
| 2 | + "id": 1, | ||
| 3 | + "type": "FAILOVER", | ||
| 4 | + "operation": "ADD", | ||
| 5 | + "treatments": [ | ||
| 6 | + { | ||
| 7 | + "instructions": [ | ||
| 8 | + { | ||
| 9 | + "type": "OUTPUT", | ||
| 10 | + "port": -3 | ||
| 11 | + }, | ||
| 12 | + { | ||
| 13 | + "type": "DROP" | ||
| 14 | + } | ||
| 15 | + ], | ||
| 16 | + "deferred": [] | ||
| 17 | + } | ||
| 18 | + ], | ||
| 19 | + "meta": { | ||
| 20 | + "criteria": [ | ||
| 21 | + { | ||
| 22 | + "type": "IN_PORT", | ||
| 23 | + "port": 23 | ||
| 24 | + } | ||
| 25 | + ] | ||
| 26 | + } | ||
| 27 | +} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment